@nok-integration/storefront-react 0.20.15 → 0.20.17

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
@@ -282,8 +282,8 @@ export declare interface CartLineItemProps {
282
282
  * should send it here too — the pair is what keeps the two surfaces agreeing.
283
283
  *
284
284
  * The market belongs on the validated shopping session rather than on the query string,
285
- * and moves there when that contract exists. This is the interim source,
286
- * not the intended one.
285
+ * and moves there when that contract exists. This is the interim source, not the intended
286
+ * one.
287
287
  */
288
288
  declare const CartMarketQuery: z.ZodObject<{
289
289
  country: z.ZodOptional<z.ZodString>;
@@ -3272,26 +3272,26 @@ declare const CreateReturnRequest: z.ZodObject<{
3272
3272
  items: z.ZodArray<z.ZodObject<{
3273
3273
  line_ref: z.ZodString;
3274
3274
  qty: z.ZodNumber;
3275
- reason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]>;
3275
+ reason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described"]>;
3276
3276
  }, "strip", z.ZodTypeAny, {
3277
3277
  qty: number;
3278
- reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3278
+ reason: "too_small" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3279
3279
  line_ref: string;
3280
3280
  }, {
3281
3281
  qty: number;
3282
- reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3282
+ reason: "too_small" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3283
3283
  line_ref: string;
3284
3284
  }>, "many">;
3285
3285
  }, "strict", z.ZodTypeAny, {
3286
3286
  items: {
3287
3287
  qty: number;
3288
- reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3288
+ reason: "too_small" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3289
3289
  line_ref: string;
3290
3290
  }[];
3291
3291
  }, {
3292
3292
  items: {
3293
3293
  qty: number;
3294
- reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3294
+ reason: "too_small" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
3295
3295
  line_ref: string;
3296
3296
  }[];
3297
3297
  }>;
@@ -3518,8 +3518,20 @@ export declare function ExploreList({ title, links }: {
3518
3518
  links: ExploreLink[];
3519
3519
  }): JSX.Element;
3520
3520
 
3521
- /** Why an item is coming back, from Figma's `Reason for return` sheet. */
3522
- declare const FanReturnReason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]>;
3521
+ /**
3522
+ * Why an item is coming back — what a fan may CHOOSE, from Figma's `Reason for return`
3523
+ * sheet, less one.
3524
+ *
3525
+ * **`changed_my_mind` was withdrawn on DAZN's instruction**, and this is a documented
3526
+ * departure from the frame rather than a drift from it. It stays available on
3527
+ * the CANCEL sheet, where it is the commonest honest answer; on a return it is the one
3528
+ * reason that says nothing a warehouse or a buyer can act on.
3529
+ *
3530
+ * Narrowing what a fan may send is the whole point, so this is the enum the request
3531
+ * validates against. Reading a return already recorded is a different question — see
3532
+ * {@link RecordedReturnReason}.
3533
+ */
3534
+ declare const FanReturnReason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described"]>;
3523
3535
 
3524
3536
  declare type FanReturnReason = z.infer<typeof FanReturnReason>;
3525
3537
 
