@fanfare-io/fanfare-sdk-react 0.19.0 → 0.20.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 CHANGED
@@ -65,13 +65,19 @@ public surface is exactly these two components plus their prop and handle types.
65
65
  Selection is configured per sequence, under either checkout arrangement. With merchant
66
66
  (`external`) checkout the widget records the pick and hands it to `onCheckoutClick` for the host to
67
67
  cart; with Fanfare (`internal`) checkout the granted panel continues into Fanfare's own checkout
68
- instead, under both checkout modes, `at_end` and `pre_auth`. Entry-time picking (choosing before you
69
- enter) is not yet available.
68
+ instead, under both checkout modes, `at_end` and `pre_auth`. Entry-time picking is live: when the server declares that a draw, timed release
69
+ or auction bid needs a product choice before entry, the module renders the picker and `enter` / `bid`
70
+ carry the pair. A host reaching the view directly checks `"loadSelectionOptions" in view` for the
71
+ required arm and reads `view.selection.required` for display.
70
72
 
71
73
  `onCheckoutClick?: (details?: SelectionCheckoutDetails) => void | Promise<void>` carries the pick
72
74
  the grant settled on — `SelectionCheckoutDetails` is a root export and reads
73
- `{ selection, product, variant, currencyCode }`, the catalogue objects behind the pair so a host can
74
- map it onto its own catalogue by handle, SKU or option values. The argument is optional: a grant
75
+ `{ selection, product, variant, currencyCode }`, the catalogue objects behind the pair. For Shopify
76
+ checkout, use the product and variant `externalReference` values rather than matching handles,
77
+ SKUs or option values. Require both references with provider `shopify`; pass their IDs through
78
+ the Shopify adapter's `productGid` and `variantGid` helpers for the checkout line. A default variant
79
+ still carries its identity when `optionValues` is empty. These references require a compatible
80
+ backend and SDK release; handle absent references before starting checkout. The argument is optional: a grant
75
81
  that settles without the widget having loaded the catalogue passes none, so a `() => void` handler
76
82
  still assigns and a `(details) => …` handler has to handle `details === undefined`.
77
83
  `GrantedPanelProps.onCtaClick` takes the same shape. Returning a promise is supported — a rejection
