@behio/storefront-sdk 0.10.0 → 0.13.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.mjs CHANGED
@@ -1,9 +1,12 @@
1
+ import {
2
+ formatPrice
3
+ } from "./chunk-YJ45WIQZ.mjs";
1
4
  import {
2
5
  BehioStorefront
3
- } from "./chunk-O3IM7PAY.mjs";
6
+ } from "./chunk-XITY2WQN.mjs";
4
7
 
5
8
  // src/react/provider.tsx
6
- import { useRef, useEffect, useMemo } from "react";
9
+ import { useRef, useEffect, useMemo, useState, useCallback } from "react";
7
10
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
8
11
 
9
12
  // src/react/context.ts
@@ -97,7 +100,9 @@ function resolveStorage(option) {
97
100
  var STORAGE_KEYS = {
98
101
  ACCESS_TOKEN: "behio_access_token",
99
102
  REFRESH_TOKEN: "behio_refresh_token",
100
- CART_SESSION: "behio_cart_session"
103
+ CART_SESSION: "behio_cart_session",
104
+ /** Shopper's chosen currency. Cookie so SSR (getBehio) reads the same value. */
105
+ CURRENCY: "behio_currency"
101
106
  };
102
107
 
103
108
  // src/react/provider.tsx
@@ -105,20 +110,37 @@ import { jsx } from "react/jsx-runtime";
105
110
  function BehioProvider({
106
111
  apiKey,
107
112
  baseUrl,
113
+ shopDomain,
108
114
  locale,
109
115
  currency,
116
+ defaultCurrency,
117
+ currencies,
118
+ onCurrencyChange,
119
+ persistCurrency = true,
120
+ currencyCookieName = STORAGE_KEYS.CURRENCY,
110
121
  storage: storageOption,
111
122
  queryClient: externalQueryClient,
112
123
  children
113
124
  }) {
114
125
  const storageAdapter = useMemo(() => resolveStorage(storageOption), [storageOption]);
126
+ const resolveInitialCurrency = () => {
127
+ if (persistCurrency) {
128
+ const stored = cookieStorage.get(currencyCookieName);
129
+ if (stored) return stored;
130
+ }
131
+ return currency;
132
+ };
133
+ const [activeCurrency, setActiveCurrency] = useState(resolveInitialCurrency);
115
134
  const clientRef = useRef(null);
116
135
  if (!clientRef.current) {
117
136
  clientRef.current = new BehioStorefront({
118
137
  apiKey,
119
138
  baseUrl,
139
+ ...shopDomain ? { shopDomain } : {},
120
140
  locale,
121
- currency
141
+ // Seed with the resolved active currency so the very first request (even
142
+ // before effects run) carries it.
143
+ ...activeCurrency ? { currency: activeCurrency } : {}
122
144
  });
123
145
  }
124
146
  const client = clientRef.current;
@@ -133,6 +155,20 @@ function BehioProvider({
133
155
  client.setCartSession(cartSession);
134
156
  }
135
157
  }, [client, storageAdapter]);
158
+ useEffect(() => {
159
+ if (!persistCurrency) return;
160
+ const stored = cookieStorage.get(currencyCookieName);
161
+ if (stored && stored !== activeCurrency) {
162
+ setActiveCurrency(stored);
163
+ client.setCurrency(stored);
164
+ }
165
+ }, []);
166
+ useEffect(() => {
167
+ if (currency !== void 0 && currency !== activeCurrency) {
168
+ setActiveCurrency(currency);
169
+ client.setCurrency(currency);
170
+ }
171
+ }, [currency]);
136
172
  const queryClientRef = useRef(null);
137
173
  const qc = useMemo(() => {
138
174
  if (externalQueryClient) return externalQueryClient;
@@ -148,15 +184,35 @@ function BehioProvider({
148
184
  }
149
185
  return queryClientRef.current;
150
186
  }, [externalQueryClient]);
187
+ const setCurrency = useCallback(
188
+ (next) => {
189
+ setActiveCurrency(next);
190
+ client.setCurrency(next);
191
+ if (persistCurrency) {
192
+ if (next) cookieStorage.set(currencyCookieName, next);
193
+ else cookieStorage.remove(currencyCookieName);
194
+ }
195
+ onCurrencyChange?.(next);
196
+ void qc.invalidateQueries({ queryKey: ["behio"] });
197
+ },
198
+ [client, qc, persistCurrency, currencyCookieName, onCurrencyChange]
199
+ );
151
200
  const ctxValue = useMemo(
152
- () => ({ client, storage: storageAdapter }),
153
- [client, storageAdapter]
201
+ () => ({
202
+ client,
203
+ storage: storageAdapter,
204
+ currency: activeCurrency,
205
+ setCurrency,
206
+ configuredDefaultCurrency: defaultCurrency,
207
+ configuredCurrencies: currencies
208
+ }),
209
+ [client, storageAdapter, activeCurrency, setCurrency, defaultCurrency, currencies]
154
210
  );
155
211
  return /* @__PURE__ */ jsx(QueryClientProvider, { client: qc, children: /* @__PURE__ */ jsx(BehioContext.Provider, { value: ctxValue, children }) });
156
212
  }
157
213
 
158
214
  // src/react/hooks/use-products.ts
159
- import { useCallback, useMemo as useMemo2, useState } from "react";
215
+ import { useCallback as useCallback2, useMemo as useMemo2, useState as useState2 } from "react";
160
216
  import { useInfiniteQuery } from "@tanstack/react-query";
161
217
 
162
218
  // src/react/utils/unwrap.ts
@@ -177,7 +233,7 @@ async function unwrap(p) {
177
233
  function useProducts(query) {
178
234
  const { client } = useBehio();
179
235
  const { initialData, enabled, page: initialPage, limit, ...filters } = query ?? {};
180
- const [page, setPage] = useState(initialPage ?? 1);
236
+ const [page, setPage] = useState2(initialPage ?? 1);
181
237
  const serializedFilters = useMemo2(() => JSON.stringify({ ...filters, limit }), [filters, limit]);
182
238
  const infinite = useInfiniteQuery({
183
239
  queryKey: ["behio", "products", serializedFilters, page],
@@ -194,13 +250,13 @@ function useProducts(query) {
194
250
  );
195
251
  const lastPage = infinite.data?.pages[infinite.data.pages.length - 1];
196
252
  const firstPage = infinite.data?.pages[0];
197
- const loadMore = useCallback(() => {
253
+ const loadMore = useCallback2(() => {
198
254
  if (infinite.hasNextPage && !infinite.isFetchingNextPage) {
199
255
  return infinite.fetchNextPage();
200
256
  }
201
257
  return Promise.resolve();
202
258
  }, [infinite]);
203
- const goToPage = useCallback((newPage) => {
259
+ const goToPage = useCallback2((newPage) => {
204
260
  setPage(newPage);
205
261
  }, []);
206
262
  return {
@@ -243,7 +299,9 @@ import { useQuery } from "@tanstack/react-query";
243
299
  function useProduct(slug, options) {
244
300
  const { client } = useBehio();
245
301
  return useQuery({
246
- queryKey: ["behio", "product", slug],
302
+ // currency + locale belong in the key so switching either refetches the
303
+ // price/translation instead of serving a stale cache hit.
304
+ queryKey: ["behio", "product", slug, options?.locale, options?.currency],
247
305
  queryFn: () => unwrap(client.catalog.getProduct(slug, {
248
306
  locale: options?.locale,
249
307
  currency: options?.currency
@@ -319,12 +377,12 @@ function useFilters(options) {
319
377
  }
320
378
 
321
379
  // src/react/hooks/use-search.ts
322
- import { useState as useState2, useEffect as useEffect2 } from "react";
380
+ import { useState as useState3, useEffect as useEffect2 } from "react";
323
381
  import { useQuery as useQuery6 } from "@tanstack/react-query";
324
382
  function useSearch(query, options) {
325
383
  const { client } = useBehio();
326
384
  const debounceMs = options?.debounceMs ?? 300;
327
- const [debouncedQuery, setDebouncedQuery] = useState2(query);
385
+ const [debouncedQuery, setDebouncedQuery] = useState3(query);
328
386
  useEffect2(() => {
329
387
  if (debounceMs <= 0) {
330
388
  setDebouncedQuery(query);
@@ -344,7 +402,7 @@ function useSearch(query, options) {
344
402
  }
345
403
 
346
404
  // src/react/hooks/use-cart.ts
347
- import { useCallback as useCallback2 } from "react";
405
+ import { useCallback as useCallback3 } from "react";
348
406
  import { useQuery as useQuery7, useMutation, useQueryClient } from "@tanstack/react-query";
349
407
  var CART_KEY = ["behio", "cart"];
350
408
  function useCart(options) {
@@ -453,31 +511,31 @@ function useCart(options) {
453
511
  storage.remove(STORAGE_KEYS.CART_SESSION);
454
512
  }
455
513
  });
456
- const addItem = useCallback2(
514
+ const addItem = useCallback3(
457
515
  (productId, quantity) => addMutation.mutateAsync({ productId, quantity }),
458
516
  [addMutation]
459
517
  );
460
- const updateQuantity = useCallback2(
518
+ const updateQuantity = useCallback3(
461
519
  (itemId, quantity) => updateMutation.mutateAsync({ itemId, quantity }),
462
520
  [updateMutation]
463
521
  );
464
- const removeItem = useCallback2(
522
+ const removeItem = useCallback3(
465
523
  (itemId) => removeMutation.mutateAsync(itemId),
466
524
  [removeMutation]
467
525
  );
468
- const clear = useCallback2(
526
+ const clear = useCallback3(
469
527
  () => clearMutation.mutateAsync(),
470
528
  [clearMutation]
471
529
  );
472
- const applyDiscount = useCallback2(
530
+ const applyDiscount = useCallback3(
473
531
  (code) => applyDiscountMutation.mutateAsync(code),
474
532
  [applyDiscountMutation]
475
533
  );
476
- const removeDiscount = useCallback2(
534
+ const removeDiscount = useCallback3(
477
535
  () => removeDiscountMutation.mutateAsync(),
478
536
  [removeDiscountMutation]
479
537
  );
480
- const merge = useCallback2(
538
+ const merge = useCallback3(
481
539
  () => mergeMutation.mutateAsync(),
482
540
  [mergeMutation]
483
541
  );
@@ -520,7 +578,7 @@ function useCartCount(options) {
520
578
  }
521
579
 
522
580
  // src/react/hooks/use-auth.ts
523
- import { useCallback as useCallback3 } from "react";
581
+ import { useCallback as useCallback4 } from "react";
524
582
  import { useQuery as useQuery9, useMutation as useMutation2, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
525
583
  var CUSTOMER_KEY = ["behio", "customer"];
526
584
  var CART_KEY3 = ["behio", "cart"];
@@ -536,7 +594,7 @@ function useAuth() {
536
594
  queryFn: () => unwrap(client.customer.getProfile()),
537
595
  enabled: isLoggedIn
538
596
  });
539
- const persistTokens = useCallback3(
597
+ const persistTokens = useCallback4(
540
598
  (tokens) => {
541
599
  client.setTokens(tokens);
542
600
  storage.set(STORAGE_KEYS.ACCESS_TOKEN, tokens.accessToken);
@@ -544,7 +602,7 @@ function useAuth() {
544
602
  },
545
603
  [client, storage]
546
604
  );
547
- const clearAuth = useCallback3(() => {
605
+ const clearAuth = useCallback4(() => {
548
606
  client.clearTokens();
549
607
  storage.remove(STORAGE_KEYS.ACCESS_TOKEN);
550
608
  storage.remove(STORAGE_KEYS.REFRESH_TOKEN);
@@ -552,7 +610,7 @@ function useAuth() {
552
610
  queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
553
611
  queryClient.invalidateQueries({ queryKey: ["behio", "addresses"] });
554
612
  }, [client, storage, queryClient]);
555
- const postAuth = useCallback3(async () => {
613
+ const postAuth = useCallback4(async () => {
556
614
  await queryClient.invalidateQueries({ queryKey: [...CUSTOMER_KEY] });
557
615
  if (client.getCartSession()) {
558
616
  try {
@@ -597,27 +655,27 @@ function useAuth() {
597
655
  const verifyEmailMutation = useMutation2({
598
656
  mutationFn: (token) => unwrap(client.auth.verifyEmail(token))
599
657
  });
600
- const login = useCallback3(
658
+ const login = useCallback4(
601
659
  (email, password) => loginMutation.mutateAsync({ email, password }).then(() => void 0),
602
660
  [loginMutation]
603
661
  );
604
- const register = useCallback3(
662
+ const register = useCallback4(
605
663
  (input) => registerMutation.mutateAsync(input).then(() => void 0),
606
664
  [registerMutation]
607
665
  );
608
- const logout = useCallback3(
666
+ const logout = useCallback4(
609
667
  () => logoutMutation.mutateAsync().then(() => void 0),
610
668
  [logoutMutation]
611
669
  );
612
- const forgotPassword = useCallback3(
670
+ const forgotPassword = useCallback4(
613
671
  (email) => forgotPasswordMutation.mutateAsync(email).then(() => void 0),
614
672
  [forgotPasswordMutation]
615
673
  );
616
- const resetPassword = useCallback3(
674
+ const resetPassword = useCallback4(
617
675
  (token, newPassword) => resetPasswordMutation.mutateAsync({ token, newPassword }).then(() => void 0),
618
676
  [resetPasswordMutation]
619
677
  );
620
- const verifyEmail = useCallback3(
678
+ const verifyEmail = useCallback4(
621
679
  (token) => verifyEmailMutation.mutateAsync(token).then(() => void 0),
622
680
  [verifyEmailMutation]
623
681
  );
@@ -641,7 +699,7 @@ function useAuth() {
641
699
  }
642
700
 
643
701
  // src/react/hooks/use-customer.ts
644
- import { useCallback as useCallback4 } from "react";
702
+ import { useCallback as useCallback5 } from "react";
645
703
  import { useQuery as useQuery10, useMutation as useMutation3, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
646
704
  var CUSTOMER_KEY2 = ["behio", "customer"];
647
705
  function useCustomer(options) {
@@ -662,7 +720,7 @@ function useCustomer(options) {
662
720
  queryClient.setQueryData([...CUSTOMER_KEY2], updated);
663
721
  }
664
722
  });
665
- const updateProfile = useCallback4(
723
+ const updateProfile = useCallback5(
666
724
  (profileData) => updateMutation.mutateAsync(profileData),
667
725
  [updateMutation]
668
726
  );
@@ -676,7 +734,7 @@ function useCustomer(options) {
676
734
  }
677
735
 
678
736
  // src/react/hooks/use-addresses.ts
679
- import { useCallback as useCallback5 } from "react";
737
+ import { useCallback as useCallback6 } from "react";
680
738
  import { useQuery as useQuery11, useMutation as useMutation4, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
681
739
  var ADDRESSES_KEY = ["behio", "addresses"];
682
740
  function useAddresses(options) {
@@ -712,15 +770,15 @@ function useAddresses(options) {
712
770
  queryClient.invalidateQueries({ queryKey: [...ADDRESSES_KEY] });
713
771
  }
714
772
  });
715
- const createAddress = useCallback5(
773
+ const createAddress = useCallback6(
716
774
  (address) => createMutation.mutateAsync(address),
717
775
  [createMutation]
718
776
  );
719
- const updateAddress = useCallback5(
777
+ const updateAddress = useCallback6(
720
778
  (addressId, addressData) => updateMutation.mutateAsync({ addressId, data: addressData }),
721
779
  [updateMutation]
722
780
  );
723
- const deleteAddress = useCallback5(
781
+ const deleteAddress = useCallback6(
724
782
  (addressId) => deleteMutation.mutateAsync(addressId),
725
783
  [deleteMutation]
726
784
  );
@@ -737,16 +795,16 @@ function useAddresses(options) {
737
795
  }
738
796
 
739
797
  // src/react/hooks/use-address-autocomplete.ts
740
- import { useState as useState3, useEffect as useEffect3, useRef as useRef2, useCallback as useCallback6 } from "react";
798
+ import { useState as useState4, useEffect as useEffect3, useRef as useRef2, useCallback as useCallback7 } from "react";
741
799
  import { useQuery as useQuery12 } from "@tanstack/react-query";
742
800
  var AC_KEY = ["behio", "address-autocomplete"];
743
801
  function useAddressAutocomplete(options) {
744
802
  const { country, debounce = 300, minChars = 3, enabled = true } = options;
745
803
  const { client } = useBehio();
746
- const [query, setQuery] = useState3("");
747
- const [debouncedQuery, setDebouncedQuery] = useState3("");
748
- const [selected, setSelected] = useState3(null);
749
- const [isSelecting, setIsSelecting] = useState3(false);
804
+ const [query, setQuery] = useState4("");
805
+ const [debouncedQuery, setDebouncedQuery] = useState4("");
806
+ const [selected, setSelected] = useState4(null);
807
+ const [isSelecting, setIsSelecting] = useState4(false);
750
808
  const timerRef = useRef2(void 0);
751
809
  useEffect3(() => {
752
810
  if (timerRef.current) clearTimeout(timerRef.current);
@@ -768,7 +826,7 @@ function useAddressAutocomplete(options) {
768
826
  staleTime: 6e4
769
827
  // Cache suggestions for 1 min
770
828
  });
771
- const select = useCallback6(
829
+ const select = useCallback7(
772
830
  async (placeId) => {
773
831
  setIsSelecting(true);
774
832
  try {
@@ -783,7 +841,7 @@ function useAddressAutocomplete(options) {
783
841
  },
784
842
  [client]
785
843
  );
786
- const clear = useCallback6(() => {
844
+ const clear = useCallback7(() => {
787
845
  setQuery("");
788
846
  setDebouncedQuery("");
789
847
  setSelected(null);
@@ -801,12 +859,12 @@ function useAddressAutocomplete(options) {
801
859
  }
802
860
 
803
861
  // src/react/hooks/use-orders.ts
804
- import { useCallback as useCallback7, useMemo as useMemo3, useState as useState4 } from "react";
862
+ import { useCallback as useCallback8, useMemo as useMemo3, useState as useState5 } from "react";
805
863
  import { useInfiniteQuery as useInfiniteQuery2 } from "@tanstack/react-query";
806
864
  function useOrders(options) {
807
865
  const { client } = useBehio();
808
866
  const { page: initialPage, limit, enabled } = options ?? {};
809
- const [page, setPage] = useState4(initialPage ?? 1);
867
+ const [page, setPage] = useState5(initialPage ?? 1);
810
868
  const infinite = useInfiniteQuery2({
811
869
  queryKey: ["behio", "orders", limit, page],
812
870
  queryFn: ({ pageParam }) => unwrap(client.orders.list({ limit, page: pageParam })),
@@ -820,13 +878,13 @@ function useOrders(options) {
820
878
  [infinite.data]
821
879
  );
822
880
  const lastPage = infinite.data?.pages[infinite.data.pages.length - 1];
823
- const loadMore = useCallback7(() => {
881
+ const loadMore = useCallback8(() => {
824
882
  if (infinite.hasNextPage && !infinite.isFetchingNextPage) {
825
883
  return infinite.fetchNextPage();
826
884
  }
827
885
  return Promise.resolve();
828
886
  }, [infinite]);
829
- const goToPage = useCallback7((newPage) => {
887
+ const goToPage = useCallback8((newPage) => {
830
888
  setPage(newPage);
831
889
  }, []);
832
890
  return {
@@ -852,7 +910,7 @@ function useOrders(options) {
852
910
  }
853
911
 
854
912
  // src/react/hooks/use-order.ts
855
- import { useCallback as useCallback8 } from "react";
913
+ import { useCallback as useCallback9 } from "react";
856
914
  import { useQuery as useQuery13, useMutation as useMutation5, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
857
915
  function useOrder(orderNumber, options) {
858
916
  const { client } = useBehio();
@@ -873,7 +931,7 @@ function useOrder(orderNumber, options) {
873
931
  queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
874
932
  }
875
933
  });
876
- const cancel = useCallback8(
934
+ const cancel = useCallback9(
877
935
  () => cancelMutation.mutateAsync(),
878
936
  [cancelMutation]
879
937
  );
@@ -887,14 +945,14 @@ function useOrder(orderNumber, options) {
887
945
  }
888
946
 
889
947
  // src/react/hooks/use-order-access.ts
890
- import { useCallback as useCallback9, useState as useState5 } from "react";
948
+ import { useCallback as useCallback10, useState as useState6 } from "react";
891
949
  import { useMutation as useMutation6 } from "@tanstack/react-query";
892
950
  function useOrderAccess() {
893
951
  const { client } = useBehio();
894
- const [orderNumber, setOrderNumber] = useState5(null);
895
- const [email, setEmail] = useState5(null);
896
- const [order, setOrder] = useState5(null);
897
- const [accessToken, setAccessToken] = useState5(null);
952
+ const [orderNumber, setOrderNumber] = useState6(null);
953
+ const [email, setEmail] = useState6(null);
954
+ const [order, setOrder] = useState6(null);
955
+ const [accessToken, setAccessToken] = useState6(null);
898
956
  const requestMutation = useMutation6({
899
957
  mutationFn: (input) => unwrap(client.orders.requestAccessCode(input.orderNumber, input.email)),
900
958
  onSuccess: (_data, input) => {
@@ -914,12 +972,12 @@ function useOrderAccess() {
914
972
  setAccessToken(result.accessToken);
915
973
  }
916
974
  });
917
- const requestCode = useCallback9(
975
+ const requestCode = useCallback10(
918
976
  (on, em) => requestMutation.mutateAsync({ orderNumber: on, email: em }),
919
977
  [requestMutation]
920
978
  );
921
- const verifyCode = useCallback9((code) => verifyMutation.mutateAsync(code), [verifyMutation]);
922
- const reset = useCallback9(() => {
979
+ const verifyCode = useCallback10((code) => verifyMutation.mutateAsync(code), [verifyMutation]);
980
+ const reset = useCallback10(() => {
923
981
  setOrderNumber(null);
924
982
  setEmail(null);
925
983
  setOrder(null);
@@ -947,12 +1005,12 @@ function useOrderAccess() {
947
1005
  }
948
1006
 
949
1007
  // src/react/hooks/use-checkout.ts
950
- import { useState as useState6, useCallback as useCallback10 } from "react";
1008
+ import { useState as useState7, useCallback as useCallback11 } from "react";
951
1009
  import { useMutation as useMutation7, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
952
1010
  function useCheckout() {
953
1011
  const { client, storage } = useBehio();
954
1012
  const queryClient = useQueryClient8();
955
- const [order, setOrder] = useState6(null);
1013
+ const [order, setOrder] = useState7(null);
956
1014
  const mutation = useMutation7({
957
1015
  mutationFn: (input) => unwrap(client.checkout.createOrder(input)),
958
1016
  onSuccess: (result) => {
@@ -962,11 +1020,11 @@ function useCheckout() {
962
1020
  queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
963
1021
  }
964
1022
  });
965
- const createOrder = useCallback10(
1023
+ const createOrder = useCallback11(
966
1024
  (input) => mutation.mutateAsync(input),
967
1025
  [mutation]
968
1026
  );
969
- const reset = useCallback10(() => {
1027
+ const reset = useCallback11(() => {
970
1028
  setOrder(null);
971
1029
  mutation.reset();
972
1030
  }, [mutation]);
@@ -1025,6 +1083,57 @@ function useShopSeo(options) {
1025
1083
  });
1026
1084
  }
1027
1085
 
1086
+ // src/react/hooks/use-currency.ts
1087
+ function dedupe(values) {
1088
+ const out = [];
1089
+ for (const v of values) {
1090
+ if (v && !out.includes(v)) out.push(v);
1091
+ }
1092
+ return out;
1093
+ }
1094
+ function useCurrency() {
1095
+ const { currency, setCurrency, configuredDefaultCurrency, configuredCurrencies } = useBehio();
1096
+ const { data: shop, isLoading } = useShopInfo();
1097
+ const defaultCurrency = configuredDefaultCurrency ?? shop?.defaultCurrency;
1098
+ const currencies = configuredCurrencies && configuredCurrencies.length > 0 ? dedupe(configuredCurrencies) : dedupe([defaultCurrency, ...shop?.supportedCurrencies ?? []]);
1099
+ return {
1100
+ currency,
1101
+ effectiveCurrency: currency ?? defaultCurrency,
1102
+ setCurrency,
1103
+ currencies,
1104
+ defaultCurrency,
1105
+ isLoading
1106
+ };
1107
+ }
1108
+
1109
+ // src/react/components/currency-switcher.tsx
1110
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
1111
+ function CurrencySwitcher({
1112
+ className,
1113
+ labels,
1114
+ showWhenSingle = false,
1115
+ ariaLabel = "Currency",
1116
+ children
1117
+ }) {
1118
+ const { currencies, effectiveCurrency, setCurrency } = useCurrency();
1119
+ if (currencies.length === 0) return null;
1120
+ if (currencies.length <= 1 && !showWhenSingle) return null;
1121
+ const label = (code) => labels?.[code] ?? code;
1122
+ if (children) {
1123
+ return /* @__PURE__ */ jsx2(Fragment, { children: children({ currencies, value: effectiveCurrency, setCurrency, label }) });
1124
+ }
1125
+ return /* @__PURE__ */ jsx2(
1126
+ "select",
1127
+ {
1128
+ className,
1129
+ "aria-label": ariaLabel,
1130
+ value: effectiveCurrency ?? "",
1131
+ onChange: (e) => setCurrency(e.target.value),
1132
+ children: currencies.map((code) => /* @__PURE__ */ jsx2("option", { value: code, children: label(code) }, code))
1133
+ }
1134
+ );
1135
+ }
1136
+
1028
1137
  // src/react/hooks/use-bundles.ts
1029
1138
  import { useQuery as useQuery17 } from "@tanstack/react-query";
1030
1139
  function useBundles(options) {
@@ -1214,23 +1323,9 @@ function useNotifyWhenAvailable() {
1214
1323
  function useBehioClient() {
1215
1324
  return useBehio().client;
1216
1325
  }
1217
-
1218
- // src/react/utils/format-price.ts
1219
- function formatPrice(amount, currency, locale) {
1220
- const resolvedLocale = locale ?? "cs";
1221
- try {
1222
- return new Intl.NumberFormat(resolvedLocale, {
1223
- style: "currency",
1224
- currency,
1225
- minimumFractionDigits: Number.isInteger(amount) ? 0 : 2,
1226
- maximumFractionDigits: 2
1227
- }).format(amount);
1228
- } catch {
1229
- return `${amount} ${currency}`;
1230
- }
1231
- }
1232
1326
  export {
1233
1327
  BehioProvider,
1328
+ CurrencySwitcher,
1234
1329
  cookieStorage,
1235
1330
  createMemoryStorage,
1236
1331
  detectStorage,
@@ -1251,6 +1346,7 @@ export {
1251
1346
  useCheckout,
1252
1347
  useCookieConsent,
1253
1348
  useCrossSell,
1349
+ useCurrency,
1254
1350
  useCustomer,
1255
1351
  useFeatured,
1256
1352
  useFilters,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@behio/storefront-sdk",
3
- "version": "0.10.0",
3
+ "version": "0.13.0",
4
4
  "description": "TypeScript SDK for Behio Headless E-Shop — core client + React hooks",
5
5
  "author": "Behio",
6
6
  "license": "MIT",