@nok-integration/storefront-react 0.17.2 → 0.18.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/index.d.ts CHANGED
@@ -114,6 +114,33 @@ declare const CartItem: z.ZodObject<{
114
114
  amount: number;
115
115
  currency: string;
116
116
  }>;
117
+ /**
118
+ * The undiscounted per-unit price, from the catalogue. Display only.
119
+ *
120
+ * Drawn as a struck-through figure under what the line costs now, with a `-NN%` badge
121
+ * over the thumbnail — Figma's cart draws every discounted line that way and, until
122
+ * this field existed, a consumer had no way to. The saving was simply invisible in the
123
+ * basket and appeared for the first time at checkout.
124
+ *
125
+ * Absent means the line is at full price, which is the ordinary case. Present only when
126
+ * it is strictly greater than `unit_price`: a compare-at equal to or below the live
127
+ * price is not a sale, and drawing one would be an invented discount.
128
+ *
129
+ * **The catalogue's figure, not an order's.** `OrderItem.compare_at_unit_price` is the
130
+ * one DAZN sent at intake and is frozen there, because a receipt whose struck price
131
+ * moves next week is not a receipt. A cart is live, so this one moves with
132
+ * merchandising — that is correct here and wrong there.
133
+ */
134
+ compare_at_unit_price: z.ZodOptional<z.ZodObject<{
135
+ amount: z.ZodNumber;
136
+ currency: z.ZodString;
137
+ }, "strict", z.ZodTypeAny, {
138
+ amount: number;
139
+ currency: string;
140
+ }, {
141
+ amount: number;
142
+ currency: string;
143
+ }>>;
117
144
  /**
118
145
  * Product title for this line, e.g. "Signature Hoodie".
119
146
  *
@@ -168,6 +195,10 @@ declare const CartItem: z.ZodObject<{
168
195
  amount: number;
169
196
  currency: string;
170
197
  };
198
+ compare_at_unit_price?: {
199
+ amount: number;
200
+ currency: string;
201
+ } | undefined;
171
202
  title?: string | undefined;
172
203
  image?: string | undefined;
173
204
  attributes?: Record<string, string> | undefined;
@@ -183,6 +214,10 @@ declare const CartItem: z.ZodObject<{
183
214
  amount: number;
184
215
  currency: string;
185
216
  };
217
+ compare_at_unit_price?: {
218
+ amount: number;
219
+ currency: string;
220
+ } | undefined;
186
221
  title?: string | undefined;
187
222
  image?: string | undefined;
188
223
  attributes?: Record<string, string> | undefined;
@@ -222,6 +257,10 @@ export declare interface CartLineItemProps {
222
257
  * above, for a host with its own catalogue data.
223
258
  */
224
259
  compareAt?: Money;
260
+ /**
261
+ * Overrides the percentage on the badge. Normally omitted: given a `compareAt`, the
262
+ * badge is derived from it and the two figures cannot then disagree.
263
+ */
225
264
  discountPct?: number;
226
265
  maxQty?: number;
227
266
  onQtyChange: (qty: number) => void;
@@ -297,10 +336,7 @@ export declare interface CartViewProps {
297
336
  * Label for the primary CTA. Default `Proceed to checkout`.
298
337
  *
299
338
  * DAZN's checkout is the next step and DAZN name it; a host whose own wording is
300
- * "Continue" or "Go to checkout" should not have to accept ours. The locked-cart label
301
- * is deliberately NOT configurable — it takes the fan back to a checkout that already
302
- * exists, which is a different action from starting one, and a host renaming it could
303
- * imply a second checkout is being created.
339
+ * "Continue" or "Go to checkout" should not have to accept ours.
304
340
  */
305
341
  checkoutLabel?: string;
306
342
  }
@@ -2498,6 +2534,10 @@ declare function createClient(options: ClientOptions): {
2498
2534
  image?: string | undefined;
2499
2535
  available?: number | undefined;
2500
2536
  title?: string | undefined;
2537
+ compare_at_unit_price?: {
2538
+ amount: number;
2539
+ currency: string;
2540
+ } | undefined;
2501
2541
  }[];
2502
2542
  cart_id: string;
2503
2543
  totals: {
@@ -2517,12 +2557,20 @@ declare function createClient(options: ClientOptions): {
2517
2557
  amount: number;
2518
2558
  currency: string;
2519
2559
  };
2560
+ discount?: {
2561
+ amount: number;
2562
+ currency: string;
2563
+ } | undefined;
2520
2564
  };
2521
2565
  locked?: {
2522
2566
  since: string;
2523
2567
  reason: "checkout_handoff";
2524
2568
  expires_at?: string | undefined;
2525
2569
  } | undefined;
2570
+ hold?: {
2571
+ expires_at: string;
2572
+ taken_at: string;
2573
+ } | undefined;
2526
2574
  hidden_lines?: ("shipping" | "tax")[] | undefined;
2527
2575
  }>;
2528
2576
  get: () => Promise<{
@@ -2542,6 +2590,10 @@ declare function createClient(options: ClientOptions): {
2542
2590
  image?: string | undefined;
2543
2591
  available?: number | undefined;
2544
2592
  title?: string | undefined;
2593
+ compare_at_unit_price?: {
2594
+ amount: number;
2595
+ currency: string;
2596
+ } | undefined;
2545
2597
  }[];
2546
2598
  cart_id: string;
2547
2599
  totals: {
@@ -2561,12 +2613,20 @@ declare function createClient(options: ClientOptions): {
2561
2613
  amount: number;
2562
2614
  currency: string;
2563
2615
  };
2616
+ discount?: {
2617
+ amount: number;
2618
+ currency: string;
2619
+ } | undefined;
2564
2620
  };
2565
2621
  locked?: {
2566
2622
  since: string;
2567
2623
  reason: "checkout_handoff";
2568
2624
  expires_at?: string | undefined;
2569
2625
  } | undefined;
2626
+ hold?: {
2627
+ expires_at: string;
2628
+ taken_at: string;
2629
+ } | undefined;
2570
2630
  hidden_lines?: ("shipping" | "tax")[] | undefined;
2571
2631
  }>;
2572
2632
  addItem: (body: AddCartItemRequest) => Promise<{
@@ -2586,6 +2646,10 @@ declare function createClient(options: ClientOptions): {
2586
2646
  image?: string | undefined;
2587
2647
  available?: number | undefined;
2588
2648
  title?: string | undefined;
2649
+ compare_at_unit_price?: {
2650
+ amount: number;
2651
+ currency: string;
2652
+ } | undefined;
2589
2653
  }[];
2590
2654
  cart_id: string;
2591
2655
  totals: {
@@ -2605,12 +2669,20 @@ declare function createClient(options: ClientOptions): {
2605
2669
  amount: number;
2606
2670
  currency: string;
2607
2671
  };
2672
+ discount?: {
2673
+ amount: number;
2674
+ currency: string;
2675
+ } | undefined;
2608
2676
  };
2609
2677
  locked?: {
2610
2678
  since: string;
2611
2679
  reason: "checkout_handoff";
2612
2680
  expires_at?: string | undefined;
2613
2681
  } | undefined;
2682
+ hold?: {
2683
+ expires_at: string;
2684
+ taken_at: string;
2685
+ } | undefined;
2614
2686
  hidden_lines?: ("shipping" | "tax")[] | undefined;
2615
2687
  }>;
2616
2688
  updateItem: (sku: string, body: UpdateCartItemRequest) => Promise<{
@@ -2630,6 +2702,10 @@ declare function createClient(options: ClientOptions): {
2630
2702
  image?: string | undefined;
2631
2703
  available?: number | undefined;
2632
2704
  title?: string | undefined;
2705
+ compare_at_unit_price?: {
2706
+ amount: number;
2707
+ currency: string;
2708
+ } | undefined;
2633
2709
  }[];
2634
2710
  cart_id: string;
2635
2711
  totals: {
@@ -2649,12 +2725,20 @@ declare function createClient(options: ClientOptions): {
2649
2725
  amount: number;
2650
2726
  currency: string;
2651
2727
  };
2728
+ discount?: {
2729
+ amount: number;
2730
+ currency: string;
2731
+ } | undefined;
2652
2732
  };
2653
2733
  locked?: {
2654
2734
  since: string;
2655
2735
  reason: "checkout_handoff";
2656
2736
  expires_at?: string | undefined;
2657
2737
  } | undefined;
2738
+ hold?: {
2739
+ expires_at: string;
2740
+ taken_at: string;
2741
+ } | undefined;
2658
2742
  hidden_lines?: ("shipping" | "tax")[] | undefined;
2659
2743
  }>;
