@fanfare-io/fanfare-sdk-solid 0.22.0 → 0.24.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/README.md +37 -0
- package/dist/components/auth/auth-form.d.ts +9 -1
- package/dist/components/checkout/card-brand.d.ts +2 -0
- package/dist/components/checkout/checkout-processing-panel.d.ts +4 -3
- package/dist/components/checkout/payment-collection-panel.d.ts +3 -3
- package/dist/components/checkout/payment-method-list.d.ts +18 -0
- package/dist/components/checkout/receipt-panel.d.ts +4 -3
- package/dist/components/compositions/journey-gate.d.ts +3 -1
- package/dist/components/internal/queue-module.d.ts +2 -0
- package/dist/components/primitives/checkbox.d.ts +6 -0
- package/dist/components/primitives/index.d.ts +1 -0
- package/dist/components/primitives/spinner.d.ts +5 -0
- package/dist/components/widgets/experience-widget.d.ts +8 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/use-experience-timing.d.ts +27 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4153 -3908
- package/dist/styles/base.css +1 -1
- package/dist/styles/theme.css +137 -3
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -44,6 +44,43 @@ Solid applications can use `FanfareProvider`, `ExperienceWidget`, and `useExperi
|
|
|
44
44
|
|
|
45
45
|
`slots` override targeted states while keeping the default widget flow. `children` receives `{ journey, view, snapshot, error, start, isStarting }` when you want to render the full state yourself. Solid `ExperienceWidget` accepts both `class` and `className`.
|
|
46
46
|
|
|
47
|
+
Mounted inside a shadow root, the widget's styleable elements export CSS parts named after their
|
|
48
|
+
`data-slot`, so a page styles them with `::part()` — `fanfare-host::part(auction-cta)`. The
|
|
49
|
+
attribution footer and every element that contains its "Powered by Fanfare" row are
|
|
50
|
+
deliberately not parts: the widget root and the panel cards that carry that row. The payment
|
|
51
|
+
card field is not a part either. A panel whose footer holds no attribution row keeps its card
|
|
52
|
+
as a part — `auction-module` is one; [`docs/STYLING.md`](./docs/STYLING.md#parts) lists every
|
|
53
|
+
part and every exception.
|
|
54
|
+
|
|
55
|
+
### Experience timing
|
|
56
|
+
|
|
57
|
+
`useExperienceTiming(() => experienceId)` takes the experience id as an accessor and reads that experience's public
|
|
58
|
+
timing once when it mounts, and again when the id changes or you call `refresh()`:
|
|
59
|
+
|
|
60
|
+
| `status()` | `timing()` |
|
|
61
|
+
| ----------- | ------------------------------------------------------------------------- |
|
|
62
|
+
| `"loading"` | `undefined` — the first read for this experience has not finished |
|
|
63
|
+
| `"error"` | `undefined` — the read failed; call `refresh()` to try again |
|
|
64
|
+
| `"ready"` | the `ExperienceTiming`, or `null` when the experience publishes no timing |
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { useExperienceTiming } from "@fanfare-io/fanfare-sdk-solid";
|
|
68
|
+
import { Show } from "solid-js";
|
|
69
|
+
|
|
70
|
+
function DropStatus(props: { experienceId: string }) {
|
|
71
|
+
const timing = useExperienceTiming(() => props.experienceId);
|
|
72
|
+
return <Show when={timing.status() === "ready" && timing.timing()}>{(t) => <span>{t().status}</span>}</Show>;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`ExperienceTiming` is a type exported from `@fanfare-io/fanfare-sdk-core/experiences`. Its `status` is `upcoming`,
|
|
77
|
+
`open` or `closed`, with `nextOpensAt` and `lastClosedAt` around it. `closesAt` is
|
|
78
|
+
present only while the experience is open, and is `null` when the open run has no end. The primitive never polls
|
|
79
|
+
or schedules a re-read at a boundary, and adds no retry of its own: once `ready`, the result stays as read until
|
|
80
|
+
you call `refresh()`.
|
|
81
|
+
During a refresh the previous result stays in place — a `ready` result keeps its timing and an `error` stays
|
|
82
|
+
`error` — until the new read settles. Primitives that read the same experience at the same time share one request.
|
|
83
|
+
|
|
47
84
|
## Selection
|
|
48
85
|
|
|
49
86
|
Some experiences capture which product and variant a consumer gets. `ExperienceWidget` renders that
|
|
@@ -2,7 +2,9 @@ import { JSX } from 'solid-js';
|
|
|
2
2
|
import { PanelHeadingVariant } from '../module';
|
|
3
3
|
import { AuthInputMode } from './auth-input';
|
|
4
4
|
export interface AuthFormProps {
|
|
5
|
-
onSubmit?: (credential: string, type: AuthInputMode
|
|
5
|
+
onSubmit?: (credential: string, type: AuthInputMode, options?: {
|
|
6
|
+
marketingSmsConsent: boolean;
|
|
7
|
+
}) => Promise<void>;
|
|
6
8
|
onVerify?: (otp: string) => Promise<void>;
|
|
7
9
|
onSkip?: () => void | Promise<void>;
|
|
8
10
|
onSuccess?: () => void;
|
|
@@ -19,6 +21,12 @@ export interface AuthFormProps {
|
|
|
19
21
|
allowSkip?: boolean;
|
|
20
22
|
skipLabel?: string;
|
|
21
23
|
showBranding?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Shows the marketing SMS consent checkbox, its disclosure and legal line on the credential step in
|
|
26
|
+
* phone mode. Off by default: set it only when `onSubmit` reads its third argument, since a tick
|
|
27
|
+
* the handler never reads is a consent silently dropped.
|
|
28
|
+
*/
|
|
29
|
+
showMarketingSmsConsent?: boolean;
|
|
22
30
|
/** Initial step when mounting. Useful for SSR-resume or storybook lanes that need the verify step. */
|
|
23
31
|
defaultStep?: "credential" | "verify";
|
|
24
32
|
/** Initial credential (email or E.164 phone) — pairs with `defaultStep="verify"`. */
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
2
|
import { CheckoutProcessingSlotProps } from '../widgets/experience-widget';
|
|
3
3
|
/**
|
|
4
|
-
* Default processing panel shown for the gap between a submitted
|
|
5
|
-
*
|
|
4
|
+
* Default processing panel shown for the gap between a submitted checkout and the server's
|
|
5
|
+
* confirmation.
|
|
6
6
|
*
|
|
7
7
|
* The consumer must not navigate away while the payment settles, so the wait is announced rather
|
|
8
|
-
* than shown only as motion.
|
|
8
|
+
* than shown only as motion. It reads as the same callout the payment panel shows while a bank
|
|
9
|
+
* confirmation resumes, so the two waits on one payment look like one wait.
|
|
9
10
|
*/
|
|
10
11
|
export declare function CheckoutProcessingPanel(_props: CheckoutProcessingSlotProps): JSX.Element;
|
|
@@ -5,9 +5,9 @@ import { PaymentCollectionSlotProps } from '../widgets/experience-widget';
|
|
|
5
5
|
*
|
|
6
6
|
* The hold amount is rendered from the view's own figure — the client never derives one.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* An absent configuration block means its read failed. A saved method pays without Stripe.js, so
|
|
9
|
+
* with one the outage narrows to the new-card choice; with none, re-reading the configuration is
|
|
10
|
+
* the panel's only way forward.
|
|
11
11
|
*
|
|
12
12
|
* Entry has no server-side resume: a paused authorization is carried forward by submitting the
|
|
13
13
|
* identical payment input again, held here from the first submit, so exactly one payment method is
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PaymentMethodSummary } from '@fanfare-io/fanfare-sdk-core/experiences';
|
|
2
|
+
import { JSX } from 'solid-js';
|
|
3
|
+
export interface PaymentMethodListProps {
|
|
4
|
+
methods: PaymentMethodSummary[];
|
|
5
|
+
/** Unique per panel: radios sharing a name form one group across the whole document. */
|
|
6
|
+
name: string;
|
|
7
|
+
selectedId: string | undefined;
|
|
8
|
+
newCardActive: boolean;
|
|
9
|
+
/** Offer the new-card row; absent when no card entry can be mounted. */
|
|
10
|
+
cardEntryAvailable: boolean;
|
|
11
|
+
onSelectSaved: (id: string) => void;
|
|
12
|
+
onSelectNew: () => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Saved payment methods and the new-card choice, as one radio group of selector rows. The row look
|
|
16
|
+
* lives in the theme stylesheet, keyed on `payment-method-row`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function PaymentMethodList(props: PaymentMethodListProps): JSX.Element;
|
|
@@ -3,8 +3,9 @@ import { ReceiptSlotProps } from '../widgets/experience-widget';
|
|
|
3
3
|
/**
|
|
4
4
|
* Default panel for a completed Fanfare-managed payment.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
* the
|
|
6
|
+
* The purchase is the outcome: the panel is labelled as one and leads with what was paid, and the
|
|
7
|
+
* order reference follows. An admission credential appears only on the arm that carries one, and
|
|
8
|
+
* stays subordinate to the purchase: payment is terminal, so a receipt must never read as the thing
|
|
9
|
+
* that admits its holder.
|
|
9
10
|
*/
|
|
10
11
|
export declare function ReceiptPanel(props: ReceiptSlotProps): JSX.Element;
|
|
@@ -3,7 +3,9 @@ import { AuthInputMode } from '../auth/auth-input';
|
|
|
3
3
|
export type JourneyGateStage = "auth" | "access_code" | "loading" | "none";
|
|
4
4
|
export interface JourneyGateProps {
|
|
5
5
|
stage: JourneyGateStage;
|
|
6
|
-
onAuthSubmit?: (credential: string, type: AuthInputMode
|
|
6
|
+
onAuthSubmit?: (credential: string, type: AuthInputMode, options?: {
|
|
7
|
+
marketingSmsConsent: boolean;
|
|
8
|
+
}) => Promise<void>;
|
|
7
9
|
onAuthVerify?: (otp: string) => Promise<void>;
|
|
8
10
|
onAuthSkip?: () => void | Promise<void>;
|
|
9
11
|
onAuthSuccess?: () => void;
|
|
@@ -8,6 +8,8 @@ import { OutcomeReason } from '../module';
|
|
|
8
8
|
export interface QueueModuleProps {
|
|
9
9
|
display$?: ReadableAtom<QueueDisplayState>;
|
|
10
10
|
sequencePhase: "enterable" | "participating" | "granted" | "ended";
|
|
11
|
+
/** Hide live rank-derived queue metrics while the canonical queue is still pre-open. */
|
|
12
|
+
hideQueueMetrics?: boolean;
|
|
11
13
|
canEnter: boolean;
|
|
12
14
|
canLeave: boolean;
|
|
13
15
|
onEnter: () => Promise<void>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { JSX } from 'solid-js';
|
|
2
|
+
export interface CheckboxProps extends Omit<JSX.InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
3
|
+
/** Label rendered beside the control. */
|
|
4
|
+
label: JSX.Element;
|
|
5
|
+
}
|
|
6
|
+
export declare function Checkbox(props: CheckboxProps): JSX.Element;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { Badge, badgeVariants, type BadgeProps, type BadgeVariant } from './badge';
|
|
2
2
|
export { Button, buttonVariants, type ButtonProps } from './button';
|
|
3
3
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, cardVariants, type CardContentProps, type CardDescriptionProps, type CardFooterProps, type CardHeaderProps, type CardProps, type CardTitleProps, } from './card';
|
|
4
|
+
export { Checkbox, type CheckboxProps } from './checkbox';
|
|
4
5
|
export { Countdown, type CountdownProps, type CountdownSize, type CountdownTone } from './countdown';
|
|
5
6
|
export { FadePresence, type FadePresenceProps } from './fade-presence';
|
|
6
7
|
export { FanfareLogo, type FanfareLogoProps } from './fanfare-logo';
|
|
@@ -4,6 +4,11 @@ declare const spinnerVariants: (props?: ({
|
|
|
4
4
|
size?: "sm" | "md" | "lg" | null | undefined;
|
|
5
5
|
styleVariant?: "default" | "retro" | "rounded" | "clean" | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Whether `Spinner` and `Button` export their CSS `part` names. A subtree a page must never style
|
|
9
|
+
* from outside — the payment field — renders with it off.
|
|
10
|
+
*/
|
|
11
|
+
export declare const ExportPartsContext: import('solid-js').Context<boolean>;
|
|
7
12
|
export interface SpinnerProps extends JSX.SvgSVGAttributes<SVGSVGElement>, Omit<VariantProps<typeof spinnerVariants>, "styleVariant"> {
|
|
8
13
|
className?: string;
|
|
9
14
|
}
|
|
@@ -31,9 +31,16 @@ export interface StartSlotProps extends SlotProps {
|
|
|
31
31
|
isStarting: boolean;
|
|
32
32
|
}
|
|
33
33
|
export interface AuthSlotProps extends SlotProps {
|
|
34
|
-
onSubmit: (credential: string, type: AuthInputMode
|
|
34
|
+
onSubmit: (credential: string, type: AuthInputMode, options?: {
|
|
35
|
+
marketingSmsConsent: boolean;
|
|
36
|
+
}) => Promise<void>;
|
|
35
37
|
onVerify: (otp: string) => Promise<void>;
|
|
36
38
|
onSkip?: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Whether the sign-in should offer the marketing SMS consent checkbox. The widget sets it because its
|
|
41
|
+
* `onSubmit` reads the consent from its third argument; pass it to `AuthForm` with `onSubmit`.
|
|
42
|
+
*/
|
|
43
|
+
showMarketingSmsConsent?: boolean;
|
|
37
44
|
}
|
|
38
45
|
export interface AccessCodeSlotProps extends SlotProps {
|
|
39
46
|
onSubmit: (code: string) => Promise<void>;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export { useFanfareAuth } from './use-auth';
|
|
|
9
9
|
export { createBeaconTracker } from './use-beacon-tracker';
|
|
10
10
|
export { useExperienceJourney } from './use-experience-journey';
|
|
11
11
|
export type { ExperienceJourneyOptions, UseExperienceJourneyOptions, UseExperienceJourneyResult, } from './use-experience-journey';
|
|
12
|
+
export { useExperienceTiming } from './use-experience-timing';
|
|
13
|
+
export type { UseExperienceTimingResult } from './use-experience-timing';
|
|
12
14
|
export { useJourneySnapshot } from './use-journey-snapshot';
|
|
13
15
|
export { useNanostore } from './use-nanostore';
|
|
14
16
|
export { useSdkEvent } from './use-sdk-event';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ExperienceTiming } from '@fanfare-io/fanfare-sdk-core/experiences';
|
|
2
|
+
import { Accessor } from 'solid-js';
|
|
3
|
+
/**
|
|
4
|
+
* Result of {@link useExperienceTiming}.
|
|
5
|
+
*
|
|
6
|
+
* - `status() === "loading"`: the first read for this experience has not settled; `timing()` is `undefined`.
|
|
7
|
+
* - `status() === "error"`: the last read was rejected; `timing()` is `undefined` and `refresh()` reads again.
|
|
8
|
+
* - `status() === "ready"`: `timing()` is the experience's public timing, or `null` when it publishes none.
|
|
9
|
+
*/
|
|
10
|
+
export interface UseExperienceTimingResult {
|
|
11
|
+
status: Accessor<"loading" | "error" | "ready">;
|
|
12
|
+
timing: Accessor<ExperienceTiming | null | undefined>;
|
|
13
|
+
refresh(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Reads an experience's public timing once when it attaches, and again whenever
|
|
17
|
+
* `experienceId` changes or `refresh()` is called.
|
|
18
|
+
*
|
|
19
|
+
* The primitive never polls, retries or schedules work around the timing's
|
|
20
|
+
* boundaries; a caller that needs fresher timing calls `refresh()`. While a
|
|
21
|
+
* refresh is in flight the result is unchanged: a `ready` result keeps its last
|
|
22
|
+
* timing and an `error` result stays `error` until the read settles. Primitives
|
|
23
|
+
* that read the same experience at the same time on one SDK instance share a
|
|
24
|
+
* single request. Results from a superseded read, or from one still in flight
|
|
25
|
+
* after disposal, are dropped.
|
|
26
|
+
*/
|
|
27
|
+
export declare function useExperienceTiming(experienceId: Accessor<string>): UseExperienceTimingResult;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { FanfareProvider, useFanfare } from './components/provider';
|
|
9
9
|
export type { FanfareProviderProps } from './components/provider';
|
|
10
|
-
export { createBeaconTracker, useExperienceJourney, useFanfareAuth, useJourneySnapshot, useNanostore, useSdkEvent, } from './hooks';
|
|
10
|
+
export { createBeaconTracker, useExperienceJourney, useExperienceTiming, useFanfareAuth, useJourneySnapshot, useNanostore, useSdkEvent, } from './hooks';
|
|
11
|
+
export type { UseExperienceTimingResult } from './hooks';
|
|
11
12
|
export { I18nProvider, RTL_LOCALES, isRTLLocale, useTranslations } from './i18n';
|
|
12
13
|
export type { I18nConfig, I18nProviderProps, Locale, PartialTranslationMessages, RTLLocale, TextDirection, TranslateFunction, TranslateOptions, TranslationKey, TranslationMessageKey, TranslationMessages, } from './i18n';
|
|
13
14
|
export { THEME_CSS_VARS, ThemeProvider, buildThemeCssVars } from './theme';
|