@behio/storefront-sdk 0.1.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 ADDED
@@ -0,0 +1,813 @@
1
+ import {
2
+ BehioStorefront
3
+ } from "./chunk-3OJEEMLI.mjs";
4
+
5
+ // src/react/provider.tsx
6
+ import { useRef, useEffect, useMemo } from "react";
7
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
8
+
9
+ // src/react/context.ts
10
+ import { createContext, useContext } from "react";
11
+ var BehioContext = createContext(null);
12
+ function useBehio() {
13
+ const ctx = useContext(BehioContext);
14
+ if (!ctx) {
15
+ throw new Error("useBehio must be used within a <BehioProvider>");
16
+ }
17
+ return ctx;
18
+ }
19
+
20
+ // src/react/storage.ts
21
+ function getCookie(name) {
22
+ if (typeof document === "undefined") return null;
23
+ const match = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^;]*)"));
24
+ return match ? decodeURIComponent(match[1]) : null;
25
+ }
26
+ function setCookie(name, value, maxAgeDays = 30) {
27
+ if (typeof document === "undefined") return;
28
+ const maxAge = maxAgeDays * 24 * 60 * 60;
29
+ document.cookie = `${name}=${encodeURIComponent(value)}; path=/; max-age=${maxAge}; SameSite=Lax`;
30
+ }
31
+ function removeCookie(name) {
32
+ if (typeof document === "undefined") return;
33
+ document.cookie = `${name}=; path=/; max-age=0; SameSite=Lax`;
34
+ }
35
+ var cookieStorage = {
36
+ get: getCookie,
37
+ set: setCookie,
38
+ remove: removeCookie
39
+ };
40
+ var localStorageAdapter = {
41
+ get(key) {
42
+ try {
43
+ return window.localStorage.getItem(key);
44
+ } catch {
45
+ return null;
46
+ }
47
+ },
48
+ set(key, value) {
49
+ try {
50
+ window.localStorage.setItem(key, value);
51
+ } catch {
52
+ }
53
+ },
54
+ remove(key) {
55
+ try {
56
+ window.localStorage.removeItem(key);
57
+ } catch {
58
+ }
59
+ }
60
+ };
61
+ function createMemoryStorage() {
62
+ const store = /* @__PURE__ */ new Map();
63
+ return {
64
+ get(key) {
65
+ return store.get(key) ?? null;
66
+ },
67
+ set(key, value) {
68
+ store.set(key, value);
69
+ },
70
+ remove(key) {
71
+ store.delete(key);
72
+ }
73
+ };
74
+ }
75
+ var memoryStorage = createMemoryStorage();
76
+ function detectStorage() {
77
+ if (typeof document !== "undefined") {
78
+ return cookieStorage;
79
+ }
80
+ if (typeof window !== "undefined" && window.localStorage) {
81
+ return localStorageAdapter;
82
+ }
83
+ return createMemoryStorage();
84
+ }
85
+ function resolveStorage(option) {
86
+ if (!option) return detectStorage();
87
+ if (typeof option === "object") return option;
88
+ switch (option) {
89
+ case "cookies":
90
+ return cookieStorage;
91
+ case "localStorage":
92
+ return localStorageAdapter;
93
+ case "memory":
94
+ return createMemoryStorage();
95
+ }
96
+ }
97
+ var STORAGE_KEYS = {
98
+ ACCESS_TOKEN: "behio_access_token",
99
+ REFRESH_TOKEN: "behio_refresh_token",
100
+ CART_SESSION: "behio_cart_session"
101
+ };
102
+
103
+ // src/react/provider.tsx
104
+ import { jsx } from "react/jsx-runtime";
105
+ function BehioProvider({
106
+ apiKey,
107
+ baseUrl,
108
+ locale,
109
+ currency,
110
+ storage: storageOption,
111
+ queryClient: externalQueryClient,
112
+ children
113
+ }) {
114
+ const storageAdapter = useMemo(() => resolveStorage(storageOption), [storageOption]);
115
+ const clientRef = useRef(null);
116
+ if (!clientRef.current) {
117
+ clientRef.current = new BehioStorefront({
118
+ apiKey,
119
+ baseUrl,
120
+ locale,
121
+ currency
122
+ });
123
+ }
124
+ const client = clientRef.current;
125
+ useEffect(() => {
126
+ const accessToken = storageAdapter.get(STORAGE_KEYS.ACCESS_TOKEN);
127
+ const refreshToken = storageAdapter.get(STORAGE_KEYS.REFRESH_TOKEN);
128
+ if (accessToken && refreshToken) {
129
+ client.setTokens({ accessToken, refreshToken });
130
+ }
131
+ const cartSession = storageAdapter.get(STORAGE_KEYS.CART_SESSION);
132
+ if (cartSession) {
133
+ client.setCartSession(cartSession);
134
+ }
135
+ }, [client, storageAdapter]);
136
+ const queryClientRef = useRef(null);
137
+ const qc = useMemo(() => {
138
+ if (externalQueryClient) return externalQueryClient;
139
+ if (!queryClientRef.current) {
140
+ queryClientRef.current = new QueryClient({
141
+ defaultOptions: {
142
+ queries: {
143
+ staleTime: 6e4,
144
+ retry: 1
145
+ }
146
+ }
147
+ });
148
+ }
149
+ return queryClientRef.current;
150
+ }, [externalQueryClient]);
151
+ const ctxValue = useMemo(
152
+ () => ({ client, storage: storageAdapter }),
153
+ [client, storageAdapter]
154
+ );
155
+ return /* @__PURE__ */ jsx(QueryClientProvider, { client: qc, children: /* @__PURE__ */ jsx(BehioContext.Provider, { value: ctxValue, children }) });
156
+ }
157
+
158
+ // src/react/hooks/use-products.ts
159
+ import { useQuery } from "@tanstack/react-query";
160
+ function useProducts(query) {
161
+ const { client } = useBehio();
162
+ const { initialData, enabled, ...productsQuery } = query ?? {};
163
+ const serializedQuery = JSON.stringify(productsQuery);
164
+ return useQuery({
165
+ queryKey: ["behio", "products", serializedQuery],
166
+ queryFn: () => client.catalog.getProducts(productsQuery),
167
+ initialData,
168
+ enabled
169
+ });
170
+ }
171
+
172
+ // src/react/hooks/use-product.ts
173
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
174
+ function useProduct(slug, options) {
175
+ const { client } = useBehio();
176
+ return useQuery2({
177
+ queryKey: ["behio", "product", slug],
178
+ queryFn: () => client.catalog.getProduct(slug, {
179
+ locale: options?.locale,
180
+ currency: options?.currency
181
+ }),
182
+ initialData: options?.initialData,
183
+ enabled: options?.enabled ?? !!slug
184
+ });
185
+ }
186
+
187
+ // src/react/hooks/use-categories.ts
188
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
189
+ function useCategories(locale) {
190
+ const { client } = useBehio();
191
+ return useQuery3({
192
+ queryKey: ["behio", "categories", locale],
193
+ queryFn: async () => {
194
+ const result = await client.catalog.getCategories(locale);
195
+ return result.categories;
196
+ }
197
+ });
198
+ }
199
+
200
+ // src/react/hooks/use-labels.ts
201
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
202
+ function useLabels(locale) {
203
+ const { client } = useBehio();
204
+ return useQuery4({
205
+ queryKey: ["behio", "labels", locale],
206
+ queryFn: async () => {
207
+ const result = await client.catalog.getLabels(locale);
208
+ return result.labels;
209
+ }
210
+ });
211
+ }
212
+
213
+ // src/react/hooks/use-featured.ts
214
+ import { useQuery as useQuery5 } from "@tanstack/react-query";
215
+ function useFeatured(options) {
216
+ const { client } = useBehio();
217
+ return useQuery5({
218
+ queryKey: ["behio", "featured", options?.locale, options?.currency],
219
+ queryFn: () => client.catalog.getFeatured({
220
+ locale: options?.locale,
221
+ currency: options?.currency
222
+ }),
223
+ initialData: options?.initialData,
224
+ enabled: options?.enabled
225
+ });
226
+ }
227
+
228
+ // src/react/hooks/use-filters.ts
229
+ import { useQuery as useQuery6 } from "@tanstack/react-query";
230
+ function useFilters() {
231
+ const { client } = useBehio();
232
+ return useQuery6({
233
+ queryKey: ["behio", "filters"],
234
+ queryFn: async () => {
235
+ const result = await client.catalog.getFilters();
236
+ return result.filters;
237
+ }
238
+ });
239
+ }
240
+
241
+ // src/react/hooks/use-search.ts
242
+ import { useState, useEffect as useEffect2 } from "react";
243
+ import { useQuery as useQuery7 } from "@tanstack/react-query";
244
+ function useSearch(query, options) {
245
+ const { client } = useBehio();
246
+ const debounceMs = options?.debounceMs ?? 300;
247
+ const [debouncedQuery, setDebouncedQuery] = useState(query);
248
+ useEffect2(() => {
249
+ if (debounceMs <= 0) {
250
+ setDebouncedQuery(query);
251
+ return;
252
+ }
253
+ const timer = setTimeout(() => setDebouncedQuery(query), debounceMs);
254
+ return () => clearTimeout(timer);
255
+ }, [query, debounceMs]);
256
+ return useQuery7({
257
+ queryKey: ["behio", "search", debouncedQuery, options?.page, options?.limit],
258
+ queryFn: () => client.catalog.search(debouncedQuery, {
259
+ page: options?.page,
260
+ limit: options?.limit
261
+ }),
262
+ enabled: (options?.enabled ?? true) && debouncedQuery.length > 0
263
+ });
264
+ }
265
+
266
+ // src/react/hooks/use-cart.ts
267
+ import { useCallback } from "react";
268
+ import { useQuery as useQuery8, useMutation, useQueryClient } from "@tanstack/react-query";
269
+ var CART_KEY = ["behio", "cart"];
270
+ function useCart() {
271
+ const { client, storage } = useBehio();
272
+ const queryClient = useQueryClient();
273
+ const {
274
+ data: cart,
275
+ isLoading,
276
+ error
277
+ } = useQuery8({
278
+ queryKey: [...CART_KEY],
279
+ queryFn: () => client.cart.get(),
280
+ // Only fetch if we have a cart session or are logged in
281
+ enabled: !!client.getCartSession() || !!client.getAccessToken()
282
+ });
283
+ const addMutation = useMutation({
284
+ mutationFn: async ({ productId, quantity }) => {
285
+ return client.cart.addItem({ productId, quantity: quantity ?? 1 });
286
+ },
287
+ onSuccess: (result) => {
288
+ if (result.newSessionToken) {
289
+ storage.set(STORAGE_KEYS.CART_SESSION, result.newSessionToken);
290
+ }
291
+ queryClient.setQueryData([...CART_KEY], result);
292
+ }
293
+ });
294
+ const updateMutation = useMutation({
295
+ mutationFn: async ({ itemId, quantity }) => {
296
+ return client.cart.updateQuantity(itemId, quantity);
297
+ },
298
+ onMutate: async ({ itemId, quantity }) => {
299
+ await queryClient.cancelQueries({ queryKey: [...CART_KEY] });
300
+ const previous = queryClient.getQueryData([...CART_KEY]);
301
+ if (previous) {
302
+ const updatedItems = previous.items.map(
303
+ (item) => item.id === itemId ? { ...item, quantity, totalPrice: item.unitPrice * quantity } : item
304
+ );
305
+ queryClient.setQueryData([...CART_KEY], {
306
+ ...previous,
307
+ items: updatedItems,
308
+ itemCount: updatedItems.reduce((sum, i) => sum + i.quantity, 0)
309
+ });
310
+ }
311
+ return { previous };
312
+ },
313
+ onError: (_err, _vars, context) => {
314
+ if (context?.previous) {
315
+ queryClient.setQueryData([...CART_KEY], context.previous);
316
+ }
317
+ },
318
+ onSettled: () => {
319
+ queryClient.invalidateQueries({ queryKey: [...CART_KEY] });
320
+ }
321
+ });
322
+ const removeMutation = useMutation({
323
+ mutationFn: async (itemId) => {
324
+ return client.cart.removeItem(itemId);
325
+ },
326
+ onMutate: async (itemId) => {
327
+ await queryClient.cancelQueries({ queryKey: [...CART_KEY] });
328
+ const previous = queryClient.getQueryData([...CART_KEY]);
329
+ if (previous) {
330
+ const updatedItems = previous.items.filter((item) => item.id !== itemId);
331
+ queryClient.setQueryData([...CART_KEY], {
332
+ ...previous,
333
+ items: updatedItems,
334
+ itemCount: updatedItems.reduce((sum, i) => sum + i.quantity, 0)
335
+ });
336
+ }
337
+ return { previous };
338
+ },
339
+ onError: (_err, _vars, context) => {
340
+ if (context?.previous) {
341
+ queryClient.setQueryData([...CART_KEY], context.previous);
342
+ }
343
+ },
344
+ onSettled: () => {
345
+ queryClient.invalidateQueries({ queryKey: [...CART_KEY] });
346
+ }
347
+ });
348
+ const clearMutation = useMutation({
349
+ mutationFn: () => client.cart.clear(),
350
+ onSuccess: () => {
351
+ queryClient.setQueryData([...CART_KEY], null);
352
+ client.clearCartSession();
353
+ storage.remove(STORAGE_KEYS.CART_SESSION);
354
+ }
355
+ });
356
+ const applyDiscountMutation = useMutation({
357
+ mutationFn: (code) => client.cart.applyDiscount(code),
358
+ onSuccess: (result) => {
359
+ queryClient.setQueryData([...CART_KEY], result);
360
+ }
361
+ });
362
+ const removeDiscountMutation = useMutation({
363
+ mutationFn: () => client.cart.removeDiscount(),
364
+ onSuccess: (result) => {
365
+ queryClient.setQueryData([...CART_KEY], result);
366
+ }
367
+ });
368
+ const mergeMutation = useMutation({
369
+ mutationFn: () => client.cart.merge(),
370
+ onSuccess: (result) => {
371
+ queryClient.setQueryData([...CART_KEY], result);
372
+ client.clearCartSession();
373
+ storage.remove(STORAGE_KEYS.CART_SESSION);
374
+ }
375
+ });
376
+ const addItem = useCallback(
377
+ (productId, quantity) => addMutation.mutateAsync({ productId, quantity }),
378
+ [addMutation]
379
+ );
380
+ const updateQuantity = useCallback(
381
+ (itemId, quantity) => updateMutation.mutateAsync({ itemId, quantity }),
382
+ [updateMutation]
383
+ );
384
+ const removeItem = useCallback(
385
+ (itemId) => removeMutation.mutateAsync(itemId),
386
+ [removeMutation]
387
+ );
388
+ const clear = useCallback(
389
+ () => clearMutation.mutateAsync(),
390
+ [clearMutation]
391
+ );
392
+ const applyDiscount = useCallback(
393
+ (code) => applyDiscountMutation.mutateAsync(code),
394
+ [applyDiscountMutation]
395
+ );
396
+ const removeDiscount = useCallback(
397
+ () => removeDiscountMutation.mutateAsync(),
398
+ [removeDiscountMutation]
399
+ );
400
+ const merge = useCallback(
401
+ () => mergeMutation.mutateAsync(),
402
+ [mergeMutation]
403
+ );
404
+ return {
405
+ cart: cart ?? null,
406
+ isLoading,
407
+ error,
408
+ // Actions
409
+ addItem,
410
+ updateQuantity,
411
+ removeItem,
412
+ clear,
413
+ applyDiscount,
414
+ removeDiscount,
415
+ merge,
416
+ // Computed
417
+ itemCount: cart?.itemCount ?? 0,
418
+ isEmpty: !cart || cart.items.length === 0,
419
+ // Mutation states
420
+ isAdding: addMutation.isPending,
421
+ isUpdating: updateMutation.isPending,
422
+ isRemoving: removeMutation.isPending
423
+ };
424
+ }
425
+
426
+ // src/react/hooks/use-cart-count.ts
427
+ import { useQuery as useQuery9, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
428
+ var CART_KEY2 = ["behio", "cart"];
429
+ function useCartCount() {
430
+ const { client } = useBehio();
431
+ const queryClient = useQueryClient2();
432
+ const cachedCart = queryClient.getQueryData([...CART_KEY2]);
433
+ const { data } = useQuery9({
434
+ queryKey: [...CART_KEY2],
435
+ queryFn: () => client.cart.get(),
436
+ enabled: !cachedCart && (!!client.getCartSession() || !!client.getAccessToken())
437
+ });
438
+ const cart = cachedCart ?? data;
439
+ return cart?.itemCount ?? 0;
440
+ }
441
+
442
+ // src/react/hooks/use-auth.ts
443
+ import { useCallback as useCallback2 } from "react";
444
+ import { useQuery as useQuery10, useMutation as useMutation2, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
445
+ var CUSTOMER_KEY = ["behio", "customer"];
446
+ var CART_KEY3 = ["behio", "cart"];
447
+ function useAuth() {
448
+ const { client, storage } = useBehio();
449
+ const queryClient = useQueryClient3();
450
+ const isLoggedIn = !!client.getAccessToken();
451
+ const {
452
+ data: customer,
453
+ isLoading
454
+ } = useQuery10({
455
+ queryKey: [...CUSTOMER_KEY],
456
+ queryFn: () => client.customer.getProfile(),
457
+ enabled: isLoggedIn
458
+ });
459
+ const persistTokens = useCallback2(
460
+ (tokens) => {
461
+ client.setTokens(tokens);
462
+ storage.set(STORAGE_KEYS.ACCESS_TOKEN, tokens.accessToken);
463
+ storage.set(STORAGE_KEYS.REFRESH_TOKEN, tokens.refreshToken);
464
+ },
465
+ [client, storage]
466
+ );
467
+ const clearAuth = useCallback2(() => {
468
+ client.clearTokens();
469
+ storage.remove(STORAGE_KEYS.ACCESS_TOKEN);
470
+ storage.remove(STORAGE_KEYS.REFRESH_TOKEN);
471
+ queryClient.setQueryData([...CUSTOMER_KEY], null);
472
+ queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
473
+ queryClient.invalidateQueries({ queryKey: ["behio", "addresses"] });
474
+ }, [client, storage, queryClient]);
475
+ const postAuth = useCallback2(async () => {
476
+ await queryClient.invalidateQueries({ queryKey: [...CUSTOMER_KEY] });
477
+ if (client.getCartSession()) {
478
+ try {
479
+ await client.cart.merge();
480
+ client.clearCartSession();
481
+ storage.remove(STORAGE_KEYS.CART_SESSION);
482
+ } catch {
483
+ }
484
+ }
485
+ queryClient.invalidateQueries({ queryKey: [...CART_KEY3] });
486
+ }, [client, storage, queryClient]);
487
+ const loginMutation = useMutation2({
488
+ mutationFn: async ({ email, password }) => {
489
+ return client.auth.login({ email, password });
490
+ },
491
+ onSuccess: async (tokens) => {
492
+ persistTokens(tokens);
493
+ await postAuth();
494
+ }
495
+ });
496
+ const registerMutation = useMutation2({
497
+ mutationFn: async (input) => {
498
+ return client.auth.register(input);
499
+ },
500
+ onSuccess: async (tokens) => {
501
+ persistTokens(tokens);
502
+ await postAuth();
503
+ }
504
+ });
505
+ const logoutMutation = useMutation2({
506
+ mutationFn: () => client.auth.logout(),
507
+ onSettled: () => {
508
+ clearAuth();
509
+ }
510
+ });
511
+ const forgotPasswordMutation = useMutation2({
512
+ mutationFn: (email) => client.auth.forgotPassword(email)
513
+ });
514
+ const resetPasswordMutation = useMutation2({
515
+ mutationFn: ({ token, newPassword }) => client.auth.resetPassword(token, newPassword)
516
+ });
517
+ const verifyEmailMutation = useMutation2({
518
+ mutationFn: (token) => client.auth.verifyEmail(token)
519
+ });
520
+ const login = useCallback2(
521
+ (email, password) => loginMutation.mutateAsync({ email, password }).then(() => void 0),
522
+ [loginMutation]
523
+ );
524
+ const register = useCallback2(
525
+ (input) => registerMutation.mutateAsync(input).then(() => void 0),
526
+ [registerMutation]
527
+ );
528
+ const logout = useCallback2(
529
+ () => logoutMutation.mutateAsync().then(() => void 0),
530
+ [logoutMutation]
531
+ );
532
+ const forgotPassword = useCallback2(
533
+ (email) => forgotPasswordMutation.mutateAsync(email).then(() => void 0),
534
+ [forgotPasswordMutation]
535
+ );
536
+ const resetPassword = useCallback2(
537
+ (token, newPassword) => resetPasswordMutation.mutateAsync({ token, newPassword }).then(() => void 0),
538
+ [resetPasswordMutation]
539
+ );
540
+ const verifyEmail = useCallback2(
541
+ (token) => verifyEmailMutation.mutateAsync(token).then(() => void 0),
542
+ [verifyEmailMutation]
543
+ );
544
+ return {
545
+ isLoggedIn,
546
+ customer: customer ?? null,
547
+ isLoading,
548
+ // Actions
549
+ login,
550
+ register,
551
+ logout,
552
+ forgotPassword,
553
+ resetPassword,
554
+ verifyEmail,
555
+ // Mutation states
556
+ isLoggingIn: loginMutation.isPending,
557
+ isRegistering: registerMutation.isPending,
558
+ loginError: loginMutation.error,
559
+ registerError: registerMutation.error
560
+ };
561
+ }
562
+
563
+ // src/react/hooks/use-customer.ts
564
+ import { useCallback as useCallback3 } from "react";
565
+ import { useQuery as useQuery11, useMutation as useMutation3, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
566
+ var CUSTOMER_KEY2 = ["behio", "customer"];
567
+ function useCustomer() {
568
+ const { client } = useBehio();
569
+ const queryClient = useQueryClient4();
570
+ const {
571
+ data,
572
+ isLoading,
573
+ error
574
+ } = useQuery11({
575
+ queryKey: [...CUSTOMER_KEY2],
576
+ queryFn: () => client.customer.getProfile(),
577
+ enabled: !!client.getAccessToken()
578
+ });
579
+ const updateMutation = useMutation3({
580
+ mutationFn: (data2) => client.customer.updateProfile(data2),
581
+ onSuccess: (updated) => {
582
+ queryClient.setQueryData([...CUSTOMER_KEY2], updated);
583
+ }
584
+ });
585
+ const updateProfile = useCallback3(
586
+ (profileData) => updateMutation.mutateAsync(profileData),
587
+ [updateMutation]
588
+ );
589
+ return {
590
+ data: data ?? null,
591
+ isLoading,
592
+ error,
593
+ updateProfile,
594
+ isUpdating: updateMutation.isPending
595
+ };
596
+ }
597
+
598
+ // src/react/hooks/use-addresses.ts
599
+ import { useCallback as useCallback4 } from "react";
600
+ import { useQuery as useQuery12, useMutation as useMutation4, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
601
+ var ADDRESSES_KEY = ["behio", "addresses"];
602
+ function useAddresses() {
603
+ const { client } = useBehio();
604
+ const queryClient = useQueryClient5();
605
+ const {
606
+ data,
607
+ isLoading,
608
+ error
609
+ } = useQuery12({
610
+ queryKey: [...ADDRESSES_KEY],
611
+ queryFn: async () => {
612
+ const result = await client.customer.getAddresses();
613
+ return result.items;
614
+ },
615
+ enabled: !!client.getAccessToken()
616
+ });
617
+ const createMutation = useMutation4({
618
+ mutationFn: (address) => client.customer.createAddress(address),
619
+ onSuccess: () => {
620
+ queryClient.invalidateQueries({ queryKey: [...ADDRESSES_KEY] });
621
+ }
622
+ });
623
+ const updateMutation = useMutation4({
624
+ mutationFn: ({ addressId, data: data2 }) => client.customer.updateAddress(addressId, data2),
625
+ onSuccess: () => {
626
+ queryClient.invalidateQueries({ queryKey: [...ADDRESSES_KEY] });
627
+ }
628
+ });
629
+ const deleteMutation = useMutation4({
630
+ mutationFn: (addressId) => client.customer.deleteAddress(addressId),
631
+ onSuccess: () => {
632
+ queryClient.invalidateQueries({ queryKey: [...ADDRESSES_KEY] });
633
+ }
634
+ });
635
+ const createAddress = useCallback4(
636
+ (address) => createMutation.mutateAsync(address),
637
+ [createMutation]
638
+ );
639
+ const updateAddress = useCallback4(
640
+ (addressId, addressData) => updateMutation.mutateAsync({ addressId, data: addressData }),
641
+ [updateMutation]
642
+ );
643
+ const deleteAddress = useCallback4(
644
+ (addressId) => deleteMutation.mutateAsync(addressId),
645
+ [deleteMutation]
646
+ );
647
+ return {
648
+ addresses: data ?? [],
649
+ isLoading,
650
+ error,
651
+ createAddress,
652
+ updateAddress,
653
+ deleteAddress,
654
+ isCreating: createMutation.isPending,
655
+ isDeleting: deleteMutation.isPending
656
+ };
657
+ }
658
+
659
+ // src/react/hooks/use-orders.ts
660
+ import { useQuery as useQuery13 } from "@tanstack/react-query";
661
+ function useOrders(options) {
662
+ const { client } = useBehio();
663
+ return useQuery13({
664
+ queryKey: ["behio", "orders", options?.page, options?.limit],
665
+ queryFn: () => client.orders.list({
666
+ page: options?.page,
667
+ limit: options?.limit
668
+ }),
669
+ enabled: (options?.enabled ?? true) && !!client.getAccessToken()
670
+ });
671
+ }
672
+
673
+ // src/react/hooks/use-order.ts
674
+ import { useCallback as useCallback5 } from "react";
675
+ import { useQuery as useQuery14, useMutation as useMutation5, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
676
+ function useOrder(orderNumber) {
677
+ const { client } = useBehio();
678
+ const queryClient = useQueryClient6();
679
+ const {
680
+ data,
681
+ isLoading,
682
+ error
683
+ } = useQuery14({
684
+ queryKey: ["behio", "order", orderNumber],
685
+ queryFn: () => client.orders.get(orderNumber),
686
+ enabled: !!orderNumber && !!client.getAccessToken()
687
+ });
688
+ const cancelMutation = useMutation5({
689
+ mutationFn: () => client.orders.cancel(orderNumber),
690
+ onSuccess: (updated) => {
691
+ queryClient.setQueryData(["behio", "order", orderNumber], updated);
692
+ queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
693
+ }
694
+ });
695
+ const cancel = useCallback5(
696
+ () => cancelMutation.mutateAsync(),
697
+ [cancelMutation]
698
+ );
699
+ return {
700
+ data: data ?? null,
701
+ isLoading,
702
+ error,
703
+ cancel,
704
+ isCancelling: cancelMutation.isPending
705
+ };
706
+ }
707
+
708
+ // src/react/hooks/use-checkout.ts
709
+ import { useState as useState2, useCallback as useCallback6 } from "react";
710
+ import { useMutation as useMutation6, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
711
+ function useCheckout() {
712
+ const { client, storage } = useBehio();
713
+ const queryClient = useQueryClient7();
714
+ const [order, setOrder] = useState2(null);
715
+ const mutation = useMutation6({
716
+ mutationFn: (input) => client.checkout.createOrder(input),
717
+ onSuccess: (result) => {
718
+ setOrder(result);
719
+ storage.remove(STORAGE_KEYS.CART_SESSION);
720
+ queryClient.invalidateQueries({ queryKey: ["behio", "cart"] });
721
+ queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
722
+ }
723
+ });
724
+ const createOrder = useCallback6(
725
+ (input) => mutation.mutateAsync(input),
726
+ [mutation]
727
+ );
728
+ const reset = useCallback6(() => {
729
+ setOrder(null);
730
+ mutation.reset();
731
+ }, [mutation]);
732
+ return {
733
+ createOrder,
734
+ isCreating: mutation.isPending,
735
+ error: mutation.error,
736
+ order,
737
+ reset
738
+ };
739
+ }
740
+
741
+ // src/react/hooks/use-pages.ts
742
+ import { useQuery as useQuery15 } from "@tanstack/react-query";
743
+ function usePages(locale) {
744
+ const { client } = useBehio();
745
+ return useQuery15({
746
+ queryKey: ["behio", "pages", locale],
747
+ queryFn: async () => {
748
+ const result = await client.pages.list(locale);
749
+ return result.pages;
750
+ }
751
+ });
752
+ }
753
+ function usePage(slug, locale) {
754
+ const { client } = useBehio();
755
+ return useQuery15({
756
+ queryKey: ["behio", "page", slug, locale],
757
+ queryFn: () => client.pages.get(slug, locale),
758
+ enabled: !!slug
759
+ });
760
+ }
761
+
762
+ // src/react/hooks/use-shop-info.ts
763
+ import { useQuery as useQuery16 } from "@tanstack/react-query";
764
+ function useShopInfo() {
765
+ const { client } = useBehio();
766
+ return useQuery16({
767
+ queryKey: ["behio", "shop-info"],
768
+ queryFn: () => client.getShopInfo()
769
+ });
770
+ }
771
+
772
+ // src/react/utils/format-price.ts
773
+ function formatPrice(amount, currency, locale) {
774
+ const resolvedLocale = locale ?? "cs";
775
+ try {
776
+ return new Intl.NumberFormat(resolvedLocale, {
777
+ style: "currency",
778
+ currency,
779
+ minimumFractionDigits: Number.isInteger(amount) ? 0 : 2,
780
+ maximumFractionDigits: 2
781
+ }).format(amount);
782
+ } catch {
783
+ return `${amount} ${currency}`;
784
+ }
785
+ }
786
+ export {
787
+ BehioProvider,
788
+ cookieStorage,
789
+ createMemoryStorage,
790
+ detectStorage,
791
+ formatPrice,
792
+ localStorageAdapter,
793
+ memoryStorage,
794
+ useAddresses,
795
+ useAuth,
796
+ useBehio,
797
+ useCart,
798
+ useCartCount,
799
+ useCategories,
800
+ useCheckout,
801
+ useCustomer,
802
+ useFeatured,
803
+ useFilters,
804
+ useLabels,
805
+ useOrder,
806
+ useOrders,
807
+ usePage,
808
+ usePages,
809
+ useProduct,
810
+ useProducts,
811
+ useSearch,
812
+ useShopInfo
813
+ };