@@ -5276,6 +5288,12 @@ export declare function resolveSku(variants: ProductVariant[], size: string | nu
5276
5288
  * Ordered by how often a fan picks them rather than alphabetically, which is the design's
5277
5289
  * choice and not ours to re-sort: the two sizing reasons lead because sizing is what most
5278
5290
  * clothing returns are about.
5291
+ *
5292
+ * **Five, not the frame's six.** `changed_my_mind` was withdrawn on DAZN's instruction —
5293
+ * a documented departure, not a drift. It stays on the CANCEL sheet, where it
5294
+ * is the commonest honest answer; on a return it is the one reason that tells neither the
5295
+ * warehouse nor the buyer anything they can act on. Returns already reported under it are
5296
+ * unaffected and still read — the contract keeps it as a recorded value.
5279
5297
  */
5280
5298
  export declare const RETURN_REASONS: readonly ReasonOption<FanReturnReason>[];
5281
5299
 
@@ -5539,14 +5557,14 @@ export declare interface ReturnLabelViewProps {
5539
5557
  declare const ReturnRequestItem: z.ZodObject<{
5540
5558
  line_ref: z.ZodString;
5541
5559
  qty: z.ZodNumber;
5542
- reason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]>;
5560
+ reason: z.ZodEnum<["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described"]>;
5543
5561
  }, "strip", z.ZodTypeAny, {
5544
5562
  qty: number;
5545
- reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5563
+ reason: "too_small" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5546
5564
  line_ref: string;
5547
5565
  }, {
5548
5566
  qty: number;
5549
- reason: "too_small" | "changed_my_mind" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5567
+ reason: "too_small" | "too_large" | "arrived_too_late" | "item_damaged" | "not_as_described";
5550
5568
  line_ref: string;
5551
5569
  }>;
5552
5570
 
package/dist/index.mjs CHANGED
@@ -4695,7 +4695,7 @@ function requireOrderTracking() {
4695
4695
  Object.defineProperty(exports, "__esModule", {
4696
4696
  value: true
4697
4697
  });
4698
- exports.ReturnDetail = exports.ReturnItem = exports.ReturnProgressEntry = exports.CreateReturnRequest = exports.ReturnRequestItem = exports.FanReturnReason = exports.RequestCancellationRequest = exports.FanCancelReason = exports.OrderDetail = exports.ReturnSummary = exports.OrderList = exports.ReturnSummaryItem = exports.OrderSummaryItem = exports.ReturnOutcome = exports.ReturnStatus = exports.OrderItem = exports.OrderTracking = exports.OrderProgressEntry = exports.OrderProgressStep = void 0;
4698
+ exports.ReturnDetail = exports.ReturnItem = exports.ReturnProgressEntry = exports.CreateReturnRequest = exports.ReturnRequestItem = exports.RecordedReturnReason = exports.FanReturnReason = exports.RequestCancellationRequest = exports.FanCancelReason = exports.OrderDetail = exports.ReturnSummary = exports.OrderList = exports.ReturnSummaryItem = exports.OrderSummaryItem = exports.ReturnOutcome = exports.ReturnStatus = exports.OrderItem = exports.OrderTracking = exports.OrderProgressEntry = exports.OrderProgressStep = void 0;
4699
4699
  const zod_1 = requireZod();
4700
4700
  const money_1 = requireMoney();
4701
4701
  const ids_1 = requireIds();
@@ -4786,7 +4786,8 @@ function requireOrderTracking() {
4786
4786
  exports.RequestCancellationRequest = zod_1.z.object({
4787
4787
  reason: exports.FanCancelReason
4788
4788
  }).strict();
4789
- exports.FanReturnReason = zod_1.z.enum(["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]);
4789
+ exports.FanReturnReason = zod_1.z.enum(["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described"]);
4790
+ exports.RecordedReturnReason = zod_1.z.enum([...exports.FanReturnReason.options, "changed_my_mind"]);
4790
4791
  exports.ReturnRequestItem = zod_1.z.object({
4791
4792
  line_ref: zod_1.z.string().min(1),
4792
4793
  qty: zod_1.z.number().int().positive(),
@@ -4805,7 +4806,7 @@ function requireOrderTracking() {
4805
4806
  line_ref: zod_1.z.string().min(1),
4806
4807
  sku: common_1.Sku,
4807
4808
  qty: zod_1.z.number().int().positive(),
4808
- reason: exports.FanReturnReason,
4809
+ reason: exports.RecordedReturnReason,
4809
4810
  unit_price: money_1.Money,
4810
4811
  compare_at_unit_price: money_1.Money.optional(),
4811
4812
  title: zod_1.z.string().optional(),
@@ -5188,6 +5189,60 @@ function requireClient() {
5188
5189
  return client;
5189
5190
  }
5190
5191
  var clientExports = requireClient();
5192
+ const TOP = {
5193
+ doc: 0,
5194
+ pane: 0
5195
+ };
5196
+ const places = /* @__PURE__ */ new Map();
5197
+ let returnedTo = null;
5198
+ function here() {
5199
+ if (typeof window === "undefined") return "";
5200
+ const { pathname, search, hash } = window.location;
5201
+ return pathname + search + hash;
5202
+ }
5203
+ if (typeof window !== "undefined") {
5204
+ window.addEventListener("popstate", () => {
5205
+ returnedTo = here();
5206
+ }, {
5207
+ capture: true
5208
+ });
5209
+ }
5210
+ function cameBack() {
5211
+ return returnedTo !== null && returnedTo === here();
5212
+ }
5213
+ function returnOffset(key) {
5214
+ if (!cameBack() || returnedTo !== key) return null;
5215
+ return places.get(key) ?? null;
5216
+ }
5217
+ function settleReturn() {
5218
+ returnedTo = null;
5219
+ }
5220
+ function remember(key, offset) {
5221
+ places.set(key, offset);
5222
+ }
5223
+ let latestScreen = 0;
5224
+ let currentScreen = 0;
5225
+ function claimScreen() {
5226
+ latestScreen += 1;
5227
+ currentScreen = latestScreen;
5228
+ return currentScreen;
5229
+ }
5230
+ function leaveScreen() {
5231
+ currentScreen = 0;
5232
+ settleReturn();
5233
+ }
5234
+ function isCurrentScreen(screen2) {
5235
+ return screen2 === currentScreen;
5236
+ }
5237
+ function placeOf(pane) {
5238
+ return {
5239
+ doc: window.scrollY || document.documentElement.scrollTop || 0,
5240
+ pane: pane ? pane.scrollTop : 0
5241
+ };
5242
+ }
5243
+ function reached(now, at) {
5244
+ return Math.abs(now.doc - at.doc) <= 1 && Math.abs(now.pane - at.pane) <= 1;
5245
+ }
5191
5246
  const HOLD_MS = 2500;
5192
5247
  function withoutRestoration() {
5193
5248
  const history = typeof window !== "undefined" ? window.history : void 0;
@@ -5200,11 +5255,14 @@ function withoutRestoration() {
5200
5255
  };
5201
5256
  }
5202
5257
  function scrollToTop(box2) {
5258
+ scrollToOffset(0, box2);
5259
+ }
5260
+ function scrollToOffset(offset, box2) {
5203
5261
  const target = box2 ?? document.documentElement;
5204
5262
  const behaviour = target.style.scrollBehavior;
5205
5263
  target.style.scrollBehavior = "auto";
5206
- if (box2) box2.scrollTop = 0;
5207
- else window.scrollTo(0, 0);
5264
+ if (box2) box2.scrollTop = offset;
5265
+ else window.scrollTo(0, offset);
5208
5266
  target.style.scrollBehavior = behaviour;
5209
5267
  }
5210
5268
  function scrollerOf(el) {
@@ -5230,17 +5288,20 @@ const holds = /* @__PURE__ */ new Set();
5230
5288
  function releaseHolds() {
5231
5289
  for (const end2 of Array.from(holds)) end2();
5232
5290
  }
5233
- function anchorTop(onMoved = () => true, onEnd, box2 = null) {
5291
+ function anchorTop(onMoved = () => true, onEnd, box2 = null, at = TOP) {
5234
5292
  let released = false;
5235
5293
  let touching = false;
5236
5294
  const top2 = () => {
5237
5295
  if (released || touching) return;
5238
5296
  const document_ = window.scrollY || document.documentElement.scrollTop || 0;
5239
5297
  const pane = box2 ? box2.scrollTop : 0;
5240
- if (document_ <= 0 && pane <= 0) return;
5298
+ const off = (now, want) => want === 0 ? now > 0 : Math.abs(now - want) > 1;
5299
+ const documentOff = off(document_, at.doc);
5300
+ const paneOff = box2 !== null && off(pane, at.pane);
5301
+ if (!documentOff && !paneOff) return;
5241
5302
  if (!onMoved()) return;
5242
- if (document_ > 0) scrollToTop();
5243
- if (box2 && pane > 0) scrollToTop(box2);
5303
+ if (documentOff) scrollToOffset(at.doc);
5304
+ if (box2 && paneOff) scrollToOffset(at.pane, box2);
5244
5305
  };
5245
5306
  const down = (event) => {
5246
5307
  if (event.type !== "pointerdown" || event.pointerType === "touch") {
@@ -5320,6 +5381,7 @@ function onResize(el, resized) {
5320
5381
  }
5321
5382
  function anchorToTop() {
5322
5383
  if (typeof window === "undefined") return;
5384
+ leaveScreen();
5323
5385
  const top2 = () => scrollToTop();
5324
5386
  top2();
5325
5387
  if (typeof window.requestAnimationFrame === "function") window.requestAnimationFrame(top2);
@@ -5728,7 +5790,7 @@ const neutral$2 = "_neutral_1bagf_12";
5728
5790
  const success$1 = "_success_1bagf_17";
5729
5791
  const critical$2 = "_critical_1bagf_22";
5730
5792
  const promo = "_promo_1bagf_27";
5731
- const styles$R = {
5793
+ const styles$S = {
5732
5794
  badge: badge$5,
5733
5795
  neutral: neutral$2,
5734
5796
  success: success$1,
@@ -5737,39 +5799,42 @@ const styles$R = {
5737
5799
  };
5738
5800
  function Badge({ tone = "neutral", children }) {
5739
5801
  return jsx("span", {
5740
- className: [styles$R.badge, styles$R[tone]].join(" "),
5802
+ className: [styles$S.badge, styles$S[tone]].join(" "),
5741
5803
  children
5742
5804
  });
5743
5805
  }
5744
- const button$1 = "_button_17pvl_1";
5745
- const fullWidth = "_fullWidth_17pvl_25";
5746
- const primary = "_primary_17pvl_29";
5747
- const secondary = "_secondary_17pvl_34";
5748
- const ghost = "_ghost_17pvl_40";
5749
- const spinner = "_spinner_17pvl_83";
5750
- const spin = "_spin_17pvl_83";
5751
- const styles$Q = {
5806
+ const button$1 = "_button_ci424_1";
5807
+ const fullWidth = "_fullWidth_ci424_25";
5808
+ const primary = "_primary_ci424_29";
5809
+ const secondary = "_secondary_ci424_34";
5810
+ const ghost = "_ghost_ci424_40";
5811
+ const styles$R = {
5752
5812
  button: button$1,
5753
5813
  fullWidth,
5754
5814
  primary,
5755
5815
  secondary,
5756
- ghost,
5757
- spinner,
5758
- spin
5816
+ ghost
5817
+ };
5818
+ const spinner = "_spinner_1rueh_5";
5819
+ const styles$Q = {
5820
+ spinner
5759
5821
  };
5822
+ function Spinner({ className }) {
5823
+ return jsx("span", {
5824
+ className: [styles$Q.spinner, className ?? ""].filter(Boolean).join(" "),
5825
+ "aria-hidden": "true"
5826
+ });
5827
+ }
5760
5828
  const Button = forwardRef(function Button2({ variant = "primary", loading = false, fullWidth: fullWidth2 = false, disabled: disabled2, children, className, type = "button", ...rest }, ref) {
5761
5829
  const isDisabled = disabled2 || loading;
5762
5830
  return jsxs("button", {
5763
5831
  ref,
5764
5832
  type,
5765
- className: [styles$Q.button, styles$Q[variant], fullWidth2 ? styles$Q.fullWidth : "", className ?? ""].filter(Boolean).join(" "),
5833
+ className: [styles$R.button, styles$R[variant], fullWidth2 ? styles$R.fullWidth : "", className ?? ""].filter(Boolean).join(" "),
5766
5834
  disabled: isDisabled,
5767
5835
  "aria-busy": loading || void 0,
5768
5836
  ...rest,
5769
- children: [loading && jsx("span", {
5770
- className: styles$Q.spinner,
5771
- "aria-hidden": "true"
5772
- }), jsx("span", {
5837
+ children: [loading && jsx(Spinner, {}), jsx("span", {
5773
5838
  children
5774
5839
  })]
5775
5840
  });
@@ -5863,22 +5928,62 @@ function useScreenAnchor(ref, enabled = true) {
5863
5928
  if (!el || !enabled) return;
5864
5929
  const restore = withoutRestoration();
5865
5930
  let moved = false;
5866
- const hold = () => anchorTop(() => beginsOnTheFirstViewport(el), (end2) => {
5867
- if (end2 === "moved") moved = true;
5868
- }, scrollerOf(el));
5869
- let release = hold();
5870
- const again = () => {
5931
+ let holding = false;
5932
+ let returning = false;
5933
+ let at = TOP;
5934
+ const settle = () => {
5935
+ returning = false;
5936
+ settleReturn();
5937
+ };
5938
+ const hold = (entered) => {
5939
+ if (entered) {
5940
+ const back = returnOffset(here());
5941
+ returning = back !== null;
5942
+ at = back ?? TOP;
5943
+ }
5944
+ holding = true;
5945
+ return anchorTop(() => beginsOnTheFirstViewport(el), (end2) => {
5946
+ holding = false;
5947
+ if (end2 === "moved") moved = true;
5948
+ if (returning && end2 === "moved") settle();
5949
+ }, scrollerOf(el), at);
5950
+ };
5951
+ let screen2 = claimScreen();
5952
+ let release = hold(true);
5953
+ const again = (entered) => {
5871
5954
  release();
5872
- release = hold();
5955
+ release = hold(entered);
5873
5956
  };
5874
5957
  const unobserve = onReveal(el, () => {
5875
5958
  moved = false;
5876
- again();
5959
+ screen2 = claimScreen();
5960
+ again(true);
5877
5961
  });
5878
5962
  const settled = onResize(el, () => {
5879
- if (!moved) again();
5963
+ if (!moved) again(false);
5964
+ });
5965
+ const fan = (event) => {
5966
+ if (movesThePage(event)) moved = true;
5967
+ };
5968
+ for (const type of RELEASES) window.addEventListener(type, fan, {
5969
+ passive: true
5970
+ });
5971
+ const note2 = () => {
5972
+ if (!isCurrentScreen(screen2)) return;
5973
+ const now = placeOf(scrollerOf(el));
5974
+ if (returning && reached(now, at)) settle();
5975
+ if (holding) return;
5976
+ remember(here(), now);
5977
+ };
5978
+ document.addEventListener("scroll", note2, {
5979
+ capture: true,
5980
+ passive: true
5880
5981
  });
5881
5982
  return () => {
5983
+ for (const type of RELEASES) window.removeEventListener(type, fan);
5984
+ document.removeEventListener("scroll", note2, {
5985
+ capture: true
5986
+ });
5882
5987
  settled();
5883
5988
  unobserve();
5884
5989
  release();
@@ -6160,6 +6265,7 @@ const ES = {
6160
6265
  "Your items will show up here once you've added to your cart.": "Sus artículos aparecerán aquí cuando los añada a la cesta.",
6161
6266
  "Complete your DAZN sign-up to check out. Your cart is saved.": "Complete su registro en DAZN para finalizar la compra. Su cesta está guardada.",
6162
6267
  "Your orders will show up here once you've shopped.": "Sus pedidos aparecerán aquí cuando haya comprado.",
6268
+ "Your return label is not ready yet. Try again in a moment.": "Tu etiqueta de devolución todavía no está lista. Vuelve a intentarlo dentro de un momento.",
6163
6269
  "We'll let you know": "Le avisaremos",
6164
6270
  "{0} — as soon as it is back": "{0} — en cuanto vuelva a estar disponible",
6165
6271
  "Size {0}": "Talla {0}",
@@ -7583,9 +7689,6 @@ const RETURN_REASONS = [{
7583
7689
  }, {
7584
7690
  value: "not_as_described",
7585
7691
  label: "Item doesn't match description"
7586
- }, {
7587
- value: "changed_my_mind",
7588
- label: "Changed my mind"
7589
7692
  }];
7590
7693
  const REASON_LABEL = new Map(RETURN_REASONS.map((r) => [r.value, r.label]));
7591
7694
  function unitsLeft(item2) {
@@ -7746,8 +7849,61 @@ const styles$A = {
7746
7849
  download,
7747
7850
  note: note$1
7748
7851
  };
7852
+ const PREPARE_TIMEOUT_MS = 6e4;
7853
+ function useLabelDownload(labelUrl) {
7854
+ const [preparing, setPreparing] = useState(false);
7855
+ const [unavailable, setUnavailable] = useState(false);
7856
+ const [ready, setReady] = useState(false);
7857
+ const live = useRef(true);
7858
+ useEffect(() => {
7859
+ live.current = true;
7860
+ return () => {
7861
+ live.current = false;
7862
+ };
7863
+ }, []);
7864
+ const onDownload = useCallback((event) => {
7865
+ if (!labelUrl || ready) return;
7866
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) {
7867
+ return;
7868
+ }
7869
+ event.preventDefault();
7870
+ if (preparing) return;
7871
+ setUnavailable(false);
7872
+ setPreparing(true);
7873
+ const until = Date.now() + PREPARE_TIMEOUT_MS;
7874
+ void (async () => {
7875
+ for (; ; ) {
7876
+ let ok = false;
7877
+ try {
7878
+ ok = (await fetch(labelUrl, {
7879
+ method: "HEAD"
7880
+ })).ok;
7881
+ } catch {
7882
+ }
7883
+ if (!live.current) return;
7884
+ if (ok) {
7885
+ setPreparing(false);
7886
+ setReady(true);
7887
+ window.location.href = labelUrl;
7888
+ return;
7889
+ }
7890
+ if (Date.now() >= until) break;
7891
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
7892
+ if (!live.current) return;
7893
+ }
7894
+ setPreparing(false);
7895
+ setUnavailable(true);
7896
+ })();
7897
+ }, [labelUrl, preparing, ready]);
7898
+ return {
7899
+ preparing,
7900
+ unavailable,
7901
+ onDownload
7902
+ };
7903
+ }
7749
7904
  function ReturnLabelView({ ret, onDone }) {
7750
7905
  const t = useT();
7906
+ const { preparing, unavailable, onDownload } = useLabelDownload(ret.label_url);
7751
7907
  return jsxs("div", {
7752
7908
  className: styles$A.page,
7753
7909
  children: [jsxs("div", {
@@ -7788,10 +7944,17 @@ function ReturnLabelView({ ret, onDone }) {
7788
7944
  href: ret.label_url,
7789
7945
  target: "_blank",
7790
7946
  rel: "noopener noreferrer",
7791
- children: [t("Download return label"), jsx("span", {
7947
+ onClick: onDownload,
7948
+ "aria-busy": preparing || void 0,
7949
+ "aria-disabled": preparing || void 0,
7950
+ children: [preparing && jsx(Spinner, {}), t("Download return label"), jsx("span", {
7792
7951
  className: "visually-hidden",
7793
7952
  children: ` ${t("(opens in a new tab)")}`
7794
7953
  })]
7954
+ }), unavailable && jsx("p", {
7955
+ className: styles$A.note,
7956
+ role: "status",
7957
+ children: t("Your return label is not ready yet. Try again in a moment.")
7795
7958
  }), ret.label_email && jsxs("p", {
7796
7959
  className: styles$A.note,
7797
7960
  children: [t("You’ll receive a shipping label PDF to your email as well."), jsx("br", {}), ret.label_email]
@@ -8150,7 +8313,7 @@ function OrderTrackingContent({ orderRef, locale: localeProp, onStartReturn, onO
8150
8313
  useEffect(() => {
8151
8314
  void load();
8152
8315
  }, [load]);
8153
- const cancelled = order?.status === "cancelled";
8316
+ const cancelled = state === "ready" && order?.status === "cancelled";
8154
8317
  const cancelledPage = useRef(null);
8155
8318
  useBrowserLayoutEffect(() => {
8156
8319
  if (!cancelled) return;
@@ -8784,6 +8947,7 @@ function ReturnCard({ ret, locale, onOpen }) {
8784
8947
  });
8785
8948
  }
8786
8949
  function ReturnThumbnails({ ret }) {
8950
+ const t = useT();
8787
8951
  const images = ret.images ?? [];
8788
8952
  const hidden = ret.item_count - TILES + 1;
8789
8953
  const overflow = images.length >= TILES && hidden > 1 ? hidden : 0;
@@ -8815,7 +8979,7 @@ function ReturnThumbnails({ ret }) {
8815
8979
  children: ["+", overflow]
8816
8980
  }), jsx("span", {
8817
8981
  className: "visually-hidden",
8818
- children: `and ${overflow} more items`
8982
+ children: t("and {0} more items", overflow)
8819
8983
  })]
8820
8984
  })]
8821
8985
  }, `${src}-${i}`);
@@ -8823,6 +8987,7 @@ function ReturnThumbnails({ ret }) {
8823
8987
  });
8824
8988
  }
8825
8989
  function OrderCard({ order, locale, onOpen }) {
8990
+ const t = useT();
8826
8991
  const body3 = jsxs(Fragment, {
8827
8992
  children: [jsxs("div", {
8828
8993
  className: styles$v.head,
@@ -8830,7 +8995,7 @@ function OrderCard({ order, locale, onOpen }) {
8830
8995
  className: styles$v.heading,
8831
8996
  children: [jsx("span", {
8832
8997
  className: styles$v.title,
8833
- children: `Order #${shortRef(order.order_ref)}`
8998
+ children: t("Order #{0}", shortRef(order.order_ref))
8834
8999
  }), jsx("span", {
8835
9000
  className: styles$v.date,
8836
9001
  children: formatPlaced(order.placed_at, locale)
@@ -8861,6 +9026,7 @@ function OrderCard({ order, locale, onOpen }) {
8861
9026
  });
8862
9027
  }
8863
9028
  function Thumbnails({ order }) {
9029
+ const t = useT();
8864
9030
  const images = order.images ?? (order.image ? [order.image] : []);
8865
9031
  const hidden = order.item_count - TILES + 1;
8866
9032
  const overflow = images.length >= TILES && hidden > 1 ? hidden : 0;
@@ -8892,7 +9058,7 @@ function Thumbnails({ order }) {
8892
9058
  children: ["+", overflow]
8893
9059
  }), jsx("span", {
8894
9060
  className: "visually-hidden",
8895
- children: `and ${overflow} more items`
9061
+ children: t("and {0} more items", overflow)
8896
9062
  })]
8897
9063
  })]
8898
9064
  }, `${src}-${i}`);
@@ -10480,7 +10646,7 @@ function ColorSelector({ colours, selected: selected2, onSelect }) {
10480
10646
  }), lowStock2 && jsx("span", {
10481
10647
  className: styles$f.stockBadge,
10482
10648
  "aria-hidden": "true",
10483
- children: `${c.remaining} left`
10649
+ children: t("{0} left", c.remaining)
10484
10650
  })]
10485
10651
  }, c.value);
10486
10652
  })
@@ -11593,15 +11759,26 @@ function useDocumentSnap(ref, enabled = true) {
11593
11759
  passive: true
11594
11760
  });
11595
11761
  };
11762
+ let at = TOP;
11763
+ let returning = false;
11764
+ let holding = false;
11765
+ const settle = () => {
11766
+ returning = false;
11767
+ settleReturn();
11768
+ };
11596
11769
  const top2 = () => {
11597
- scrollToTop();
11598
- if (pane) scrollToTop(pane);
11770
+ scrollToOffset(at.doc);
11771
+ if (pane) scrollToOffset(at.pane, pane);
11599
11772
  };
11600
11773
  let frame2 = null;
11601
11774
  let release = () => {
11602
11775
  };
11603
11776
  const anchor2 = () => {
11604
11777
  release();
11778
+ const back = returnOffset(here());
11779
+ returning = back !== null;
11780
+ at = back ?? TOP;
11781
+ holding = true;
11605
11782
  if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
11606
11783
  window.cancelAnimationFrame(frame2);
11607
11784
  }
@@ -11617,18 +11794,42 @@ function useDocumentSnap(ref, enabled = true) {
11617
11794
  snapOnAtTouch();
11618
11795
  }
11619
11796
  return true;
11620
- }, void 0, pane);
11797
+ }, (end2) => {
11798
+ holding = false;
11799
+ if (returning && end2 === "moved") settle();
11800
+ }, pane, at);
11621
11801
  };
11802
+ let screen2 = claimScreen();
11622
11803
  anchor2();
11623
11804
  const history = window.history;
11624
11805
  const previousRestoration = history && "scrollRestoration" in history ? history.scrollRestoration : null;
11625
11806
  if (previousRestoration !== null) history.scrollRestoration = "manual";
11626
11807
  const onPageShow = (event) => {
11627
- if (event.persisted) anchor2();
11808
+ if (event.persisted) {
11809
+ screen2 = claimScreen();
11810
+ anchor2();
11811
+ }
11628
11812
  };
11629
11813
  window.addEventListener("pageshow", onPageShow);
11630
- const unobserve = onReveal(el, anchor2);
11814
+ const unobserve = onReveal(el, () => {
11815
+ screen2 = claimScreen();
11816
+ anchor2();
11817
+ });
11818
+ const note2 = () => {
11819
+ if (!isCurrentScreen(screen2)) return;
11820
+ const now = placeOf(pane);
11821
+ if (returning && reached(now, at)) settle();
11822
+ if (holding) return;
11823
+ remember(here(), now);
11824
+ };
11825
+ document.addEventListener("scroll", note2, {
11826
+ capture: true,
11827
+ passive: true
11828
+ });
11631
11829
  return () => {
11830
+ document.removeEventListener("scroll", note2, {
11831
+ capture: true
11832
+ });
11632
11833
  unobserve();
11633
11834
  release();
11634
11835
  if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
@@ -4695,7 +4695,7 @@ function requireOrderTracking() {
4695
4695
  Object.defineProperty(exports, "__esModule", {
4696
4696
  value: true
4697
4697
  });
4698
- exports.ReturnDetail = exports.ReturnItem = exports.ReturnProgressEntry = exports.CreateReturnRequest = exports.ReturnRequestItem = exports.FanReturnReason = exports.RequestCancellationRequest = exports.FanCancelReason = exports.OrderDetail = exports.ReturnSummary = exports.OrderList = exports.ReturnSummaryItem = exports.OrderSummaryItem = exports.ReturnOutcome = exports.ReturnStatus = exports.OrderItem = exports.OrderTracking = exports.OrderProgressEntry = exports.OrderProgressStep = void 0;
4698
+ exports.ReturnDetail = exports.ReturnItem = exports.ReturnProgressEntry = exports.CreateReturnRequest = exports.ReturnRequestItem = exports.RecordedReturnReason = exports.FanReturnReason = exports.RequestCancellationRequest = exports.FanCancelReason = exports.OrderDetail = exports.ReturnSummary = exports.OrderList = exports.ReturnSummaryItem = exports.OrderSummaryItem = exports.ReturnOutcome = exports.ReturnStatus = exports.OrderItem = exports.OrderTracking = exports.OrderProgressEntry = exports.OrderProgressStep = void 0;
4699
4699
  const zod_1 = requireZod();
4700
4700
  const money_1 = requireMoney();
4701
4701
  const ids_1 = requireIds();
@@ -4786,7 +4786,8 @@ function requireOrderTracking() {
4786
4786
  exports.RequestCancellationRequest = zod_1.z.object({
4787
4787
  reason: exports.FanCancelReason
4788
4788
  }).strict();
4789
- exports.FanReturnReason = zod_1.z.enum(["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described", "changed_my_mind"]);
4789
+ exports.FanReturnReason = zod_1.z.enum(["too_large", "too_small", "arrived_too_late", "item_damaged", "not_as_described"]);
4790
+ exports.RecordedReturnReason = zod_1.z.enum([...exports.FanReturnReason.options, "changed_my_mind"]);
4790
4791
  exports.ReturnRequestItem = zod_1.z.object({
4791
4792
  line_ref: zod_1.z.string().min(1),
4792
4793
  qty: zod_1.z.number().int().positive(),
@@ -4805,7 +4806,7 @@ function requireOrderTracking() {
4805
4806
  line_ref: zod_1.z.string().min(1),
4806
4807
  sku: common_1.Sku,
4807
4808
  qty: zod_1.z.number().int().positive(),
4808
- reason: exports.FanReturnReason,
4809
+ reason: exports.RecordedReturnReason,
4809
4810
  unit_price: money_1.Money,
4810
4811
  compare_at_unit_price: money_1.Money.optional(),
4811
4812
  title: zod_1.z.string().optional(),
@@ -5188,6 +5189,60 @@ function requireClient() {
5188
5189
  return client;
5189
5190
  }
5190
5191
  var clientExports = requireClient();
5192
+ const TOP = {
5193
+ doc: 0,
5194
+ pane: 0
5195
+ };
5196
+ const places = /* @__PURE__ */ new Map();
5197
+ let returnedTo = null;
5198
+ function here() {
5199
+ if (typeof window === "undefined") return "";
5200
+ const { pathname, search, hash } = window.location;
5201
+ return pathname + search + hash;
5202
+ }
5203
+ if (typeof window !== "undefined") {
5204
+ window.addEventListener("popstate", () => {
5205
+ returnedTo = here();
5206
+ }, {
5207
+ capture: true
5208
+ });
5209
+ }
5210
+ function cameBack() {
5211
+ return returnedTo !== null && returnedTo === here();
5212
+ }
5213
+ function returnOffset(key) {
5214
+ if (!cameBack() || returnedTo !== key) return null;
5215
+ return places.get(key) ?? null;
5216
+ }
5217
+ function settleReturn() {
5218
+ returnedTo = null;
5219
+ }
5220
+ function remember(key, offset) {
5221
+ places.set(key, offset);
5222
+ }
5223
+ let latestScreen = 0;
5224
+ let currentScreen = 0;
5225
+ function claimScreen() {
5226
+ latestScreen += 1;
5227
+ currentScreen = latestScreen;
5228
+ return currentScreen;
5229
+ }
5230
+ function leaveScreen() {
5231
+ currentScreen = 0;
5232
+ settleReturn();
5233
+ }
5234
+ function isCurrentScreen(screen2) {
5235
+ return screen2 === currentScreen;
5236
+ }
5237
+ function placeOf(pane) {
5238
+ return {
5239
+ doc: window.scrollY || document.documentElement.scrollTop || 0,
5240
+ pane: pane ? pane.scrollTop : 0
5241
+ };
5242
+ }
5243
+ function reached(now, at) {
5244
+ return Math.abs(now.doc - at.doc) <= 1 && Math.abs(now.pane - at.pane) <= 1;
5245
+ }
5191
5246
  const HOLD_MS = 2500;
5192
5247
  function withoutRestoration() {
5193
5248
  const history = typeof window !== "undefined" ? window.history : void 0;
@@ -5200,11 +5255,14 @@ function withoutRestoration() {
5200
5255
  };
5201
5256
  }
5202
5257
  function scrollToTop(box2) {
5258
+ scrollToOffset(0, box2);
5259
+ }
5260
+ function scrollToOffset(offset, box2) {
5203
5261
  const target = box2 ?? document.documentElement;
5204
5262
  const behaviour = target.style.scrollBehavior;
5205
5263
  target.style.scrollBehavior = "auto";
5206
- if (box2) box2.scrollTop = 0;
5207
- else window.scrollTo(0, 0);
5264
+ if (box2) box2.scrollTop = offset;
5265
+ else window.scrollTo(0, offset);
5208
5266
  target.style.scrollBehavior = behaviour;
5209
5267
  }
5210
5268
  function scrollerOf(el) {
@@ -5230,17 +5288,20 @@ const holds = /* @__PURE__ */ new Set();
5230
5288
  function releaseHolds() {
5231
5289
  for (const end2 of Array.from(holds)) end2();
5232
5290
  }
5233
- function anchorTop(onMoved = () => true, onEnd, box2 = null) {
5291
+ function anchorTop(onMoved = () => true, onEnd, box2 = null, at = TOP) {
5234
5292
  let released = false;
5235
5293
  let touching = false;
5236
5294
  const top2 = () => {
5237
5295
  if (released || touching) return;
5238
5296
  const document_ = window.scrollY || document.documentElement.scrollTop || 0;
5239
5297
  const pane = box2 ? box2.scrollTop : 0;
5240
- if (document_ <= 0 && pane <= 0) return;
5298
+ const off = (now, want) => want === 0 ? now > 0 : Math.abs(now - want) > 1;
5299
+ const documentOff = off(document_, at.doc);
5300
+ const paneOff = box2 !== null && off(pane, at.pane);
5301
+ if (!documentOff && !paneOff) return;
5241
5302
  if (!onMoved()) return;
5242
- if (document_ > 0) scrollToTop();
5243
- if (box2 && pane > 0) scrollToTop(box2);
5303
+ if (documentOff) scrollToOffset(at.doc);
5304
+ if (box2 && paneOff) scrollToOffset(at.pane, box2);
5244
5305
  };
5245
5306
  const down = (event) => {
5246
5307
  if (event.type !== "pointerdown" || event.pointerType === "touch") {
@@ -5320,6 +5381,7 @@ function onResize(el, resized) {
5320
5381
  }
5321
5382
  function anchorToTop() {
5322
5383
  if (typeof window === "undefined") return;
5384
+ leaveScreen();
5323
5385
  const top2 = () => scrollToTop();
5324
5386
  top2();
5325
5387
  if (typeof window.requestAnimationFrame === "function") window.requestAnimationFrame(top2);
@@ -5728,7 +5790,7 @@ const neutral$2 = "_neutral_1bagf_12";
5728
5790
  const success$1 = "_success_1bagf_17";
5729
5791
  const critical$2 = "_critical_1bagf_22";
5730
5792
  const promo = "_promo_1bagf_27";
5731
- const styles$R = {
5793
+ const styles$S = {
5732
5794
  badge: badge$5,
5733
5795
  neutral: neutral$2,
5734
5796
  success: success$1,
@@ -5737,39 +5799,42 @@ const styles$R = {
5737
5799
  };
5738
5800
  function Badge({ tone = "neutral", children }) {
5739
5801
  return jsx("span", {
5740
- className: [styles$R.badge, styles$R[tone]].join(" "),
5802
+ className: [styles$S.badge, styles$S[tone]].join(" "),
5741
5803
  children
5742
5804
  });
5743
5805
  }
5744
- const button$1 = "_button_17pvl_1";
5745
- const fullWidth = "_fullWidth_17pvl_25";
5746
- const primary = "_primary_17pvl_29";
5747
- const secondary = "_secondary_17pvl_34";
5748
- const ghost = "_ghost_17pvl_40";
5749
- const spinner = "_spinner_17pvl_83";
5750
- const spin = "_spin_17pvl_83";
5751
- const styles$Q = {
5806
+ const button$1 = "_button_ci424_1";
5807
+ const fullWidth = "_fullWidth_ci424_25";
5808
+ const primary = "_primary_ci424_29";
5809
+ const secondary = "_secondary_ci424_34";
5810
+ const ghost = "_ghost_ci424_40";
5811
+ const styles$R = {
5752
5812
  button: button$1,
5753
5813
  fullWidth,
5754
5814
  primary,
5755
5815
  secondary,
5756
- ghost,
5757
- spinner,
5758
- spin
5816
+ ghost
5817
+ };
5818
+ const spinner = "_spinner_1rueh_5";
5819
+ const styles$Q = {
5820
+ spinner
5759
5821
  };
5822
+ function Spinner({ className }) {
5823
+ return jsx("span", {
5824
+ className: [styles$Q.spinner, className ?? ""].filter(Boolean).join(" "),
5825
+ "aria-hidden": "true"
5826
+ });
5827
+ }
5760
5828
  const Button = forwardRef(function Button2({ variant = "primary", loading = false, fullWidth: fullWidth2 = false, disabled: disabled2, children, className, type = "button", ...rest }, ref) {
5761
5829
  const isDisabled = disabled2 || loading;
5762
5830
  return jsxs("button", {
5763
5831
  ref,
5764
5832
  type,
5765
- className: [styles$Q.button, styles$Q[variant], fullWidth2 ? styles$Q.fullWidth : "", className ?? ""].filter(Boolean).join(" "),
5833
+ className: [styles$R.button, styles$R[variant], fullWidth2 ? styles$R.fullWidth : "", className ?? ""].filter(Boolean).join(" "),
5766
5834
  disabled: isDisabled,
5767
5835
  "aria-busy": loading || void 0,
5768
5836
  ...rest,
5769
- children: [loading && jsx("span", {
5770
- className: styles$Q.spinner,
5771
- "aria-hidden": "true"
5772
- }), jsx("span", {
5837
+ children: [loading && jsx(Spinner, {}), jsx("span", {
5773
5838
  children
5774
5839
  })]
5775
5840
  });
@@ -5863,22 +5928,62 @@ function useScreenAnchor(ref, enabled = true) {
5863
5928
  if (!el || !enabled) return;
5864
5929
  const restore = withoutRestoration();
5865
5930
  let moved = false;
5866
- const hold = () => anchorTop(() => beginsOnTheFirstViewport(el), (end2) => {
5867
- if (end2 === "moved") moved = true;
5868
- }, scrollerOf(el));
5869
- let release = hold();
5870
- const again = () => {
5931
+ let holding = false;
5932
+ let returning = false;
5933
+ let at = TOP;
5934
+ const settle = () => {
5935
+ returning = false;
5936
+ settleReturn();
5937
+ };
5938
+ const hold = (entered) => {
5939
+ if (entered) {
5940
+ const back = returnOffset(here());
5941
+ returning = back !== null;
5942
+ at = back ?? TOP;
5943
+ }
5944
+ holding = true;
5945
+ return anchorTop(() => beginsOnTheFirstViewport(el), (end2) => {
5946
+ holding = false;
5947
+ if (end2 === "moved") moved = true;
5948
+ if (returning && end2 === "moved") settle();
5949
+ }, scrollerOf(el), at);
5950
+ };
5951
+ let screen2 = claimScreen();
5952
+ let release = hold(true);
5953
+ const again = (entered) => {
5871
5954
  release();
5872
- release = hold();
5955
+ release = hold(entered);
5873
5956
  };
5874
5957
  const unobserve = onReveal(el, () => {
5875
5958
  moved = false;
5876
- again();
5959
+ screen2 = claimScreen();
5960
+ again(true);
5877
5961
  });
5878
5962
  const settled = onResize(el, () => {
5879
- if (!moved) again();
5963
+ if (!moved) again(false);
5964
+ });
5965
+ const fan = (event) => {
5966
+ if (movesThePage(event)) moved = true;
5967
+ };
5968
+ for (const type of RELEASES) window.addEventListener(type, fan, {
5969
+ passive: true
5970
+ });
5971
+ const note2 = () => {
5972
+ if (!isCurrentScreen(screen2)) return;
5973
+ const now = placeOf(scrollerOf(el));
5974
+ if (returning && reached(now, at)) settle();
5975
+ if (holding) return;
5976
+ remember(here(), now);
5977
+ };
5978
+ document.addEventListener("scroll", note2, {
5979
+ capture: true,
5980
+ passive: true
5880
5981
  });
5881
5982
  return () => {
5983
+ for (const type of RELEASES) window.removeEventListener(type, fan);
5984
+ document.removeEventListener("scroll", note2, {
5985
+ capture: true
5986
+ });
5882
5987
  settled();
5883
5988
  unobserve();
5884
5989
  release();
@@ -6160,6 +6265,7 @@ const ES = {
6160
6265
  "Your items will show up here once you've added to your cart.": "Sus artículos aparecerán aquí cuando los añada a la cesta.",
6161
6266
  "Complete your DAZN sign-up to check out. Your cart is saved.": "Complete su registro en DAZN para finalizar la compra. Su cesta está guardada.",
6162
6267
  "Your orders will show up here once you've shopped.": "Sus pedidos aparecerán aquí cuando haya comprado.",
6268
+ "Your return label is not ready yet. Try again in a moment.": "Tu etiqueta de devolución todavía no está lista. Vuelve a intentarlo dentro de un momento.",
6163
6269
  "We'll let you know": "Le avisaremos",
6164
6270
  "{0} — as soon as it is back": "{0} — en cuanto vuelva a estar disponible",
6165
6271
  "Size {0}": "Talla {0}",
@@ -7583,9 +7689,6 @@ const RETURN_REASONS = [{
7583
7689
  }, {
7584
7690
  value: "not_as_described",
7585
7691
  label: "Item doesn't match description"
7586
- }, {
7587
- value: "changed_my_mind",
7588
- label: "Changed my mind"
7589
7692
  }];
7590
7693
  const REASON_LABEL = new Map(RETURN_REASONS.map((r) => [r.value, r.label]));
7591
7694
  function unitsLeft(item2) {
@@ -7746,8 +7849,61 @@ const styles$A = {
7746
7849
  download,
7747
7850
  note: note$1
7748
7851
  };
7852
+ const PREPARE_TIMEOUT_MS = 6e4;
7853
+ function useLabelDownload(labelUrl) {
7854
+ const [preparing, setPreparing] = useState(false);
7855
+ const [unavailable, setUnavailable] = useState(false);
7856
+ const [ready, setReady] = useState(false);
7857
+ const live = useRef(true);
7858
+ useEffect(() => {
7859
+ live.current = true;
7860
+ return () => {
7861
+ live.current = false;
7862
+ };
7863
+ }, []);
7864
+ const onDownload = useCallback((event) => {
7865
+ if (!labelUrl || ready) return;
7866
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) {
7867
+ return;
7868
+ }
7869
+ event.preventDefault();
7870
+ if (preparing) return;
7871
+ setUnavailable(false);
7872
+ setPreparing(true);
7873
+ const until = Date.now() + PREPARE_TIMEOUT_MS;
7874
+ void (async () => {
7875
+ for (; ; ) {
7876
+ let ok = false;
7877
+ try {
7878
+ ok = (await fetch(labelUrl, {
7879
+ method: "HEAD"
7880
+ })).ok;
7881
+ } catch {
7882
+ }
7883
+ if (!live.current) return;
7884
+ if (ok) {
7885
+ setPreparing(false);
7886
+ setReady(true);
7887
+ window.location.href = labelUrl;
7888
+ return;
7889
+ }
7890
+ if (Date.now() >= until) break;
7891
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
7892
+ if (!live.current) return;
7893
+ }
7894
+ setPreparing(false);
7895
+ setUnavailable(true);
7896
+ })();
7897
+ }, [labelUrl, preparing, ready]);
7898
+ return {
7899
+ preparing,
7900
+ unavailable,
7901
+ onDownload
7902
+ };
7903
+ }
7749
7904
  function ReturnLabelView({ ret, onDone }) {
7750
7905
  const t = useT();
7906
+ const { preparing, unavailable, onDownload } = useLabelDownload(ret.label_url);
7751
7907
  return jsxs("div", {
7752
7908
  className: styles$A.page,
7753
7909
  children: [jsxs("div", {
@@ -7788,10 +7944,17 @@ function ReturnLabelView({ ret, onDone }) {
7788
7944
  href: ret.label_url,
7789
7945
  target: "_blank",
7790
7946
  rel: "noopener noreferrer",
7791
- children: [t("Download return label"), jsx("span", {
7947
+ onClick: onDownload,
7948
+ "aria-busy": preparing || void 0,
7949
+ "aria-disabled": preparing || void 0,
7950
+ children: [preparing && jsx(Spinner, {}), t("Download return label"), jsx("span", {
7792
7951
  className: "visually-hidden",
7793
7952
  children: ` ${t("(opens in a new tab)")}`
7794
7953
  })]
7954
+ }), unavailable && jsx("p", {
7955
+ className: styles$A.note,
7956
+ role: "status",
7957
+ children: t("Your return label is not ready yet. Try again in a moment.")
7795
7958
  }), ret.label_email && jsxs("p", {
7796
7959
  className: styles$A.note,
7797
7960
  children: [t("You’ll receive a shipping label PDF to your email as well."), jsx("br", {}), ret.label_email]
@@ -8150,7 +8313,7 @@ function OrderTrackingContent({ orderRef, locale: localeProp, onStartReturn, onO
8150
8313
  useEffect(() => {
8151
8314
  void load();
8152
8315
  }, [load]);
8153
- const cancelled = order?.status === "cancelled";
8316
+ const cancelled = state === "ready" && order?.status === "cancelled";
8154
8317
  const cancelledPage = useRef(null);
8155
8318
  useBrowserLayoutEffect(() => {
8156
8319
  if (!cancelled) return;
@@ -8784,6 +8947,7 @@ function ReturnCard({ ret, locale, onOpen }) {
8784
8947
  });
8785
8948
  }
8786
8949
  function ReturnThumbnails({ ret }) {
8950
+ const t = useT();
8787
8951
  const images = ret.images ?? [];
8788
8952
  const hidden = ret.item_count - TILES + 1;
8789
8953
  const overflow = images.length >= TILES && hidden > 1 ? hidden : 0;
@@ -8815,7 +8979,7 @@ function ReturnThumbnails({ ret }) {
8815
8979
  children: ["+", overflow]
8816
8980
  }), jsx("span", {
8817
8981
  className: "visually-hidden",
8818
- children: `and ${overflow} more items`
8982
+ children: t("and {0} more items", overflow)
8819
8983
  })]
8820
8984
  })]
8821
8985
  }, `${src}-${i}`);
@@ -8823,6 +8987,7 @@ function ReturnThumbnails({ ret }) {
8823
8987
  });
8824
8988
  }
8825
8989
  function OrderCard({ order, locale, onOpen }) {
8990
+ const t = useT();
8826
8991
  const body3 = jsxs(Fragment, {
8827
8992
  children: [jsxs("div", {
8828
8993
  className: styles$v.head,
@@ -8830,7 +8995,7 @@ function OrderCard({ order, locale, onOpen }) {
8830
8995
  className: styles$v.heading,
8831
8996
  children: [jsx("span", {
8832
8997
  className: styles$v.title,
8833
- children: `Order #${shortRef(order.order_ref)}`
8998
+ children: t("Order #{0}", shortRef(order.order_ref))
8834
8999
  }), jsx("span", {
8835
9000
  className: styles$v.date,
8836
9001
  children: formatPlaced(order.placed_at, locale)
@@ -8861,6 +9026,7 @@ function OrderCard({ order, locale, onOpen }) {
8861
9026
  });
8862
9027
  }
8863
9028
  function Thumbnails({ order }) {
9029
+ const t = useT();
8864
9030
  const images = order.images ?? (order.image ? [order.image] : []);
8865
9031
  const hidden = order.item_count - TILES + 1;
8866
9032
  const overflow = images.length >= TILES && hidden > 1 ? hidden : 0;
@@ -8892,7 +9058,7 @@ function Thumbnails({ order }) {
8892
9058
  children: ["+", overflow]
8893
9059
  }), jsx("span", {
8894
9060
  className: "visually-hidden",
8895
- children: `and ${overflow} more items`
9061
+ children: t("and {0} more items", overflow)
8896
9062
  })]
8897
9063
  })]
8898
9064
  }, `${src}-${i}`);
@@ -10480,7 +10646,7 @@ function ColorSelector({ colours, selected: selected2, onSelect }) {
10480
10646
  }), lowStock2 && jsx("span", {
10481
10647
  className: styles$f.stockBadge,
10482
10648
  "aria-hidden": "true",
10483
- children: `${c.remaining} left`
10649
+ children: t("{0} left", c.remaining)
10484
10650
  })]
10485
10651
  }, c.value);
10486
10652
  })
@@ -11593,15 +11759,26 @@ function useDocumentSnap(ref, enabled = true) {
11593
11759
  passive: true
11594
11760
  });
11595
11761
  };
11762
+ let at = TOP;
11763
+ let returning = false;
11764
+ let holding = false;
11765
+ const settle = () => {
11766
+ returning = false;
11767
+ settleReturn();
11768
+ };
11596
11769
  const top2 = () => {
11597
- scrollToTop();
11598
- if (pane) scrollToTop(pane);
11770
+ scrollToOffset(at.doc);
11771
+ if (pane) scrollToOffset(at.pane, pane);
11599
11772
  };
11600
11773
  let frame2 = null;
11601
11774
  let release = () => {
11602
11775
  };
11603
11776
  const anchor2 = () => {
11604
11777
  release();
11778
+ const back = returnOffset(here());
11779
+ returning = back !== null;
11780
+ at = back ?? TOP;
11781
+ holding = true;
11605
11782
  if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
11606
11783
  window.cancelAnimationFrame(frame2);
11607
11784
  }
@@ -11617,18 +11794,42 @@ function useDocumentSnap(ref, enabled = true) {
11617
11794
  snapOnAtTouch();
11618
11795
  }
11619
11796
  return true;
11620
- }, void 0, pane);
11797
+ }, (end2) => {
11798
+ holding = false;
11799
+ if (returning && end2 === "moved") settle();
11800
+ }, pane, at);
11621
11801
  };
11802
+ let screen2 = claimScreen();
11622
11803
  anchor2();
11623
11804
  const history = window.history;
11624
11805
  const previousRestoration = history && "scrollRestoration" in history ? history.scrollRestoration : null;
11625
11806
  if (previousRestoration !== null) history.scrollRestoration = "manual";
11626
11807
  const onPageShow = (event) => {
11627
- if (event.persisted) anchor2();
11808
+ if (event.persisted) {
11809
+ screen2 = claimScreen();
11810
+ anchor2();
11811
+ }
11628
11812
  };
11629
11813
  window.addEventListener("pageshow", onPageShow);
11630
- const unobserve = onReveal(el, anchor2);
11814
+ const unobserve = onReveal(el, () => {
11815
+ screen2 = claimScreen();
11816
+ anchor2();
11817
+ });
11818
+ const note2 = () => {
11819
+ if (!isCurrentScreen(screen2)) return;
11820
+ const now = placeOf(pane);
11821
+ if (returning && reached(now, at)) settle();
11822
+ if (holding) return;
11823
+ remember(here(), now);
11824
+ };
11825
+ document.addEventListener("scroll", note2, {
11826
+ capture: true,
11827
+ passive: true
11828
+ });
11631
11829
  return () => {
11830
+ document.removeEventListener("scroll", note2, {
11831
+ capture: true
11832
+ });
11632
11833
  unobserve();
11633
11834
  release();
11634
11835
  if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
@@ -133,7 +133,7 @@
133
133
  background: var(--color-surface-max);
134
134
  color: var(--color-text-strong);
135
135
  }
136
- ._button_17pvl_1 {
136
+ ._button_ci424_1 {
137
137
  display: inline-flex;
138
138
  align-items: center;
139
139
  justify-content: center;
@@ -151,52 +151,57 @@
151
151
  transition: background-color 120ms ease, opacity 120ms ease;
152
152
  -webkit-tap-highlight-color: transparent;
153
153
  }
154
- ._fullWidth_17pvl_25 {
154
+ ._fullWidth_ci424_25 {
155
155
  width: 100%;
156
156
  }
157
- ._primary_17pvl_29 {
157
+ ._primary_ci424_29 {
158
158
  background: var(--color-surface-max);
159
159
  color: var(--color-text-strong);
160
160
  }
161
- ._secondary_17pvl_34 {
161
+ ._secondary_ci424_34 {
162
162
  background: transparent;
163
163
  color: var(--color-text-default);
164
164
  border-color: var(--color-border-default);
165
165
  }
166
- ._ghost_17pvl_40 {
166
+ ._ghost_ci424_40 {
167
167
  background: transparent;
168
168
  color: var(--color-text-default);
169
169
  border-color: transparent;
170
170
  }
171
- ._button_17pvl_1:disabled {
171
+ ._button_ci424_1:disabled {
172
172
  cursor: not-allowed;
173
173
  }
174
- ._primary_17pvl_29:disabled {
174
+ ._primary_ci424_29:disabled {
175
175
  background: var(--color-surface-bold);
176
176
  color: var(--color-text-disabled);
177
177
  }
178
- ._secondary_17pvl_34:disabled,
179
- ._ghost_17pvl_40:disabled {
178
+ ._secondary_ci424_34:disabled,
179
+ ._ghost_ci424_40:disabled {
180
180
  opacity: 0.5;
181
181
  }
182
- ._button_17pvl_1:focus-visible {
182
+ ._button_ci424_1:focus-visible {
183
183
  outline: 2px solid var(--color-surface-max);
184
184
  outline-offset: 2px;
185
185
  }
186
- ._spinner_17pvl_83 {
186
+ ._spinner_1rueh_5 {
187
187
  width: 20px;
188
188
  height: 20px;
189
189
  margin: 2px;
190
190
  border-radius: var(--radius-full);
191
191
  border: 2px solid currentColor;
192
192
  border-top-color: transparent;
193
- animation: _spin_17pvl_83 700ms linear infinite;
193
+ animation: _spin_1rueh_5 700ms linear infinite;
194
194
  }
195
- @keyframes _spin_17pvl_83 {
195
+ @keyframes _spin_1rueh_5 {
196
196
  to {
197
197
  transform: rotate(360deg);
198
198
  }
199
199
  }
200
+ @media (prefers-reduced-motion: reduce) {
201
+ ._spinner_1rueh_5 {
202
+ animation-duration: 2400ms;
203
+ }
204
+ }
200
205
  ._skeleton_1nxz7_1 {
201
206
  display: block;
202
207
  background:
package/dist/styles.css CHANGED
@@ -133,7 +133,7 @@
133
133
  background: var(--color-surface-max);
134
134
  color: var(--color-text-strong);
135
135
  }
136
- ._button_17pvl_1 {
136
+ ._button_ci424_1 {
137
137
  display: inline-flex;
138
138
  align-items: center;
139
139
  justify-content: center;
@@ -151,52 +151,57 @@
151
151
  transition: background-color 120ms ease, opacity 120ms ease;
152
152
  -webkit-tap-highlight-color: transparent;
153
153
  }
154
- ._fullWidth_17pvl_25 {
154
+ ._fullWidth_ci424_25 {
155
155
  width: 100%;
156
156
  }
157
- ._primary_17pvl_29 {
157
+ ._primary_ci424_29 {
158
158
  background: var(--color-surface-max);
159
159
  color: var(--color-text-strong);
160
160
  }
161
- ._secondary_17pvl_34 {
161
+ ._secondary_ci424_34 {
162
162
  background: transparent;
163
163
  color: var(--color-text-default);
164
164
  border-color: var(--color-border-default);
165
165
  }
166
- ._ghost_17pvl_40 {
166
+ ._ghost_ci424_40 {
167
167
  background: transparent;
168
168
  color: var(--color-text-default);
169
169
  border-color: transparent;
170
170
  }
171
- ._button_17pvl_1:disabled {
171
+ ._button_ci424_1:disabled {
172
172
  cursor: not-allowed;
173
173
  }
174
- ._primary_17pvl_29:disabled {
174
+ ._primary_ci424_29:disabled {
175
175
  background: var(--color-surface-bold);
176
176
  color: var(--color-text-disabled);
177
177
  }
178
- ._secondary_17pvl_34:disabled,
179
- ._ghost_17pvl_40:disabled {
178
+ ._secondary_ci424_34:disabled,
179
+ ._ghost_ci424_40:disabled {
180
180
  opacity: 0.5;
181
181
  }
182
- ._button_17pvl_1:focus-visible {
182
+ ._button_ci424_1:focus-visible {
183
183
  outline: 2px solid var(--color-surface-max);
184
184
  outline-offset: 2px;
185
185
  }
186
- ._spinner_17pvl_83 {
186
+ ._spinner_1rueh_5 {
187
187
  width: 20px;
188
188
  height: 20px;
189
189
  margin: 2px;
190
190
  border-radius: var(--radius-full);
191
191
  border: 2px solid currentColor;
192
192
  border-top-color: transparent;
193
- animation: _spin_17pvl_83 700ms linear infinite;
193
+ animation: _spin_1rueh_5 700ms linear infinite;
194
194
  }
195
- @keyframes _spin_17pvl_83 {
195
+ @keyframes _spin_1rueh_5 {
196
196
  to {
197
197
  transform: rotate(360deg);
198
198
  }
199
199
  }
200
+ @media (prefers-reduced-motion: reduce) {
201
+ ._spinner_1rueh_5 {
202
+ animation-duration: 2400ms;
203
+ }
204
+ }
200
205
  ._skeleton_1nxz7_1 {
201
206
  display: block;
202
207
  background:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nok-integration/storefront-react",
3
- "version": "0.20.15",
3
+ "version": "0.20.17",
4
4
  "description": "Mountable React storefront components: catalogue, product detail and cart, mounted directly into a host DOM tree. No iframe.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",