@behio/storefront-sdk 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.d.mts CHANGED
@@ -4153,6 +4153,13 @@ declare function useCart(options?: UseCartOptions): {
4153
4153
  updateQuantity: (itemId: string, quantity: number) => Promise<Cart>;
4154
4154
  removeItem: (itemId: string) => Promise<Cart>;
4155
4155
  clear: () => Promise<void>;
4156
+ addBundle: (bundle: string | {
4157
+ id: string;
4158
+ } | {
4159
+ slug: string;
4160
+ }, quantity?: number) => Promise<Cart>;
4161
+ updateBundleQuantity: (lineId: string, quantity: number) => Promise<Cart>;
4162
+ removeBundle: (lineId: string) => Promise<Cart>;
4156
4163
  applyDiscount: (code: string) => Promise<Cart>;
4157
4164
  removeDiscount: () => Promise<Cart>;
4158
4165
  merge: () => Promise<Cart>;
@@ -4161,6 +4168,7 @@ declare function useCart(options?: UseCartOptions): {
4161
4168
  isAdding: boolean;
4162
4169
  isUpdating: boolean;
4163
4170
  isRemoving: boolean;
4171
+ isUpdatingBundle: boolean;
4164
4172
  };
4165
4173
 
4166
4174
  interface UseCartCountOptions {
package/dist/react.d.ts CHANGED
@@ -4153,6 +4153,13 @@ declare function useCart(options?: UseCartOptions): {
4153
4153
  updateQuantity: (itemId: string, quantity: number) => Promise<Cart>;
4154
4154
  removeItem: (itemId: string) => Promise<Cart>;
4155
4155
  clear: () => Promise<void>;
4156
+ addBundle: (bundle: string | {
4157
+ id: string;
4158
+ } | {
4159
+ slug: string;
4160
+ }, quantity?: number) => Promise<Cart>;
4161
+ updateBundleQuantity: (lineId: string, quantity: number) => Promise<Cart>;
4162
+ removeBundle: (lineId: string) => Promise<Cart>;
4156
4163
  applyDiscount: (code: string) => Promise<Cart>;
4157
4164
  removeDiscount: () => Promise<Cart>;
4158
4165
  merge: () => Promise<Cart>;
@@ -4161,6 +4168,7 @@ declare function useCart(options?: UseCartOptions): {
4161
4168
  isAdding: boolean;
4162
4169
  isUpdating: boolean;
4163
4170
  isRemoving: boolean;
4171
+ isUpdatingBundle: boolean;
4164
4172
  };
4165
4173
 
4166
4174
  interface UseCartCountOptions {
package/dist/react.js CHANGED
@@ -2799,6 +2799,16 @@ function useCart(options) {
2799
2799
  queryClient.setQueryData([...CART_KEY], result);
2800
2800
  void refreshBundleQueries(queryClient);
2801
2801
  };
2802
+ (0, import_react5.useEffect)(
2803
+ () => client.on("cart:updated", (data) => {
2804
+ if (!data || typeof data !== "object" || !("items" in data)) return;
2805
+ const session = client.getCartSession();
2806
+ if (session) storage.set(STORAGE_KEYS.CART_SESSION, session);
2807
+ void acceptCart(data);
2808
+ }),
2809
+ // acceptCart only closes over queryClient, which is stable per provider.
2810
+ [client, queryClient, storage]
2811
+ );
2802
2812
  const addMutation = (0, import_react_query12.useMutation)({
2803
2813
  mutationFn: async ({ productId, quantity }) => {
2804
2814
  return unwrap(client.cart.addItem({ productId, quantity: quantity ?? 1 }));
@@ -2831,6 +2841,26 @@ function useCart(options) {
2831
2841
  queryClient.invalidateQueries({ queryKey: [...CART_KEY] });
2832
2842
  }
2833
2843
  });
2844
+ const acceptBundleCart = async (result) => {
2845
+ const session = result.newSessionToken ?? result.sessionToken;
2846
+ if (session) storage.set(STORAGE_KEYS.CART_SESSION, session);
2847
+ await acceptCart(result);
2848
+ };
2849
+ const addBundleMutation = (0, import_react_query12.useMutation)({
2850
+ mutationFn: async ({ bundle, quantity }) => unwrap(client.cart.addBundle(bundle, quantity ?? 1)),
2851
+ onMutate: cancelCartRead,
2852
+ onSuccess: acceptBundleCart
2853
+ });
2854
+ const updateBundleMutation = (0, import_react_query12.useMutation)({
2855
+ mutationFn: async ({ lineId, quantity }) => unwrap(client.cart.updateBundleQuantity(lineId, quantity)),
2856
+ onMutate: cancelCartRead,
2857
+ onSuccess: acceptBundleCart
2858
+ });
2859
+ const removeBundleMutation = (0, import_react_query12.useMutation)({
2860
+ mutationFn: async (lineId) => unwrap(client.cart.removeBundle(lineId)),
2861
+ onMutate: cancelCartRead,
2862
+ onSuccess: acceptBundleCart
2863
+ });
2834
2864
  const clearMutation = (0, import_react_query12.useMutation)({
2835
2865
  mutationFn: () => unwrap(client.cart.clear()),
2836
2866
  onMutate: cancelCartRead,
@@ -2879,6 +2909,18 @@ function useCart(options) {
2879
2909
  () => clearMutation.mutateAsync(),
2880
2910
  [clearMutation]
2881
2911
  );
2912
+ const addBundle = (0, import_react5.useCallback)(
2913
+ (bundle, quantity) => addBundleMutation.mutateAsync({ bundle, quantity }),
2914
+ [addBundleMutation]
2915
+ );
2916
+ const updateBundleQuantity = (0, import_react5.useCallback)(
2917
+ (lineId, quantity) => updateBundleMutation.mutateAsync({ lineId, quantity }),
2918
+ [updateBundleMutation]
2919
+ );
2920
+ const removeBundle = (0, import_react5.useCallback)(
2921
+ (lineId) => removeBundleMutation.mutateAsync(lineId),
2922
+ [removeBundleMutation]
2923
+ );
2882
2924
  const applyDiscount = (0, import_react5.useCallback)(
2883
2925
  (code) => applyDiscountMutation.mutateAsync(code),
2884
2926
  [applyDiscountMutation]
@@ -2900,6 +2942,9 @@ function useCart(options) {
2900
2942
  updateQuantity,
2901
2943
  removeItem,
2902
2944
  clear,
2945
+ addBundle,
2946
+ updateBundleQuantity,
2947
+ removeBundle,
2903
2948
  applyDiscount,
2904
2949
  removeDiscount,
2905
2950
  merge,
@@ -2909,7 +2954,8 @@ function useCart(options) {
2909
2954
  // Mutation states
2910
2955
  isAdding: addMutation.isPending,
2911
2956
  isUpdating: updateMutation.isPending,
2912
- isRemoving: removeMutation.isPending
2957
+ isRemoving: removeMutation.isPending,
2958
+ isUpdatingBundle: addBundleMutation.isPending || updateBundleMutation.isPending || removeBundleMutation.isPending
2913
2959
  };
2914
2960
  }
2915
2961
 
package/dist/react.mjs CHANGED
@@ -2658,7 +2658,7 @@ function useSearch(query, options) {
2658
2658
  }
2659
2659
 
2660
2660
  // src/react/hooks/use-cart.ts
2661
- import { useCallback as useCallback3 } from "react";
2661
+ import { useCallback as useCallback3, useEffect as useEffect3 } from "react";
2662
2662
  import { useQuery as useQuery10, useMutation, useQueryClient } from "@tanstack/react-query";
2663
2663
 
2664
2664
  // src/react/utils/refresh-bundle-queries.ts
@@ -2689,6 +2689,16 @@ function useCart(options) {
2689
2689
  queryClient.setQueryData([...CART_KEY], result);
2690
2690
  void refreshBundleQueries(queryClient);
2691
2691
  };
2692
+ useEffect3(
2693
+ () => client.on("cart:updated", (data) => {
2694
+ if (!data || typeof data !== "object" || !("items" in data)) return;
2695
+ const session = client.getCartSession();
2696
+ if (session) storage.set(STORAGE_KEYS.CART_SESSION, session);
2697
+ void acceptCart(data);
2698
+ }),
2699
+ // acceptCart only closes over queryClient, which is stable per provider.
2700
+ [client, queryClient, storage]
2701
+ );
2692
2702
  const addMutation = useMutation({
2693
2703
  mutationFn: async ({ productId, quantity }) => {
2694
2704
  return unwrap(client.cart.addItem({ productId, quantity: quantity ?? 1 }));
@@ -2721,6 +2731,26 @@ function useCart(options) {
2721
2731
  queryClient.invalidateQueries({ queryKey: [...CART_KEY] });
2722
2732
  }
2723
2733
  });
2734
+ const acceptBundleCart = async (result) => {
2735
+ const session = result.newSessionToken ?? result.sessionToken;
2736
+ if (session) storage.set(STORAGE_KEYS.CART_SESSION, session);
2737
+ await acceptCart(result);
2738
+ };
2739
+ const addBundleMutation = useMutation({
2740
+ mutationFn: async ({ bundle, quantity }) => unwrap(client.cart.addBundle(bundle, quantity ?? 1)),
2741
+ onMutate: cancelCartRead,
2742
+ onSuccess: acceptBundleCart
2743
+ });
2744
+ const updateBundleMutation = useMutation({
2745
+ mutationFn: async ({ lineId, quantity }) => unwrap(client.cart.updateBundleQuantity(lineId, quantity)),
2746
+ onMutate: cancelCartRead,
2747
+ onSuccess: acceptBundleCart
2748
+ });
2749
+ const removeBundleMutation = useMutation({
2750
+ mutationFn: async (lineId) => unwrap(client.cart.removeBundle(lineId)),
2751
+ onMutate: cancelCartRead,
2752
+ onSuccess: acceptBundleCart
2753
+ });
2724
2754
  const clearMutation = useMutation({
2725
2755
  mutationFn: () => unwrap(client.cart.clear()),
2726
2756
  onMutate: cancelCartRead,
@@ -2769,6 +2799,18 @@ function useCart(options) {
2769
2799
  () => clearMutation.mutateAsync(),
2770
2800
  [clearMutation]
2771
2801
  );
2802
+ const addBundle = useCallback3(
2803
+ (bundle, quantity) => addBundleMutation.mutateAsync({ bundle, quantity }),
2804
+ [addBundleMutation]
2805
+ );
2806
+ const updateBundleQuantity = useCallback3(
2807
+ (lineId, quantity) => updateBundleMutation.mutateAsync({ lineId, quantity }),
2808
+ [updateBundleMutation]
2809
+ );
2810
+ const removeBundle = useCallback3(
2811
+ (lineId) => removeBundleMutation.mutateAsync(lineId),
2812
+ [removeBundleMutation]
2813
+ );
2772
2814
  const applyDiscount = useCallback3(
2773
2815
  (code) => applyDiscountMutation.mutateAsync(code),
2774
2816
  [applyDiscountMutation]
@@ -2790,6 +2832,9 @@ function useCart(options) {
2790
2832
  updateQuantity,
2791
2833
  removeItem,
2792
2834
  clear,
2835
+ addBundle,
2836
+ updateBundleQuantity,
2837
+ removeBundle,
2793
2838
  applyDiscount,
2794
2839
  removeDiscount,
2795
2840
  merge,
@@ -2799,7 +2844,8 @@ function useCart(options) {
2799
2844
  // Mutation states
2800
2845
  isAdding: addMutation.isPending,
2801
2846
  isUpdating: updateMutation.isPending,
2802
- isRemoving: removeMutation.isPending
2847
+ isRemoving: removeMutation.isPending,
2848
+ isUpdatingBundle: addBundleMutation.isPending || updateBundleMutation.isPending || removeBundleMutation.isPending
2803
2849
  };
2804
2850
  }
2805
2851
 
@@ -3064,7 +3110,7 @@ function useAddresses(options) {
3064
3110
  }
3065
3111
 
3066
3112
  // src/react/hooks/use-address-autocomplete.ts
3067
- import { useState as useState4, useEffect as useEffect3, useRef as useRef2, useCallback as useCallback7 } from "react";
3113
+ import { useState as useState4, useEffect as useEffect4, useRef as useRef2, useCallback as useCallback7 } from "react";
3068
3114
  import { useQuery as useQuery15 } from "@tanstack/react-query";
3069
3115
  var AC_KEY = ["behio", "address-autocomplete"];
3070
3116
  function useAddressAutocomplete(options) {
@@ -3075,7 +3121,7 @@ function useAddressAutocomplete(options) {
3075
3121
  const [selected, setSelected] = useState4(null);
3076
3122
  const [isSelecting, setIsSelecting] = useState4(false);
3077
3123
  const timerRef = useRef2(void 0);
3078
- useEffect3(() => {
3124
+ useEffect4(() => {
3079
3125
  if (timerRef.current) clearTimeout(timerRef.current);
3080
3126
  if (query.length < minChars) {
3081
3127
  setDebouncedQuery("");
@@ -3503,14 +3549,14 @@ function usePaymentMethods(options) {
3503
3549
  }
3504
3550
 
3505
3551
  // src/react/hooks/use-personal-offers.ts
3506
- import { useCallback as useCallback8, useEffect as useEffect4, useState as useState5 } from "react";
3552
+ import { useCallback as useCallback8, useEffect as useEffect5, useState as useState5 } from "react";
3507
3553
  import { useMutation as useMutation10, useQuery as useQuery26, useQueryClient as useQueryClient12 } from "@tanstack/react-query";
3508
3554
  function usePersonalOffers(options) {
3509
3555
  const { client } = useBehio();
3510
3556
  const queryClient = useQueryClient12();
3511
3557
  const [polledVid, setPolledVid] = useState5(null);
3512
3558
  const explicitVid = options?.visitorId;
3513
- useEffect4(() => {
3559
+ useEffect5(() => {
3514
3560
  if (explicitVid) return;
3515
3561
  const read = () => {
3516
3562
  const vid = client.getAnalyticsVisitorId();
@@ -3562,7 +3608,7 @@ function usePersonalOffers(options) {
3562
3608
  }
3563
3609
 
3564
3610
  // src/react/hooks/use-visitor-messages.ts
3565
- import { useCallback as useCallback9, useEffect as useEffect5, useRef as useRef3, useState as useState6 } from "react";
3611
+ import { useCallback as useCallback9, useEffect as useEffect6, useRef as useRef3, useState as useState6 } from "react";
3566
3612
  import { useQuery as useQuery27, useQueryClient as useQueryClient13 } from "@tanstack/react-query";
3567
3613
  function useVisitorMessages(options) {
3568
3614
  const { client } = useBehio();
@@ -3570,7 +3616,7 @@ function useVisitorMessages(options) {
3570
3616
  const [polledVid, setPolledVid] = useState6(null);
3571
3617
  const seenRef = useRef3(/* @__PURE__ */ new Set());
3572
3618
  const explicitVid = options?.visitorId;
3573
- useEffect5(() => {
3619
+ useEffect6(() => {
3574
3620
  if (explicitVid) return;
3575
3621
  const read = () => {
3576
3622
  const vid = client.getAnalyticsVisitorId();
@@ -3607,7 +3653,7 @@ function useVisitorMessages(options) {
3607
3653
  );
3608
3654
  const onMessage = options?.onMessage;
3609
3655
  const dispatchDom = options?.dispatchDomEvents !== false;
3610
- useEffect5(() => {
3656
+ useEffect6(() => {
3611
3657
  for (const message of data?.items ?? []) {
3612
3658
  if (seenRef.current.has(message.id)) continue;
3613
3659
  seenRef.current.add(message.id);
@@ -4093,7 +4139,7 @@ function CurrencySwitcher({
4093
4139
  }
4094
4140
 
4095
4141
  // src/react/components/storefront-scripts.tsx
4096
- import { useEffect as useEffect6, useMemo as useMemo5, useRef as useRef4, useState as useState10 } from "react";
4142
+ import { useEffect as useEffect7, useMemo as useMemo5, useRef as useRef4, useState as useState10 } from "react";
4097
4143
 
4098
4144
  // src/react/hooks/use-consent.ts
4099
4145
  import { useQuery as useQuery35, useMutation as useMutation16, useQueryClient as useQueryClient16 } from "@tanstack/react-query";
@@ -4185,7 +4231,7 @@ function injectHtml(target, html, start = false) {
4185
4231
  function StorefrontScripts({ visitorId: visitorIdProp, initialScripts } = {}) {
4186
4232
  const { data } = useShopScripts({ enabled: initialScripts === void 0, initialData: initialScripts ? { scripts: initialScripts } : void 0 });
4187
4233
  const [visitorId, setVisitorId] = useState10(visitorIdProp ?? "");
4188
- useEffect6(() => {
4234
+ useEffect7(() => {
4189
4235
  if (visitorIdProp) return;
4190
4236
  try {
4191
4237
  const v = localStorage.getItem(VISITOR_KEY);
@@ -4205,7 +4251,7 @@ function StorefrontScripts({ visitorId: visitorIdProp, initialScripts } = {}) {
4205
4251
  [scripts]
4206
4252
  );
4207
4253
  const activeConsented = useRef4(/* @__PURE__ */ new Set());
4208
- useEffect6(() => {
4254
+ useEffect7(() => {
4209
4255
  if (typeof document === "undefined") return;
4210
4256
  const nextConsented = new Set(scripts.filter((s) => s.consentRequired).map((s) => s.id));
4211
4257
  const revoked = [...activeConsented.current].some((id) => !nextConsented.has(id));
@@ -4229,7 +4275,7 @@ function StorefrontScripts({ visitorId: visitorIdProp, initialScripts } = {}) {
4229
4275
  }
4230
4276
 
4231
4277
  // src/react/components/behio-analytics.tsx
4232
- import { useEffect as useEffect7 } from "react";
4278
+ import { useEffect as useEffect8 } from "react";
4233
4279
 
4234
4280
  // src/react/hooks/use-behio-client.ts
4235
4281
  function useBehioClient() {
@@ -4239,7 +4285,7 @@ function useBehioClient() {
4239
4285
  // src/react/components/behio-analytics.tsx
4240
4286
  function BehioAnalyticsTracker() {
4241
4287
  const client = useBehioClient();
4242
- useEffect7(() => {
4288
+ useEffect8(() => {
4243
4289
  if (typeof window === "undefined") return;
4244
4290
  const w = window;
4245
4291
  if (w.__behioAnalytics) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@behio/storefront-sdk",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "TypeScript SDK for Behio headless e-commerce: core client + React hooks",
5
5
  "author": "Behio",
6
6
  "license": "MIT",