@@ -110,6 +116,11 @@ the catalogue, so wrap it in `useCallback` or hoist it out of the render. `Produ
110
116
  a `ProductSelectorHandle` (`focus()`, `refresh()`) through `ref`; `refresh()` is what a host calls
111
117
  after a sold-out failure.
112
118
 
119
+ `selectError` is already-translated copy rendered inline beneath the grid, and it sits in the same
120
+ tree as the rows and chips with no memo boundary, so changing it re-renders the whole selector.
121
+ Hold it as state written only when an action rejects and cleared when the next action starts, so it
122
+ tracks the outcome of a submit rather than the current draft.
123
+
113
124
  ## Error handling
114
125
 
115
126
  The widget classifies every failure into one of four **dispositions** and surfaces it accordingly, so a recoverable error stays in context instead of replacing the screen:
@@ -7,7 +7,7 @@ import { AuthInputMode } from '../auth/auth-input';
7
7
  import { OutcomeAction } from '../compositions/outcome-panel';
8
8
  import * as React from "react";
9
9
  type ParticipationType = "queue" | "draw" | "auction" | "timed_release" | "appointment";
10
- type EnterableSlotSequence = Extract<SequenceView, {
10
+ export type EnterableSlotSequence = Extract<SequenceView, {
11
11
  phase: "enterable";
12
12
  mechanism: ParticipationType;
13
13
  }>;
@@ -8,4 +8,5 @@
8
8
  */
9
9
  export { ExperienceWidget, type AccessCodeSlotProps, type AuthSlotProps, type EndedSlotProps, type EnterableSlotProps, type ErrorSlotProps, type ExperienceRenderProps, type ExperienceWidgetProps, type ExperienceWidgetSlots, type ExpiredSlotProps, type GrantedSlotProps, type LoadingSlotProps, type ParticipatingSlotProps, type SlotProps, type StartSlotProps, type UpcomingSlotProps, type WaitlistSlotProps, } from './experience-widget';
10
10
  export { LoadingView, StartView, UpcomingModule, WaitlistView, type LoadingViewProps, type StartViewProps, type UpcomingModuleProps, type WaitlistViewProps, } from './internal';
11
+ export type { EnterableSlotSequence } from './experience-widget';
11
12
  export { AuctionModule, DrawModule, QueueModule, TimedReleaseModule, type AuctionModuleProps, type DrawModuleProps, type QueueModuleProps, type TimedReleaseModuleProps, } from './internal';
@@ -56,6 +56,8 @@ export interface DrawModuleProps {
56
56
  selectionLockedReason?: "checkout" | "final";
57
57
  /** Already-translated selection failure from the widget, rendered beside the acting control. */
58
58
  selectError?: string | null;
59
+ /** The refusal code behind `selectError`; a stock refusal refetches the catalogue once. */
60
+ selectErrorCode?: string | null;
59
61
  /** Every local pick-surface transition, product-only drafts included; feeds the page-bridge event. */
60
62
  onDraftChange?: (draft: SelectionDraft) => void;
61
63
  /** The terminal was reached because the stock ran out, not because this entrant lost. */
@@ -71,7 +73,7 @@ export interface DrawModuleProps {
71
73
  /** Additional class name */
72
74
  className?: string;
73
75
  }
74
- export declare function DrawModule({ display$, sequencePhase, canEnter, canLeave, onEnter, onLeave, isEntering, isLeaving, countdownTo, grant: _grant, expiresAt, checkoutUrl, onCheckoutClick, outcomeReason, outcomeAction, onReenter, isReentering, className, selectionRequired, loadSelectionOptions, recordedSelection, selectionAvailability, onSelectionChange, grantedSelection, settlement, onSelect, selectionLockedReason, selectError, stockDenied, onDraftChange, }: DrawModuleProps): import("react/jsx-runtime").JSX.Element | null;
76
+ export declare function DrawModule({ display$, sequencePhase, canEnter, canLeave, onEnter, onLeave, isEntering, isLeaving, countdownTo, grant: _grant, expiresAt, checkoutUrl, onCheckoutClick, outcomeReason, outcomeAction, onReenter, isReentering, className, selectionRequired, loadSelectionOptions, recordedSelection, selectionAvailability, onSelectionChange, grantedSelection, settlement, onSelect, selectionLockedReason, selectError, selectErrorCode, stockDenied, onDraftChange, }: DrawModuleProps): import("react/jsx-runtime").JSX.Element | null;
75
77
  export declare namespace DrawModule {
76
78
  var displayName: string;
77
79
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Internal Widget Views
3
3
  *
4
- * These are internal components used by ExperienceWidget for stage rendering.
5
- * Not exported publicly - use slots to override these views.
4
+ * The stage modules ExperienceWidget renders. The four distribution modules are also root-exported
5
+ * for hosts composing their own widget; slots remain the override path inside ExperienceWidget.
6
6
  */
7
7
  export { AppointmentModule, type AppointmentModuleProps } from './appointment-module';
8
8
  export { AuctionModule, type AuctionModuleProps } from './auction-module';
@@ -9,5 +9,5 @@
9
9
  */
10
10
  export { ProductSelector } from './product-selector';
11
11
  export type { ProductSelectorHandle, ProductSelectorProps } from './product-selector';
12
- export { SelectionSummary } from './selection-summary';
12
+ export { SELECTION_LOCKED_COPY, SelectionSummary } from './selection-summary';
13
13
  export type { SelectionLockedReason, SelectionSummaryProps } from './selection-summary';
@@ -17,6 +17,12 @@ export interface SelectionSummaryProps {
17
17
  onChangeRequest?(): void;
18
18
  className?: string;
19
19
  }
20
+ /** The sentence a locked summary reads out, by the reason it is locked. */
21
+ export declare const SELECTION_LOCKED_COPY: {
22
+ readonly checkout: "selection.locked.checkout";
23
+ readonly final: "selection.locked.final";
24
+ readonly bid: "selection.locked.bid";
25
+ };
20
26
  /**
21
27
  * A compact read-out of a pick that has already been captured.
22
28
  *
@@ -41,6 +41,8 @@ export interface TimedReleaseModuleProps {
41
41
  selectionLockedReason?: "checkout" | "final";
42
42
  /** Already-translated selection failure from the widget, rendered beside the acting control. */
43
43
  selectError?: string | null;
44
+ /** The refusal code behind `selectError`; a stock refusal refetches the catalogue once. */
45
+ selectErrorCode?: string | null;
44
46
  /** Every local pick-surface transition, product-only drafts included; feeds the page-bridge event. */
45
47
  onDraftChange?: (draft: SelectionDraft) => void;
46
48
  /** The terminal was reached because the stock ran out, not because this entrant lost. */
@@ -54,7 +56,7 @@ export interface TimedReleaseModuleProps {
54
56
  isReentering?: boolean;
55
57
  className?: string;
56
58
  }
57
- export declare function TimedReleaseModule({ display$, sequencePhase, canEnter, canLeave, onEnter, onLeave, onComplete, isEntering, isLeaving, countdownTo, checkoutUrl, onCheckoutClick, grant: _grant, expiresAt, outcomeReason, outcomeAction, onReenter, isReentering, className, selectionRequired, loadSelectionOptions, recordedSelection, selectionAvailability, grantedSelection, settlement, onSelect, selectionLockedReason, selectError, stockDenied, onDraftChange, }: TimedReleaseModuleProps): import("react/jsx-runtime").JSX.Element | null;
59
+ export declare function TimedReleaseModule({ display$, sequencePhase, canEnter, canLeave, onEnter, onLeave, onComplete, isEntering, isLeaving, countdownTo, checkoutUrl, onCheckoutClick, grant: _grant, expiresAt, outcomeReason, outcomeAction, onReenter, isReentering, className, selectionRequired, loadSelectionOptions, recordedSelection, selectionAvailability, grantedSelection, settlement, onSelect, selectionLockedReason, selectError, selectErrorCode, stockDenied, onDraftChange, }: TimedReleaseModuleProps): import("react/jsx-runtime").JSX.Element | null;
58
60
  export declare namespace TimedReleaseModule {
59
61
  var displayName: string;
60
62
  }