2660
2744
  removeItem: (sku: string) => Promise<{
@@ -2674,6 +2758,10 @@ declare function createClient(options: ClientOptions): {
2674
2758
  image?: string | undefined;
2675
2759
  available?: number | undefined;
2676
2760
  title?: string | undefined;
2761
+ compare_at_unit_price?: {
2762
+ amount: number;
2763
+ currency: string;
2764
+ } | undefined;
2677
2765
  }[];
2678
2766
  cart_id: string;
2679
2767
  totals: {
@@ -2693,12 +2781,20 @@ declare function createClient(options: ClientOptions): {
2693
2781
  amount: number;
2694
2782
  currency: string;
2695
2783
  };
2784
+ discount?: {
2785
+ amount: number;
2786
+ currency: string;
2787
+ } | undefined;
2696
2788
  };
2697
2789
  locked?: {
2698
2790
  since: string;
2699
2791
  reason: "checkout_handoff";
2700
2792
  expires_at?: string | undefined;
2701
2793
  } | undefined;
2794
+ hold?: {
2795
+ expires_at: string;
2796
+ taken_at: string;
2797
+ } | undefined;
2702
2798
  hidden_lines?: ("shipping" | "tax")[] | undefined;
2703
2799
  }>;
2704
2800
  /**
@@ -2810,6 +2906,104 @@ declare function createClient(options: ClientOptions): {
2810
2906
  brand: string;
2811
2907
  last4?: string | undefined;
2812
2908
  } | undefined;
2909
+ returns?: {
2910
+ status: "reported" | "package_received" | "completed";
2911
+ return_ref: string;
2912
+ reported_at: string;
2913
+ }[] | undefined;
2914
+ estimated_delivery?: {
2915
+ from: string;
2916
+ to: string;
2917
+ } | undefined;
2918
+ tracking?: {
2919
+ carrier: string;
2920
+ url?: string | undefined;
2921
+ reference?: string | undefined;
2922
+ } | undefined;
2923
+ can_cancel?: boolean | undefined;
2924
+ can_return?: boolean | undefined;
2925
+ }>;
2926
+ /**
2927
+ * Ask for the order to be cancelled (ADR-0024). Returns the order as it now stands.
2928
+ *
2929
+ * A request, not a refund: DAZN are merchant of record and the money is theirs to
2930
+ * move. This records the fan's ask and hands it on.
2931
+ */
2932
+ requestCancellation: (orderRef: string, body: RequestCancellationRequest) => Promise<{
2933
+ status: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
2934
+ currency: string;
2935
+ items: {
2936
+ sku: string;
2937
+ qty: number;
2938
+ unit_price: {
2939
+ amount: number;
2940
+ currency: string;
2941
+ };
2942
+ line_total: {
2943
+ amount: number;
2944
+ currency: string;
2945
+ };
2946
+ line_ref: string;
2947
+ cancelled_qty: number;
2948
+ refunded_qty: number;
2949
+ attributes?: Record<string, string> | undefined;
2950
+ image?: string | undefined;
2951
+ title?: string | undefined;
2952
+ compare_at_unit_price?: {
2953
+ amount: number;
2954
+ currency: string;
2955
+ } | undefined;
2956
+ }[];
2957
+ totals: {
2958
+ shipping: {
2959
+ amount: number;
2960
+ currency: string;
2961
+ };
2962
+ tax: {
2963
+ amount: number;
2964
+ currency: string;
2965
+ };
2966
+ items: {
2967
+ amount: number;
2968
+ currency: string;
2969
+ };
2970
+ grand_total: {
2971
+ amount: number;
2972
+ currency: string;
2973
+ };
2974
+ discount?: {
2975
+ amount: number;
2976
+ currency: string;
2977
+ } | undefined;
2978
+ };
2979
+ order_ref: string;
2980
+ placed_at: string;
2981
+ ship_to: {
2982
+ country: string;
2983
+ name: string;
2984
+ line1: string;
2985
+ city: string;
2986
+ postcode: string;
2987
+ line2?: string | undefined;
2988
+ region?: string | undefined;
2989
+ };
2990
+ headline: string;
2991
+ progress: {
2992
+ label: string;
2993
+ step: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
2994
+ current: boolean;
2995
+ at?: string | undefined;
2996
+ }[];
2997
+ email?: string | undefined;
2998
+ payment?: {
2999
+ brand: string;
3000
+ last4?: string | undefined;
3001
+ } | undefined;
3002
+ returns?: {
3003
+ status: "reported" | "package_received" | "completed";
3004
+ return_ref: string;
3005
+ reported_at: string;
3006
+ }[] | undefined;
2813
3007
  estimated_delivery?: {
2814
3008
  from: string;
2815
3009
  to: string;
@@ -2819,6 +3013,73 @@ declare function createClient(options: ClientOptions): {
2819
3013
  url?: string | undefined;
2820
3014
  reference?: string | undefined;
2821
3015
  } | undefined;
3016
+ can_cancel?: boolean | undefined;
3017
+ can_return?: boolean | undefined;
3018
+ }>;
3019
+ /** Report items coming back, and get the return — including its label when ready. */
3020
+ createReturn: (orderRef: string, body: CreateReturnRequest) => Promise<{
3021
+ status: "reported" | "package_received" | "completed";
3022
+ items: {
3023
+ sku: string;
3024
+ qty: number;
3025
+ unit_price: {
3026
+ amount: number;
3027
+ currency: string;
3028
+ };
3029
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3030
+ line_ref: string;
3031
+ attributes?: Record<string, string> | undefined;
3032
+ image?: string | undefined;
3033
+ title?: string | undefined;
3034
+ compare_at_unit_price?: {
3035
+ amount: number;
3036
+ currency: string;
3037
+ } | undefined;
3038
+ }[];
3039
+ order_ref: string;
3040
+ return_ref: string;
3041
+ reported_at: string;
3042
+ progress: {
3043
+ label: string;
3044
+ step: "reported" | "package_received" | "completed";
3045
+ current: boolean;
3046
+ at?: string | undefined;
3047
+ }[];
3048
+ label_url?: string | undefined;
3049
+ label_email?: string | undefined;
3050
+ }>;
3051
+ };
3052
+ returns: {
3053
+ get: (returnRef: string) => Promise<{
3054
+ status: "reported" | "package_received" | "completed";
3055
+ items: {
3056
+ sku: string;
3057
+ qty: number;
3058
+ unit_price: {
3059
+ amount: number;
3060
+ currency: string;
3061
+ };
3062
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3063
+ line_ref: string;
3064
+ attributes?: Record<string, string> | undefined;
3065
+ image?: string | undefined;
3066
+ title?: string | undefined;
3067
+ compare_at_unit_price?: {
3068
+ amount: number;
3069
+ currency: string;
3070
+ } | undefined;
3071
+ }[];
3072
+ order_ref: string;
3073
+ return_ref: string;
3074
+ reported_at: string;
3075
+ progress: {
3076
+ label: string;
3077
+ step: "reported" | "package_received" | "completed";
3078
+ current: boolean;
3079
+ at?: string | undefined;
3080
+ }[];
3081
+ label_url?: string | undefined;
3082
+ label_email?: string | undefined;
2822
3083
  }>;
2823
3084
  };
2824
3085
  /**
@@ -2868,6 +3129,37 @@ declare function createClient(options: ClientOptions): {
2868
3129
  };
2869
3130
  };
2870
3131
 
3132
+ /** `POST /v1/orders/{order_ref}/returns` */
3133
+ declare const CreateReturnRequest: z.ZodObject<{
3134
+ items: z.ZodArray<z.ZodObject<{
3135
+ line_ref: z.ZodString;
3136
+ qty: z.ZodNumber;
3137
+ reason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]>;
3138
+ }, "strip", z.ZodTypeAny, {
3139
+ qty: number;
3140
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3141
+ line_ref: string;
3142
+ }, {
3143
+ qty: number;
3144
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3145
+ line_ref: string;
3146
+ }>, "many">;
3147
+ }, "strict", z.ZodTypeAny, {
3148
+ items: {
3149
+ qty: number;
3150
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3151
+ line_ref: string;
3152
+ }[];
3153
+ }, {
3154
+ items: {
3155
+ qty: number;
3156
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3157
+ line_ref: string;
3158
+ }[];
3159
+ }>;
3160
+
3161
+ declare type CreateReturnRequest = z.infer<typeof CreateReturnRequest>;
3162
+
2871
3163
  /**
2872
3164
  * The session seam, implemented once at the transport level.
2873
3165
  *
@@ -3000,7 +3292,7 @@ export declare interface EmptyStateProps {
3000
3292
  * | invalid_request | 400 | malformed body or missing field |
3001
3293
  * | unauthorized | 401 | missing/invalid session or credentials |
3002
3294
  * | out_of_stock | 409 | requested qty exceeds available stock |
3003
- * | cart_locked | 409 | cart handed to checkout; mutations refused |
3295
+ * | cart_locked | 409 | RETIRED (ADR-0025); defined, never raised |
3004
3296
  * | sku_not_found | 404 | a referenced SKU/product does not exist |
3005
3297
  * | category_not_found | 404 | a referenced category code does not exist |
3006
3298
  * | amount_mismatch | 422 | totals do not match the authorised amount |
@@ -3023,7 +3315,7 @@ declare type ErrorCode = z.infer<typeof ErrorCode>;
3023
3315
  * | invalid_request | 400 | malformed body or missing field |
3024
3316
  * | unauthorized | 401 | missing/invalid session or credentials |
3025
3317
  * | out_of_stock | 409 | requested qty exceeds available stock |
3026
- * | cart_locked | 409 | cart handed to checkout; mutations refused |
3318
+ * | cart_locked | 409 | RETIRED (ADR-0025); defined, never raised |
3027
3319
  * | sku_not_found | 404 | a referenced SKU/product does not exist |
3028
3320
  * | category_not_found | 404 | a referenced category code does not exist |
3029
3321
  * | amount_mismatch | 422 | totals do not match the authorised amount |
@@ -3079,6 +3371,11 @@ export declare function ExploreList({ title, links }: {
3079
3371
  links: ExploreLink[];
3080
3372
  }): JSX.Element;
3081
3373
 
3374
+ /** Why an item is coming back, from Figma's `Reason for return` sheet. */
3375
+ declare const FanReturnReason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]>;
3376
+
3377
+ declare type FanReturnReason = z.infer<typeof FanReturnReason>;
3378
+
3082
3379
  /** Horizontal chip filter bar for the PLP. Chips are toggle buttons. */
