@nok-integration/storefront-react 0.29.10 → 0.29.12

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
@@ -5289,7 +5289,7 @@ declare class ProductCache {
5289
5289
  * the size error). Add-to-cart calls the engine through the session so a 401 silently
5290
5290
  * re-handshakes.
5291
5291
  */
5292
- export declare function ProductDetail({ product, inventory, recommendations, claim, breadcrumb, help, }: ProductDetailProps): JSX.Element;
5292
+ export declare function ProductDetail({ product, inventory, recommendations, claim, breadcrumb, help, initialVariantSku, }: ProductDetailProps): JSX.Element;
5293
5293
 
5294
5294
  export declare interface ProductDetailProps {
5295
5295
  product: Product;
@@ -5303,6 +5303,7 @@ export declare interface ProductDetailProps {
5303
5303
  claim?: (sku: string) => Promise<void>;
5304
5304
  breadcrumb?: ReactNode;
5305
5305
  help?: ReactNode;
5306
+ initialVariantSku?: string;
5306
5307
  }
5307
5308
 
5308
5309
  /**
package/dist/index.mjs CHANGED
@@ -5692,6 +5692,72 @@ function withAuthorization(init, token) {
5692
5692
  headers
5693
5693
  };
5694
5694
  }
5695
+ const KEY = "dazn-shop.set-aside";
5696
+ const KEPT_FOR = 30 * 24 * 60 * 60 * 1e3;
5697
+ function read() {
5698
+ try {
5699
+ const raw = localStorage.getItem(KEY);
5700
+ if (!raw) return null;
5701
+ const value2 = JSON.parse(raw);
5702
+ if (!Array.isArray(value2.lines) || typeof value2.at !== "number") return null;
5703
+ if (Date.now() - value2.at > KEPT_FOR) {
5704
+ localStorage.removeItem(KEY);
5705
+ return null;
5706
+ }
5707
+ const lines2 = value2.lines.filter((l) => !!l && typeof l.sku === "string" && Number.isInteger(l.qty) && l.qty > 0);
5708
+ return {
5709
+ lines: lines2,
5710
+ armed: value2.armed === true,
5711
+ at: value2.at
5712
+ };
5713
+ } catch {
5714
+ return null;
5715
+ }
5716
+ }
5717
+ function write(value2) {
5718
+ try {
5719
+ if (value2) localStorage.setItem(KEY, JSON.stringify(value2));
5720
+ else localStorage.removeItem(KEY);
5721
+ } catch {
5722
+ return;
5723
+ }
5724
+ }
5725
+ function setAside(lines2) {
5726
+ if (lines2.length === 0 || read()) return;
5727
+ write({
5728
+ lines: lines2,
5729
+ armed: false,
5730
+ at: Date.now()
5731
+ });
5732
+ }
5733
+ function armSetAside() {
5734
+ const stored2 = read();
5735
+ if (stored2) write({
5736
+ ...stored2,
5737
+ armed: true
5738
+ });
5739
+ }
5740
+ let restoring = false;
5741
+ async function restoreSetAside(cart2, writer, query, { force = false } = {}) {
5742
+ const stored2 = read();
5743
+ if (!stored2 || restoring) return cart2;
5744
+ if (!force && (!stored2.armed || cart2.vip)) return cart2;
5745
+ restoring = true;
5746
+ write(null);
5747
+ let latest = cart2;
5748
+ try {
5749
+ for (const line2 of stored2.lines) {
5750
+ if (latest.items.some((i) => i.sku === line2.sku)) continue;
5751
+ latest = await writer.addItem({
5752
+ sku: line2.sku,
5753
+ qty: line2.qty
5754
+ }, query).catch(() => latest);
5755
+ }
5756
+ } finally {
5757
+ restoring = false;
5758
+ }
5759
+ return latest;
5760
+ }
5695
5761
  const ScreenTitleContext = createContext({
5696
5762
  title: void 0,
5697
5763
  trailing: "default",
@@ -5722,7 +5788,9 @@ function ScreenTitleProvider({ children }) {
5722
5788
  return jsx(ScreenTitleContext.Provider, {
5723
5789
  value: value2,
5724
5790
  children: jsx(ScreenNavProvider, {
5725
- children
5791
+ children: jsx(ScreenBackdropProvider, {
5792
+ children
5793
+ })
5726
5794
  })
5727
5795
  });
5728
5796
  }
@@ -5787,6 +5855,43 @@ function useSetScreenNav(crumbs2, tone) {
5787
5855
  });
5788
5856
  }, [claim, key, tone, suppressed]);
5789
5857
  }
5858
+ const ScreenBackdropContext = createContext({
5859
+ backdrop: "plain",
5860
+ claim: () => () => {
5861
+ }
5862
+ });
5863
+ function ScreenBackdropProvider({ children }) {
5864
+ const [backdrop, setBackdrop] = useState("plain");
5865
+ const held = useRef(0);
5866
+ const claim = useCallback((next) => {
5867
+ held.current += 1;
5868
+ const mine = held.current;
5869
+ setBackdrop(next);
5870
+ return () => {
5871
+ if (held.current !== mine) return;
5872
+ setBackdrop("plain");
5873
+ };
5874
+ }, []);
5875
+ const value2 = useMemo(() => ({
5876
+ backdrop,
5877
+ claim
5878
+ }), [backdrop, claim]);
5879
+ return jsx(ScreenBackdropContext.Provider, {
5880
+ value: value2,
5881
+ children
5882
+ });
5883
+ }
5884
+ function useScreenBackdrop() {
5885
+ return useContext(ScreenBackdropContext).backdrop;
5886
+ }
5887
+ function useSetScreenBackdrop(backdrop) {
5888
+ const { claim } = useContext(ScreenBackdropContext);
5889
+ const suppressed = useContext(SuppressedContext);
5890
+ useEffect(() => {
5891
+ if (suppressed) return;
5892
+ return claim(backdrop);
5893
+ }, [claim, backdrop, suppressed]);
5894
+ }
5790
5895
  const ShopContext = createContext(null);
5791
5896
  const CartCacheContext = createContext(null);
5792
5897
  function DaznShopProvider({ children, ...config }) {
@@ -5846,24 +5951,24 @@ function DaznShopProvider({ children, ...config }) {
5846
5951
  carts.set(cart2);
5847
5952
  return cart2;
5848
5953
  };
5849
- const read = (fn) => (...args) => {
5954
+ const read2 = (fn) => (...args) => {
5850
5955
  const before = carts.revision;
5851
5956
  return fn(...args).then((cart2) => carts.revision === before ? remember2(cart2) : cart2);
5852
5957
  };
5853
- const write = (fn) => (...args) => fn(...args).then(remember2);
5958
+ const write2 = (fn) => (...args) => fn(...args).then(remember2);
5854
5959
  return {
5855
5960
  ...client2,
5856
5961
  cart: {
5857
5962
  ...client2.cart,
5858
- create: read(client2.cart.create),
5859
- get: read(client2.cart.get),
5860
- addItem: write(client2.cart.addItem),
5861
- updateItem: write(client2.cart.updateItem),
5862
- removeItem: write(client2.cart.removeItem)
5963
+ create: read2(client2.cart.create),
5964
+ get: (...args) => read2(client2.cart.get)(...args).then((cart2) => restoreSetAside(cart2, client2.cart, args[0]).then((latest) => latest === cart2 ? cart2 : remember2(latest))),
5965
+ addItem: write2(client2.cart.addItem),
5966
+ updateItem: write2(client2.cart.updateItem),
5967
+ removeItem: write2(client2.cart.removeItem)
5863
5968
  },
5864
5969
  vip: {
5865
5970
  ...client2.vip,
5866
- addToCart: write(client2.vip.addToCart)
5971
+ addToCart: write2(client2.vip.addToCart)
5867
5972
  }
5868
5973
  };
5869
5974
  }, [client2, carts]);
@@ -12195,7 +12300,7 @@ const styles$e = {
12195
12300
  cta: cta$3,
12196
12301
  shop
12197
12302
  };
12198
- function ProductDetail({ product, inventory: inventory2, recommendations = [], claim, breadcrumb: breadcrumb2, help: help2 }) {
12303
+ function ProductDetail({ product, inventory: inventory2, recommendations = [], claim, breadcrumb: breadcrumb2, help: help2, initialVariantSku }) {
12199
12304
  const t = useT();
12200
12305
  const toast2 = useToast();
12201
12306
  const { api, emit } = useShop();
@@ -12227,11 +12332,12 @@ function ProductDetail({ product, inventory: inventory2, recommendations = [], c
12227
12332
  const hasSizes = useMemo(() => sizeOptions(variants).length > 0, [variants]);
12228
12333
  const hasColours = baseColours.length > 0;
12229
12334
  const structured = hasSizes || hasColours;
12230
- const [selectedSize, setSelectedSize] = useState(null);
12231
- const [selectedColour, setSelectedColour] = useState(hasColours ? baseColours.find((c) => c.available)?.value ?? baseColours[0].value : null);
12335
+ const preselected = initialVariantSku ? variants.find((v) => v.sku === initialVariantSku) : void 0;
12336
+ const [selectedSize, setSelectedSize] = useState(preselected?.attributes.size ?? null);
12337
+ const [selectedColour, setSelectedColour] = useState(preselected?.attributes.colour ?? preselected?.attributes.color ?? (hasColours ? baseColours.find((c) => c.available)?.value ?? baseColours[0].value : null));
12232
12338
  const sizes2 = useMemo(() => sizeOptions(variants, selectedColour), [variants, selectedColour]);
12233
12339
  const colours = useMemo(() => colourOptions(variants, selectedSize), [variants, selectedSize]);
12234
- const [genericSku, setGenericSku] = useState(null);
12340
+ const [genericSku, setGenericSku] = useState(preselected && !structured ? preselected.sku : null);
12235
12341
  const [busy, setBusy] = useState(null);
12236
12342
  const [sizeError, setSizeError] = useState(false);
12237
12343
  const [reminded, setReminded] = useState([]);
@@ -13284,9 +13390,12 @@ function ProductView({ sku, initialData, showRecommendations = true, onNotFound
13284
13390
  if (product) {
13285
13391
  return jsx(ProductDetail, {
13286
13392
  product,
13393
+ ...sku === product.sku ? {} : {
13394
+ initialVariantSku: sku
13395
+ },
13287
13396
  inventory: inventory2,
13288
13397
  recommendations
13289
- }, product.sku);
13398
+ }, sku === product.sku ? product.sku : `${product.sku}:${sku}`);
13290
13399
  }
13291
13400
  if (loading) return jsx(ScreenSkeleton, {
13292
13401
  tone: "light"
@@ -14713,18 +14822,18 @@ function requireDist() {
14713
14822
  return dist;
14714
14823
  }
14715
14824
  var distExports = requireDist();
14716
- const hero$1 = "_hero_dctyt_1";
14717
- const image$1 = "_image_dctyt_11";
14718
- const foot = "_foot_dctyt_34";
14719
- const text$1 = "_text_dctyt_40";
14720
- const logo$1 = "_logo_dctyt_48";
14721
- const copy$1 = "_copy_dctyt_53";
14722
- const headline = "_headline_dctyt_62";
14723
- const body = "_body_dctyt_70";
14724
- const cta$2 = "_cta_dctyt_79";
14725
- const video = "_video_dctyt_83";
14726
- const desktopOnly = "_desktopOnly_dctyt_87";
14727
- const phoneOnly$1 = "_phoneOnly_dctyt_97";
14825
+ const hero$1 = "_hero_15sq4_1";
14826
+ const image$1 = "_image_15sq4_11";
14827
+ const foot = "_foot_15sq4_34";
14828
+ const text$1 = "_text_15sq4_40";
14829
+ const logo$1 = "_logo_15sq4_48";
14830
+ const copy$1 = "_copy_15sq4_53";
14831
+ const headline = "_headline_15sq4_62";
14832
+ const body = "_body_15sq4_70";
14833
+ const cta$2 = "_cta_15sq4_79";
14834
+ const video = "_video_15sq4_83";
14835
+ const desktopOnly = "_desktopOnly_15sq4_87";
14836
+ const phoneOnly$1 = "_phoneOnly_15sq4_97";
14728
14837
  const hero$2 = {
14729
14838
  hero: hero$1,
14730
14839
  image: image$1,
@@ -14744,6 +14853,7 @@ function VipHero({ hero: hero2, onContinue }) {
14744
14853
  const assetUrl = useAssetUrl();
14745
14854
  const ref = useRef(null);
14746
14855
  useTopOffset(ref, "--vip-hero-top");
14856
+ useSetScreenBackdrop("media");
14747
14857
  const desktopImage = hero2.desktop_image ?? null;
14748
14858
  const desktopVideo = hero2.desktop_video ?? null;
14749
14859
  const wide2 = desktopImage !== null || desktopVideo !== null;
@@ -14821,6 +14931,7 @@ function VipInviteNotice({ title: title2, body: body3 }) {
14821
14931
  const navigate = useNavigate();
14822
14932
  const ref = useRef(null);
14823
14933
  useTopOffset(ref, "--vip-hero-top");
14934
+ useSetScreenBackdrop("media");
14824
14935
  const explore = () => {
14825
14936
  if (navigate) {
14826
14937
  navigate("/");
@@ -15096,8 +15207,12 @@ function ActiveLanding({ token, invite, screen: screen2 }) {
15096
15207
  }
15097
15208
  try {
15098
15209
  const current2 = await api.cart.get().catch(() => null);
15099
- if (current2?.vip?.invite_ref === invite.invite_ref) {
15100
- for (const line2 of current2.items) await api.cart.removeItem(line2.sku);
15210
+ if (current2 && current2.items.length > 0) {
15211
+ if (!current2.vip) setAside(current2.items.map((line2) => ({
15212
+ sku: line2.sku,
15213
+ qty: line2.qty
15214
+ })));
15215
+ for (const line2 of current2.items) await api.cart.removeItem(line2.sku).catch(() => null);
15101
15216
  }
15102
15217
  const target = locatorOf(token);
15103
15218
  if (!target) throw new Error("invalid invite link");
@@ -15106,6 +15221,7 @@ function ActiveLanding({ token, invite, screen: screen2 }) {
15106
15221
  sku: variantSku,
15107
15222
  qty: 1
15108
15223
  });
15224
+ armSetAside();
15109
15225
  emit({
15110
15226
  type: "cart_updated",
15111
15227
  itemCount: cart2.items.reduce((n, i) => n + i.qty, 0),
@@ -15120,6 +15236,10 @@ function ActiveLanding({ token, invite, screen: screen2 }) {
15120
15236
  window.location.assign(checkout_url);
15121
15237
  } catch (err) {
15122
15238
  const code = codeOf(err);
15239
+ const now = await api.cart.get().catch(() => null);
15240
+ if (now && !now.vip) await restoreSetAside(now, api.cart, void 0, {
15241
+ force: true
15242
+ });
15123
15243
  if (code === "unauthorized") {
15124
15244
  emit({
15125
15245
  type: "session_required",
@@ -15282,7 +15402,7 @@ function useDocumentSnap(ref, enabled = true) {
15282
15402
  };
15283
15403
  let at = TOP;
15284
15404
  let returning = false;
15285
- let restoring = false;
15405
+ let restoring2 = false;
15286
15406
  let holding = false;
15287
15407
  const settle = () => {
15288
15408
  returning = false;
@@ -15299,13 +15419,13 @@ function useDocumentSnap(ref, enabled = true) {
15299
15419
  release();
15300
15420
  const back = returnOffset(here());
15301
15421
  returning = back !== null;
15302
- restoring = returning;
15422
+ restoring2 = returning;
15303
15423
  at = back ?? TOP;
15304
15424
  holding = true;
15305
15425
  if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
15306
15426
  window.cancelAnimationFrame(frame2);
15307
15427
  }
15308
- if (restoring) snapOn();
15428
+ if (restoring2) snapOn();
15309
15429
  else snapOff();
15310
15430
  top2();
15311
15431
  frame2 = typeof window.requestAnimationFrame === "function" ? window.requestAnimationFrame(() => {
@@ -15313,7 +15433,7 @@ function useDocumentSnap(ref, enabled = true) {
15313
15433
  snapOn();
15314
15434
  }) : null;
15315
15435
  release = anchorTop(() => {
15316
- if (snapping && !restoring) {
15436
+ if (snapping && !restoring2) {
15317
15437
  const layout = layoutOf();
15318
15438
  if (layout !== snappedLayout) {
15319
15439
  snappedLayout = layout;
@@ -16292,17 +16412,17 @@ function useScrolledUnder(enabled) {
16292
16412
  const [scrolled2, setScrolled] = useState(false);
16293
16413
  useEffect(() => {
16294
16414
  if (!enabled) return;
16295
- const read = (event) => {
16415
+ const read2 = (event) => {
16296
16416
  const target = event?.target;
16297
16417
  const top2 = target && target !== document && target instanceof HTMLElement ? target.scrollTop : window.scrollY || document.documentElement.scrollTop;
16298
16418
  setScrolled(top2 > 0);
16299
16419
  };
16300
- read();
16301
- document.addEventListener("scroll", read, {
16420
+ read2();
16421
+ document.addEventListener("scroll", read2, {
16302
16422
  capture: true,
16303
16423
  passive: true
16304
16424
  });
16305
- return () => document.removeEventListener("scroll", read, {
16425
+ return () => document.removeEventListener("scroll", read2, {
16306
16426
  capture: true
16307
16427
  });
16308
16428
  }, [enabled]);
@@ -16354,7 +16474,9 @@ function CheckoutBar({ title: title2, onClose, closeLabel, className }) {
16354
16474
  })]
16355
16475
  });
16356
16476
  }
16357
- function ShopBar({ onBack, onMenu, title: title2, showCart, floating: floating2 = false, scrolled: scrolled2, backLabel, menuLabel, className }) {
16477
+ function ShopBar({ onBack, onMenu, title: title2, showCart, floating: floatingProp, scrolled: scrolled2, backLabel, menuLabel, className }) {
16478
+ const backdrop = useScreenBackdrop();
16479
+ const floating2 = floatingProp ?? backdrop === "media";
16358
16480
  const t = useT();
16359
16481
  const cartCount = useCartCount();
16360
16482
  const screenTitle = useScreenTitle();
@@ -5692,6 +5692,72 @@ function withAuthorization(init, token) {
5692
5692
  headers
5693
5693
  };
5694
5694
  }
5695
+ const KEY = "dazn-shop.set-aside";
5696
+ const KEPT_FOR = 30 * 24 * 60 * 60 * 1e3;
5697
+ function read() {
5698
+ try {
5699
+ const raw = localStorage.getItem(KEY);
5700
+ if (!raw) return null;
5701
+ const value2 = JSON.parse(raw);
5702
+ if (!Array.isArray(value2.lines) || typeof value2.at !== "number") return null;
5703
+ if (Date.now() - value2.at > KEPT_FOR) {
5704
+ localStorage.removeItem(KEY);
5705
+ return null;
5706
+ }
5707
+ const lines2 = value2.lines.filter((l) => !!l && typeof l.sku === "string" && Number.isInteger(l.qty) && l.qty > 0);
5708
+ return {
5709
+ lines: lines2,
5710
+ armed: value2.armed === true,
5711
+ at: value2.at
5712
+ };
5713
+ } catch {
5714
+ return null;
5715
+ }
5716
+ }
5717
+ function write(value2) {
5718
+ try {
5719
+ if (value2) localStorage.setItem(KEY, JSON.stringify(value2));
5720
+ else localStorage.removeItem(KEY);
5721
+ } catch {
5722
+ return;
5723
+ }
5724
+ }
5725
+ function setAside(lines2) {
5726
+ if (lines2.length === 0 || read()) return;
5727
+ write({
5728
+ lines: lines2,
5729
+ armed: false,
5730
+ at: Date.now()
5731
+ });
5732
+ }
5733
+ function armSetAside() {
5734
+ const stored2 = read();
5735
+ if (stored2) write({
5736
+ ...stored2,
5737
+ armed: true
5738
+ });
5739
+ }
5740
+ let restoring = false;
5741
+ async function restoreSetAside(cart2, writer, query, { force = false } = {}) {
5742
+ const stored2 = read();
5743
+ if (!stored2 || restoring) return cart2;
5744
+ if (!force && (!stored2.armed || cart2.vip)) return cart2;
5745
+ restoring = true;
5746
+ write(null);
5747
+ let latest = cart2;
5748
+ try {
5749
+ for (const line2 of stored2.lines) {
5750
+ if (latest.items.some((i) => i.sku === line2.sku)) continue;
5751
+ latest = await writer.addItem({
5752
+ sku: line2.sku,
5753
+ qty: line2.qty
5754
+ }, query).catch(() => latest);
5755
+ }
5756
+ } finally {
5757
+ restoring = false;
5758
+ }
5759
+ return latest;
5760
+ }
5695
5761
  const ScreenTitleContext = createContext({
5696
5762
  title: void 0,
5697
5763
  trailing: "default",
@@ -5722,7 +5788,9 @@ function ScreenTitleProvider({ children }) {
5722
5788
  return jsx(ScreenTitleContext.Provider, {
5723
5789
  value: value2,
5724
5790
  children: jsx(ScreenNavProvider, {
5725
- children
5791
+ children: jsx(ScreenBackdropProvider, {
5792
+ children
5793
+ })
5726
5794
  })
5727
5795
  });
5728
5796
  }
@@ -5787,6 +5855,43 @@ function useSetScreenNav(crumbs2, tone) {
5787
5855
  });
5788
5856
  }, [claim, key, tone, suppressed]);
5789
5857
  }
5858
+ const ScreenBackdropContext = createContext({
5859
+ backdrop: "plain",
5860
+ claim: () => () => {
5861
+ }
5862
+ });
5863
+ function ScreenBackdropProvider({ children }) {
5864
+ const [backdrop, setBackdrop] = useState("plain");
5865
+ const held = useRef(0);
5866
+ const claim = useCallback((next) => {
5867
+ held.current += 1;
5868
+ const mine = held.current;
5869
+ setBackdrop(next);
5870
+ return () => {
5871
+ if (held.current !== mine) return;
5872
+ setBackdrop("plain");
5873
+ };
5874
+ }, []);
5875
+ const value2 = useMemo(() => ({
5876
+ backdrop,
5877
+ claim
5878
+ }), [backdrop, claim]);
5879
+ return jsx(ScreenBackdropContext.Provider, {
5880
+ value: value2,
5881
+ children
5882
+ });
5883
+ }
5884
+ function useScreenBackdrop() {
5885
+ return useContext(ScreenBackdropContext).backdrop;
5886
+ }
5887
+ function useSetScreenBackdrop(backdrop) {
5888
+ const { claim } = useContext(ScreenBackdropContext);
5889
+ const suppressed = useContext(SuppressedContext);
5890
+ useEffect(() => {
5891
+ if (suppressed) return;
5892
+ return claim(backdrop);
5893
+ }, [claim, backdrop, suppressed]);
5894
+ }
5790
5895
  const ShopContext = createContext(null);
5791
5896
  const CartCacheContext = createContext(null);
5792
5897
  function DaznShopProvider({ children, ...config }) {
@@ -5846,24 +5951,24 @@ function DaznShopProvider({ children, ...config }) {
5846
5951
  carts.set(cart2);
5847
5952
  return cart2;
5848
5953
  };
5849
- const read = (fn) => (...args) => {
5954
+ const read2 = (fn) => (...args) => {
5850
5955
  const before = carts.revision;
5851
5956
  return fn(...args).then((cart2) => carts.revision === before ? remember2(cart2) : cart2);
5852
5957
  };
5853
- const write = (fn) => (...args) => fn(...args).then(remember2);
5958
+ const write2 = (fn) => (...args) => fn(...args).then(remember2);
5854
5959
  return {
5855
5960
  ...client2,
5856
5961
  cart: {
5857
5962
  ...client2.cart,
5858
- create: read(client2.cart.create),
5859
- get: read(client2.cart.get),
5860
- addItem: write(client2.cart.addItem),
5861
- updateItem: write(client2.cart.updateItem),
5862
- removeItem: write(client2.cart.removeItem)
5963
+ create: read2(client2.cart.create),
5964
+ get: (...args) => read2(client2.cart.get)(...args).then((cart2) => restoreSetAside(cart2, client2.cart, args[0]).then((latest) => latest === cart2 ? cart2 : remember2(latest))),
5965
+ addItem: write2(client2.cart.addItem),
5966
+ updateItem: write2(client2.cart.updateItem),
5967
+ removeItem: write2(client2.cart.removeItem)
5863
5968
  },
5864
5969
  vip: {
5865
5970
  ...client2.vip,
5866
- addToCart: write(client2.vip.addToCart)
5971
+ addToCart: write2(client2.vip.addToCart)
5867
5972
  }
5868
5973
  };
5869
5974
  }, [client2, carts]);
@@ -12195,7 +12300,7 @@ const styles$e = {
12195
12300
  cta: cta$3,
12196
12301
  shop
12197
12302
  };
12198
- function ProductDetail({ product, inventory: inventory2, recommendations = [], claim, breadcrumb: breadcrumb2, help: help2 }) {
12303
+ function ProductDetail({ product, inventory: inventory2, recommendations = [], claim, breadcrumb: breadcrumb2, help: help2, initialVariantSku }) {
12199
12304
  const t = useT();
12200
12305
  const toast2 = useToast();
12201
12306
  const { api, emit } = useShop();
@@ -12227,11 +12332,12 @@ function ProductDetail({ product, inventory: inventory2, recommendations = [], c
12227
12332
  const hasSizes = useMemo(() => sizeOptions(variants).length > 0, [variants]);
12228
12333
  const hasColours = baseColours.length > 0;
12229
12334
  const structured = hasSizes || hasColours;
12230
- const [selectedSize, setSelectedSize] = useState(null);
12231
- const [selectedColour, setSelectedColour] = useState(hasColours ? baseColours.find((c) => c.available)?.value ?? baseColours[0].value : null);
12335
+ const preselected = initialVariantSku ? variants.find((v) => v.sku === initialVariantSku) : void 0;
12336
+ const [selectedSize, setSelectedSize] = useState(preselected?.attributes.size ?? null);
12337
+ const [selectedColour, setSelectedColour] = useState(preselected?.attributes.colour ?? preselected?.attributes.color ?? (hasColours ? baseColours.find((c) => c.available)?.value ?? baseColours[0].value : null));
12232
12338
  const sizes2 = useMemo(() => sizeOptions(variants, selectedColour), [variants, selectedColour]);
12233
12339
  const colours = useMemo(() => colourOptions(variants, selectedSize), [variants, selectedSize]);
12234
- const [genericSku, setGenericSku] = useState(null);
12340
+ const [genericSku, setGenericSku] = useState(preselected && !structured ? preselected.sku : null);
12235
12341
  const [busy, setBusy] = useState(null);
12236
12342
  const [sizeError, setSizeError] = useState(false);
12237
12343
  const [reminded, setReminded] = useState([]);
@@ -13284,9 +13390,12 @@ function ProductView({ sku, initialData, showRecommendations = true, onNotFound
13284
13390
  if (product) {
13285
13391
  return jsx(ProductDetail, {
13286
13392
  product,
13393
+ ...sku === product.sku ? {} : {
13394
+ initialVariantSku: sku
13395
+ },
13287
13396
  inventory: inventory2,
13288
13397
  recommendations
13289
- }, product.sku);
13398
+ }, sku === product.sku ? product.sku : `${product.sku}:${sku}`);
13290
13399
  }
13291
13400
  if (loading) return jsx(ScreenSkeleton, {
13292
13401
  tone: "light"
@@ -14713,18 +14822,18 @@ function requireDist() {
14713
14822
  return dist;
14714
14823
  }
14715
14824
  var distExports = requireDist();
14716
- const hero$1 = "_hero_dctyt_1";
14717
- const image$1 = "_image_dctyt_11";
14718
- const foot = "_foot_dctyt_34";
14719
- const text$1 = "_text_dctyt_40";
14720
- const logo$1 = "_logo_dctyt_48";
14721
- const copy$1 = "_copy_dctyt_53";
14722
- const headline = "_headline_dctyt_62";
14723
- const body = "_body_dctyt_70";
14724
- const cta$2 = "_cta_dctyt_79";
14725
- const video = "_video_dctyt_83";
14726
- const desktopOnly = "_desktopOnly_dctyt_87";
14727
- const phoneOnly$1 = "_phoneOnly_dctyt_97";
14825
+ const hero$1 = "_hero_15sq4_1";
14826
+ const image$1 = "_image_15sq4_11";
14827
+ const foot = "_foot_15sq4_34";
14828
+ const text$1 = "_text_15sq4_40";
14829
+ const logo$1 = "_logo_15sq4_48";
14830
+ const copy$1 = "_copy_15sq4_53";
14831
+ const headline = "_headline_15sq4_62";
14832
+ const body = "_body_15sq4_70";
14833
+ const cta$2 = "_cta_15sq4_79";
14834
+ const video = "_video_15sq4_83";
14835
+ const desktopOnly = "_desktopOnly_15sq4_87";
14836
+ const phoneOnly$1 = "_phoneOnly_15sq4_97";
14728
14837
  const hero$2 = {
14729
14838
  hero: hero$1,
14730
14839
  image: image$1,
@@ -14744,6 +14853,7 @@ function VipHero({ hero: hero2, onContinue }) {
14744
14853
  const assetUrl = useAssetUrl();
14745
14854
  const ref = useRef(null);
14746
14855
  useTopOffset(ref, "--vip-hero-top");
14856
+ useSetScreenBackdrop("media");
14747
14857
  const desktopImage = hero2.desktop_image ?? null;
14748
14858
  const desktopVideo = hero2.desktop_video ?? null;
14749
14859
  const wide2 = desktopImage !== null || desktopVideo !== null;
@@ -14821,6 +14931,7 @@ function VipInviteNotice({ title: title2, body: body3 }) {
14821
14931
  const navigate = useNavigate();
14822
14932
  const ref = useRef(null);
14823
14933
  useTopOffset(ref, "--vip-hero-top");
14934
+ useSetScreenBackdrop("media");
14824
14935
  const explore = () => {
14825
14936
  if (navigate) {
14826
14937
  navigate("/");
@@ -15096,8 +15207,12 @@ function ActiveLanding({ token, invite, screen: screen2 }) {
15096
15207
  }
15097
15208
  try {
15098
15209
  const current2 = await api.cart.get().catch(() => null);
15099
- if (current2?.vip?.invite_ref === invite.invite_ref) {
15100
- for (const line2 of current2.items) await api.cart.removeItem(line2.sku);
15210
+ if (current2 && current2.items.length > 0) {
15211
+ if (!current2.vip) setAside(current2.items.map((line2) => ({
15212
+ sku: line2.sku,
15213
+ qty: line2.qty
15214
+ })));
15215
+ for (const line2 of current2.items) await api.cart.removeItem(line2.sku).catch(() => null);
15101
15216
  }
15102
15217
  const target = locatorOf(token);
15103
15218
  if (!target) throw new Error("invalid invite link");
@@ -15106,6 +15221,7 @@ function ActiveLanding({ token, invite, screen: screen2 }) {
15106
15221
  sku: variantSku,
15107
15222
  qty: 1
15108
15223
  });
15224
+ armSetAside();
15109
15225
  emit({
15110
15226
  type: "cart_updated",
15111
15227
  itemCount: cart2.items.reduce((n, i) => n + i.qty, 0),
@@ -15120,6 +15236,10 @@ function ActiveLanding({ token, invite, screen: screen2 }) {
15120
15236
  window.location.assign(checkout_url);
15121
15237
  } catch (err) {
15122
15238
  const code = codeOf(err);
15239
+ const now = await api.cart.get().catch(() => null);
15240
+ if (now && !now.vip) await restoreSetAside(now, api.cart, void 0, {
15241
+ force: true
15242
+ });
15123
15243
  if (code === "unauthorized") {
15124
15244
  emit({
15125
15245
  type: "session_required",
@@ -15282,7 +15402,7 @@ function useDocumentSnap(ref, enabled = true) {
15282
15402
  };
15283
15403
  let at = TOP;
15284
15404
  let returning = false;
15285
- let restoring = false;
15405
+ let restoring2 = false;
15286
15406
  let holding = false;
15287
15407
  const settle = () => {
15288
15408
  returning = false;
@@ -15299,13 +15419,13 @@ function useDocumentSnap(ref, enabled = true) {
15299
15419
  release();
15300
15420
  const back = returnOffset(here());
15301
15421
  returning = back !== null;
15302
- restoring = returning;
15422
+ restoring2 = returning;
15303
15423
  at = back ?? TOP;
15304
15424
  holding = true;
15305
15425
  if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
15306
15426
  window.cancelAnimationFrame(frame2);
15307
15427
  }
15308
- if (restoring) snapOn();
15428
+ if (restoring2) snapOn();
15309
15429
  else snapOff();
15310
15430
  top2();
15311
15431
  frame2 = typeof window.requestAnimationFrame === "function" ? window.requestAnimationFrame(() => {
@@ -15313,7 +15433,7 @@ function useDocumentSnap(ref, enabled = true) {
15313
15433
  snapOn();
15314
15434
  }) : null;
15315
15435
  release = anchorTop(() => {
15316
- if (snapping && !restoring) {
15436
+ if (snapping && !restoring2) {
15317
15437
  const layout = layoutOf();
15318
15438
  if (layout !== snappedLayout) {
15319
15439
  snappedLayout = layout;
@@ -16292,17 +16412,17 @@ function useScrolledUnder(enabled) {
16292
16412
  const [scrolled2, setScrolled] = useState(false);
16293
16413
  useEffect(() => {
16294
16414
  if (!enabled) return;
16295
- const read = (event) => {
16415
+ const read2 = (event) => {
16296
16416
  const target = event?.target;
16297
16417
  const top2 = target && target !== document && target instanceof HTMLElement ? target.scrollTop : window.scrollY || document.documentElement.scrollTop;
16298
16418
  setScrolled(top2 > 0);
16299
16419
  };
16300
- read();
16301
- document.addEventListener("scroll", read, {
16420
+ read2();
16421
+ document.addEventListener("scroll", read2, {
16302
16422
  capture: true,
16303
16423
  passive: true
16304
16424
  });
16305
- return () => document.removeEventListener("scroll", read, {
16425
+ return () => document.removeEventListener("scroll", read2, {
16306
16426
  capture: true
16307
16427
  });
16308
16428
  }, [enabled]);
@@ -16354,7 +16474,9 @@ function CheckoutBar({ title: title2, onClose, closeLabel, className }) {
16354
16474
  })]
16355
16475
  });
16356
16476
  }
16357
- function ShopBar({ onBack, onMenu, title: title2, showCart, floating: floating2 = false, scrolled: scrolled2, backLabel, menuLabel, className }) {
16477
+ function ShopBar({ onBack, onMenu, title: title2, showCart, floating: floatingProp, scrolled: scrolled2, backLabel, menuLabel, className }) {
16478
+ const backdrop = useScreenBackdrop();
16479
+ const floating2 = floatingProp ?? backdrop === "media";
16358
16480
  const t = useT();
16359
16481
  const cartCount = useCartCount();
16360
16482
  const screenTitle = useScreenTitle();
@@ -4684,20 +4684,20 @@
4684
4684
  display: block;
4685
4685
  }
4686
4686
  }
4687
- ._hero_dctyt_1 {
4687
+ ._hero_15sq4_1 {
4688
4688
  position: relative;
4689
4689
  display: flex;
4690
4690
  flex-direction: column;
4691
4691
  justify-content: flex-end;
4692
- min-height: clamp(480px, calc(100svh - var(--vip-hero-top, 0px)), 812px);
4692
+ min-height: max(480px, calc(100svh - var(--vip-hero-top, 0px)));
4693
4693
  overflow: hidden;
4694
4694
  background: var(--color-surface-default);
4695
4695
  }
4696
- ._image_dctyt_11 {
4696
+ ._image_15sq4_11 {
4697
4697
  position: absolute;
4698
4698
  inset: 0;
4699
4699
  }
4700
- ._image_dctyt_11::after {
4700
+ ._image_15sq4_11::after {
4701
4701
  content: "";
4702
4702
  position: absolute;
4703
4703
  inset: 0;
@@ -4709,27 +4709,27 @@
4709
4709
  rgba(8, 14, 18, 0) 382px);
4710
4710
  pointer-events: none;
4711
4711
  }
4712
- ._image_dctyt_11 img {
4712
+ ._image_15sq4_11 img {
4713
4713
  object-fit: cover;
4714
4714
  object-position: top center;
4715
4715
  }
4716
- ._foot_dctyt_34 {
4716
+ ._foot_15sq4_34 {
4717
4717
  position: relative;
4718
4718
  display: flex;
4719
4719
  flex-direction: column;
4720
4720
  }
4721
- ._text_dctyt_40 {
4721
+ ._text_15sq4_40 {
4722
4722
  display: flex;
4723
4723
  flex-direction: column;
4724
4724
  align-items: center;
4725
4725
  gap: var(--space-16);
4726
4726
  padding: 0 var(--space-16) var(--space-8);
4727
4727
  }
4728
- ._text_dctyt_40 ._logo_dctyt_48 {
4728
+ ._text_15sq4_40 ._logo_15sq4_48 {
4729
4729
  width: 48px;
4730
4730
  height: 48px;
4731
4731
  }
4732
- ._copy_dctyt_53 {
4732
+ ._copy_15sq4_53 {
4733
4733
  display: flex;
4734
4734
  flex-direction: column;
4735
4735
  gap: 6px;
@@ -4737,14 +4737,14 @@
4737
4737
  text-align: center;
4738
4738
  overflow-wrap: break-word;
4739
4739
  }
4740
- ._headline_dctyt_62 {
4740
+ ._headline_15sq4_62 {
4741
4741
  margin: 0;
4742
4742
  font-size: 36px;
4743
4743
  line-height: 1.1;
4744
4744
  font-weight: var(--font-weight-bold);
4745
4745
  color: var(--color-text-default);
4746
4746
  }
4747
- ._body_dctyt_70 {
4747
+ ._body_15sq4_70 {
4748
4748
  margin: 0;
4749
4749
  font-size: var(--type-paragraph-size);
4750
4750
  line-height: var(--type-paragraph-line);
@@ -4752,69 +4752,69 @@
4752
4752
  color: var(--color-text-default);
4753
4753
  white-space: pre-line;
4754
4754
  }
4755
- ._cta_dctyt_79 {
4755
+ ._cta_15sq4_79 {
4756
4756
  padding: var(--space-16) var(--space-16) var(--space-24);
4757
4757
  }
4758
- ._video_dctyt_83 {
4758
+ ._video_15sq4_83 {
4759
4759
  object-fit: cover;
4760
4760
  }
4761
- ._desktopOnly_dctyt_87 {
4761
+ ._desktopOnly_15sq4_87 {
4762
4762
  display: none;
4763
4763
  }
4764
4764
  @media (min-width: 1200px) {
4765
- ._hero_dctyt_1 {
4765
+ ._hero_15sq4_1 {
4766
4766
  justify-content: center;
4767
4767
  min-height: max(480px, calc(100svh - var(--vip-hero-top, 0px)));
4768
4768
  }
4769
- ._phoneOnly_dctyt_97 {
4769
+ ._phoneOnly_15sq4_97 {
4770
4770
  display: none;
4771
4771
  }
4772
- ._desktopOnly_dctyt_87 {
4772
+ ._desktopOnly_15sq4_87 {
4773
4773
  display: block;
4774
4774
  }
4775
- ._image_dctyt_11::after {
4775
+ ._image_15sq4_11::after {
4776
4776
  background:
4777
4777
  linear-gradient(
4778
4778
  to right,
4779
4779
  rgba(8, 14, 18, 0.9) 0,
4780
4780
  rgba(8, 14, 18, 0) 53.33%);
4781
4781
  }
4782
- ._image_dctyt_11 img,
4783
- ._video_dctyt_83 {
4782
+ ._image_15sq4_11 img,
4783
+ ._video_15sq4_83 {
4784
4784
  object-position: center;
4785
4785
  }
4786
- ._foot_dctyt_34 {
4786
+ ._foot_15sq4_34 {
4787
4787
  gap: var(--space-16);
4788
4788
  width: 100%;
4789
4789
  max-width: 624px;
4790
4790
  padding-left: 64px;
4791
4791
  }
4792
- ._text_dctyt_40 {
4792
+ ._text_15sq4_40 {
4793
4793
  align-items: flex-start;
4794
4794
  padding: 0;
4795
4795
  }
4796
- ._text_dctyt_40 ._logo_dctyt_48 {
4796
+ ._text_15sq4_40 ._logo_15sq4_48 {
4797
4797
  display: none;
4798
4798
  }
4799
- ._copy_dctyt_53 {
4799
+ ._copy_15sq4_53 {
4800
4800
  gap: var(--space-16);
4801
4801
  text-align: left;
4802
4802
  }
4803
- ._headline_dctyt_62 {
4803
+ ._headline_15sq4_62 {
4804
4804
  font-size: 64px;
4805
4805
  line-height: 0.9375;
4806
4806
  letter-spacing: -0.64px;
4807
4807
  }
4808
- ._body_dctyt_70 {
4808
+ ._body_15sq4_70 {
4809
4809
  max-width: 520px;
4810
4810
  font-size: 20px;
4811
4811
  line-height: 1.4;
4812
4812
  white-space: normal;
4813
4813
  }
4814
- ._cta_dctyt_79 {
4814
+ ._cta_15sq4_79 {
4815
4815
  padding: var(--space-8) 0 0;
4816
4816
  }
4817
- ._cta_dctyt_79 > * {
4817
+ ._cta_15sq4_79 > * {
4818
4818
  width: auto;
4819
4819
  min-width: 173px;
4820
4820
  }
package/dist/styles.css CHANGED
@@ -4684,20 +4684,20 @@
4684
4684
  display: block;
4685
4685
  }
4686
4686
  }
4687
- ._hero_dctyt_1 {
4687
+ ._hero_15sq4_1 {
4688
4688
  position: relative;
4689
4689
  display: flex;
4690
4690
  flex-direction: column;
4691
4691
  justify-content: flex-end;
4692
- min-height: clamp(480px, calc(100svh - var(--vip-hero-top, 0px)), 812px);
4692
+ min-height: max(480px, calc(100svh - var(--vip-hero-top, 0px)));
4693
4693
  overflow: hidden;
4694
4694
  background: var(--color-surface-default);
4695
4695
  }
4696
- ._image_dctyt_11 {
4696
+ ._image_15sq4_11 {
4697
4697
  position: absolute;
4698
4698
  inset: 0;
4699
4699
  }
4700
- ._image_dctyt_11::after {
4700
+ ._image_15sq4_11::after {
4701
4701
  content: "";
4702
4702
  position: absolute;
4703
4703
  inset: 0;
@@ -4709,27 +4709,27 @@
4709
4709
  rgba(8, 14, 18, 0) 382px);
4710
4710
  pointer-events: none;
4711
4711
  }
4712
- ._image_dctyt_11 img {
4712
+ ._image_15sq4_11 img {
4713
4713
  object-fit: cover;
4714
4714
  object-position: top center;
4715
4715
  }
4716
- ._foot_dctyt_34 {
4716
+ ._foot_15sq4_34 {
4717
4717
  position: relative;
4718
4718
  display: flex;
4719
4719
  flex-direction: column;
4720
4720
  }
4721
- ._text_dctyt_40 {
4721
+ ._text_15sq4_40 {
4722
4722
  display: flex;
4723
4723
  flex-direction: column;
4724
4724
  align-items: center;
4725
4725
  gap: var(--space-16);
4726
4726
  padding: 0 var(--space-16) var(--space-8);
4727
4727
  }
4728
- ._text_dctyt_40 ._logo_dctyt_48 {
4728
+ ._text_15sq4_40 ._logo_15sq4_48 {
4729
4729
  width: 48px;
4730
4730
  height: 48px;
4731
4731
  }
4732
- ._copy_dctyt_53 {
4732
+ ._copy_15sq4_53 {
4733
4733
  display: flex;
4734
4734
  flex-direction: column;
4735
4735
  gap: 6px;
@@ -4737,14 +4737,14 @@
4737
4737
  text-align: center;
4738
4738
  overflow-wrap: break-word;
4739
4739
  }
4740
- ._headline_dctyt_62 {
4740
+ ._headline_15sq4_62 {
4741
4741
  margin: 0;
4742
4742
  font-size: 36px;
4743
4743
  line-height: 1.1;
4744
4744
  font-weight: var(--font-weight-bold);
4745
4745
  color: var(--color-text-default);
4746
4746
  }
4747
- ._body_dctyt_70 {
4747
+ ._body_15sq4_70 {
4748
4748
  margin: 0;
4749
4749
  font-size: var(--type-paragraph-size);
4750
4750
  line-height: var(--type-paragraph-line);
@@ -4752,69 +4752,69 @@
4752
4752
  color: var(--color-text-default);
4753
4753
  white-space: pre-line;
4754
4754
  }
4755
- ._cta_dctyt_79 {
4755
+ ._cta_15sq4_79 {
4756
4756
  padding: var(--space-16) var(--space-16) var(--space-24);
4757
4757
  }
4758
- ._video_dctyt_83 {
4758
+ ._video_15sq4_83 {
4759
4759
  object-fit: cover;
4760
4760
  }
4761
- ._desktopOnly_dctyt_87 {
4761
+ ._desktopOnly_15sq4_87 {
4762
4762
  display: none;
4763
4763
  }
4764
4764
  @media (min-width: 1200px) {
4765
- ._hero_dctyt_1 {
4765
+ ._hero_15sq4_1 {
4766
4766
  justify-content: center;
4767
4767
  min-height: max(480px, calc(100svh - var(--vip-hero-top, 0px)));
4768
4768
  }
4769
- ._phoneOnly_dctyt_97 {
4769
+ ._phoneOnly_15sq4_97 {
4770
4770
  display: none;
4771
4771
  }
4772
- ._desktopOnly_dctyt_87 {
4772
+ ._desktopOnly_15sq4_87 {
4773
4773
  display: block;
4774
4774
  }
4775
- ._image_dctyt_11::after {
4775
+ ._image_15sq4_11::after {
4776
4776
  background:
4777
4777
  linear-gradient(
4778
4778
  to right,
4779
4779
  rgba(8, 14, 18, 0.9) 0,
4780
4780
  rgba(8, 14, 18, 0) 53.33%);
4781
4781
  }
4782
- ._image_dctyt_11 img,
4783
- ._video_dctyt_83 {
4782
+ ._image_15sq4_11 img,
4783
+ ._video_15sq4_83 {
4784
4784
  object-position: center;
4785
4785
  }
4786
- ._foot_dctyt_34 {
4786
+ ._foot_15sq4_34 {
4787
4787
  gap: var(--space-16);
4788
4788
  width: 100%;
4789
4789
  max-width: 624px;
4790
4790
  padding-left: 64px;
4791
4791
  }
4792
- ._text_dctyt_40 {
4792
+ ._text_15sq4_40 {
4793
4793
  align-items: flex-start;
4794
4794
  padding: 0;
4795
4795
  }
4796
- ._text_dctyt_40 ._logo_dctyt_48 {
4796
+ ._text_15sq4_40 ._logo_15sq4_48 {
4797
4797
  display: none;
4798
4798
  }
4799
- ._copy_dctyt_53 {
4799
+ ._copy_15sq4_53 {
4800
4800
  gap: var(--space-16);
4801
4801
  text-align: left;
4802
4802
  }
4803
- ._headline_dctyt_62 {
4803
+ ._headline_15sq4_62 {
4804
4804
  font-size: 64px;
4805
4805
  line-height: 0.9375;
4806
4806
  letter-spacing: -0.64px;
4807
4807
  }
4808
- ._body_dctyt_70 {
4808
+ ._body_15sq4_70 {
4809
4809
  max-width: 520px;
4810
4810
  font-size: 20px;
4811
4811
  line-height: 1.4;
4812
4812
  white-space: normal;
4813
4813
  }
4814
- ._cta_dctyt_79 {
4814
+ ._cta_15sq4_79 {
4815
4815
  padding: var(--space-8) 0 0;
4816
4816
  }
4817
- ._cta_dctyt_79 > * {
4817
+ ._cta_15sq4_79 > * {
4818
4818
  width: auto;
4819
4819
  min-width: 173px;
4820
4820
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nok-integration/storefront-react",
3
- "version": "0.29.10",
3
+ "version": "0.29.12",
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",