tf-checkout-react 2.0.0-beta.25 → 2.0.0-beta.27

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/docs/API.html ADDED
@@ -0,0 +1,1002 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'">
7
+ <title>Ticket Fairy React checkout API reference</title>
8
+ <style>
9
+ :root { color-scheme: light; font-family: system-ui, -apple-system, sans-serif; }
10
+ body { color: #1d2032; background: #fff; line-height: 1.55; margin: 0; overflow-wrap: anywhere; }
11
+ main { max-width: 75rem; min-width: 0; margin: 0 auto; padding: 2rem 1.25rem 5rem; }
12
+ h1, h2, h3, h4 { line-height: 1.25; scroll-margin-top: 1rem; }
13
+ h1 { font-size: clamp(1.8rem, 3vw, 2.5rem); }
14
+ h2 { margin-top: 2.5rem; border-bottom: 1px solid #d4d8e4; padding-bottom: .35rem; }
15
+ a { color: #5020b8; text-decoration-thickness: .08em; }
16
+ a:focus-visible { outline: 3px solid #7a51e7; outline-offset: 3px; }
17
+ pre { box-sizing: border-box; max-width: 100%; overflow-x: auto; padding: 1rem; background: #f3f2f8; border-radius: .5rem; }
18
+ code { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: .9em; overflow-wrap: anywhere; }
19
+ pre code { font-size: .875rem; overflow-wrap: normal; white-space: pre; }
20
+ table { box-sizing: border-box; border-collapse: collapse; display: block; overflow-x: auto; max-width: 100%; }
21
+ th, td { border: 1px solid #d4d8e4; padding: .5rem .65rem; text-align: left; vertical-align: top; }
22
+ th { background: #f3f2f8; }
23
+ .skip { position: absolute; left: -10000px; }
24
+ .skip:focus { position: static; display: inline-block; padding: .5rem; }
25
+ @media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
26
+ </style>
27
+ </head>
28
+ <body>
29
+ <a class="skip" href="#main">Skip to content</a>
30
+ <main id="main">
31
+ <h1 id="react-checkout-api-reference">React checkout API reference</h1>
32
+ <p>This reference describes the public surface of
33
+ <code>tf-checkout-react</code> version <code>2.0.0-beta.27</code>. It
34
+ supplements the package's npm README with examples and an inventory of
35
+ the shared facade and hooks. The package's installed
36
+ <code>dist/index.d.ts</code> is the exact versioned source for complete
37
+ signatures and DTO fields. A named export or a typed payment method does
38
+ not establish that the matching backend feature, account permission or
39
+ payment provider is enabled.</p>
40
+ <p>For installation, a complete quick start, and examples of the
41
+ ready-made, single-page and step-by-step layouts, start with the <a
42
+ href="https://unpkg.com/tf-checkout-react@2.0.0-beta.27/docs/GUIDE.html#choose-a-checkout-layout">checkout
43
+ guide</a>. This file is the detailed component, engine and API
44
+ reference.</p>
45
+ <p>All examples assume <code>configureCheckout</code> has run, and React
46
+ Query examples are under a host <code>QueryClientProvider</code>. Use a
47
+ registered public SDK client ID and an empty <code>clientSecret</code>
48
+ in a browser. Never ship a confidential client secret.</p>
49
+ <h2 id="configure-and-persist-sessions">Configure and persist
50
+ sessions</h2>
51
+ <p>The following adapter keeps values in memory for the life of this
52
+ JavaScript module. Use it for a test or a deliberately non-persistent
53
+ browser session; refresh loses the session. Production persistence and
54
+ security are the host's choice. For an async backing store, the required
55
+ synchronous methods operate on a loaded mirror and optional
56
+ <code>flush()</code> waits for pending writes; initialize the mirror
57
+ before configuring and await relevant writes before claiming
58
+ success.</p>
59
+ <pre class="ts"><code>import { configureCheckout, type StorageAdapter } from &#39;tf-checkout-react&#39;
60
+
61
+ const values = new Map&lt;string, string&gt;()
62
+ const storage: StorageAdapter = {
63
+ getItem(key) { return values.get(key) ?? null },
64
+ setItem(key, value) { values.set(key, value) },
65
+ removeItem(key) { values.delete(key) },
66
+ }
67
+
68
+ configureCheckout({
69
+ env: &#39;STAG&#39;,
70
+ clientId: &#39;PUBLIC_SDK_CLIENT_ID&#39;,
71
+ clientSecret: &#39;&#39;,
72
+ cookieAuth: true,
73
+ storage,
74
+ })</code></pre>
75
+ <p>The default web adapter uses <code>localStorage</code>.
76
+ <code>createMemoryStorage()</code> supplies a ready-made in-memory
77
+ adapter. <code>getConfig()</code> reads the active resolved config, and
78
+ <code>isConfigured()</code> reports whether configuration has occurred.
79
+ Do not expose credentials by logging that config.
80
+ <code>configureCheckout</code> is global and should run before mounting;
81
+ a second configuration replaces the first. In an SSR app, initialize the
82
+ SDK in a client entry, and never share a module-level buyer session
83
+ between server requests. <code>auth</code> is a per-request header
84
+ function whose result normally merges after SDK headers. Protected
85
+ requests enforce session isolation: guest bootstrap strips sensitive
86
+ buyer/session headers after the merge. Do not attach privileged server
87
+ credentials in browser code.</p>
88
+ <p>A checkout buyer identity has event-scoped authority.
89
+ <code>hooks.useAuthSession()</code> observes session state, but a UI
90
+ flag, local token or checkout buyer profile does not itself authorize
91
+ private account data. Coordinate logout, buyer changes, query-cache use
92
+ and cart ownership with the host. <code>clearSession()</code> and
93
+ <code>clearCheckoutGuestSession()</code> are lower-level session
94
+ operations; use the appropriate authorized logout flow where a backend
95
+ session must also end.</p>
96
+ <h2 id="compose-navigation">Compose navigation</h2>
97
+ <p><code>Tickets</code> and <code>SeatMap</code> report when a cart is
98
+ ready; the host owns navigation when composing individual sections. This
99
+ skeleton connects seated selection to its view. This wiring recipe is
100
+ not a standalone app: configure and mount it under
101
+ <code>QueryClientProvider</code>. Its seat Back changes views only; it
102
+ does not itself release held seats or cancel an in-flight reservation or
103
+ cart priming. Before allowing a conflicting selection, coordinate that
104
+ work and hold expiry or release under your deployed backend
105
+ contract.</p>
106
+ <pre class="tsx"><code>import { useState } from &#39;react&#39;
107
+ import {
108
+ AddOns, BillingInfo, CheckoutProvider, Payment, SeatMap, Tickets, WaiverSigning,
109
+ } from &#39;tf-checkout-react&#39;
110
+
111
+ export function CheckoutLayout({ eventId }: { eventId: string }) {
112
+ const [view, setView] = useState&lt;&#39;tickets&#39; | &#39;seats&#39; | &#39;checkout&#39;&gt;(&#39;tickets&#39;)
113
+ const [notice, setNotice] = useState(&#39;&#39;)
114
+ return (
115
+ &lt;CheckoutProvider&gt;
116
+ &lt;div hidden={view !== &#39;tickets&#39;}&gt;
117
+ &lt;Tickets
118
+ eventId={eventId}
119
+ onSelectSeats={() =&gt; setView(&#39;seats&#39;)}
120
+ onContinue={() =&gt; setView(&#39;checkout&#39;)}
121
+ /&gt;
122
+ &lt;/div&gt;
123
+ {view === &#39;seats&#39; &amp;&amp; (
124
+ &lt;&gt;
125
+ &lt;button type=&quot;button&quot; onClick={() =&gt; setView(&#39;tickets&#39;)}&gt;Back to tickets&lt;/button&gt;
126
+ &lt;SeatMap eventId={eventId} onContinue={() =&gt; setView(&#39;checkout&#39;)} /&gt;
127
+ &lt;/&gt;
128
+ )}
129
+ {view === &#39;checkout&#39; &amp;&amp; (
130
+ &lt;&gt;
131
+ &lt;AddOns eventId={eventId} /&gt;
132
+ &lt;BillingInfo eventId={eventId} /&gt;
133
+ &lt;WaiverSigning eventId={eventId} /&gt;
134
+ &lt;Payment eventId={eventId} onComplete={(order) =&gt; {
135
+ setNotice(order.pending ? &#39;Payment pending&#39; : &#39;Order submitted&#39;)
136
+ }} /&gt;
137
+ &lt;p role=&quot;status&quot;&gt;{notice}&lt;/p&gt;
138
+ &lt;/&gt;
139
+ )}
140
+ &lt;/CheckoutProvider&gt;
141
+ )
142
+ }</code></pre>
143
+ <p>Real navigation must also implement checkout Edit/Back, preserve
144
+ entered details, and handle expiry, payment in flight, retained orders
145
+ and buyer/session changes. Do not unconditionally discard or replace a
146
+ cart on Back during a payment. Use <code>EmbeddedCheckout</code> for its
147
+ built-in Back and guarded Edit behavior; when building your own,
148
+ preserve validation and server reservation behavior. The host can use
149
+ <code>useCheckoutContext()</code> inside the provider to read the shared
150
+ checkout and <code>useCheckoutValidation()</code> to coordinate section
151
+ validation.</p>
152
+ <p>The provider's <code>value?: UseCheckout</code> accepts a checkout
153
+ created by the host's <code>useCheckout</code>; pass the same instance
154
+ to all sections of that flow. Omit it to let the provider create one and
155
+ wire the default installment picker. Checkout state is app-wide by
156
+ default; two hook calls do not create isolated carts.
157
+ <code>useCheckout</code> takes <code>{ ports?, options? }</code> once at
158
+ first render. A custom <code>ports</code> object is merged over browser
159
+ defaults and may provide <code>providerPage</code>,
160
+ <code>openUrl</code>, <code>onInstallmentOffers</code> or other payment
161
+ capabilities, but its type omits <code>confirmer</code> and cannot
162
+ replace the web hook's <code>webConfirmer</code>. Use the lower-level
163
+ <code>createEngine</code> configuration for a custom confirmer.
164
+ <code>options</code> includes <code>stripePublishableKey</code>,
165
+ <code>merchantIdentifier</code>, <code>merchantCountryCode</code>,
166
+ <code>merchantName</code>, <code>googlePayTestEnv</code>,
167
+ <code>redirectReturnUrl</code> and <code>urlScheme</code>. Only set
168
+ options appropriate to your host and payment provider.</p>
169
+ <h2 id="data-and-action-contracts">Data and action contracts</h2>
170
+ <h3 id="catalog-and-reservation">Catalog and reservation</h3>
171
+ <p><code>hooks.useTicketsWithMeta(eventId)</code> loads current ticket
172
+ types along with promo, waiting-list and bundle metadata.
173
+ <code>useTicketCatalog</code> manages the catalog and selection state
174
+ used by the standard ticket picker. The following renders a read-only
175
+ status; use the actual catalog row to construct
176
+ <code>TicketSelection</code> and reserve with <code>setTickets</code>
177
+ after the buyer chooses a quantity.</p>
178
+ <pre class="tsx"><code>import { hooks } from &#39;tf-checkout-react&#39;
179
+
180
+ export function EventAvailability({ eventId }: { eventId: string }) {
181
+ const query = hooks.useTicketsWithMeta(eventId)
182
+ if (query.isPending) return &lt;p role=&quot;status&quot;&gt;Loading availability…&lt;/p&gt;
183
+ if (query.isError) return &lt;button onClick={() =&gt; void query.refetch()}&gt;Retry&lt;/button&gt;
184
+ const { tickets, waitingList } = query.data
185
+ return &lt;p&gt;{tickets.length} ticket types; waiting list: {waitingList?.state ?? &#39;unavailable&#39;}&lt;/p&gt;
186
+ }</code></pre>
187
+ <p><code>TicketSelection = { id, name, optionName, price, quantity, currency }</code>.
188
+ <code>id</code> is the current opaque encrypted ID from the catalog. A
189
+ stable optional API <code>selectionKey</code> can preserve the buyer's
190
+ selected quantity across ID rotation; the latest encrypted ID is still
191
+ used on cart requests. For time-slot events, pass the actual available
192
+ date to <code>useTimeSlotTickets(eventId, date)</code> and respect the
193
+ backend's dated context. <code>useEventAddons(eventId)</code> loads
194
+ add-ons;
195
+ <code>ttf.events.filterAddonsForTickets(list, checkout.ticketTypeIds)</code>
196
+ filters for the primed ticket types. Call
197
+ <code>setAddons({ [addonId]: quantity })</code> to reprice.</p>
198
+ <p><code>setSeats(eventId, SeatLine[])</code> uses reserved seat IDs and
199
+ the corresponding tier/ticket relation, option and price. The seat-map
200
+ reservation has a server expiry.
201
+ <code>setSeatsIo(eventId, SeatsIoSelection)</code> is the separate
202
+ seats.io path. Neither method makes stale availability authoritative.
203
+ Use <code>resumeCart(eventId, { isFromResale? })</code> only after the
204
+ preceding flow has created the server cart in the matching session.</p>
205
+ <h3 id="billing-and-captures">Billing and captures</h3>
206
+ <p>The following code illustrates the setter shapes; the inputs must
207
+ come from actual buyer entry and the event's current configuration. It
208
+ does not attempt payment or assert that these fields alone satisfy a
209
+ particular event.</p>
210
+ <pre class="tsx"><code>import { useCheckout, type CheckoutBilling, type CheckoutHolder } from &#39;tf-checkout-react&#39;
211
+
212
+ export function SaveBuyer({ billing, holders }: {
213
+ billing: CheckoutBilling
214
+ holders: CheckoutHolder[]
215
+ }) {
216
+ const checkout = useCheckout()
217
+ function save() {
218
+ checkout.setBilling(billing)
219
+ checkout.setHolders(holders)
220
+ }
221
+ return &lt;button disabled={checkout.orderFixed} onClick={save}&gt;Save details&lt;/button&gt;
222
+ }</code></pre>
223
+ <p><code>CheckoutBilling</code> requires <code>firstName</code>,
224
+ <code>lastName</code> and <code>email</code>, with optional
225
+ <code>confirmEmail</code>, <code>phone</code>,
226
+ <code>phoneVerificationToken</code>,
227
+ <code>phoneFirstUseKnownEmail</code>, <code>streetAddress</code>,
228
+ <code>city</code>, <code>zip</code>, <code>countryId</code>,
229
+ <code>stateId</code>, <code>countryCode</code>, <code>stateCode</code>,
230
+ <code>stateRequired</code>, <code>dobDay</code>, <code>dobMonth</code>,
231
+ <code>dobYear</code>, <code>nationality</code>, <code>gender</code>,
232
+ <code>instagramHandle</code> and <code>dataCapture</code>. Backend
233
+ country/state IDs are not ISO codes; use
234
+ <code>ttf.geo.countries()</code> and <code>ttf.geo.states(...)</code> or
235
+ their hooks. <code>confirmEmail</code> is a UI check and is not sent as
236
+ an independent buyer email. A phone verification token must be the
237
+ server-issued proof for the matching event and phone.</p>
238
+ <p><code>CheckoutHolder</code> requires <code>firstName</code>,
239
+ <code>lastName</code>, <code>email</code>, and optionally has
240
+ <code>phone</code>, numeric backend <code>ticketTypeId</code> expressed
241
+ as a string, and <code>ticketDataCapture</code>. Holder requirements can
242
+ be stricter than the type's optional fields.
243
+ <code>CheckoutConsent</code> has <code>ttfOptIn</code> and
244
+ <code>brandOptIn</code> booleans; <code>EventCondition</code> acceptance
245
+ is recorded separately. In stock <code>BillingInfo</code>, however,
246
+ supplying <code>privacyPolicy</code> replaces the Ticket Fairy marketing
247
+ control with a required privacy checkbox that writes the
248
+ <strong>same</strong> <code>consent.ttfOptIn</code> value, submitted as
249
+ <code>ttf_opt_in</code>. This path does not independently capture
250
+ privacy and Ticket Fairy marketing choices. <code>brandOptIn</code> is
251
+ separate. Hosts requiring independent choices need an alternative whose
252
+ UI, payload and backend behavior have been verified; do not rely on the
253
+ stock <code>privacyPolicy</code> prop for that requirement.</p>
254
+ <p>For a host condition provide
255
+ <code>{ id, name, content, isRequired }</code> and record acceptance
256
+ with <code>acceptCondition(id, true)</code> or
257
+ <code>setAcceptedConditions(map)</code>. These are client gates, not a
258
+ replacement for server validation. <code>Payment</code> renders
259
+ <code>content</code> (or <code>name</code> as a fallback) as HTML;
260
+ supply trusted or sanitized content and verify how server-provided
261
+ conditions are handled as well.</p>
262
+ <p>Do not combine required stock <code>privacyPolicy</code> with
263
+ <code>skipBillingWhenProfileComplete</code> /
264
+ <code>skipWhenProfileComplete</code>: an eligible skip can hide the
265
+ privacy and marketing controls while <code>Payment</code> still requires
266
+ the privacy value. Keep billing visible and test both guest and
267
+ signed-in flows.</p>
268
+ <p><code>checkBuyerEmail(email)</code> starts a request; it does not
269
+ debounce it. The stock <code>BillingInfo</code> delays calls, but
270
+ headless hosts should debounce and coordinate in-flight checks. A late
271
+ response for an older email in the same cart can overwrite the snapshot.
272
+ Compare <code>existingAccountEmail</code> to the current trimmed input
273
+ before showing a match and recheck the current value if needed.</p>
274
+ <p><code>customFields</code> is an array of
275
+ <code>EventCustomFieldGroup</code> with order, ticket or add-on scope;
276
+ <code>CustomFieldValues</code> maps field names to strings or string
277
+ arrays. Order answers belong in <code>billing.dataCapture</code>, ticket
278
+ answers in each holder's <code>ticketDataCapture</code>, and add-on
279
+ answers in <code>setAddonDataCapture</code> keyed by add-on ID. Apply
280
+ ticket-scoped questions only to matching ticket types. Image capture has
281
+ format and size constraints and needs the SDK's image handling; validate
282
+ on the deployed server too. In this beta the backend owns conditional
283
+ requiredness and hosted-checkout conditional visibility is not fully
284
+ reproduced. Test the actual event's branches before release.</p>
285
+ <p>During priming, failed custom-field, checkout-config, add-on or
286
+ event-condition reads fall back to empty/default data and are not
287
+ recorded in <code>unavailableDetails</code>. The engine and stock UI
288
+ cannot gate requirements they did not load. Do not treat an empty list
289
+ as proof that no requirement exists; verify failure behavior and
290
+ implement tested host safeguards for mandatory fields and
291
+ acknowledgments. Server answer validation is not proof that a condition
292
+ was acknowledged.</p>
293
+ <p>If <code>unavailableDetails</code> includes <code>'waiver'</code>,
294
+ the read failed without establishing whether a waiver exists. Before
295
+ money may have moved, placement retries that read and blocks if it
296
+ remains unknown; <code>reloadCheckoutDetails()</code> also retries it. A
297
+ retained order with a possible payment follows separate recovery and
298
+ needs reconciliation. For a custom waiver UI,
299
+ <code>holdWaiverSigning(index)</code> returns a hold or
300
+ <code>null</code>; complete or cancel the upload, attach via
301
+ <code>setWaiverSignature(index, signature, hold)</code> only while the
302
+ binding remains current, and release the hold. The standard
303
+ <code>WaiverSigning</code> component performs this coordination. Edits
304
+ made when <code>orderFixed</code> is true are not a way to amend an
305
+ already placed order.</p>
306
+ <h3 id="placement-and-recovery">Placement and recovery</h3>
307
+ <p><code>placeOrder(method?, options?)</code> returns
308
+ <code>Promise&lt;PlaceOrderResult&gt;</code>; options include
309
+ <code>autoRunIdVerification</code>, <code>idVerification</code> and
310
+ <code>claimCard</code>. The default method is card. Supply the method
311
+ appropriate to the event and the active payment field. Inspect
312
+ <code>pending</code>, <code>pendingVoucherUrl</code> and
313
+ <code>needIdVerification</code>; <code>orderHash</code> is an order
314
+ reference, not a universal proof of settlement. Provider and server
315
+ reconciliation controls fulfilment. For zero-total orders, this SDK
316
+ ignores the free-registration response body and reports
317
+ <code>needIdVerification: false</code>. Verification or approval may
318
+ still be required; <code>free: true</code> is not proof of ticket
319
+ issuance. The default inline <code>EmbeddedCheckout</code> can
320
+ nevertheless show confirmed or ticket-available copy while approval or
321
+ verification is still outstanding. Use
322
+ <code>confirmationMode="redirect"</code> with host-owned authoritative
323
+ order and verification status, or a custom composed confirmation gated
324
+ on that status. If status is unavailable, contact support. Do not retry
325
+ payment for a free order. <code>OrderConfirmation</code> does not check
326
+ payment status before rendering its default
327
+ confirmed/ticket-availability copy. Gate it on authoritative appropriate
328
+ status; when the result is pending, show pending UI and any voucher
329
+ instead. The in-flow <code>Confirmation</code> component reads the
330
+ current result's pending state but shows confirmed copy when
331
+ <code>pending</code> is absent or false, even for paid orders whose
332
+ final settlement has not been independently verified. Use a host-owned
333
+ status route with <code>confirmationMode="redirect"</code> or a custom
334
+ composed confirmation gated on authoritative order and provider status.
335
+ Redirect omits inline ID verification; arrange it when
336
+ <code>needIdVerification</code> is true. For
337
+ <code>EmbeddedCheckout</code> in redirect mode, provide
338
+ <code>onComplete</code> to route the result.
339
+ <code>ResumedCheckout</code> defaults to redirect and likewise needs
340
+ that callback; otherwise its successful flow remains in the loading
341
+ transition. Inline mode has the confirmation and verification-copy
342
+ limitations described here. The stock <code>IDVerification</code> and
343
+ routed <code>OrderIDVerification</code> verified messages say tickets
344
+ are on their way but do not verify settlement or issuance. Use a
345
+ host-owned neutral verification and status UI when appropriate. If
346
+ <code>onComplete</code> navigates away or unmounts the checkout, inline
347
+ verification will not appear; keep the provider mounted or handle
348
+ verification at the destination.</p>
349
+ <p>For custom verification,
350
+ <code>runIdVerification(orderHash, options)</code> does not open a URL
351
+ by itself. Supply <code>openUrl</code>, validate the provider URL and
352
+ open it in the browser; handle a missing URL or blocked/failed opening.
353
+ The engine swallows asynchronous <code>openUrl</code> rejections, so
354
+ catch and record failures in that callback while showing neutral status.
355
+ Handle <code>onPhase</code> and browser returns;
356
+ <code>registerForegroundListener</code> can recheck on return and
357
+ returns an unsubscribe function. Alternatively, return <code>true</code>
358
+ from <code>onRequired</code> to take over: the engine resolves
359
+ <code>undefined</code> and neither opens nor polls. A timeout or poll
360
+ error rejects with copy promising payment is safe and tickets will be
361
+ emailed; replace it with neutral status and reconcile authoritative
362
+ payment, verification and issuance. Verification alone proves neither
363
+ settlement nor issuance.</p>
364
+ <p>For a custom Stripe card step, the following demonstrates the
365
+ boundary between host-collected data and SDK placement. Render it only
366
+ after reserving a cart and confirming that Stripe card is offered.
367
+ <code>canSubmit</code> must reflect the actual event's required answers,
368
+ add-ons, consent and waivers; it is not a substitute for server
369
+ validation. This example stops further attempts after an error until the
370
+ host has reconciled the outcome.</p>
371
+ <pre class="tsx"><code>import { useState } from &#39;react&#39;
372
+ import {
373
+ CardInput, useCheckout, type CheckoutBilling, type CheckoutConsent,
374
+ type CheckoutHolder,
375
+ } from &#39;tf-checkout-react&#39;
376
+
377
+ export function StripeCardStep(props: {
378
+ billing: CheckoutBilling
379
+ holders: CheckoutHolder[]
380
+ consent: CheckoutConsent
381
+ acceptedConditions: Record&lt;string, boolean&gt;
382
+ canSubmit: boolean
383
+ }) {
384
+ const checkout = useCheckout()
385
+ const [notice, setNotice] = useState(&#39;&#39;)
386
+ const [needsReview, setNeedsReview] = useState(false)
387
+ async function pay() {
388
+ checkout.setBilling(props.billing)
389
+ checkout.setHolders(props.holders)
390
+ checkout.setConsent(props.consent)
391
+ checkout.setAcceptedConditions(props.acceptedConditions)
392
+ try {
393
+ const order = await checkout.placeOrder(&#39;card&#39;)
394
+ setNotice(order.pending ? &#39;Payment pending&#39; : `Order reference: ${order.orderHash}`)
395
+ } catch {
396
+ setNeedsReview(true)
397
+ setNotice(&#39;The payment outcome needs review. Please contact support.&#39;)
398
+ }
399
+ }
400
+ return &lt;div&gt;
401
+ &lt;CardInput /&gt;
402
+ &lt;button disabled={!props.canSubmit || checkout.isBusy || needsReview || checkout.status !== &#39;ready&#39;}
403
+ onClick={() =&gt; void pay()}&gt;Pay&lt;/button&gt;
404
+ &lt;p role=&quot;status&quot;&gt;{notice}&lt;/p&gt;
405
+ &lt;/div&gt;
406
+ }</code></pre>
407
+ <p>The host should display <code>needIdVerification</code> and any
408
+ pending voucher as appropriate, check the authoritative result, and
409
+ provide a recovery path. A production UI also needs field labels,
410
+ accessible errors and a way to recover after a confirmed decline; do not
411
+ automatically repeat the charge in a catch.</p>
412
+ <p><code>Confirmation</code> defaults its share URL to
413
+ <code>window.location.href</code> and shows generic referral copy for
414
+ non-pending orders without checking organizer eligibility. That URL may
415
+ contain unrelated query parameters or lack a buyer-specific referral.
416
+ <code>EmbeddedCheckout</code> does not expose a <code>shareUrl</code>
417
+ prop. In a composed flow pass a verified eligible buyer-specific
418
+ <code>shareUrl</code>, or pass <code>shareUrl=""</code> to suppress
419
+ sharing. Server-backed <code>OrderConfirmation</code> and
420
+ <code>Rewards</code> can use response data where the backend supplies
421
+ it; first gate <code>OrderConfirmation</code> on an authoritative
422
+ appropriate payment status.</p>
423
+ <pre class="tsx"><code>import { useState } from &#39;react&#39;
424
+ import { useCheckout } from &#39;tf-checkout-react&#39;
425
+
426
+ export function StartOver() {
427
+ const checkout = useCheckout()
428
+ const [notice, setNotice] = useState(&#39;&#39;)
429
+ async function startOver() {
430
+ if (checkout.status === &#39;placing&#39;) setNotice(&#39;Finishing your payment…&#39;)
431
+ const reset = await checkout.resetWhenSettled()
432
+ setNotice(reset ? &#39;Choose tickets to start again.&#39; : &#39;Unable to start over. Check your order or contact support.&#39;)
433
+ }
434
+ return &lt;div&gt;
435
+ &lt;button onClick={() =&gt; void startOver()}&gt;Start over&lt;/button&gt;
436
+ &lt;p role=&quot;status&quot;&gt;{notice}&lt;/p&gt;
437
+ &lt;/div&gt;
438
+ }</code></pre>
439
+ <p>A retained order can represent an unknown payment outcome. Never
440
+ infer a safe new charge from an error, closed window or network timeout.
441
+ <code>resetWhenSettled</code> can also return <code>false</code> for a
442
+ retired checkout, so check current session/context before choosing
443
+ recovery. The exported <code>PAID_ORDER_PENDING_MESSAGE</code> tells the
444
+ buyer to press Pay again; a <code>false</code> result alone is not
445
+ enough to use that instruction or establish a safe retry. For custom
446
+ provider ports, return a settled dismissal on closure/unmount; custom
447
+ confirmer errors should classify only proven no-charge outcomes as
448
+ <code>declined</code>, <code>cancelled</code> or
449
+ <code>notStarted</code>, with <code>unknown</code> for uncertainty.
450
+ <code>UNSUPPORTED_GATEWAY</code> indicates the necessary platform
451
+ capability is not available, not that every provider failure is safe to
452
+ retry.</p>
453
+ <p>The beta.27 declaration comments for <code>reset</code> and
454
+ <code>PAID_ORDER_PENDING_MESSAGE</code> say pressing Pay again finishes
455
+ an unconfirmed order; the <code>resetWhenSettled</code> comment omits
456
+ retired checkouts as a reason for <code>false</code>. Those comments do
457
+ not establish that a retry is safe; check the current session and
458
+ reconcile first. Stock <code>Payment</code> can also display an engine
459
+ message telling the buyer to press Pay again when payment is
460
+ unconfirmed. That wording does not prove a retry is safe. If neutral
461
+ guidance is required, use a custom payment flow with host-controlled
462
+ error UI, retain the order and reconcile before recovery.</p>
463
+ <h2 id="auth-component-contracts">Auth component contracts</h2>
464
+ <p><code>AuthModal</code> owns a complete modal flow. Supply
465
+ <code>open</code>, <code>onClose</code> and, for public checkout
466
+ sign-in, <code>checkoutEventId</code>. Optional fields are
467
+ <code>initialView</code>, <code>initialEmail</code>,
468
+ <code>message</code>, <code>allowRegistration</code>,
469
+ <code>allowPasswordReset</code>,
470
+ <code>requireRegistrationAddress</code>,
471
+ <code>registrationFields</code>, <code>logoUrl</code>,
472
+ <code>className</code>, <code>onCheckoutAuthenticated</code> and
473
+ <code>onAuthenticated</code>. The callbacks correspond to checkout-buyer
474
+ and full-account profiles respectively; they are not interchangeable
475
+ authority. The registered backend journey decides which path is
476
+ available. The web checkout popup uses browser cryptography, a state
477
+ value and PKCE, checks the message origin and window, and can be
478
+ blocked, closed or time out. Never treat popup closure as successful
479
+ authentication.</p>
480
+ <p>The exported controlled forms can be combined with
481
+ <code>hooks.useAuthFlow</code>; they are not an authentication backend
482
+ on their own:</p>
483
+ <table>
484
+ <thead>
485
+ <tr>
486
+ <th>Form</th>
487
+ <th>Required props</th>
488
+ <th>Optional props</th>
489
+ </tr>
490
+ </thead>
491
+ <tbody>
492
+ <tr>
493
+ <td><code>LoginForm</code></td>
494
+ <td><code>onSubmit(input)</code></td>
495
+ <td><code>initialEmail</code>, <code>errors</code>, <code>error</code>,
496
+ <code>loading</code>, <code>allowPasswordReset</code>,
497
+ <code>onForgotPassword(email)</code>,
498
+ <code>onFieldChange(field)</code>.</td>
499
+ </tr>
500
+ <tr>
501
+ <td><code>RegisterForm</code></td>
502
+ <td><code>onSubmit(input, options)</code></td>
503
+ <td><code>initialEmail</code>, <code>errors</code>, <code>error</code>,
504
+ <code>loading</code>, <code>requireAddress</code>,
505
+ <code>requireTerms</code>, <code>completionRefresh</code>,
506
+ <code>onFieldChange(field)</code>. <code>completionRefresh</code>
507
+ supplies <code>retryAfter</code>, <code>onRequest()</code> and
508
+ <code>onVerify(code)</code>.</td>
509
+ </tr>
510
+ <tr>
511
+ <td><code>ForgotPasswordForm</code></td>
512
+ <td><code>onSubmit(email)</code>, <code>onBackToLogin(email)</code></td>
513
+ <td><code>initialEmail</code>, <code>errors</code>, <code>error</code>,
514
+ <code>successMessage</code>, <code>loading</code>,
515
+ <code>onFieldChange</code>.</td>
516
+ </tr>
517
+ <tr>
518
+ <td><code>ResetPasswordForm</code></td>
519
+ <td><code>token</code></td>
520
+ <td><code>onSuccess</code>, <code>onBackToLogin</code>.</td>
521
+ </tr>
522
+ <tr>
523
+ <td><code>TwoFactorForm</code></td>
524
+ <td><code>loading</code>, <code>error</code>,
525
+ <code>successMessage</code>, <code>smsAvailable</code>,
526
+ <code>smsRetryAfter</code>, <code>onSubmit(code)</code>,
527
+ <code>onSendSms()</code>, <code>onCancel()</code></td>
528
+ <td>None.</td>
529
+ </tr>
530
+ <tr>
531
+ <td><code>EmailCodeForm</code></td>
532
+ <td><code>initialEmail</code>, <code>sent</code>, <code>target</code>,
533
+ <code>retryAfter</code>, <code>loading</code>, <code>error</code>,
534
+ <code>successMessage</code>, <code>onRequest(email)</code>,
535
+ <code>onVerify(code)</code>, <code>onBack()</code></td>
536
+ <td>None.</td>
537
+ </tr>
538
+ <tr>
539
+ <td><code>PhoneAuthView</code></td>
540
+ <td><code>flow: PhoneAuthenticationFlow</code></td>
541
+ <td><code>allowCreation</code>, <code>allowPasswordReset</code>,
542
+ <code>termsUrl</code>, <code>privacyUrl</code>.</td>
543
+ </tr>
544
+ </tbody>
545
+ </table>
546
+ <p>Use the exported <code>AuthLoginInput</code>,
547
+ <code>AuthRegistrationInput</code>, <code>AuthFieldErrors</code>,
548
+ <code>AuthFieldName</code>, <code>AuthFlowView</code> and form
549
+ <code>*Props</code> types for exact values. Phone checkout requires
550
+ <code>sdkCheckoutPhoneAuth</code> and a matching deployed journey; do
551
+ not enable it just because the view exists. Complete any two-factor or
552
+ email/phone challenge before treating a buyer as authenticated. The
553
+ built-in modal's default <code>allowRegistration</code>,
554
+ <code>allowPasswordReset</code> and
555
+ <code>requireRegistrationAddress</code> are all <code>true</code>.
556
+ Public checkout registration and account completion force address
557
+ collection even when the option is <code>false</code>.</p>
558
+ <h2 id="payment-input-contracts">Payment input contracts</h2>
559
+ <p><code>CardInput</code> accepts <code>className?</code>, Stripe
560
+ card-element <code>style?</code>, <code>owner?</code> (default
561
+ <code>'checkout'</code>) and <code>visible?</code> (default
562
+ <code>true</code>). <code>StripePaymentElement</code> accepts
563
+ <code>className?</code>, <code>elementsConfig?</code>,
564
+ <code>wallets?</code> (<code>applePay?</code>, <code>googlePay?</code>),
565
+ Stripe <code>options?</code> and <code>owner?</code>.
566
+ <code>XenditCardInput</code> accepts <code>className?</code>,
567
+ <code>inputClassName?</code>, and
568
+ <code>onValidationChange?(message: string | null)</code>; the consumer
569
+ renders that message. Standard <code>Payment</code> mounts the
570
+ applicable field.</p>
571
+ <p>A separate bundle and ticket checkout can compete for the same
572
+ payment SDK. The web hook's default claim uses the <code>checkout</code>
573
+ owner's registered Payment Element if present, otherwise its
574
+ <code>CardInput</code>, and refuses if neither is available. For a
575
+ custom owner, <code>claimCardField(owner)</code> claims only
576
+ <code>CardInput</code>. For a <code>StripePaymentElement</code>, use
577
+ <code>cardClaimStep('webPaymentElement', () =&gt; webConfirmer.claimPaymentElement(owner))</code>
578
+ as the <code>placeOrder</code> <code>claimCard</code> step; for
579
+ <code>CardInput</code>, use a <code>webCard</code> claim step that calls
580
+ <code>webConfirmer.releasePaymentElement()</code> before
581
+ <code>claimCardField(owner)</code>. The standard <code>Payment</code>
582
+ component handles the claims and key changes. Don't assume the most
583
+ recently mounted field is the one belonging to an order. For a custom
584
+ owner, these helpers produce the appropriate step to pass as
585
+ <code>placeOrder('card', { claimCard })</code>:</p>
586
+ <pre class="ts"><code>import { cardClaimStep, claimCardField, webConfirmer, type CardClaimStep } from &#39;tf-checkout-react&#39;
587
+
588
+ export function claimCustomCard(owner: string): CardClaimStep {
589
+ return cardClaimStep(&#39;webCard&#39;, () =&gt; {
590
+ webConfirmer.releasePaymentElement()
591
+ return claimCardField(owner)
592
+ })
593
+ }
594
+
595
+ export function claimCustomPaymentElement(owner: string): CardClaimStep {
596
+ return cardClaimStep(&#39;webPaymentElement&#39;, () =&gt; webConfirmer.claimPaymentElement(owner))
597
+ }</code></pre>
598
+ <p><code>webConfirmer</code>, <code>webPorts</code> and
599
+ <code>webXenditTokenizer</code> are shared platform instances; factories
600
+ are available for advanced platform work. The generic
601
+ <code>createEngine({ ports, options?, store? })</code> requires a
602
+ payment confirmer and applicable optional ports. A custom integration
603
+ must preserve the same ownership, redirect, pending and error
604
+ guarantees.</p>
605
+ <h2 id="hooks-inventory">Hooks inventory</h2>
606
+ <p>Import these from the <code>hooks</code> namespace. Function
607
+ signatures and returned flow state are in the declarations; React Query
608
+ hooks require a query client. Many accept optional query/mutation
609
+ options. Names being exported do not imply that every feature is
610
+ deployed for your integration.</p>
611
+ <table>
612
+ <thead>
613
+ <tr>
614
+ <th>Domain</th>
615
+ <th>Hook names</th>
616
+ </tr>
617
+ </thead>
618
+ <tbody>
619
+ <tr>
620
+ <td>Event/catalog</td>
621
+ <td><code>useEvent</code>, <code>useTickets</code>,
622
+ <code>useTicketsWithMeta</code>, <code>useTimeSlotTickets</code>,
623
+ <code>useEventAddons</code>, <code>useEventBundles</code>,
624
+ <code>useTicketCatalog</code>, <code>useFeaturedEvents</code>.</td>
625
+ </tr>
626
+ <tr>
627
+ <td>Geo</td>
628
+ <td><code>useCountries</code>, <code>useStates</code>.</td>
629
+ </tr>
630
+ <tr>
631
+ <td>Checkout</td>
632
+ <td><code>useCheckout</code> (shared lower-level binding),
633
+ <code>useAppCheckoutSession</code>,
634
+ <code>useCheckoutBuyerProfile</code>,
635
+ <code>useCheckoutPhoneIdentity</code>,
636
+ <code>useCheckoutImageField</code>,
637
+ <code>useCheckoutPaymentMethods</code>, <code>useAddOnSelection</code>,
638
+ <code>useSeatSelection</code>, <code>useSeatsIoSelection</code>,
639
+ <code>useAccommodationSelection</code>, <code>useWaiverSigning</code>.
640
+ Use the top-level web <code>useCheckout</code> for pre-wired web
641
+ ports.</td>
642
+ </tr>
643
+ <tr>
644
+ <td>Codes and engagement</td>
645
+ <td><code>useWaitingListForm</code>, <code>useJoinWaitingList</code>,
646
+ <code>useAttributeReferrer</code>, <code>useValidatePhone</code>,
647
+ <code>useSendRsvp</code>.</td>
648
+ </tr>
649
+ <tr>
650
+ <td>Auth/session</td>
651
+ <td><code>useAuthSession</code>, <code>useSessionAction</code>,
652
+ <code>useAuthFlow</code>, <code>useLogin</code>,
653
+ <code>useRegister</code>, <code>useRegisterAccount</code>,
654
+ <code>useRestorePassword</code>, <code>useRestorePasswordRn</code>,
655
+ <code>useResetPassword</code>, <code>useLogout</code>,
656
+ <code>useCheckEmailExists</code>, <code>useVerifyTwoFactor</code>,
657
+ <code>useSendTwoFactorSms</code>,
658
+ <code>useRequestAccountEmailCode</code>,
659
+ <code>useVerifyAccountEmailCode</code>, <code>useCompleteAccount</code>,
660
+ <code>usePhoneAuthentication</code>.</td>
661
+ </tr>
662
+ <tr>
663
+ <td>Buyer/profile</td>
664
+ <td><code>useProfile</code>, <code>useUpdateAccount</code>,
665
+ <code>useUpdateProfile</code>, <code>useSavePhone</code>,
666
+ <code>useSendPhoneCode</code>, <code>useVerifyPhoneCode</code>,
667
+ <code>useProfileGender</code>, <code>useLinkedAccounts</code>,
668
+ <code>useAccountEmailEnrichment</code>.</td>
669
+ </tr>
670
+ <tr>
671
+ <td>Orders/tickets</td>
672
+ <td><code>useOrders</code>, <code>useOrder</code>,
673
+ <code>useTicketChangeOptions</code>, <code>useTicketChange</code>,
674
+ <code>useTicketRefund</code>, <code>useTicketGift</code>,
675
+ <code>useTicketResale</code>, <code>useCustomerPasses</code>,
676
+ <code>useAccountInformation</code>,
677
+ <code>useAccountPlanManagement</code>.</td>
678
+ </tr>
679
+ <tr>
680
+ <td>Bundles/gateway</td>
681
+ <td><code>useBundlePurchase</code>, <code>useBundleFlow</code>,
682
+ <code>useConfirmerHolder</code>, <code>useTicketGatewayWait</code>,
683
+ <code>useBundleStarting</code>, <code>useTicketCardForm</code>,
684
+ <code>useTicketCardOwner</code>.</td>
685
+ </tr>
686
+ <tr>
687
+ <td>Rewards</td>
688
+ <td><code>useOrderRewards</code>, <code>useAccountRewards</code>,
689
+ <code>useSubmitPrizeDetails</code>, <code>useCreatePack</code>,
690
+ <code>useJoinPack</code>, <code>useLeavePack</code>,
691
+ <code>useRegenerateShareCard</code>,
692
+ <code>useAccountRewardsSummary</code>,
693
+ <code>useReceiptRewards</code>.</td>
694
+ </tr>
695
+ <tr>
696
+ <td>Account/community</td>
697
+ <td><code>useAccountPreferences</code>,
698
+ <code>useInterestSelection</code>,
699
+ <code>useNotificationPreferences</code>,
700
+ <code>useAccountDeletion</code>, <code>useFriends</code>,
701
+ <code>useProfileSettings</code>, <code>useFriendProfile</code>,
702
+ <code>useSavedEvents</code>, <code>useSavedEvent</code>,
703
+ <code>useEventComments</code>, <code>useEventCommentImage</code>,
704
+ <code>useEventDiscussion</code>, <code>useWordPostReaction</code>.</td>
705
+ </tr>
706
+ <tr>
707
+ <td>Travel</td>
708
+ <td><code>useTrips</code>, <code>useTrip</code>,
709
+ <code>useDiscoveryTravel</code>.</td>
710
+ </tr>
711
+ <tr>
712
+ <td>Coordination</td>
713
+ <td><code>useLiveScope</code>, <code>useLockBusy</code>,
714
+ <code>useHeldScopes</code>, <code>useScopedState</code>,
715
+ <code>useOnOrderReleased</code>, <code>useOnEventChange</code>. These
716
+ are lower-level lifecycle/ownership helpers.</td>
717
+ </tr>
718
+ </tbody>
719
+ </table>
720
+ <p>For account order history, <code>useOrders(query?, options?)</code>
721
+ takes pagination and filters; <code>useOrder(orderId, options?)</code>
722
+ takes a numeric order ID string. A public order hash is used for
723
+ <code>OrderConfirmation</code>, <code>OrderIDVerification</code>, and
724
+ rewards, not as a numeric account order ID. Check the declarations for
725
+ each shape and make the appropriate authorized request.</p>
726
+ <h2 id="ttf-facade-inventory"><code>ttf</code> facade inventory</h2>
727
+ <p>These functions are grouped under the configured <code>ttf</code>
728
+ export. They are low-level calls; the engine and components perform
729
+ additional sequencing, preflight, state and payment coordination. Raw
730
+ functions are also exported in the <code>api</code> namespace. Calling a
731
+ low-level endpoint directly does not grant a buyer permission or
732
+ guarantee a safe payment retry.</p>
733
+ <p><code>ttf.events.requiredCustomFieldLabels(eventId)</code> returns
734
+ <code>[]</code> if its lookup fails as well as when no matching required
735
+ order/ticket labels exist. An empty result is not proof that the event
736
+ has no required custom fields.</p>
737
+ <table>
738
+ <thead>
739
+ <tr>
740
+ <th>Namespace</th>
741
+ <th>Methods</th>
742
+ </tr>
743
+ </thead>
744
+ <tbody>
745
+ <tr>
746
+ <td><code>ttf.events</code></td>
747
+ <td><code>featured</code>, <code>details</code>, <code>tickets</code>,
748
+ <code>ticketsWithMeta</code>, <code>bundles</code>,
749
+ <code>startBundlePurchase</code>, <code>info</code>,
750
+ <code>conditions</code>, <code>timeSlotTickets</code>,
751
+ <code>customFields</code>, <code>requiredCustomFieldLabels</code>,
752
+ <code>addons</code>, <code>filterAddonsForTickets</code>,
753
+ <code>submitPromoCode</code>, <code>setCurrency</code>,
754
+ <code>authenticate</code>, <code>track</code>,
755
+ <code>updateOrderDataCapture</code>,
756
+ <code>updateTicketDataCapture</code>.</td>
757
+ </tr>
758
+ <tr>
759
+ <td><code>ttf.cart</code></td>
760
+ <td><code>add</code>, <code>addSeats</code>, <code>get</code>,
761
+ <code>checkoutConfigs</code>, <code>price</code>,
762
+ <code>priceBreakdown</code>, <code>paymentConfig</code>,
763
+ <code>preOrderMethods</code>, <code>checkBuyerEmail</code>.</td>
764
+ </tr>
765
+ <tr>
766
+ <td><code>ttf.order</code></td>
767
+ <td><code>create</code>, <code>review</code>,
768
+ <code>mapProfileToBilling</code>, <code>completeFreeRegistration</code>,
769
+ <code>confirmSuccess</code>, <code>idVerificationStatus</code>,
770
+ <code>verifyCustomer</code>.</td>
771
+ </tr>
772
+ <tr>
773
+ <td><code>ttf.payment</code></td>
774
+ <td><code>startAdyen</code>, <code>adyenPage</code>,
775
+ <code>changeMethodType</code>, <code>confirmRedirect</code>,
776
+ <code>prepareOxxo</code>, <code>xenditEWalletCharge</code>,
777
+ <code>xenditCardCharge</code>, <code>installmentOffers</code>,
778
+ <code>confirmInstallments</code>, <code>createPaymentPlan</code>,
779
+ <code>chargeSavedCardPlan</code>, <code>changeMethod</code>,
780
+ <code>paypalForm</code>.</td>
781
+ </tr>
782
+ <tr>
783
+ <td><code>ttf.seatmap</code></td>
784
+ <td><code>startSession</code>, <code>data</code>, <code>statuses</code>,
785
+ <code>reserve</code>, <code>removeReserved</code>,
786
+ <code>refreshReservation</code>.</td>
787
+ </tr>
788
+ <tr>
789
+ <td><code>ttf.engagement</code></td>
790
+ <td><code>attributeReferrer</code>, <code>joinWaitingList</code>,
791
+ <code>sendRsvp</code>, <code>validatePhone</code>.</td>
792
+ </tr>
793
+ <tr>
794
+ <td><code>ttf.geo</code></td>
795
+ <td><code>countries</code>, <code>states</code>.</td>
796
+ </tr>
797
+ <tr>
798
+ <td><code>ttf.confirmation</code></td>
799
+ <td><code>get</code>.</td>
800
+ </tr>
801
+ <tr>
802
+ <td><code>ttf.orders</code></td>
803
+ <td><code>list</code>, <code>get</code>, <code>myTickets</code>,
804
+ <code>updateOrderCustomFields</code>,
805
+ <code>updateTicketHolderCustomFields</code>,
806
+ <code>updateAddOnCustomFields</code>.</td>
807
+ </tr>
808
+ <tr>
809
+ <td><code>ttf.ticketChanges</code></td>
810
+ <td><code>options</code>, <code>change</code>,
811
+ <code>joinWaitlist</code>, <code>leaveWaitlist</code>,
812
+ <code>history</code>.</td>
813
+ </tr>
814
+ <tr>
815
+ <td><code>ttf.resale</code></td>
816
+ <td><code>sell</code>, <code>remove</code>, <code>process</code>,
817
+ <code>decline</code>.</td>
818
+ </tr>
819
+ <tr>
820
+ <td><code>ttf.refunds</code></td>
821
+ <td><code>options</code>, <code>submit</code>.</td>
822
+ </tr>
823
+ <tr>
824
+ <td><code>ttf.gifts</code></td>
825
+ <td><code>options</code>, <code>send</code>, <code>cancel</code>.</td>
826
+ </tr>
827
+ <tr>
828
+ <td><code>ttf.passes</code></td>
829
+ <td><code>list</code>, <code>get</code>, <code>events</code>,
830
+ <code>bookings</code>, <code>redeem</code>, <code>cancel</code>.</td>
831
+ </tr>
832
+ <tr>
833
+ <td><code>ttf.rewards</code></td>
834
+ <td><code>forOrder</code>, <code>forAccount</code>,
835
+ <code>submitPrizeDetails</code>, <code>createPack</code>,
836
+ <code>joinPack</code>, <code>leavePack</code>,
837
+ <code>regenerateShareCard</code>.</td>
838
+ </tr>
839
+ <tr>
840
+ <td><code>ttf.waivers</code></td>
841
+ <td><code>forCheckout</code>, <code>uploadSignatureImage</code>.</td>
842
+ </tr>
843
+ <tr>
844
+ <td><code>ttf.extras</code></td>
845
+ <td><code>accommodation</code>, <code>quoteAccommodation</code>,
846
+ <code>reserve</code>.</td>
847
+ </tr>
848
+ <tr>
849
+ <td><code>ttf.trips</code></td>
850
+ <td><code>list</code>, <code>get</code>.</td>
851
+ </tr>
852
+ <tr>
853
+ <td><code>ttf.profile</code></td>
854
+ <td><code>get</code>, <code>updateAccount</code>, <code>update</code>,
855
+ <code>savePhone</code>, <code>sendPhoneCode</code>,
856
+ <code>verifyPhoneCode</code>.</td>
857
+ </tr>
858
+ <tr>
859
+ <td><code>ttf.preferences</code></td>
860
+ <td><code>getNotifications</code>, <code>saveNotifications</code>,
861
+ <code>get</code>, <code>save</code>, <code>connectAppleMusic</code>,
862
+ <code>disconnectAppleMusic</code>, <code>connectSpotify</code>,
863
+ <code>disconnectSpotify</code>.</td>
864
+ </tr>
865
+ <tr>
866
+ <td><code>ttf.friends</code></td>
867
+ <td><code>list</code>, <code>preview</code>, <code>command</code>,
868
+ <code>saveSettings</code>, <code>saveProfileSettings</code>,
869
+ <code>matchContacts</code>, <code>profile</code>.</td>
870
+ </tr>
871
+ <tr>
872
+ <td><code>ttf.savedEvents</code></td>
873
+ <td><code>list</code>, <code>status</code>, <code>save</code>.</td>
874
+ </tr>
875
+ <tr>
876
+ <td><code>ttf.comments</code></td>
877
+ <td><code>list</code>, <code>image</code>, <code>create</code>,
878
+ <code>update</code>, <code>remove</code>, <code>react</code>,
879
+ <code>report</code>, <code>block</code>, <code>moderate</code>.</td>
880
+ </tr>
881
+ <tr>
882
+ <td><code>ttf.word</code></td>
883
+ <td><code>getReaction</code>, <code>setReaction</code>.</td>
884
+ </tr>
885
+ <tr>
886
+ <td><code>ttf.preRegistration</code></td>
887
+ <td><code>confirm</code>, <code>influencers</code>,
888
+ <code>confirmationPage</code>, <code>submitShareAction</code>.</td>
889
+ </tr>
890
+ <tr>
891
+ <td><code>ttf.delegation</code></td>
892
+ <td><code>checkCustomerExists</code>, <code>pageInfo</code>,
893
+ <code>issueTicket</code>.</td>
894
+ </tr>
895
+ <tr>
896
+ <td><code>ttf.auth</code></td>
897
+ <td>Checkout: <code>loginForCheckout</code>,
898
+ <code>loginCheckoutWithVerifiedPhone</code>,
899
+ <code>registerForCheckout</code>, <code>getCheckoutBuyerProfile</code>,
900
+ <code>requestCheckoutEmailCode</code>,
901
+ <code>verifyCheckoutEmailCode</code>,
902
+ <code>verifyCheckoutTwoFactor</code>,
903
+ <code>sendCheckoutTwoFactorSms</code>,
904
+ <code>cancelCheckoutTwoFactor</code>, <code>logoutFromCheckout</code>,
905
+ <code>signInWithCheckoutBrowser</code>. Account/session:
906
+ <code>login</code>, <code>register</code>, <code>registerAccount</code>,
907
+ <code>logout</code>, <code>verifyTwoFactor</code>,
908
+ <code>cancelTwoFactor</code>, <code>sendTwoFactorSms</code>,
909
+ <code>signInWithBrowser</code>, <code>beginBrowserSignIn</code>,
910
+ <code>exchangeBrowserSignIn</code>, <code>checkEmailExists</code>.
911
+ Recovery/proof: <code>restorePassword</code>,
912
+ <code>restorePasswordRn</code>, <code>validateResetToken</code>,
913
+ <code>resetPassword</code>, <code>requestAccountEmailCode</code>,
914
+ <code>verifyAccountEmailCode</code>, <code>completeAccount</code>,
915
+ <code>requestCheckoutPhoneCode</code>,
916
+ <code>verifyCheckoutPhoneCode</code>,
917
+ <code>loginWithVerifiedPhone</code>, <code>mintVerificationUrl</code>,
918
+ <code>getVerificationInfo</code>, <code>updateVerificationStatus</code>.
919
+ Account management: <code>getLinkedAccounts</code>,
920
+ <code>linkAccount</code>, <code>disconnectAccount</code>,
921
+ <code>getAccountDeletionStatus</code>,
922
+ <code>sendAccountDeletionCode</code>, <code>deleteAccount</code>.</td>
923
+ </tr>
924
+ </tbody>
925
+ </table>
926
+ <p><code>ttf.events.track(eventId, { pageUrl?, page?, orderHash? })</code>
927
+ is explicit event tracking. The host owns its trigger, consent and
928
+ deduplication. Account and post-purchase methods can require a different
929
+ authority from public checkout. Never log raw credentials, buyer answers
930
+ or payment-provider payloads.</p>
931
+ <h2 id="ui-type-reference">UI type reference</h2>
932
+ <p>In addition to the checkout/section prop tables in the npm README,
933
+ these primitives expose the following contracts:</p>
934
+ <ul>
935
+ <li><code>Card</code> accepts HTML <code>div</code> attributes.
936
+ <code>SectionHeader</code> requires <code>title</code> and accepts
937
+ <code>step</code>, <code>pills</code>, <code>className</code>.
938
+ <code>Pill</code> takes <code>children</code> and
939
+ <code>muted</code>.</li>
940
+ <li><code>Button</code> accepts normal button attributes and
941
+ <code>variant</code>, <code>block</code>, <code>loading</code>.
942
+ <code>Field</code> takes <code>children</code>, <code>label</code>,
943
+ <code>error</code>, <code>invalid</code>, <code>className</code>;
944
+ <code>FieldRow</code> takes <code>children</code> and
945
+ <code>className</code>.</li>
946
+ <li><code>Input</code>, <code>Textarea</code>, <code>Select</code>
947
+ accept the matching HTML attributes and <code>invalid</code>;
948
+ <code>Checkbox</code> accepts input attributes and
949
+ <code>label</code>.</li>
950
+ <li><code>CustomFieldInput</code> requires <code>field</code>,
951
+ <code>value</code>, <code>onChange</code> and accepts
952
+ <code>error</code>. <code>CustomFieldGroupFields</code> requires
953
+ <code>group</code>, <code>values</code>,
954
+ <code>onChange(name, value)</code> and accepts
955
+ <code>ticketTypeId</code>. The UI's <code>customFieldsComplete</code>
956
+ helper does not replace server conditional-field validation.</li>
957
+ <li><code>PaymentMethods</code> is controlled: <code>options</code>,
958
+ <code>selected</code>, <code>onSelect</code>, <code>extraValues</code>,
959
+ <code>onExtraChange</code> are required. <code>showValidation</code>,
960
+ <code>children</code>, <code>inputSlotFor</code>, <code>className</code>
961
+ are optional. <code>PaymentMethodOption</code> identifies the
962
+ label/value, method ID and optional extra input.</li>
963
+ <li><code>Stepper</code> and <code>QuantitySelect</code> require
964
+ <code>value</code> and <code>onChange</code>; both accept
965
+ <code>min</code>, <code>max</code>, <code>step</code>,
966
+ <code>disabled</code>, <code>className</code>.
967
+ <code>QuantitySelect</code> also accepts an accessible
968
+ <code>label</code>.</li>
969
+ <li><code>PriceLine</code> requires <code>amount</code>, with
970
+ <code>currency</code>, <code>original</code>, <code>note</code>,
971
+ <code>className</code>. <code>Timer</code> requires
972
+ <code>seconds</code>, with <code>urgentAt</code>, <code>label</code>,
973
+ <code>className</code>; <code>TimerBanner</code> accepts optional
974
+ <code>seconds</code>, <code>urgentAt</code>, <code>message</code>,
975
+ <code>className</code>. <code>Loader</code> accepts
976
+ <code>className</code>.</li>
977
+ <li><code>SignaturePad</code> requires
978
+ <code>onChange(pngDataUrl, inkLength)</code>, <code>label</code> and
979
+ <code>clearLabel</code>; <code>disabled</code> is optional.
980
+ <code>FrozenFields</code> takes <code>children</code> and an optional
981
+ <code>frozen</code>, using a disabled fieldset.
982
+ <code>I18nProvider</code> takes optional <code>locale</code>,
983
+ <code>messages</code> and <code>children</code>; <code>useT()</code>
984
+ reads its translator.</li>
985
+ </ul>
986
+ <p><code>CheckoutTheme</code> supports <code>colorScheme</code>,
987
+ <code>accent</code>, <code>accentHover</code>,
988
+ <code>accentContrast</code>, <code>surface</code>,
989
+ <code>surfaceMuted</code>, <code>text</code>, <code>muted</code>,
990
+ <code>border</code>, <code>error</code>, <code>success</code>,
991
+ <code>radiusCard</code>, <code>radiusControl</code>,
992
+ <code>shadow</code>, <code>font</code>, <code>fontSize</code> and
993
+ <code>maxWidth</code>. <code>themeToVars</code> returns corresponding
994
+ CSS custom properties. <code>LocaleCode</code> accepts
995
+ <code>en-GB</code>, <code>en-US</code>, <code>es-MX</code>,
996
+ <code>fr</code>, <code>de</code>, <code>ru</code>, <code>id</code>;
997
+ translations may fall back to English. Always verify event-specific
998
+ copy, contrast, focus handling and third-party payment widgets in the
999
+ host.</p>
1000
+ </main>
1001
+ </body>
1002
+ </html>