3083
3380
  export declare function FilterBar({ options, active, onToggle, onClear }: FilterBarProps): JSX.Element;
3084
3381
 
@@ -3291,74 +3588,538 @@ export declare interface OrderConfirmationViewProps {
3291
3588
  }
3292
3589
 
3293
3590
  /**
3294
- * The fan's orders (Figma `mobile/order/list`, ADR-0015).
3295
- *
3296
- * Read-only, like the detail screen it links to. Cancellation and returns are DAZN's under
3297
- * ADR-0008, so the design's return states have no data behind them — see
3298
- * {@link OrderStatusBadge}.
3299
- *
3300
- * Scoped to the session at the engine: `GET /v1/orders` takes no customer parameter, so
3301
- * there is no identifier a caller could supply to read somebody else's history.
3302
- */
3303
- export declare function OrderListView(props: OrderListViewProps): JSX.Element;
3304
-
3305
- export declare interface OrderListViewProps {
3306
- /** Opens one order. Without it the rows render as static cards rather than dead links. */
3307
- onOpenOrder?: (orderRef: string) => void;
3308
- /** The empty state's call to action — the design's "Continue shopping" button. */
3309
- onStartShopping?: () => void;
3310
- /** Overrides the provider's locale for dates. */
3311
- locale?: string;
3312
- }
3313
-
3314
- /**
3315
- * One row of the timeline.
3316
- *
3317
- * **`at` is present only for a step that has actually happened.** A future step has no
3318
- * date, rather than a projected one: a predicted date rendered in the same place as a
3319
- * recorded one is indistinguishable from a promise, and this timeline is the fan's
3320
- * evidence of what occurred.
3321
- */
3322
- declare const OrderProgressEntry: z.ZodObject<{
3323
- step: z.ZodEnum<["packing", "on_its_way", "out_for_delivery", "delivered", "cancelled"]>;
3324
- /** Ready-to-render label for the step, localised with the rest of the response. */
3325
- label: z.ZodString;
3326
- /** When the step completed. Absent = not reached yet. */
3327
- at: z.ZodOptional<z.ZodString>;
3328
- /** Exactly one entry is `current`; every earlier one is complete. */
3329
- current: z.ZodBoolean;
3330
- }, "strip", z.ZodTypeAny, {
3331
- label: string;
3332
- step: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
3333
- current: boolean;
3334
- at?: string | undefined;
3335
- }, {
3336
- label: string;
3337
- step: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
3338
- current: boolean;
3339
- at?: string | undefined;
3340
- }>;
3341
-
3342
- declare type OrderProgressEntry = z.infer<typeof OrderProgressEntry>;
3343
-
3344
- /**
3345
- * A step in the fan-facing progress timeline.
3346
- *
3347
- * Deliberately NOT the warehouse status enum. That has eight values a picker acts on
3348
- * (`received`, `allocated`, `picking`, `packed`, …) and a fan neither sees nor benefits
3349
- * from the difference between them. The engine collapses them; this is the collapsed form.
3591
+ * `GET /v1/orders/{order_ref}` one order in full.
3350
3592
  *
3351
- * The set is open-ended on purpose `out_for_delivery` exists only when a carrier tells us
3352
- * so, and a market with collection would add a step. A consumer must render the steps it is
3353
- * given, in order, and must not assume a fixed count.
3593
+ * **`estimated_delivery` is a window, not a date, and it is advisory.** It comes from the
3594
+ * fulfilment side rather than from DAZN, so it reflects when the warehouse expects to have
3595
+ * it delivered. Absent when nothing can be estimated — which is honest, and better than a
3596
+ * date the fan will hold us to.
3354
3597
  */
