@fanfare-io/fanfare-sdk-react 0.11.0 → 0.12.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.
- package/dist/components/checkout/checkout-processing-panel.d.ts +10 -0
- package/dist/components/checkout/index.d.ts +4 -0
- package/dist/components/checkout/payment-collection-panel.d.ts +18 -0
- package/dist/components/checkout/receipt-panel.d.ts +10 -0
- package/dist/components/checkout/reservation-checkout-panel.d.ts +18 -0
- package/dist/components/checkout/stripe-card-field.d.ts +29 -0
- package/dist/components/checkout/stripe-client.d.ts +71 -0
- package/dist/components/checkout/use-payment-challenge.d.ts +32 -0
- package/dist/components/checkout/use-payment-method-selection.d.ts +8 -0
- package/dist/components/widgets/experience-widget.d.ts +78 -2
- package/dist/hooks/use-fanfare-dom-bridge.d.ts +57 -0
- package/dist/hooks/use-sdk-event.d.ts +20 -0
- package/dist/index-Ce5dVdo3.js +6053 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +59 -5192
- package/dist/lib/currency.d.ts +10 -0
- package/dist/stripe-card-field-D1b4Y7LK.js +170 -0
- package/dist/styles/base.css +1 -1
- package/package.json +18 -15
- package/dist/components/widgets/draw/draw-actions.d.ts +0 -40
- package/dist/components/widgets/draw/index.d.ts +0 -6
- package/dist/components/widgets/queue/index.d.ts +0 -6
- package/dist/components/widgets/queue/queue-actions.d.ts +0 -36
- package/dist/components/widgets/timed-release/index.d.ts +0 -6
- package/dist/components/widgets/timed-release/timed-release-actions.d.ts +0 -38
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CheckoutProcessingSlotProps } from '../widgets/experience-widget';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Default processing panel shown for the gap between a submitted reservation checkout and the
|
|
5
|
+
* server's confirmation.
|
|
6
|
+
*
|
|
7
|
+
* The consumer must not navigate away while the payment settles, so the wait is announced rather
|
|
8
|
+
* than shown only as motion.
|
|
9
|
+
*/
|
|
10
|
+
export declare function CheckoutProcessingPanel(_props: CheckoutProcessingSlotProps): React.ReactElement;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PaymentCollectionSlotProps } from '../widgets/experience-widget';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Default payment-collection panel for pre-auth distributions, rendered both when the consumer is
|
|
5
|
+
* about to enter and when a failed authorization leaves a retry open.
|
|
6
|
+
*
|
|
7
|
+
* The hold amount is rendered from the view's own figure — the client never derives one.
|
|
8
|
+
*
|
|
9
|
+
* The configuration block reaches this panel on the entry mount only. A retry is offered from an
|
|
10
|
+
* ended view, which carries none, so that mount renders payment as unavailable and a consumer with
|
|
11
|
+
* a saved method submits without needing Stripe.js at all.
|
|
12
|
+
*
|
|
13
|
+
* Entry has no server-side resume: a paused authorization is carried forward by submitting the
|
|
14
|
+
* identical payment input again, held here from the first submit, so exactly one payment method is
|
|
15
|
+
* minted across the whole flow. An ended view carries no pending action, so the retry mount reaches
|
|
16
|
+
* none of this.
|
|
17
|
+
*/
|
|
18
|
+
export declare function PaymentCollectionPanel({ preAuthAmount, preAuthCurrencyCode, savedPaymentMethods, paymentProvider, onEnter, isEntering, intent, pendingAction, onRetryPaymentConfig, ...slotProps }: PaymentCollectionSlotProps): React.ReactElement;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReceiptSlotProps } from '../widgets/experience-widget';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Default panel for a completed Fanfare-managed payment.
|
|
5
|
+
*
|
|
6
|
+
* The order reference is the outcome. An admission credential appears only on the arm that carries
|
|
7
|
+
* one, and stays subordinate to the purchase: payment is terminal, so a receipt must never read as
|
|
8
|
+
* the thing that admits its holder.
|
|
9
|
+
*/
|
|
10
|
+
export declare function ReceiptPanel(props: ReceiptSlotProps): React.ReactElement;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReservationCheckoutSlotProps } from '../widgets/experience-widget';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Default reservation-checkout panel for post-win checkout flows.
|
|
5
|
+
*
|
|
6
|
+
* `Countdown`'s `onComplete` is a no-op: the journey machine owns the reservation's expiry (it
|
|
7
|
+
* arms its own timer and transitions the sequence to `ended` when the deadline passes), so the
|
|
8
|
+
* panel never disables itself locally — it simply stops being rendered once the phase changes.
|
|
9
|
+
*
|
|
10
|
+
* Elements renders only on the internal-processor arm. The discriminator is `processor`; an absent
|
|
11
|
+
* configuration block on that arm means the configuration read failed, which is a retryable outage
|
|
12
|
+
* inside a ticking window — never a signal that another processor is in play.
|
|
13
|
+
*
|
|
14
|
+
* A pending action adds visible substates over the same screen rather than replacing it: the card
|
|
15
|
+
* field stays mounted through the whole challenge, because a consumer whose bank prompt failed may
|
|
16
|
+
* need to submit again with the card they already typed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function ReservationCheckoutPanel({ reservation, savedPaymentMethods, processor, paymentProvider, pendingAction, onConfirm, onResume, isConfirming, onRetryPaymentConfig, ...slotProps }: ReservationCheckoutSlotProps): React.ReactElement;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { StripeClientConfig } from './stripe-client';
|
|
2
|
+
/**
|
|
3
|
+
* The SDK's card-entry field: a Stripe Card Element and the controller that turns it into a
|
|
4
|
+
* payment-method id. It knows nothing about reservations, pre-auth, or amounts.
|
|
5
|
+
*
|
|
6
|
+
* `@stripe/stripe-js` is a type-only dependency across the SDK, so no vendor bytes ship in any
|
|
7
|
+
* chunk. This module is the one lazy split: it is reached only through a dynamic `import()` from
|
|
8
|
+
* the panel that renders new-card entry, so the Card Element wiring stays out of the adapter's
|
|
9
|
+
* entry chunk. Nothing statically imported from `src/index.ts` may reach it.
|
|
10
|
+
*
|
|
11
|
+
* Stripe.js is unsupported inside a shadow root, and the Solid adapter's web components attach one
|
|
12
|
+
* unconditionally, so the element mounts into a container this file appends to the light DOM and
|
|
13
|
+
* positions over its in-panel anchor. The theme's custom properties do not cross the shadow
|
|
14
|
+
* boundary, so the resolved values the card style needs are copied onto that container.
|
|
15
|
+
*/
|
|
16
|
+
import * as React from "react";
|
|
17
|
+
export interface StripeCardController {
|
|
18
|
+
/** Resolves the `pm_…` id, or rejects with an `Error` carrying already-localized copy. */
|
|
19
|
+
createPaymentMethod: () => Promise<string>;
|
|
20
|
+
}
|
|
21
|
+
export interface StripeCardFieldProps {
|
|
22
|
+
config: StripeClientConfig;
|
|
23
|
+
onController: (controller: StripeCardController | null) => void;
|
|
24
|
+
onChange?: (state: {
|
|
25
|
+
complete: boolean;
|
|
26
|
+
errorMessage: string | null;
|
|
27
|
+
}) => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function StripeCardField({ config, onController, onChange }: StripeCardFieldProps): React.ReactElement;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ReservationPaymentAffordance } from '@fanfare-io/fanfare-sdk-core/experiences';
|
|
2
|
+
import { Stripe, StripeConstructor, StripeElementStyle } from '@stripe/stripe-js';
|
|
3
|
+
/**
|
|
4
|
+
* The wire block a checkout-capable view carries, reached through the adapter's declared
|
|
5
|
+
* dependency on `fanfare-sdk-core` rather than the contracts package: core re-exports the contract
|
|
6
|
+
* types so adapter modules never resolve `@fanfare-io/fanfare-sdk-contracts` directly.
|
|
7
|
+
*/
|
|
8
|
+
type PaymentProviderConfig = NonNullable<ReservationPaymentAffordance["paymentProvider"]>;
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
Stripe?: StripeConstructor;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export interface StripeClientConfig {
|
|
15
|
+
publishableKey: string;
|
|
16
|
+
stripeAccount?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Loads Stripe.js once per page. A failure is never retained: a memoized rejection would strand
|
|
20
|
+
* every subsequent payer on the page, not just the one whose load failed. Retry is the caller's
|
|
21
|
+
* decision — this module never schedules one.
|
|
22
|
+
*/
|
|
23
|
+
export declare function loadStripeJs(): Promise<StripeConstructor>;
|
|
24
|
+
/**
|
|
25
|
+
* One Stripe client per (publishable key, connected account). A construction that rejects drops
|
|
26
|
+
* its cache entry for the same reason the loader does.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getStripe(config: StripeClientConfig): Promise<Stripe>;
|
|
29
|
+
/**
|
|
30
|
+
* Re-serializes a theme color into the spelling a CSS color parser produces.
|
|
31
|
+
*
|
|
32
|
+
* Custom properties are untyped, so a theme color arrives from `getComputedStyle` as whatever token
|
|
33
|
+
* stream the stylesheet declared — and a minifier is free to rewrite `oklch(0.63 0.24 25)` as
|
|
34
|
+
* `oklch(63% .24 25)`. Stripe's element options go through a stricter parser than CSS's: a spelling
|
|
35
|
+
* every browser accepts can still be rejected there, and the rejection is silent — the element
|
|
36
|
+
* mounts a frame that never renders its input. The invariant this restores is that colors reach
|
|
37
|
+
* Stripe in the serialization its parser accepts.
|
|
38
|
+
*
|
|
39
|
+
* `null` means the value is not a color the parser recognizes, and the caller must omit the key
|
|
40
|
+
* rather than guess: assigning an unparsable value leaves `fillStyle` on its previous one, so
|
|
41
|
+
* emitting the read-back would emit some other color entirely. Where no parser exists — server
|
|
42
|
+
* rendering, or a DOM without canvas — the value passes through: the mismatch only arises where a
|
|
43
|
+
* real browser serializes computed styles.
|
|
44
|
+
*/
|
|
45
|
+
export declare function normalizeCssColor(value: string): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Maps the SDK theme's resolved custom properties onto the Card Element's `style` option. Stripe's
|
|
48
|
+
* `Appearance` API governs the Elements group Payment Element consumes and does not reach the
|
|
49
|
+
* legacy Card Element, so `style` is the only theming path — there is deliberately no second one.
|
|
50
|
+
*
|
|
51
|
+
* Property names are the values of `THEME_CSS_VARS` (the adapter's `theme/theme.types.ts`), spelled
|
|
52
|
+
* literally here because this file must stay identical across adapters. `--ff-color-primary` and
|
|
53
|
+
* `--ff-color-background` have no Card Element equivalent: the element's background is the host
|
|
54
|
+
* page's, supplied by the panel around the iframe.
|
|
55
|
+
*
|
|
56
|
+
* Every color is re-serialized on the way out; a color the parser rejects is omitted, which leaves
|
|
57
|
+
* Stripe on its own default for that slot. The font stack is not a color and is forwarded as read.
|
|
58
|
+
*/
|
|
59
|
+
export declare function deriveStripeCardStyle(root: HTMLElement): StripeElementStyle;
|
|
60
|
+
/**
|
|
61
|
+
* The one binding between a view's wire configuration and a Stripe client.
|
|
62
|
+
*
|
|
63
|
+
* `null` means no usable Stripe client configuration reached this view. On a checkout-capable arm
|
|
64
|
+
* that has exactly one cause — the configuration read failed — because the processor discriminator
|
|
65
|
+
* is the `processor` field (reserved) or `checkoutMode` (enterable), never the presence of this
|
|
66
|
+
* block. The condition is transient and retryable.
|
|
67
|
+
*/
|
|
68
|
+
export declare function resolveStripeClientConfig(source: PaymentProviderConfig | undefined): StripeClientConfig | null;
|
|
69
|
+
/** Test-only seam over every memo this module holds. Never exported from an adapter's public entry. */
|
|
70
|
+
export declare function resetStripeClientCache(): void;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { StripeClientConfig } from './stripe-client';
|
|
2
|
+
/** `idle` covers both "no challenge yet" and "this attempt has settled". */
|
|
3
|
+
export type PaymentChallengePhase = "idle" | "challenging" | "resuming";
|
|
4
|
+
/**
|
|
5
|
+
* How the last attempt ended, when it ended badly — the fact a panel needs to offer the right way
|
|
6
|
+
* out, which the error copy alone cannot carry.
|
|
7
|
+
*
|
|
8
|
+
* - `cancelled` — the prompt ended without the card being refused: the consumer dismissed it, or the
|
|
9
|
+
* authentication behind it failed. Reopening that same prompt is the recovery.
|
|
10
|
+
* - `declined` — the card was refused, or the prompt could not be opened at all. That secret is
|
|
11
|
+
* spent; only a fresh submission can produce another.
|
|
12
|
+
* - `resume_failed` — the prompt succeeded and the operation behind it did not. The challenge is
|
|
13
|
+
* answered, so the recovery is to run that operation again, never to reopen the prompt.
|
|
14
|
+
*/
|
|
15
|
+
export type PaymentChallengeRecovery = "cancelled" | "declined" | "resume_failed";
|
|
16
|
+
export interface PaymentChallenge {
|
|
17
|
+
phase: PaymentChallengePhase;
|
|
18
|
+
/** Localized copy for the attempt that produced it; terminal until another attempt starts. */
|
|
19
|
+
error: string | null;
|
|
20
|
+
/** Set together with `error`, and cleared when the next attempt starts. */
|
|
21
|
+
recovery: PaymentChallengeRecovery | null;
|
|
22
|
+
/**
|
|
23
|
+
* Open the bank prompt for `clientSecret`. Once per secret per instance: a repeat call carrying a
|
|
24
|
+
* secret this instance already launched is a no-op, and a genuinely new secret launches again.
|
|
25
|
+
*/
|
|
26
|
+
launch: (clientSecret: string, resume: () => Promise<void>) => void;
|
|
27
|
+
/** Reopen the same prompt on the consumer's own instruction, then run the same resume. */
|
|
28
|
+
retry: (clientSecret: string, resume: () => Promise<void>) => void;
|
|
29
|
+
}
|
|
30
|
+
/** Test-only seam. Never exported from the adapter's public entry. */
|
|
31
|
+
export declare function resetPaymentChallengeState(): void;
|
|
32
|
+
export declare function usePaymentChallenge(config: StripeClientConfig | null): PaymentChallenge;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PaymentMethodSummary } from '@fanfare-io/fanfare-sdk-core/experiences';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks the selected saved payment method for a checkout panel. The list can still be loading on
|
|
4
|
+
* mount (nothing selected yet) or a previously selected card can be removed out from under the
|
|
5
|
+
* panel — falls back to the default method, else the first, else `undefined`, both on initial
|
|
6
|
+
* mount and whenever the list changes, so submit never carries a stale/deleted `paymentMethodId`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function usePaymentMethodSelection(savedPaymentMethods: PaymentMethodSummary[]): [string | undefined, (id: string) => void];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BotMitigationState, RoutingChallenge } from '@fanfare-io/fanfare-sdk-core/challenges';
|
|
2
|
-
import { JourneyHandle, JourneySnapshot, JourneyView, SequenceView } from '@fanfare-io/fanfare-sdk-core/experiences';
|
|
2
|
+
import { CheckoutNextAction, CheckoutProcessor, FanfareCheckoutResult, JourneyHandle, JourneySnapshot, JourneyView, PaymentInput, PaymentMethodSummary, ReservationPaymentAffordance, SequenceView } from '@fanfare-io/fanfare-sdk-core/experiences';
|
|
3
3
|
import { BrandTheme, WidgetVariant } from '../../theme';
|
|
4
4
|
import { AuthInputMode } from '../auth/auth-input';
|
|
5
5
|
import * as React from "react";
|
|
@@ -59,6 +59,74 @@ export interface GrantedSlotProps extends SlotProps {
|
|
|
59
59
|
grant?: string;
|
|
60
60
|
expiresAt?: number;
|
|
61
61
|
}
|
|
62
|
+
export interface PaymentCollectionSlotProps extends SlotProps {
|
|
63
|
+
preAuthAmount: string;
|
|
64
|
+
preAuthCurrencyCode: string;
|
|
65
|
+
savedPaymentMethods: PaymentMethodSummary[];
|
|
66
|
+
/** Rejects on a recoverable payment failure (e.g. a declined card) — the panel owns recovery UI for its own submit. */
|
|
67
|
+
onEnter: (paymentInput: PaymentInput) => Promise<void>;
|
|
68
|
+
isEntering: boolean;
|
|
69
|
+
/** "enter" collects payment before first entry; "reenter" collects payment to retry after a failed or expired authorization hold. */
|
|
70
|
+
intent: "enter" | "reenter";
|
|
71
|
+
/**
|
|
72
|
+
* Client configuration for the processor authorizing this entry, as the server supplied it.
|
|
73
|
+
* Carried by the enterable arm only — a retry is offered from an ended view, which holds no
|
|
74
|
+
* configuration.
|
|
75
|
+
*/
|
|
76
|
+
paymentProvider?: PaymentProviderConfig;
|
|
77
|
+
/** Present while the processor is waiting on an out-of-band action; re-submitting entry resolves it. */
|
|
78
|
+
pendingAction?: CheckoutNextAction;
|
|
79
|
+
/**
|
|
80
|
+
* Re-reads the consumer's journeys from the server so a provider configuration that was missing
|
|
81
|
+
* or unreadable at render can arrive. This is the panel's only recovery when `paymentProvider` is
|
|
82
|
+
* absent — the value is a prop, so nothing the panel does to its own state can produce it.
|
|
83
|
+
*/
|
|
84
|
+
onRetryPaymentConfig?: () => Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The processor's client configuration block, named through the affordance that carries it: core
|
|
88
|
+
* re-exports the affordance but not the contract's own name for this shape.
|
|
89
|
+
*/
|
|
90
|
+
type PaymentProviderConfig = NonNullable<ReservationPaymentAffordance["paymentProvider"]>;
|
|
91
|
+
export interface ReservationCheckoutSlotProps extends SlotProps {
|
|
92
|
+
reservation: {
|
|
93
|
+
token: string;
|
|
94
|
+
expiresAt: number;
|
|
95
|
+
};
|
|
96
|
+
savedPaymentMethods: PaymentMethodSummary[];
|
|
97
|
+
/** Which processor executes this reservation's payment leg; narrow before rendering processor-specific UI. */
|
|
98
|
+
processor: CheckoutProcessor;
|
|
99
|
+
/** Client configuration for the processor settling this reservation, as the server supplied it. */
|
|
100
|
+
paymentProvider?: PaymentProviderConfig;
|
|
101
|
+
/** Present while the processor is waiting on an out-of-band action; complete it, then call `onResume`. */
|
|
102
|
+
pendingAction?: CheckoutNextAction;
|
|
103
|
+
/** Rejects on a recoverable payment failure (e.g. a declined card) — the panel owns recovery UI for its own submit. */
|
|
104
|
+
onConfirm: (paymentInput: PaymentInput) => Promise<void>;
|
|
105
|
+
/** Re-submits the paused checkout after `pendingAction` has been completed. Idempotent server-side. */
|
|
106
|
+
onResume: () => Promise<void>;
|
|
107
|
+
isConfirming: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Re-reads the consumer's journeys from the server so a provider configuration that was missing
|
|
110
|
+
* or unreadable at render can arrive. This is the panel's only recovery when `paymentProvider` is
|
|
111
|
+
* absent — the value is a prop, so nothing the panel does to its own state can produce it.
|
|
112
|
+
*/
|
|
113
|
+
onRetryPaymentConfig?: () => Promise<void>;
|
|
114
|
+
}
|
|
115
|
+
export type CheckoutProcessingSlotProps = SlotProps;
|
|
116
|
+
/**
|
|
117
|
+
* A Fanfare-managed payment is terminal: it produces a receipt, never an admission credential. The
|
|
118
|
+
* `grant` arm carries the credential the mechanism itself issued alongside the payment; a purchase
|
|
119
|
+
* that ends the journey has no credential to carry, so the arms are discriminated rather than
|
|
120
|
+
* making the grant optional — a slot implementation can never read one that does not exist.
|
|
121
|
+
*/
|
|
122
|
+
export type ReceiptSlotProps = SlotProps & ({
|
|
123
|
+
kind: "grant";
|
|
124
|
+
admissionGrant: string;
|
|
125
|
+
checkout: FanfareCheckoutResult;
|
|
126
|
+
} | {
|
|
127
|
+
kind: "purchase";
|
|
128
|
+
checkout: FanfareCheckoutResult;
|
|
129
|
+
});
|
|
62
130
|
export interface ExpiredSlotProps extends SlotProps {
|
|
63
131
|
reason: string;
|
|
64
132
|
endedAt?: Date;
|
|
@@ -93,6 +161,10 @@ export interface ExperienceWidgetSlots {
|
|
|
93
161
|
enterable?: (props: EnterableSlotProps) => React.ReactNode;
|
|
94
162
|
participating?: (props: ParticipatingSlotProps) => React.ReactNode;
|
|
95
163
|
granted?: (props: GrantedSlotProps) => React.ReactNode;
|
|
164
|
+
paymentCollection?: (props: PaymentCollectionSlotProps) => React.ReactNode;
|
|
165
|
+
reservationCheckout?: (props: ReservationCheckoutSlotProps) => React.ReactNode;
|
|
166
|
+
checkoutProcessing?: (props: CheckoutProcessingSlotProps) => React.ReactNode;
|
|
167
|
+
receipt?: (props: ReceiptSlotProps) => React.ReactNode;
|
|
96
168
|
expired?: (props: ExpiredSlotProps) => React.ReactNode;
|
|
97
169
|
ended?: (props: EndedSlotProps) => React.ReactNode;
|
|
98
170
|
error?: (props: ErrorSlotProps) => React.ReactNode;
|
|
@@ -129,12 +201,16 @@ export interface ExperienceWidgetProps {
|
|
|
129
201
|
onJourneyChange?: (snapshot: JourneySnapshot) => void;
|
|
130
202
|
/** Called when the journey receives a grant */
|
|
131
203
|
onGranted?: (grant: string) => void;
|
|
204
|
+
/** Called when a Fanfare-managed checkout completes (pre-auth capture or post-win reservation checkout) */
|
|
205
|
+
onFanfareCheckout?: (result: FanfareCheckoutResult) => void;
|
|
206
|
+
/** Called when the consumer wins a `post_win` distribution and must complete checkout before `expiresAt` */
|
|
207
|
+
onReserved?: (expiresAt: number) => void;
|
|
132
208
|
/** Called when an error occurs */
|
|
133
209
|
onError?: (error: Error) => void;
|
|
134
210
|
/** Additional class name */
|
|
135
211
|
className?: string;
|
|
136
212
|
}
|
|
137
|
-
export declare function ExperienceWidget({ experienceId, autoStart, accessCode, autoEnterWaitlist, theme, variant, slots, children, checkoutUrl, onJourneyChange, onGranted, onError, className, }: ExperienceWidgetProps): import("react/jsx-runtime").JSX.Element;
|
|
213
|
+
export declare function ExperienceWidget({ experienceId, autoStart, accessCode, autoEnterWaitlist, theme, variant, slots, children, checkoutUrl, onJourneyChange, onGranted, onFanfareCheckout, onReserved, onError, className, }: ExperienceWidgetProps): import("react/jsx-runtime").JSX.Element;
|
|
138
214
|
export declare namespace ExperienceWidget {
|
|
139
215
|
var displayName: string;
|
|
140
216
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirrors one journey into a stable DOM target.
|
|
3
|
+
*
|
|
4
|
+
* The bridge latches `data-fanfare-version`, `data-fanfare-experience-id`,
|
|
5
|
+
* `data-fanfare-stage`, `data-fanfare-phase`, `data-fanfare-mechanism`,
|
|
6
|
+
* `data-fanfare-expires-at`, and `data-fanfare-outcome` on `opts.target`,
|
|
7
|
+
* defaulting to `document.documentElement`, and dispatches `fanfare:state-change`
|
|
8
|
+
* on that same element. Queue position is event-only, and a terminal outcome
|
|
9
|
+
* crosses as its type alone — the free-text qualifier that may accompany one
|
|
10
|
+
* stays on the typed SDK surface.
|
|
11
|
+
* Installation happens in an effect, so the first paint can be unbridged;
|
|
12
|
+
* vanilla `createDomBridge` stamps synchronously.
|
|
13
|
+
*
|
|
14
|
+
* Install stamps the current state and emits nothing; events are
|
|
15
|
+
* transition-only, so a consumer waiting for one may wait arbitrarily long — or
|
|
16
|
+
* forever, when the journey has ended or its queue is stable — and should read
|
|
17
|
+
* the latched attributes instead of expecting an initial event.
|
|
18
|
+
*
|
|
19
|
+
* Unmounting or changing `experienceId` disposes the bridge, which returns the
|
|
20
|
+
* bridge attributes to their pre-install state. Changing `opts.target` does not
|
|
21
|
+
* reinstall it. The target must be an
|
|
22
|
+
* already-mounted, stable element; a `ref.current` read in the render that
|
|
23
|
+
* creates the ref is null. Use this hook from a keyed subtree to move targets.
|
|
24
|
+
* `{ target: ref.current ?? undefined }` — the natural React spelling —
|
|
25
|
+
* silently bridges `document.documentElement`, because a nullish target is
|
|
26
|
+
* indistinguishable from "no target wanted".
|
|
27
|
+
*
|
|
28
|
+
* Calling this hook twice for the same experience and target is unsupported:
|
|
29
|
+
* it duplicates events, creates conflicting stamps, and allows one owner to
|
|
30
|
+
* remove the other owner's stamps during teardown. Distinct experiences alone
|
|
31
|
+
* do not separate two hooks: two calls with no `opts.target` both stamp
|
|
32
|
+
* `document.documentElement` and contend for the same attribute names, so give
|
|
33
|
+
* each call its own target when a page bridges more than one experience. The
|
|
34
|
+
* hook also creates the journey on read when one does not already exist, which
|
|
35
|
+
* arms its pollers.
|
|
36
|
+
*
|
|
37
|
+
* A reinstall emits nothing. When the context SDK identity changes — the `ssr`
|
|
38
|
+
* read-only SDK swapping to the live SDK on first paint, or a provider
|
|
39
|
+
* re-init — the hook disposes and reinstalls; install stamps without emitting,
|
|
40
|
+
* so an events-only consumer never learns of a delta it did not cause. The
|
|
41
|
+
* attributes remain correct.
|
|
42
|
+
*
|
|
43
|
+
* Dispose the bridge before destroying its handle or SDK. Destroying either
|
|
44
|
+
* while the bridge is live emits one final ready-projection event and restamps
|
|
45
|
+
* ready attributes — a reset the bridge cannot distinguish from a legitimate
|
|
46
|
+
* restart. Under `FanfareProvider`, unmount is safe: the provider defers SDK
|
|
47
|
+
* destruction through its lifecycle queue, so this hook's dispose runs first
|
|
48
|
+
* and that path emits no such event. When the provider replaces its SDK
|
|
49
|
+
* without unmounting the bridge — a change to a config value, or `ssr` mode
|
|
50
|
+
* dropping `publishableKey` — that ordering is not guaranteed and a live
|
|
51
|
+
* bridge may emit one final ready event and restamp. A caller supplying its
|
|
52
|
+
* own SDK through `FanfareContext` gets no deferral and is a direct-destroy
|
|
53
|
+
* caller.
|
|
54
|
+
*/
|
|
55
|
+
export declare function useFanfareDomBridge(experienceId: string | undefined, opts?: {
|
|
56
|
+
target?: Element;
|
|
57
|
+
}): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SDKEvents } from '@fanfare-io/fanfare-sdk-core/events';
|
|
2
|
+
type SDKEventKey = keyof SDKEvents;
|
|
3
|
+
/**
|
|
4
|
+
* Subscribe to a typed Fanfare SDK event for the lifetime of the component.
|
|
5
|
+
*
|
|
6
|
+
* The handler is read from a ref refreshed on every render, so passing an inline
|
|
7
|
+
* closure never re-subscribes. The subscription is re-established when the SDK
|
|
8
|
+
* instance identity changes (the provider swapping its first-paint SDK for the
|
|
9
|
+
* live one) or when `event` changes; events emitted during such a swap are not
|
|
10
|
+
* delivered.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* useSdkEvent("journey:granted", (data) => {
|
|
15
|
+
* analytics.track("granted", { experienceId: data.experienceId });
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function useSdkEvent<K extends SDKEventKey>(event: K, handler: (data: SDKEvents[K]) => void): void;
|
|
20
|
+
export {};
|