3355
- declare const OrderProgressStep: z.ZodEnum<["packing", "on_its_way", "out_for_delivery", "delivered", "cancelled"]>;
3356
-
3357
- declare type OrderProgressStep = z.infer<typeof OrderProgressStep>;
3358
-
3359
- /**
3360
- * Fulfilment order status. Lives here (not in a synchronous order contract) because the
3361
- * engine no longer owns orders (ADR-0008) order/fulfilment status reaches us only as
3598
+ declare const OrderDetail: z.ZodObject<{
3599
+ order_ref: z.ZodBranded<z.ZodString, "OrderRef">;
3600
+ placed_at: z.ZodString;
3601
+ currency: z.ZodString;
3602
+ /**
3603
+ * Where the order confirmation went, for the confirmation screen's "We've sent a
3604
+ * confirmation to ..." line. The address DAZN gave us at intake, echoed back.
3605
+ *
3606
+ * Returned only on the detail read, which is already scoped to the order's own owner,
3607
+ * and never on the list. It is PII: render it, and keep it out of logs and analytics
3608
+ * like every other address in this package.
3609
+ *
3610
+ * Optional because intake's is: a market whose carrier takes no email places orders
3611
+ * without one. Absent means the line is not drawn, never that a placeholder is.
3612
+ */
3613
+ email: z.ZodOptional<z.ZodString>;
3614
+ status: z.ZodEnum<["packing", "on_its_way", "out_for_delivery", "delivered", "cancelled"]>;
3615
+ headline: z.ZodString;
3616
+ estimated_delivery: z.ZodOptional<z.ZodObject<{
3617
+ from: z.ZodString;
3618
+ to: z.ZodString;
3619
+ }, "strip", z.ZodTypeAny, {
3620
+ from: string;
3621
+ to: string;
3622
+ }, {
3623
+ from: string;
3624
+ to: string;
3625
+ }>>;
3626
+ progress: z.ZodArray<z.ZodObject<{
3627
+ step: z.ZodEnum<["packing", "on_its_way", "out_for_delivery", "delivered", "cancelled"]>;
3628
+ /** Ready-to-render label for the step, localised with the rest of the response. */
3629
+ label: z.ZodString;
3630
+ /** When the step completed. Absent = not reached yet. */
3631
+ at: z.ZodOptional<z.ZodString>;
3632
+ /** Exactly one entry is `current`; every earlier one is complete. */
3633
+ current: z.ZodBoolean;
3634
+ }, "strip", z.ZodTypeAny, {
3635
+ label: string;
3636
+ step: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
3637
+ current: boolean;
3638
+ at?: string | undefined;
3639
+ }, {
3640
+ label: string;
3641
+ step: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
3642
+ current: boolean;
3643
+ at?: string | undefined;
3644
+ }>, "many">;
3645
+ tracking: z.ZodOptional<z.ZodObject<{
3646
+ carrier: z.ZodString;
3647
+ reference: z.ZodOptional<z.ZodString>;
3648
+ url: z.ZodOptional<z.ZodString>;
3649
+ }, "strip", z.ZodTypeAny, {
3650
+ carrier: string;
3651
+ url?: string | undefined;
3652
+ reference?: string | undefined;
3653
+ }, {
3654
+ carrier: string;
3655
+ url?: string | undefined;
3656
+ reference?: string | undefined;
3657
+ }>>;
3658
+ items: z.ZodArray<z.ZodObject<{
3659
+ line_ref: z.ZodString;
3660
+ sku: z.ZodString;
3661
+ qty: z.ZodNumber;
3662
+ unit_price: z.ZodObject<{
3663
+ amount: z.ZodNumber;
3664
+ currency: z.ZodString;
3665
+ }, "strict", z.ZodTypeAny, {
3666
+ amount: number;
3667
+ currency: string;
3668
+ }, {
3669
+ amount: number;
3670
+ currency: string;
3671
+ }>;
3672
+ line_total: z.ZodObject<{
3673
+ amount: z.ZodNumber;
3674
+ currency: z.ZodString;
3675
+ }, "strict", z.ZodTypeAny, {
3676
+ amount: number;
3677
+ currency: string;
3678
+ }, {
3679
+ amount: number;
3680
+ currency: string;
3681
+ }>;
3682
+ /**
3683
+ * The undiscounted per-unit price, echoed from intake. Display only.
3684
+ *
3685
+ * Drawn as a struck-through price with a saving badge beside what was paid. Absent
3686
+ * means the line was sold at full price, which is the ordinary case; see `OrderLine`
3687
+ * for why this is DAZN's figure and not our catalogue's.
3688
+ */
3689
+ compare_at_unit_price: z.ZodOptional<z.ZodObject<{
3690
+ amount: z.ZodNumber;
3691
+ currency: z.ZodString;
3692
+ }, "strict", z.ZodTypeAny, {
3693
+ amount: number;
3694
+ currency: string;
3695
+ }, {
3696
+ amount: number;
3697
+ currency: string;
3698
+ }>>;
3699
+ title: z.ZodOptional<z.ZodString>;
3700
+ image: z.ZodOptional<z.ZodString>;
3701
+ /** Variant attributes, e.g. `{ size: 'M' }`. Same shape as everywhere else. */
3702
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
3703
+ /**
3704
+ * Units of this line cancelled or refunded so far. Present so a partially cancelled
3705
+ * order reads honestly instead of showing the original quantity as though nothing
3706
+ * happened. Zero is the normal case and is sent rather than omitted.
3707
+ */
3708
+ cancelled_qty: z.ZodNumber;
3709
+ refunded_qty: z.ZodNumber;
3710
+ }, "strip", z.ZodTypeAny, {
3711
+ sku: string;
3712
+ qty: number;
3713
+ unit_price: {
3714
+ amount: number;
3715
+ currency: string;
3716
+ };
3717
+ line_total: {
3718
+ amount: number;
3719
+ currency: string;
3720
+ };
3721
+ line_ref: string;
3722
+ cancelled_qty: number;
3723
+ refunded_qty: number;
3724
+ compare_at_unit_price?: {
3725
+ amount: number;
3726
+ currency: string;
3727
+ } | undefined;
3728
+ title?: string | undefined;
3729
+ image?: string | undefined;
3730
+ attributes?: Record<string, string> | undefined;
3731
+ }, {
3732
+ sku: string;
3733
+ qty: number;
3734
+ unit_price: {
3735
+ amount: number;
3736
+ currency: string;
3737
+ };
3738
+ line_total: {
3739
+ amount: number;
3740
+ currency: string;
3741
+ };
3742
+ line_ref: string;
3743
+ cancelled_qty: number;
3744
+ refunded_qty: number;
3745
+ compare_at_unit_price?: {
3746
+ amount: number;
3747
+ currency: string;
3748
+ } | undefined;
3749
+ title?: string | undefined;
3750
+ image?: string | undefined;
3751
+ attributes?: Record<string, string> | undefined;
3752
+ }>, "many">;
3753
+ ship_to: z.ZodObject<{
3754
+ name: z.ZodString;
3755
+ line1: z.ZodString;
3756
+ line2: z.ZodOptional<z.ZodString>;
3757
+ city: z.ZodString;
3758
+ region: z.ZodOptional<z.ZodString>;
3759
+ postcode: z.ZodString;
3760
+ country: z.ZodString;
3761
+ }, "strip", z.ZodTypeAny, {
3762
+ country: string;
3763
+ name: string;
3764
+ line1: string;
3765
+ city: string;
3766
+ postcode: string;
3767
+ line2?: string | undefined;
3768
+ region?: string | undefined;
3769
+ }, {
3770
+ country: string;
3771
+ name: string;
3772
+ line1: string;
3773
+ city: string;
3774
+ postcode: string;
3775
+ line2?: string | undefined;
3776
+ region?: string | undefined;
3777
+ }>;
3778
+ payment: z.ZodOptional<z.ZodObject<{
3779
+ brand: z.ZodString;
3780
+ last4: z.ZodOptional<z.ZodString>;
3781
+ }, "strip", z.ZodTypeAny, {
3782
+ brand: string;
3783
+ last4?: string | undefined;
3784
+ }, {
3785
+ brand: string;
3786
+ last4?: string | undefined;
3787
+ }>>;
3788
+ /** Exactly what DAZN charged, echoed. Never recomputed here. */
3789
+ totals: z.ZodObject<{
3790
+ items: z.ZodObject<{
3791
+ amount: z.ZodNumber;
3792
+ currency: z.ZodString;
3793
+ }, "strict", z.ZodTypeAny, {
3794
+ amount: number;
3795
+ currency: string;
3796
+ }, {
3797
+ amount: number;
3798
+ currency: string;
3799
+ }>;
3800
+ shipping: z.ZodObject<{
3801
+ amount: z.ZodNumber;
3802
+ currency: z.ZodString;
3803
+ }, "strict", z.ZodTypeAny, {
3804
+ amount: number;
3805
+ currency: string;
3806
+ }, {
3807
+ amount: number;
3808
+ currency: string;
3809
+ }>;
3810
+ tax: z.ZodObject<{
3811
+ amount: z.ZodNumber;
3812
+ currency: z.ZodString;
3813
+ }, "strict", z.ZodTypeAny, {
3814
+ amount: number;
3815
+ currency: string;
3816
+ }, {
3817
+ amount: number;
3818
+ currency: string;
3819
+ }>;
3820
+ discount: z.ZodOptional<z.ZodObject<{
3821
+ amount: z.ZodNumber;
3822
+ currency: z.ZodString;
3823
+ }, "strict", z.ZodTypeAny, {
3824
+ amount: number;
3825
+ currency: string;
3826
+ }, {
3827
+ amount: number;
3828
+ currency: string;
3829
+ }>>;
3830
+ grand_total: z.ZodObject<{
3831
+ amount: z.ZodNumber;
3832
+ currency: z.ZodString;
3833
+ }, "strict", z.ZodTypeAny, {
3834
+ amount: number;
3835
+ currency: string;
3836
+ }, {
3837
+ amount: number;
3838
+ currency: string;
3839
+ }>;
3840
+ }, "strip", z.ZodTypeAny, {
3841
+ shipping: {
3842
+ amount: number;
3843
+ currency: string;
3844
+ };
3845
+ tax: {
3846
+ amount: number;
3847
+ currency: string;
3848
+ };
3849
+ items: {
3850
+ amount: number;
3851
+ currency: string;
3852
+ };
3853
+ grand_total: {
3854
+ amount: number;
3855
+ currency: string;
3856
+ };
3857
+ discount?: {
3858
+ amount: number;
3859
+ currency: string;
3860
+ } | undefined;
3861
+ }, {
3862
+ shipping: {
3863
+ amount: number;
3864
+ currency: string;
3865
+ };
3866
+ tax: {
3867
+ amount: number;
3868
+ currency: string;
3869
+ };
3870
+ items: {
3871
+ amount: number;
3872
+ currency: string;
3873
+ };
3874
+ grand_total: {
3875
+ amount: number;
3876
+ currency: string;
3877
+ };
3878
+ discount?: {
3879
+ amount: number;
3880
+ currency: string;
3881
+ } | undefined;
3882
+ }>;
3883
+ /**
3884
+ * Whether this order can still be cancelled, and whether it can be returned.
3885
+ *
3886
+ * **Decided by the engine and sent, not derived by the consumer from `status`.** The
3887
+ * rule involves a dispatch cut-off and a returns window that a screen has no way of
3888
+ * knowing, and two consumers deriving it independently would disagree the day either
3889
+ * moves. Absent means no — an older engine that has never heard of either draws
3890
+ * neither button, which is the safe way round for an action that cannot be undone.
3891
+ */
3892
+ can_cancel: z.ZodOptional<z.ZodBoolean>;
3893
+ can_return: z.ZodOptional<z.ZodBoolean>;
3894
+ /** Returns already reported against this order. Absent/empty = none. */
3895
+ returns: z.ZodOptional<z.ZodArray<z.ZodObject<{
3896
+ return_ref: z.ZodString;
3897
+ status: z.ZodEnum<["reported", "package_received", "completed"]>;
3898
+ reported_at: z.ZodString;
3899
+ }, "strip", z.ZodTypeAny, {
3900
+ status: "reported" | "package_received" | "completed";
3901
+ return_ref: string;
3902
+ reported_at: string;
3903
+ }, {
3904
+ status: "reported" | "package_received" | "completed";
3905
+ return_ref: string;
3906
+ reported_at: string;
3907
+ }>, "many">>;
3908
+ }, "strip", z.ZodTypeAny, {
3909
+ status: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
3910
+ currency: string;
3911
+ items: {
3912
+ sku: string;
3913
+ qty: number;
3914
+ unit_price: {
3915
+ amount: number;
3916
+ currency: string;
3917
+ };
3918
+ line_total: {
3919
+ amount: number;
3920
+ currency: string;
3921
+ };
3922
+ line_ref: string;
3923
+ cancelled_qty: number;
3924
+ refunded_qty: number;
3925
+ compare_at_unit_price?: {
3926
+ amount: number;
3927
+ currency: string;
3928
+ } | undefined;
3929
+ title?: string | undefined;
3930
+ image?: string | undefined;
3931
+ attributes?: Record<string, string> | undefined;
3932
+ }[];
3933
+ totals: {
3934
+ shipping: {
3935
+ amount: number;
3936
+ currency: string;
3937
+ };
3938
+ tax: {
3939
+ amount: number;
3940
+ currency: string;
3941
+ };
3942
+ items: {
3943
+ amount: number;
3944
+ currency: string;
3945
+ };
3946
+ grand_total: {
3947
+ amount: number;
3948
+ currency: string;
3949
+ };
3950
+ discount?: {
3951
+ amount: number;
3952
+ currency: string;
3953
+ } | undefined;
3954
+ };
3955
+ order_ref: string & z.BRAND<"OrderRef">;
3956
+ placed_at: string;
3957
+ ship_to: {
3958
+ country: string;
3959
+ name: string;
3960
+ line1: string;
3961
+ city: string;
3962
+ postcode: string;
3963
+ line2?: string | undefined;
3964
+ region?: string | undefined;
3965
+ };
3966
+ headline: string;
3967
+ progress: {
3968
+ label: string;
3969
+ step: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
3970
+ current: boolean;
3971
+ at?: string | undefined;
3972
+ }[];
3973
+ email?: string | undefined;
3974
+ payment?: {
3975
+ brand: string;
3976
+ last4?: string | undefined;
3977
+ } | undefined;
3978
+ returns?: {
3979
+ status: "reported" | "package_received" | "completed";
3980
+ return_ref: string;
3981
+ reported_at: string;
3982
+ }[] | undefined;
3983
+ estimated_delivery?: {
3984
+ from: string;
3985
+ to: string;
3986
+ } | undefined;
3987
+ tracking?: {
3988
+ carrier: string;
3989
+ url?: string | undefined;
3990
+ reference?: string | undefined;
3991
+ } | undefined;
3992
+ can_cancel?: boolean | undefined;
3993
+ can_return?: boolean | undefined;
3994
+ }, {
3995
+ status: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
3996
+ currency: string;
3997
+ items: {
3998
+ sku: string;
3999
+ qty: number;
4000
+ unit_price: {
4001
+ amount: number;
4002
+ currency: string;
4003
+ };
4004
+ line_total: {
4005
+ amount: number;
4006
+ currency: string;
4007
+ };
4008
+ line_ref: string;
4009
+ cancelled_qty: number;
4010
+ refunded_qty: number;
4011
+ compare_at_unit_price?: {
4012
+ amount: number;
4013
+ currency: string;
4014
+ } | undefined;
4015
+ title?: string | undefined;
4016
+ image?: string | undefined;
4017
+ attributes?: Record<string, string> | undefined;
4018
+ }[];
4019
+ totals: {
4020
+ shipping: {
4021
+ amount: number;
4022
+ currency: string;
4023
+ };
4024
+ tax: {
4025
+ amount: number;
4026
+ currency: string;
4027
+ };
4028
+ items: {
4029
+ amount: number;
4030
+ currency: string;
4031
+ };
4032
+ grand_total: {
4033
+ amount: number;
4034
+ currency: string;
4035
+ };
4036
+ discount?: {
4037
+ amount: number;
4038
+ currency: string;
4039
+ } | undefined;
4040
+ };
4041
+ order_ref: string;
4042
+ placed_at: string;
4043
+ ship_to: {
4044
+ country: string;
4045
+ name: string;
4046
+ line1: string;
4047
+ city: string;
4048
+ postcode: string;
4049
+ line2?: string | undefined;
4050
+ region?: string | undefined;
4051
+ };
4052
+ headline: string;
4053
+ progress: {
4054
+ label: string;
4055
+ step: "packing" | "on_its_way" | "out_for_delivery" | "delivered" | "cancelled";
4056
+ current: boolean;
4057
+ at?: string | undefined;
4058
+ }[];
4059
+ email?: string | undefined;
4060
+ payment?: {
4061
+ brand: string;
4062
+ last4?: string | undefined;
4063
+ } | undefined;
4064
+ returns?: {
4065
+ status: "reported" | "package_received" | "completed";
4066
+ return_ref: string;
4067
+ reported_at: string;
4068
+ }[] | undefined;
4069
+ estimated_delivery?: {
4070
+ from: string;
4071
+ to: string;
4072
+ } | undefined;
4073
+ tracking?: {
4074
+ carrier: string;
4075
+ url?: string | undefined;
4076
+ reference?: string | undefined;
4077
+ } | undefined;
4078
+ can_cancel?: boolean | undefined;
4079
+ can_return?: boolean | undefined;
4080
+ }>;
4081
+
4082
+ declare type OrderDetail = z.infer<typeof OrderDetail>;
4083
+
4084
+ /**
4085
+ * The fan's orders (Figma `mobile/order/list`, ADR-0015).
4086
+ *
4087
+ * Read-only, like the detail screen it links to. Cancellation and returns are DAZN's under
4088
+ * ADR-0008, so the design's return states have no data behind them — see
4089
+ * {@link OrderStatusBadge}.
4090
+ *
4091
+ * Scoped to the session at the engine: `GET /v1/orders` takes no customer parameter, so
4092
+ * there is no identifier a caller could supply to read somebody else's history.
4093
+ */
4094
+ export declare function OrderListView(props: OrderListViewProps): JSX.Element;
4095
+
4096
+ export declare interface OrderListViewProps {
4097
+ /** Opens one order. Without it the rows render as static cards rather than dead links. */
4098
+ onOpenOrder?: (orderRef: string) => void;
4099
+ /** The empty state's call to action — the design's "Continue shopping" button. */
4100
+ onStartShopping?: () => void;
4101
+ /** Overrides the provider's locale for dates. */
4102
+ locale?: string;
4103
+ }
4104
+
4105
+ /**
4106
+ * A step in the fan-facing progress timeline.
4107
+ *
4108
+ * Deliberately NOT the warehouse status enum. That has eight values a picker acts on
4109
+ * (`received`, `allocated`, `picking`, `packed`, …) and a fan neither sees nor benefits
4110
+ * from the difference between them. The engine collapses them; this is the collapsed form.
4111
+ *
4112
+ * The set is open-ended on purpose — `out_for_delivery` exists only when a carrier tells us
4113
+ * so, and a market with collection would add a step. A consumer must render the steps it is
4114
+ * given, in order, and must not assume a fixed count.
4115
+ */
4116
+ declare const OrderProgressStep: z.ZodEnum<["packing", "on_its_way", "out_for_delivery", "delivered", "cancelled"]>;
4117
+
4118
+ declare type OrderProgressStep = z.infer<typeof OrderProgressStep>;
4119
+
4120
+ /**
4121
+ * Fulfilment order status. Lives here (not in a synchronous order contract) because the
4122
+ * engine no longer owns orders (ADR-0008) — order/fulfilment status reaches us only as
3362
4123
  * async events (Odoo → engine → consumers). DAZN is authoritative for completed orders.
3363
4124
  */
3364
4125
  declare const OrderStatus: z.ZodEnum<["confirmed", "packed", "shipped", "delivered", "cancelled", "refunded"]>;
@@ -3397,8 +4158,17 @@ export declare interface OrderSummaryProps {
3397
4158
  * changes at checkout. DAZN owns checkout and therefore owns delivery and tax
3398
4159
  * (ADR-0008), so in the cart both are genuinely unknown rather than genuinely free.
3399
4160
  *
3400
- * When anything is deferred the grand total is withheld too: a total that omits
3401
- * delivery is not a total. Subtotal carries the emphasis instead.
4161
+ * **The grand total is still drawn.** It used to be withheld whenever anything here was
4162
+ * deferred, on the reasoning that a total omitting delivery is not a total. DAZN
4163
+ * reviewed that on 21 Aug 2026 against the frame — which draws a Total row — and chose
4164
+ * the frame. So the row is drawn, carrying `pricing.total`, and on a cart that means the
4165
+ * items total: delivery and tax are added at DAZN's checkout and can move it by the
4166
+ * spread the design's own shipping note quotes (standard $5-16, express $15-23).
4167
+ *
4168
+ * Deferring a row therefore now changes only that row. If the withholding is ever
4169
+ * wanted back, it belongs behind an explicit prop rather than as a side effect of
4170
+ * `deferred` — a prop that silently removes a different row is the kind of surprise this
4171
+ * comment exists to prevent.
3402
4172
  */
3403
4173
  deferred?: DeferredLine[];
3404
4174
  /**
@@ -3436,7 +4206,7 @@ export declare interface OrderSummaryProps {
3436
4206
  export declare function OrderTimeline({ progress, estimatedDelivery, locale: localeProp, }: OrderTimelineProps): JSX.Element;
3437
4207
 
3438
4208
  export declare interface OrderTimelineProps {
3439
- progress: OrderProgressEntry[];
4209
+ progress: readonly TimelineEntry[];
3440
4210
  /**
3441
4211
  * The delivery window, drawn under the last step while that step is still to come.
3442
4212
  *
@@ -3459,14 +4229,18 @@ export declare interface OrderTimelineProps {
3459
4229
  * One screen with three states, and the engine's `progress` is what draws them: the widget
3460
4230
  * says where the parcel is, and everything under it is the same for all three.
3461
4231
  *
3462
- * Read-only by design. The frame's first state carries a "Cancel order" button and its
3463
- * last offers "Start a return"; **cancellation and returns remain DAZN's** under ADR-0008
3464
- * and ADR-0017, and nothing in the tracking contract can express either. A control that
3465
- * cannot complete is worse than an absent one, so neither is drawn here the return row
3466
- * is a prop for the host that owns the flow.
4232
+ * The frame's first state carries a "Cancel order" button and its last offers a return,
4233
+ * and **both are ours since 21 Aug** (ADR-0024). Cancelling happens in place, through the
4234
+ * reason sheet at the foot of this file; a return is three screens, so "Return items"
4235
+ * navigates to them. Neither moves money: DAZN remain merchant of record, and what the
4236
+ * engine records is a request handed on.
4237
+ *
4238
+ * Both are drawn on the ENGINE's say-so — `can_cancel` is its dispatch cut-off,
4239
+ * `can_return` its returns window. Neither is a status this screen can infer, and it does
4240
+ * not try.
3467
4241
  *
3468
- * "Contact support" is different, and is always drawn: the form behind it is DAZN's too,
3469
- * but the row has somewhere to go without them wiring anything, because pressing it raises
4242
+ * "Contact support" is different again: the form behind it is DAZN's, but the row has
4243
+ * somewhere to go without them wiring anything, because pressing it raises
3470
4244
  * `support_requested`.
3471
4245
  *
3472
4246
  * Below the widget this is the confirmation screen: the same rows, the same two cards, the
@@ -3480,14 +4254,35 @@ export declare interface OrderTrackingViewProps {
3480
4254
  /** Overrides the provider's locale for dates. */
3481
4255
  locale?: string;
3482
4256
  /**
3483
- * The "Need help?" block's first row, under a delivered order.
4257
+ * Open the return flow.
3484
4258
  *
3485
- * **Not ours to wire.** Returns are DAZN's under ADR-0008 and nothing in the tracking
3486
- * contract can start one, so the row is drawn only for a host that owns that flow and
3487
- * says so by passing a handler. There is no event: we cannot report a return as
3488
- * requested when nothing can act on it.
4259
+ * **Optional now, and it was once required.** Returns were DAZN's under ADR-0008, so
4260
+ * this used to be the only way the row could appear: a control that cannot complete is
4261
+ * worse than an absent one. ADR-0024 gave us the flow `POST /v1/orders/{ref}/returns`
4262
+ * and the three screens behind it — so the default is no longer "nothing happens".
4263
+ *
4264
+ * It is still the seam, because the flow is three SCREENS and only the host knows where
4265
+ * its routes are — the same reason `OrderListView` takes `onOpenOrder` rather than
4266
+ * navigating itself. What changed is what the handler leads to: mount `ReturnFlowView`
4267
+ * with this order's reference and the whole flow is there.
4268
+ *
4269
+ * Without it the control is not drawn. The SDK will not offer a button whose destination
4270
+ * does not exist, and that has not changed either.
3489
4271
  */
3490
4272
  onStartReturn?: () => void;
4273
+ /**
4274
+ * Called once the fan has confirmed a cancellation and the engine has accepted it,
4275
+ * with the order as it now stands. The screen redraws itself either way; this is for a
4276
+ * host that wants to react — refresh a list, close a sheet, send an analytics event.
4277
+ */
4278
+ onCancelled?: (order: OrderDetail) => void;
4279
+ /**
4280
+ * The cancelled screen's "Reorder". Omit it and no button renders.
4281
+ *
4282
+ * The host's, because it means "put these items back in a cart and go somewhere", and
4283
+ * only they know where that is. We raise `reorder_requested` regardless.
4284
+ */
4285
+ onReorder?: () => void;
3491
4286
  /**
3492
4287
  * The block's second row, which is always drawn under a delivered order.
3493
4288
  *
@@ -3879,6 +4674,11 @@ export declare interface ProductDetailProps {
3879
4674
  * PDP "Product details" accordion (mobile/pdp/details). Collapsed clamps the body to
3880
4675
  * three lines with a more/less toggle. Only renders when the catalogue provides a
3881
4676
  * description — no placeholder copy is invented.
4677
+ *
4678
+ * The toggle appears only when the clamp is actually hiding something. It used to render
4679
+ * for every description, so a two-line one offered a "more" that expanded to the same two
4680
+ * lines and a "Less" that collapsed to them again — reported from staging, where most
4681
+ * products have a short description.
3882
4682
  */
3883
4683
  export declare function ProductDetails({ description }: ProductDetailsProps): JSX.Element | null;
3884
4684
 
@@ -4052,9 +4852,10 @@ export declare function PromoBanner({ promo }: {
4052
4852
  *
4053
4853
  * When the cap is reached the reason is stated inline rather than the control simply
4054
4854
  * going dead — a disabled `+` with no explanation reads as a bug, and the fan cannot
4055
- * tell "we have no more" from "this is broken".
4855
+ * tell "we have no more" from "this is broken". A caller that already says it passes
4856
+ * {@link QtyStepperProps.capDescribedBy} and gets the wiring without the second copy.
4056
4857
  */
4057
- export declare function QtyStepper({ qty, max, onChange, onRemove, disabled }: QtyStepperProps): JSX.Element;
4858
+ export declare function QtyStepper({ qty, max, onChange, onRemove, disabled, capDescribedBy, }: QtyStepperProps): JSX.Element;
4058
4859
 
4059
4860
  export declare interface QtyStepperProps {
4060
4861
  qty: number;
@@ -4064,6 +4865,18 @@ export declare interface QtyStepperProps {
4064
4865
  /** Called when decrementing from 1 (the decrement becomes a delete). */
4065
4866
  onRemove?: () => void;
4066
4867
  disabled?: boolean;
4868
+ /**
4869
+ * Id of an element that already explains the cap, drawn by the caller.
4870
+ *
4871
+ * Pass this when the surrounding screen states the stock itself — the cart line draws
4872
+ * Figma's `Only N left` label under the whole line, and its out-of-stock line scrims the
4873
+ * thumbnail. Given one, the stepper points `aria-describedby` at it and renders no
4874
+ * message of its own, so the two can never say the same thing twice or disagree.
4875
+ *
4876
+ * Without it the stepper explains its own dead `+`, which is the standalone behaviour
4877
+ * and the reason the message exists at all.
4878
+ */
4879
+ capDescribedBy?: string;
4067
4880
  }
4068
4881
 
4069
4882
  /**
@@ -4091,6 +4904,64 @@ export declare interface RailCarouselProps {
4091
4904
  inset?: boolean;
4092
4905
  }
4093
4906
 
4907
+ export declare interface ReasonOption<T extends string> {
4908
+ value: T;
4909
+ label: string;
4910
+ }
4911
+
4912
+ /**
4913
+ * "Pick one reason, then confirm" — Figma `Reason for cancelling` (4632:17129) and
4914
+ * `Reason for return`.
4915
+ *
4916
+ * One component for both, because they are one component in the file: the same sheet, the
4917
+ * same rows, the same footer, differing only in their title, their options and the word on
4918
+ * the button. Building two would be two things to keep in step.
4919
+ *
4920
+ * **The confirm button starts disabled and the sheet does not preselect anything.** A
4921
+ * reason is the fan's statement about their own order, and a default would put words in
4922
+ * their mouth that the first tap then submits.
4923
+ */
4924
+ export declare function ReasonSheet<T extends string>({ title, options, ctaLabel, selected, onConfirm, onClose, closeLabel, busy, error, }: ReasonSheetProps<T>): JSX.Element;
4925
+
4926
+ export declare interface ReasonSheetProps<T extends string> {
4927
+ title: string;
4928
+ options: readonly ReasonOption<T>[];
4929
+ /** The confirm button's label — "Cancel order" on one sheet, "Select" on the other. */
4930
+ ctaLabel: string;
4931
+ /** Pre-selected value, for a sheet reopened on a line that already has a reason. */
4932
+ selected?: T;
4933
+ onConfirm: (value: T) => void;
4934
+ onClose: () => void;
4935
+ /** What the close control is called to assistive technology. */
4936
+ closeLabel: string;
4937
+ /** Marks the confirm button busy while the request is in flight. */
4938
+ busy?: boolean;
4939
+ /**
4940
+ * A failure from the action this sheet confirms, shown above the button.
4941
+ *
4942
+ * On the sheet rather than replacing the screen behind it: the order is still fine, it
4943
+ * is the request that failed, and the fan's next move is to press the same button again.
4944
+ */
4945
+ error?: string;
4946
+ }
4947
+
4948
+ /**
4949
+ * `POST /v1/orders/{order_ref}/cancellation`
4950
+ *
4951
+ * The whole order. Figma offers no per-line cancel and neither does this: the sheet has
4952
+ * one reason and one button, and a partial cancellation the fan cannot express is not a
4953
+ * shape worth carrying.
4954
+ */
4955
+ declare const RequestCancellationRequest: z.ZodObject<{
4956
+ reason: z.ZodEnum<["changed_my_mind", "ordered_by_mistake", "delivery_too_long"]>;
4957
+ }, "strict", z.ZodTypeAny, {
4958
+ reason: "changed_my_mind" | "ordered_by_mistake" | "delivery_too_long";
4959
+ }, {
4960
+ reason: "changed_my_mind" | "ordered_by_mistake" | "delivery_too_long";
4961
+ }>;
4962
+
4963
+ declare type RequestCancellationRequest = z.infer<typeof RequestCancellationRequest>;
4964
+
4094
4965
  /**
4095
4966
  * Resolve an asset path against the host-configured asset base.
4096
4967
  *
@@ -4116,6 +4987,283 @@ export declare function resolveAssetUrl(src: string, base?: string): string;
4116
4987
  */
4117
4988
  export declare function resolveSku(variants: ProductVariant[], size: string | null, colour: string | null): string | null;
4118
4989
 
4990
+ /**
4991
+ * The reasons the frame offers, in the frame's order.
4992
+ *
4993
+ * Ordered by how often a fan picks them rather than alphabetically, which is the design's
4994
+ * choice and not ours to re-sort: the two sizing reasons lead because sizing is what most
4995
+ * clothing returns are about.
4996
+ */
4997
+ export declare const RETURN_REASONS: readonly ReasonOption<FanReturnReason>[];
4998
+
4999
+ /**
5000
+ * `GET /v1/returns/{return_ref}` — one return in full.
5001
+ *
5002
+ * `label_url` is **opaque and short-lived**, like carrier tracking: render it as a
5003
+ * download, never rebuild it. Absent means the label is not ready, and the screen says so
5004
+ * rather than offering a button that 404s — the frame's own copy promises the PDF by email
5005
+ * as well, which is the path that does not depend on this link still working.
5006
+ */
5007
+ declare const ReturnDetail: z.ZodObject<{
5008
+ return_ref: z.ZodString;
5009
+ order_ref: z.ZodBranded<z.ZodString, "OrderRef">;
5010
+ status: z.ZodEnum<["reported", "package_received", "completed"]>;
5011
+ reported_at: z.ZodString;
5012
+ progress: z.ZodArray<z.ZodObject<{
5013
+ step: z.ZodEnum<["reported", "package_received", "completed"]>;
5014
+ label: z.ZodString;
5015
+ /** When the step completed. Absent = not reached yet, never a projected date. */
5016
+ at: z.ZodOptional<z.ZodString>;
5017
+ current: z.ZodBoolean;
5018
+ }, "strip", z.ZodTypeAny, {
5019
+ label: string;
5020
+ step: "reported" | "package_received" | "completed";
5021
+ current: boolean;
5022
+ at?: string | undefined;
5023
+ }, {
5024
+ label: string;
5025
+ step: "reported" | "package_received" | "completed";
5026
+ current: boolean;
5027
+ at?: string | undefined;
5028
+ }>, "many">;
5029
+ items: z.ZodArray<z.ZodObject<{
5030
+ line_ref: z.ZodString;
5031
+ sku: z.ZodString;
5032
+ qty: z.ZodNumber;
5033
+ reason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]>;
5034
+ unit_price: z.ZodObject<{
5035
+ amount: z.ZodNumber;
5036
+ currency: z.ZodString;
5037
+ }, "strict", z.ZodTypeAny, {
5038
+ amount: number;
5039
+ currency: string;
5040
+ }, {
5041
+ amount: number;
5042
+ currency: string;
5043
+ }>;
5044
+ compare_at_unit_price: z.ZodOptional<z.ZodObject<{
5045
+ amount: z.ZodNumber;
5046
+ currency: z.ZodString;
5047
+ }, "strict", z.ZodTypeAny, {
5048
+ amount: number;
5049
+ currency: string;
5050
+ }, {
5051
+ amount: number;
5052
+ currency: string;
5053
+ }>>;
5054
+ title: z.ZodOptional<z.ZodString>;
5055
+ image: z.ZodOptional<z.ZodString>;
5056
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
5057
+ }, "strip", z.ZodTypeAny, {
5058
+ sku: string;
5059
+ qty: number;
5060
+ unit_price: {
5061
+ amount: number;
5062
+ currency: string;
5063
+ };
5064
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5065
+ line_ref: string;
5066
+ compare_at_unit_price?: {
5067
+ amount: number;
5068
+ currency: string;
5069
+ } | undefined;
5070
+ title?: string | undefined;
5071
+ image?: string | undefined;
5072
+ attributes?: Record<string, string> | undefined;
5073
+ }, {
5074
+ sku: string;
5075
+ qty: number;
5076
+ unit_price: {
5077
+ amount: number;
5078
+ currency: string;
5079
+ };
5080
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5081
+ line_ref: string;
5082
+ compare_at_unit_price?: {
5083
+ amount: number;
5084
+ currency: string;
5085
+ } | undefined;
5086
+ title?: string | undefined;
5087
+ image?: string | undefined;
5088
+ attributes?: Record<string, string> | undefined;
5089
+ }>, "many">;
5090
+ label_url: z.ZodOptional<z.ZodString>;
5091
+ /**
5092
+ * Where the label PDF was sent, for the frame's "You'll receive a shipping label PDF to
5093
+ * your email as well" line. PII, like `OrderDetail.email`: render it, never log it.
5094
+ */
5095
+ label_email: z.ZodOptional<z.ZodString>;
5096
+ }, "strip", z.ZodTypeAny, {
5097
+ status: "reported" | "package_received" | "completed";
5098
+ items: {
5099
+ sku: string;
5100
+ qty: number;
5101
+ unit_price: {
5102
+ amount: number;
5103
+ currency: string;
5104
+ };
5105
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5106
+ line_ref: string;
5107
+ compare_at_unit_price?: {
5108
+ amount: number;
5109
+ currency: string;
5110
+ } | undefined;
5111
+ title?: string | undefined;
5112
+ image?: string | undefined;
5113
+ attributes?: Record<string, string> | undefined;
5114
+ }[];
5115
+ order_ref: string & z.BRAND<"OrderRef">;
5116
+ return_ref: string;
5117
+ reported_at: string;
5118
+ progress: {
5119
+ label: string;
5120
+ step: "reported" | "package_received" | "completed";
5121
+ current: boolean;
5122
+ at?: string | undefined;
5123
+ }[];
5124
+ label_url?: string | undefined;
5125
+ label_email?: string | undefined;
5126
+ }, {
5127
+ status: "reported" | "package_received" | "completed";
5128
+ items: {
5129
+ sku: string;
5130
+ qty: number;
5131
+ unit_price: {
5132
+ amount: number;
5133
+ currency: string;
5134
+ };
5135
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5136
+ line_ref: string;
5137
+ compare_at_unit_price?: {
5138
+ amount: number;
5139
+ currency: string;
5140
+ } | undefined;
5141
+ title?: string | undefined;
5142
+ image?: string | undefined;
5143
+ attributes?: Record<string, string> | undefined;
5144
+ }[];
5145
+ order_ref: string;
5146
+ return_ref: string;
5147
+ reported_at: string;
5148
+ progress: {
5149
+ label: string;
5150
+ step: "reported" | "package_received" | "completed";
5151
+ current: boolean;
5152
+ at?: string | undefined;
5153
+ }[];
5154
+ label_url?: string | undefined;
5155
+ label_email?: string | undefined;
5156
+ }>;
5157
+
5158
+ declare type ReturnDetail = z.infer<typeof ReturnDetail>;
5159
+
5160
+ /**
5161
+ * The return flow, end to end — Figma `Return flow` (4551:32294).
5162
+ *
5163
+ * **This is the piece that was missing.** `ReturnItemsView`, `ReturnLabelView` and
5164
+ * `ReturnTrackingView` are presentational: they take an order or a return and draw it.
5165
+ * Something has to load the order, post what the fan chose, and move between the three,
5166
+ * and until now nothing did — the screens were exported and nothing in this package or in
5167
+ * the app mounted them, so a flow that was built could not be reached.
5168
+ *
5169
+ * The shape follows `OrderTrackingView`: a container that owns the fetch and the state,
5170
+ * around views that own the drawing. Same reason as there — a screen that loads itself is
5171
+ * one a host can mount from a route with nothing but a reference.
5172
+ *
5173
+ * **It settles no money and it is not a refund** (ADR-0024). It records goods coming back
5174
+ * so the warehouse can expect them; DAZN remain merchant of record and tell us about the
5175
+ * refund afterwards through the inbound event.
5176
+ */
5177
+ export declare function ReturnFlowView(props: ReturnFlowViewProps): JSX.Element;
5178
+
5179
+ export declare interface ReturnFlowViewProps {
5180
+ /** DAZN's order reference. Required to START a return. */
5181
+ orderRef?: string;
5182
+ /**
5183
+ * An existing return, e.g. `ord_GB26081021-R1`. Given one, the flow opens on its
5184
+ * progress instead of on the item picker — which is what the "Return in progress" row
5185
+ * on the order screen leads to.
5186
+ */
5187
+ returnRef?: string;
5188
+ /** The label screen's "Done". Where it goes is the host's. */
5189
+ onDone?: () => void;
5190
+ /** Overrides the provider's locale for dates. */
5191
+ locale?: string;
5192
+ }
5193
+
5194
+ /**
5195
+ * "What do you want to return?" — Figma `Return flow` (4551:32294), screens 2 to 4.
5196
+ *
5197
+ * **A line is returnable only once it has a reason**, which is why the reason lives inside
5198
+ * the card rather than being asked once for the whole return: the frame puts a `Select
5199
+ * reason` control in every row, and a fan sending back two garments for two different
5200
+ * reasons is the ordinary case rather than an edge one.
5201
+ *
5202
+ * Quantity is not asked for. The frame offers no stepper, so a selected line returns in
5203
+ * full — and inventing a control the design does not draw would be the wrong way to
5204
+ * discover we needed one.
5205
+ */
5206
+ export declare function ReturnItemsView({ order, onSubmit, busy }: ReturnItemsViewProps): JSX.Element;
5207
+
5208
+ export declare interface ReturnItemsViewProps {
5209
+ order: OrderDetail;
5210
+ /** Called with the lines the fan chose. The caller posts them and shows the label. */
5211
+ onSubmit: (items: ReturnRequestItem[]) => void;
5212
+ /** Set while the request is in flight. */
5213
+ busy?: boolean;
5214
+ }
5215
+
5216
+ /**
5217
+ * "We've generated your return label" — Figma `Return flow` (4551:32294), screen 5.
5218
+ *
5219
+ * Two numbered steps and a download. The label is offered as a link rather than a
5220
+ * scripted download because the sheet a fan sees this in may be a webview, and a
5221
+ * script-driven save is exactly what a webview blocks.
5222
+ *
5223
+ * **The button is only drawn when there is a label.** The frame promises the PDF by email
5224
+ * as well, and that promise is the one that survives a link this screen cannot produce —
5225
+ * so when `label_url` is absent the email line still tells the fan where to look, and no
5226
+ * button is offered that would 404.
5227
+ */
5228
+ export declare function ReturnLabelView({ ret, onDone }: ReturnLabelViewProps): JSX.Element;
5229
+
5230
+ export declare interface ReturnLabelViewProps {
5231
+ ret: ReturnDetail;
5232
+ /** The frame's "Done". Where it goes is the host's — see `OrderConfirmationView`. */
5233
+ onDone?: () => void;
5234
+ }
5235
+
5236
+ /**
5237
+ * One line the fan is sending back.
5238
+ *
5239
+ * `qty` rather than a flag, because a line of three can have one returned, and `reason`
5240
+ * per line rather than per return, because the screen asks for it per line — the frame
5241
+ * puts a "Select reason" row inside each item card.
5242
+ */
5243
+ declare const ReturnRequestItem: z.ZodObject<{
5244
+ line_ref: z.ZodString;
5245
+ qty: z.ZodNumber;
5246
+ reason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]>;
5247
+ }, "strip", z.ZodTypeAny, {
5248
+ qty: number;
5249
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5250
+ line_ref: string;
5251
+ }, {
5252
+ qty: number;
5253
+ reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5254
+ line_ref: string;
5255
+ }>;
5256
+
5257
+ declare type ReturnRequestItem = z.infer<typeof ReturnRequestItem>;
5258
+
5259
+ export declare function ReturnTrackingView({ ret, locale: localeProp }: ReturnTrackingViewProps): JSX.Element;
5260
+
5261
+ export declare interface ReturnTrackingViewProps {
5262
+ ret: ReturnDetail;
5263
+ /** Overrides the provider's locale for the reported date. */
5264
+ locale?: string;
5265
+ }
5266
+
4119
5267
  declare interface Review {
4120
5268
  quote: string;
4121
5269
  author: string;
@@ -4182,6 +5330,23 @@ declare const SessionExchangeRequest: z.ZodObject<{
4182
5330
 
4183
5331
  declare type SessionExchangeRequest = z.infer<typeof SessionExchangeRequest>;
4184
5332
 
5333
+ /**
5334
+ * The design's `.sheet-header` (404:5379): an empty 48 slot, the drag handle, and a close
5335
+ * disc — 48 tall.
5336
+ *
5337
+ * Three slots rather than two, so the handle is centred on the SHEET rather than on what
5338
+ * is left of it once the close control has taken its corner. Drawn once here because the
5339
+ * size guide and both reason sheets instance the same component, and a second hand-built
5340
+ * copy is a second one to drift.
5341
+ */
5342
+ export declare function SheetHeader({ onClose, closeLabel }: SheetHeaderProps): JSX.Element;
5343
+
5344
+ export declare interface SheetHeaderProps {
5345
+ onClose: () => void;
5346
+ /** What the close control is called to assistive technology, e.g. "Close size guide". */
5347
+ closeLabel: string;
5348
+ }
5349
+
4185
5350
  /**
4186
5351
  * PDP shipping & returns block (mobile/pdp/shipping-info). Static informational copy —
4187
5352
  * no free-shipping threshold (per design). The shopper picks the delivery tier at
@@ -4266,6 +5431,36 @@ export declare type ShopEvent = {
4266
5431
  | {
4267
5432
  type: 'support_requested';
4268
5433
  orderRef: string;
5434
+ }
5435
+ /**
5436
+ * The fan confirmed a cancellation and the engine accepted it (ADR-0024).
5437
+ *
5438
+ * Raised after the write succeeds, never on the tap: this is a statement that an order
5439
+ * has been cancelled, and a host acting on it — refreshing a list, telling analytics —
5440
+ * must not act on one that then failed.
5441
+ */
5442
+ | {
5443
+ type: 'order_cancellation_requested';
5444
+ orderRef: string;
5445
+ reason: string;
5446
+ }
5447
+ /** "Reorder" on a cancelled order. The host owns where that goes; we only announce it. */
5448
+ | {
5449
+ type: 'reorder_requested';
5450
+ orderRef: string;
5451
+ }
5452
+ /**
5453
+ * A return has been RECORDED — the engine accepted it and minted the reference.
5454
+ *
5455
+ * Raised after the write, like the cancellation above, and for the same reason: a host
5456
+ * counting returns must not count one the engine refused. It is not a refund and must
5457
+ * not be treated as one; DAZN remain merchant of record and say what is paid back
5458
+ * (ADR-0024).
5459
+ */
5460
+ | {
5461
+ type: 'return_requested';
5462
+ orderRef: string;
5463
+ returnRef: string;
4269
5464
  } | {
4270
5465
  type: 'checkout_handoff';
4271
5466
  cartId: string;
@@ -4813,6 +6008,22 @@ declare type SupportTicketRequest = z.infer<typeof SupportTicketRequest>;
4813
6008
 
4814
6009
  export declare function swatchColour(name: string): string;
4815
6010
 
6011
+ /**
6012
+ * One row, structurally.
6013
+ *
6014
+ * Deliberately not `OrderProgressEntry` itself. The return timeline (ADR-0024) is drawn
6015
+ * by the same Figma component with a different set of steps — reported, received,
6016
+ * completed — so its entries carry a different `step` enum and would not assign. Nothing
6017
+ * here interprets `step` beyond keying on it, so the widened type costs nothing and saves
6018
+ * a second copy of the timeline that would drift from this one.
6019
+ */
6020
+ declare interface TimelineEntry {
6021
+ step: string;
6022
+ label: string;
6023
+ at?: string;
6024
+ current: boolean;
6025
+ }
6026
+
4816
6027
  /** An optional inline action, e.g. the undo offered after removing a cart line. */
4817
6028
  export declare interface ToastAction {
4818
6029
  label: string;