@behio/storefront-sdk 1.9.0 → 1.18.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.js CHANGED
@@ -42,6 +42,9 @@ __export(react_exports, {
42
42
  useAuth: () => useAuth,
43
43
  useBehio: () => useBehio,
44
44
  useBehioClient: () => useBehioClient,
45
+ useBlogPost: () => useBlogPost,
46
+ useBlogPosts: () => useBlogPosts,
47
+ useBlogs: () => useBlogs,
45
48
  useBundle: () => useBundle,
46
49
  useBundles: () => useBundles,
47
50
  useCart: () => useCart,
@@ -95,6 +98,8 @@ __export(react_exports, {
95
98
  useShopInfo: () => useShopInfo,
96
99
  useShopScripts: () => useShopScripts,
97
100
  useShopSeo: () => useShopSeo,
101
+ useSiteForm: () => useSiteForm,
102
+ useSiteFormSubmit: () => useSiteFormSubmit,
98
103
  useSubmitQuote: () => useSubmitQuote,
99
104
  useSubmitReturn: () => useSubmitReturn,
100
105
  useSubmitReview: () => useSubmitReview,
@@ -109,6 +114,38 @@ var import_react2 = require("react");
109
114
  var import_react_query = require("@tanstack/react-query");
110
115
 
111
116
  // src/types.ts
117
+ var BE_CODE_TO_ERROR = {
118
+ "be.storefront.cartIsEmpty": "CART_EMPTY",
119
+ "be.storefront.productNotFound": "PRODUCT_NOT_FOUND",
120
+ "be.storefront.productNotAvailable": "PRODUCT_NOT_FOUND",
121
+ "be.storefront.invalidEmailOrPassword": "INVALID_CREDENTIALS",
122
+ "be.storefront.currentPasswordIncorrect": "INVALID_CREDENTIALS",
123
+ "be.storefront.discountExpired": "DISCOUNT_EXPIRED",
124
+ "be.storefront.discountExpiredOrLimit": "DISCOUNT_EXPIRED",
125
+ "be.storefront.invalidDiscountCode": "INVALID_DISCOUNT",
126
+ "be.storefront.discountInvalid": "INVALID_DISCOUNT",
127
+ "be.storefront.discountInactive": "INVALID_DISCOUNT",
128
+ "be.storefront.discountWrongCurrency": "INVALID_DISCOUNT",
129
+ "be.storefront.discountNotApplicable": "INVALID_DISCOUNT",
130
+ "be.storefront.discountNotYetValid": "INVALID_DISCOUNT",
131
+ "be.storefront.discountUsageLimitReached": "INVALID_DISCOUNT",
132
+ "be.storefront.discountLimitedToGroups": "INVALID_DISCOUNT",
133
+ "be.storefront.tokenInvalid": "TOKEN_INVALID",
134
+ "be.storefront.orderAccessTokenInvalid": "TOKEN_INVALID",
135
+ "be.storefront.resetTokenInvalid": "TOKEN_INVALID",
136
+ "be.storefront.invalidVerificationToken": "TOKEN_INVALID",
137
+ "be.storefront.invalidRefreshToken": "TOKEN_INVALID",
138
+ "be.storefront.refreshTokenExpired": "TOKEN_EXPIRED",
139
+ "be.storefront.apiKeyExpired": "TOKEN_EXPIRED",
140
+ "be.storefront.customerEmailTaken": "EMAIL_ALREADY_EXISTS",
141
+ "be.storefront.orderNotCancellable": "ORDER_NOT_CANCELLABLE",
142
+ "be.storefront.orderCancelledNotReturnable": "ORDER_NOT_CANCELLABLE",
143
+ "be.validation.failed": "VALIDATION_ERROR",
144
+ "be.forms.formNotFound": "NOT_FOUND",
145
+ "be.forms.validationFailed": "VALIDATION_ERROR",
146
+ "be.forms.consentRequired": "VALIDATION_ERROR",
147
+ "be.forms.tooLarge": "VALIDATION_ERROR"
148
+ };
112
149
  var BehioApiError = class _BehioApiError extends Error {
113
150
  constructor(status, body, message) {
114
151
  super(message || `API Error ${status}`);
@@ -125,6 +162,11 @@ var BehioApiError = class _BehioApiError extends Error {
125
162
  if (status === 409) return "EMAIL_ALREADY_EXISTS";
126
163
  if (status === 429) return "RATE_LIMITED";
127
164
  if (status >= 500) return "INTERNAL_ERROR";
165
+ const rawCode = body?.code;
166
+ if (typeof rawCode === "string") {
167
+ const mapped = BE_CODE_TO_ERROR[rawCode];
168
+ if (mapped) return mapped;
169
+ }
128
170
  const msg = (body?.message || "").toLowerCase();
129
171
  if (msg.includes("invalid") && msg.includes("password"))
130
172
  return "INVALID_CREDENTIALS";
@@ -230,6 +272,8 @@ var BehioStorefront = class {
230
272
  this.orders = new OrdersModule(this);
231
273
  this.customer = new CustomerModule(this);
232
274
  this.pages = new PagesModule(this);
275
+ this.blog = new BlogModule(this);
276
+ this.forms = new FormsModule(this);
233
277
  this.wishlist = new WishlistModule(this);
234
278
  this.reviews = new ReviewsModule(this);
235
279
  this.returns = new ReturnsModule(this);
@@ -678,6 +722,7 @@ var CatalogModule = class {
678
722
  if (query.priceMin) q.priceMin = query.priceMin;
679
723
  if (query.priceMax) q.priceMax = query.priceMax;
680
724
  if (query.currency) q.currency = query.currency;
725
+ if (query.country) q.country = query.country;
681
726
  if (query.locale) q.locale = query.locale;
682
727
  if (query.sort) q.sort = query.sort;
683
728
  if (query.inStock !== void 0) q.inStock = query.inStock;
@@ -710,7 +755,7 @@ var CatalogModule = class {
710
755
  "GET",
711
756
  `/catalog/products/${slug}`,
712
757
  {
713
- query: { locale: options?.locale, currency: options?.currency }
758
+ query: { locale: options?.locale, currency: options?.currency, country: options?.country }
714
759
  }
715
760
  );
716
761
  }
@@ -932,16 +977,27 @@ var CatalogModule = class {
932
977
  { body: input }
933
978
  );
934
979
  }
935
- /** List configured payment methods (filtered by currency). */
980
+ /**
981
+ * List configured payment methods (filtered by currency). `locale` picks the
982
+ * language of `instruments[].label` / `swifts[].label` (SDK 1.14.0); pass the
983
+ * locale of the page so the instrument tiles read in the shopper's language.
984
+ */
936
985
  async listPaymentMethods(opts) {
937
986
  const query = {};
938
987
  if (opts?.currency) query.currency = opts.currency;
988
+ if (opts?.locale) query.locale = opts.locale;
989
+ if (opts?.country) query.country = opts.country;
990
+ if (opts?.shippingMethodId) query.shippingMethodId = opts.shippingMethodId;
939
991
  return this.client.request(
940
992
  "GET",
941
993
  "/catalog/payment-methods",
942
994
  { query }
943
995
  );
944
996
  }
997
+ /** Alias of `listPaymentMethods` (SDK 1.14.0). */
998
+ paymentMethods(opts) {
999
+ return this.listPaymentMethods(opts);
1000
+ }
945
1001
  };
946
1002
  var AuthModule = class {
947
1003
  constructor(client) {
@@ -1095,6 +1151,26 @@ var CartModule = class {
1095
1151
  this.client.emit("cart:updated", res.data);
1096
1152
  return res;
1097
1153
  }
1154
+ /**
1155
+ * Tell the cart where the order will ship (and, for B2B, the buyer's VAT
1156
+ * ID) so the VAT breakdown matches the checkout before the address form:
1157
+ * destination-country rate (OSS), 0 % export outside the EU, or reverse
1158
+ * charge for an EU business with a VIES-valid VAT ID. `cart.vatMode` says
1159
+ * which rule applied. SDK 1.17.0.
1160
+ *
1161
+ * ```ts
1162
+ * await client.cart.setDestination({ country: "SK" });
1163
+ * await client.cart.setDestination({ vatId: "SK2020000001" }); // "" clears
1164
+ * ```
1165
+ */
1166
+ async setDestination(input) {
1167
+ const res = await this.client.request("PUT", "/cart/destination", {
1168
+ body: input
1169
+ });
1170
+ if (res.error) return res;
1171
+ this.client.emit("cart:updated", res.data);
1172
+ return res;
1173
+ }
1098
1174
  /** Update item quantity */
1099
1175
  async updateQuantity(itemId, quantity) {
1100
1176
  const res = await this.client.request(
@@ -1246,6 +1322,30 @@ var OrdersModule = class {
1246
1322
  constructor(client) {
1247
1323
  this.client = client;
1248
1324
  }
1325
+ /**
1326
+ * Ask the backend to re-check this order's payment with the gateway.
1327
+ *
1328
+ * Call it on the thank-you page the customer lands on after paying, BEFORE
1329
+ * you read the order. Some gateways (Tatrapay+) have no server-to-server
1330
+ * notification at all, so the customer's return is the only fast way the
1331
+ * payment gets confirmed; for the others it is a safety net for a lost
1332
+ * notification.
1333
+ *
1334
+ * The response is deliberately opaque (`{ok: true}` every time, even for an
1335
+ * order number that does not exist): order numbers are sequential, so
1336
+ * anything else would turn this into a probe for other people's orders.
1337
+ * Read the actual state afterwards through a path that proves entitlement
1338
+ * ({@link get}, {@link track} or the guest access-code flow).
1339
+ *
1340
+ * Never throws for a missing order and never blocks the page: treat a
1341
+ * failure as "not confirmed yet", the backend poller catches up on its own.
1342
+ */
1343
+ async syncPaymentOnReturn(orderNumber) {
1344
+ return this.client.request(
1345
+ "POST",
1346
+ `/payments/return/${orderNumber}`
1347
+ );
1348
+ }
1249
1349
  /** List customer orders (requires auth) */
1250
1350
  async list(options) {
1251
1351
  return this.client.request(
@@ -1372,7 +1472,10 @@ var CustomerModule = class {
1372
1472
  body: address
1373
1473
  });
1374
1474
  }
1375
- /** Update address */
1475
+ /**
1476
+ * Update address. Partial: `{isDefault: true}` alone is a valid body. A
1477
+ * changed `vatId` or `country` re-runs the VIES check on the server.
1478
+ */
1376
1479
  async updateAddress(addressId, data) {
1377
1480
  return this.client.request(
1378
1481
  "PATCH",
@@ -1598,6 +1701,59 @@ var PagesModule = class {
1598
1701
  });
1599
1702
  }
1600
1703
  };
1704
+ var BlogModule = class {
1705
+ constructor(client) {
1706
+ this.client = client;
1707
+ }
1708
+ /** List the site's blogs (active only). */
1709
+ async list(locale) {
1710
+ return this.client.request("GET", "/blogs", {
1711
+ query: { locale }
1712
+ });
1713
+ }
1714
+ /** Published posts of one blog, newest first (featured first), paginated. */
1715
+ async posts(handle, query = {}) {
1716
+ return this.client.request("GET", `/blogs/${handle}/posts`, {
1717
+ query: {
1718
+ locale: query.locale,
1719
+ page: query.page,
1720
+ limit: query.limit,
1721
+ tag: query.tag
1722
+ }
1723
+ });
1724
+ }
1725
+ /** One published post with sanitised HTML content and related posts. */
1726
+ async post(handle, slug, locale) {
1727
+ return this.client.request("GET", `/blogs/${handle}/posts/${slug}`, {
1728
+ query: { locale }
1729
+ });
1730
+ }
1731
+ };
1732
+ var FormsModule = class {
1733
+ constructor(client) {
1734
+ this.client = client;
1735
+ }
1736
+ /** Public definition of one form (fields + settings). 404 for an unknown or inactive slug. */
1737
+ async get(slug) {
1738
+ return this.client.request(
1739
+ "GET",
1740
+ `/forms/${encodeURIComponent(slug)}`
1741
+ );
1742
+ }
1743
+ /**
1744
+ * Submit a response. On `be.forms.validationFailed` the returned error
1745
+ * carries per-field codes: read them with `formFieldErrors(error)`. Other
1746
+ * rejections: `be.forms.consentRequired`, `be.forms.tooLarge`,
1747
+ * `be.forms.formNotFound`; rate limit 10 submits per minute per visitor.
1748
+ */
1749
+ async submit(slug, input) {
1750
+ return this.client.request(
1751
+ "POST",
1752
+ `/forms/${encodeURIComponent(slug)}/submit`,
1753
+ { body: input, auth: false }
1754
+ );
1755
+ }
1756
+ };
1601
1757
  var WishlistModule = class {
1602
1758
  constructor(client) {
1603
1759
  this.client = client;
@@ -3185,9 +3341,10 @@ var import_react_query27 = require("@tanstack/react-query");
3185
3341
  function usePaymentMethods(options) {
3186
3342
  const { client, currency: activeCurrency } = useBehio();
3187
3343
  const currency = options?.currency ?? activeCurrency;
3344
+ const locale = options?.locale;
3188
3345
  const { data, isLoading, error, refetch } = (0, import_react_query27.useQuery)({
3189
- queryKey: ["behio", "payment-methods", currency ?? ""],
3190
- queryFn: () => unwrap(client.catalog.listPaymentMethods({ currency })),
3346
+ queryKey: ["behio", "payment-methods", currency ?? "", locale ?? ""],
3347
+ queryFn: () => unwrap(client.catalog.listPaymentMethods({ currency, ...locale ? { locale } : {} })),
3191
3348
  enabled: options?.enabled !== false
3192
3349
  });
3193
3350
  return { methods: data?.items ?? [], isLoading, error, refetch };
@@ -3565,11 +3722,134 @@ function usePage(slug, locale, options) {
3565
3722
  });
3566
3723
  }
3567
3724
 
3568
- // src/react/hooks/use-shop-info.ts
3725
+ // src/react/hooks/use-blog.ts
3569
3726
  var import_react_query36 = require("@tanstack/react-query");
3570
- function useShopInfo(options) {
3727
+ function useBlogs(locale, options) {
3571
3728
  const { client } = useBehio();
3572
3729
  return (0, import_react_query36.useQuery)({
3730
+ queryKey: ["behio", "blogs", locale],
3731
+ queryFn: async () => {
3732
+ const result = await unwrap(client.blog.list(locale));
3733
+ return result.blogs;
3734
+ },
3735
+ enabled: options?.enabled !== false
3736
+ });
3737
+ }
3738
+ function useBlogPosts(handle, query, options) {
3739
+ const { client } = useBehio();
3740
+ return (0, import_react_query36.useQuery)({
3741
+ queryKey: ["behio", "blog", handle, "posts", query?.locale, query?.page, query?.limit, query?.tag],
3742
+ queryFn: () => unwrap(client.blog.posts(handle, query)),
3743
+ enabled: options?.enabled !== false && !!handle
3744
+ });
3745
+ }
3746
+ function useBlogPost(handle, slug, locale, options) {
3747
+ const { client } = useBehio();
3748
+ return (0, import_react_query36.useQuery)({
3749
+ queryKey: ["behio", "blog", handle, "post", slug, locale],
3750
+ queryFn: () => unwrap(client.blog.post(handle, slug, locale)),
3751
+ enabled: options?.enabled !== false && !!handle && !!slug
3752
+ });
3753
+ }
3754
+
3755
+ // src/react/hooks/use-site-form.ts
3756
+ var import_react17 = require("react");
3757
+ var import_react_query37 = require("@tanstack/react-query");
3758
+
3759
+ // src/errors.ts
3760
+ function bodyOf(err) {
3761
+ const body = err instanceof BehioApiError ? err.body : err && typeof err === "object" && "body" in err ? err.body : err;
3762
+ return body && typeof body === "object" ? body : null;
3763
+ }
3764
+ function errorCode(err) {
3765
+ const body = bodyOf(err);
3766
+ if (!body) return null;
3767
+ const code = body.code ?? body.key;
3768
+ return typeof code === "string" && code.startsWith("be.") ? code : null;
3769
+ }
3770
+ function errorParams(err) {
3771
+ const body = bodyOf(err);
3772
+ const params = body?.params;
3773
+ return params && typeof params === "object" && !Array.isArray(params) ? params : {};
3774
+ }
3775
+ var FORM_FIELD_ERROR_CODES = /* @__PURE__ */ new Set([
3776
+ "required",
3777
+ "invalid",
3778
+ "tooShort",
3779
+ "tooLong",
3780
+ "min",
3781
+ "max",
3782
+ "notOption",
3783
+ "pattern"
3784
+ ]);
3785
+ function formFieldErrors(err) {
3786
+ if (errorCode(err) !== "be.forms.validationFailed") return [];
3787
+ const raw = errorParams(err).errors;
3788
+ if (!Array.isArray(raw)) return [];
3789
+ const out = [];
3790
+ for (const entry of raw) {
3791
+ if (typeof entry !== "string") continue;
3792
+ const idx = entry.lastIndexOf(":");
3793
+ if (idx <= 0) continue;
3794
+ const key = entry.slice(0, idx);
3795
+ const code = entry.slice(idx + 1);
3796
+ if (!FORM_FIELD_ERROR_CODES.has(code)) continue;
3797
+ out.push({ key, code });
3798
+ }
3799
+ return out;
3800
+ }
3801
+
3802
+ // src/react/hooks/use-site-form.ts
3803
+ function useSiteForm(slug, options) {
3804
+ const { client } = useBehio();
3805
+ return (0, import_react_query37.useQuery)({
3806
+ queryKey: ["behio", "form", slug],
3807
+ queryFn: () => unwrap(client.forms.get(slug)),
3808
+ enabled: options?.enabled !== false && !!slug
3809
+ });
3810
+ }
3811
+ function useSiteFormSubmit(slug) {
3812
+ const { client } = useBehio();
3813
+ const mutation = (0, import_react_query37.useMutation)({
3814
+ mutationFn: (input) => unwrap(client.forms.submit(slug, input))
3815
+ });
3816
+ const sdkError = mutation.error instanceof UnwrappedError ? mutation.error.sdkError : null;
3817
+ const fieldErrors = (0, import_react17.useMemo)(() => {
3818
+ const out = {};
3819
+ for (const e of formFieldErrors(sdkError)) out[e.key] = e.code;
3820
+ return out;
3821
+ }, [sdkError]);
3822
+ const errorCode2 = (0, import_react17.useMemo)(() => {
3823
+ const body = sdkError?.body;
3824
+ const code = body?.code ?? body?.key;
3825
+ return typeof code === "string" ? code : sdkError ? sdkError.code : null;
3826
+ }, [sdkError]);
3827
+ const submit = (0, import_react17.useCallback)(
3828
+ (input) => mutation.mutateAsync(input).catch(() => null),
3829
+ [mutation]
3830
+ );
3831
+ return {
3832
+ /** Resolves to the result, or null when the submit was rejected (see `fieldErrors` / `errorCode`). */
3833
+ submit,
3834
+ isSubmitting: mutation.isPending,
3835
+ isSuccess: mutation.isSuccess,
3836
+ /** `{ok, id, message, redirectUrl}` after a successful submit. */
3837
+ result: mutation.data ?? null,
3838
+ /** Field key -> validation code after a rejected submit. */
3839
+ fieldErrors,
3840
+ /** Backend error key (`be.forms.*`) or SDK code when the rejection is not per field. */
3841
+ errorCode: errorCode2,
3842
+ /** Raw SDK error (pass to `errorMessage(error, locale)` for a sentence). */
3843
+ error: sdkError,
3844
+ reset: mutation.reset
3845
+ };
3846
+ }
3847
+
3848
+ // src/react/hooks/use-shop-info.ts
3849
+ var import_react_query38 = require("@tanstack/react-query");
3850
+ function useShopInfo(options) {
3851
+ const { client } = useBehio();
3852
+ return (0, import_react_query38.useQuery)({
3573
3853
  queryKey: ["behio", "shop-info"],
3574
3854
  queryFn: () => unwrap(client.getShopInfo()),
3575
3855
  enabled: options?.enabled !== false
@@ -3577,10 +3857,10 @@ function useShopInfo(options) {
3577
3857
  }
3578
3858
 
3579
3859
  // src/react/hooks/use-shop-scripts.ts
3580
- var import_react_query37 = require("@tanstack/react-query");
3860
+ var import_react_query39 = require("@tanstack/react-query");
3581
3861
  function useShopScripts(options) {
3582
3862
  const { client } = useBehio();
3583
- return (0, import_react_query37.useQuery)({
3863
+ return (0, import_react_query39.useQuery)({
3584
3864
  queryKey: ["behio", "shop-scripts"],
3585
3865
  queryFn: () => unwrap(client.getShopScripts()),
3586
3866
  enabled: options?.enabled !== false
@@ -3588,11 +3868,11 @@ function useShopScripts(options) {
3588
3868
  }
3589
3869
 
3590
3870
  // src/react/hooks/use-shop-seo.ts
3591
- var import_react_query38 = require("@tanstack/react-query");
3871
+ var import_react_query40 = require("@tanstack/react-query");
3592
3872
  function useShopSeo(options) {
3593
3873
  const { client } = useBehio();
3594
3874
  const { locale, initialData, enabled = true } = options ?? {};
3595
- return (0, import_react_query38.useQuery)({
3875
+ return (0, import_react_query40.useQuery)({
3596
3876
  queryKey: ["behio", "shop-seo", locale ?? "_default"],
3597
3877
  queryFn: () => unwrap(client.getShopSeo(locale)),
3598
3878
  initialData,
@@ -3652,23 +3932,23 @@ function CurrencySwitcher({
3652
3932
  }
3653
3933
 
3654
3934
  // src/react/components/storefront-scripts.tsx
3655
- var import_react17 = require("react");
3935
+ var import_react18 = require("react");
3656
3936
 
3657
3937
  // src/react/hooks/use-consent.ts
3658
- var import_react_query39 = require("@tanstack/react-query");
3938
+ var import_react_query41 = require("@tanstack/react-query");
3659
3939
  function useCookieConsent(visitorId) {
3660
3940
  const { client } = useBehio();
3661
- const qc = (0, import_react_query39.useQueryClient)();
3662
- const query = (0, import_react_query39.useQuery)({
3941
+ const qc = (0, import_react_query41.useQueryClient)();
3942
+ const query = (0, import_react_query41.useQuery)({
3663
3943
  queryKey: ["behio", "consent", visitorId],
3664
3944
  queryFn: () => unwrap(client.consent.get(visitorId)),
3665
3945
  enabled: Boolean(visitorId)
3666
3946
  });
3667
- const recordMutation = (0, import_react_query39.useMutation)({
3947
+ const recordMutation = (0, import_react_query41.useMutation)({
3668
3948
  mutationFn: (input) => unwrap(client.consent.record(input)),
3669
3949
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "consent"] })
3670
3950
  });
3671
- const revokeMutation = (0, import_react_query39.useMutation)({
3951
+ const revokeMutation = (0, import_react_query41.useMutation)({
3672
3952
  mutationFn: () => unwrap(client.consent.revoke(visitorId)),
3673
3953
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "consent"] })
3674
3954
  });
@@ -3742,8 +4022,8 @@ function injectHtml(target, html) {
3742
4022
  }
3743
4023
  function StorefrontScripts({ visitorId: visitorIdProp } = {}) {
3744
4024
  const { data } = useShopScripts();
3745
- const [visitorId, setVisitorId] = (0, import_react17.useState)(visitorIdProp ?? "");
3746
- (0, import_react17.useEffect)(() => {
4025
+ const [visitorId, setVisitorId] = (0, import_react18.useState)(visitorIdProp ?? "");
4026
+ (0, import_react18.useEffect)(() => {
3747
4027
  if (visitorIdProp) return;
3748
4028
  try {
3749
4029
  const v = localStorage.getItem(VISITOR_KEY);
@@ -3753,15 +4033,15 @@ function StorefrontScripts({ visitorId: visitorIdProp } = {}) {
3753
4033
  }, [visitorIdProp]);
3754
4034
  const { data: consent } = useCookieConsent(visitorId || void 0);
3755
4035
  const analyticsOk = Boolean(consent?.analytics);
3756
- const scripts = (0, import_react17.useMemo)(
4036
+ const scripts = (0, import_react18.useMemo)(
3757
4037
  () => (data?.scripts ?? []).filter((s) => !s.consentRequired || analyticsOk),
3758
4038
  [data, analyticsOk]
3759
4039
  );
3760
- const signature = (0, import_react17.useMemo)(
4040
+ const signature = (0, import_react18.useMemo)(
3761
4041
  () => JSON.stringify(scripts.map((s) => [s.id, s.type, s.placement, s.value])),
3762
4042
  [scripts]
3763
4043
  );
3764
- (0, import_react17.useEffect)(() => {
4044
+ (0, import_react18.useEffect)(() => {
3765
4045
  if (typeof document === "undefined") return;
3766
4046
  const added = [];
3767
4047
  for (const s of scripts) {
@@ -3778,7 +4058,7 @@ function StorefrontScripts({ visitorId: visitorIdProp } = {}) {
3778
4058
  }
3779
4059
 
3780
4060
  // src/react/components/behio-analytics.tsx
3781
- var import_react18 = require("react");
4061
+ var import_react19 = require("react");
3782
4062
 
3783
4063
  // src/react/hooks/use-behio-client.ts
3784
4064
  function useBehioClient() {
@@ -3788,7 +4068,7 @@ function useBehioClient() {
3788
4068
  // src/react/components/behio-analytics.tsx
3789
4069
  function BehioAnalyticsTracker() {
3790
4070
  const client = useBehioClient();
3791
- (0, import_react18.useEffect)(() => {
4071
+ (0, import_react19.useEffect)(() => {
3792
4072
  if (typeof window === "undefined") return;
3793
4073
  const w = window;
3794
4074
  if (w.__behioAnalytics) return;
@@ -4027,10 +4307,10 @@ function utmFromSearch(search) {
4027
4307
  }
4028
4308
 
4029
4309
  // src/react/hooks/use-bundles.ts
4030
- var import_react_query40 = require("@tanstack/react-query");
4310
+ var import_react_query42 = require("@tanstack/react-query");
4031
4311
  function useBundles(options) {
4032
4312
  const { client } = useBehio();
4033
- return (0, import_react_query40.useQuery)({
4313
+ return (0, import_react_query42.useQuery)({
4034
4314
  queryKey: ["behio", "bundles"],
4035
4315
  queryFn: () => unwrap(client.catalog.getBundles()),
4036
4316
  enabled: options?.enabled ?? true,
@@ -4039,7 +4319,7 @@ function useBundles(options) {
4039
4319
  }
4040
4320
  function useBundle(slug, options) {
4041
4321
  const { client } = useBehio();
4042
- return (0, import_react_query40.useQuery)({
4322
+ return (0, import_react_query42.useQuery)({
4043
4323
  queryKey: ["behio", "bundle", slug],
4044
4324
  queryFn: () => unwrap(client.catalog.getBundle(slug)),
4045
4325
  enabled: Boolean(slug) && (options?.enabled ?? true),
@@ -4048,10 +4328,10 @@ function useBundle(slug, options) {
4048
4328
  }
4049
4329
 
4050
4330
  // src/react/hooks/use-product-group.ts
4051
- var import_react_query41 = require("@tanstack/react-query");
4331
+ var import_react_query43 = require("@tanstack/react-query");
4052
4332
  function useProductGroup(slug, options) {
4053
4333
  const { client } = useBehio();
4054
- return (0, import_react_query41.useQuery)({
4334
+ return (0, import_react_query43.useQuery)({
4055
4335
  queryKey: ["behio", "product-group", slug, options?.locale, options?.currency],
4056
4336
  queryFn: () => unwrap(
4057
4337
  client.catalog.getProductGroup(slug, {
@@ -4065,10 +4345,10 @@ function useProductGroup(slug, options) {
4065
4345
  }
4066
4346
 
4067
4347
  // src/react/hooks/use-cross-sell.ts
4068
- var import_react_query42 = require("@tanstack/react-query");
4348
+ var import_react_query44 = require("@tanstack/react-query");
4069
4349
  function useCrossSell(productSlug, options) {
4070
4350
  const { client } = useBehio();
4071
- return (0, import_react_query42.useQuery)({
4351
+ return (0, import_react_query44.useQuery)({
4072
4352
  queryKey: ["behio", "cross-sell", productSlug, options?.locale, options?.currency],
4073
4353
  queryFn: () => unwrap(
4074
4354
  client.catalog.getCrossSell(productSlug, {
@@ -4082,10 +4362,10 @@ function useCrossSell(productSlug, options) {
4082
4362
  }
4083
4363
 
4084
4364
  // src/react/hooks/use-product-promotions.ts
4085
- var import_react_query43 = require("@tanstack/react-query");
4365
+ var import_react_query45 = require("@tanstack/react-query");
4086
4366
  function useProductPromotions(productSlug, options) {
4087
4367
  const { client } = useBehio();
4088
- return (0, import_react_query43.useQuery)({
4368
+ return (0, import_react_query45.useQuery)({
4089
4369
  queryKey: ["behio", "product-promotions", productSlug],
4090
4370
  queryFn: () => unwrap(client.catalog.getProductPromotions(productSlug)),
4091
4371
  enabled: Boolean(productSlug) && (options?.enabled ?? true),
@@ -4094,11 +4374,11 @@ function useProductPromotions(productSlug, options) {
4094
4374
  }
4095
4375
 
4096
4376
  // src/react/hooks/use-gift-card.ts
4097
- var import_react_query44 = require("@tanstack/react-query");
4377
+ var import_react_query46 = require("@tanstack/react-query");
4098
4378
  function useGiftCardBalance(code, options) {
4099
4379
  const { client } = useBehio();
4100
4380
  const trimmed = code?.trim();
4101
- return (0, import_react_query44.useQuery)({
4381
+ return (0, import_react_query46.useQuery)({
4102
4382
  queryKey: ["behio", "gift-card-balance", trimmed],
4103
4383
  queryFn: () => unwrap(client.catalog.checkGiftCard(trimmed)),
4104
4384
  enabled: Boolean(trimmed && trimmed.length >= 6) && (options?.enabled ?? true)
@@ -4106,20 +4386,20 @@ function useGiftCardBalance(code, options) {
4106
4386
  }
4107
4387
 
4108
4388
  // src/react/hooks/use-wishlist.ts
4109
- var import_react_query45 = require("@tanstack/react-query");
4389
+ var import_react_query47 = require("@tanstack/react-query");
4110
4390
  function useWishlist(options) {
4111
4391
  const { client } = useBehio();
4112
- const qc = (0, import_react_query45.useQueryClient)();
4113
- const query = (0, import_react_query45.useQuery)({
4392
+ const qc = (0, import_react_query47.useQueryClient)();
4393
+ const query = (0, import_react_query47.useQuery)({
4114
4394
  queryKey: ["behio", "wishlist"],
4115
4395
  queryFn: () => unwrap(client.wishlist.get()),
4116
4396
  enabled: options?.enabled ?? true
4117
4397
  });
4118
- const addMutation = (0, import_react_query45.useMutation)({
4398
+ const addMutation = (0, import_react_query47.useMutation)({
4119
4399
  mutationFn: (productId) => unwrap(client.wishlist.add(productId)),
4120
4400
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "wishlist"] })
4121
4401
  });
4122
- const removeMutation = (0, import_react_query45.useMutation)({
4402
+ const removeMutation = (0, import_react_query47.useMutation)({
4123
4403
  mutationFn: (productId) => unwrap(client.wishlist.remove(productId)),
4124
4404
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "wishlist"] })
4125
4405
  });
@@ -4133,7 +4413,7 @@ function useWishlist(options) {
4133
4413
  }
4134
4414
  function useIsInWishlist(productId) {
4135
4415
  const { client } = useBehio();
4136
- return (0, import_react_query45.useQuery)({
4416
+ return (0, import_react_query47.useQuery)({
4137
4417
  queryKey: ["behio", "wishlist-check", productId],
4138
4418
  queryFn: () => unwrap(client.wishlist.isInWishlist(productId)),
4139
4419
  enabled: Boolean(productId)
@@ -4141,10 +4421,10 @@ function useIsInWishlist(productId) {
4141
4421
  }
4142
4422
 
4143
4423
  // src/react/hooks/use-reviews.ts
4144
- var import_react_query46 = require("@tanstack/react-query");
4424
+ var import_react_query48 = require("@tanstack/react-query");
4145
4425
  function useProductReviews(productId, options) {
4146
4426
  const { client } = useBehio();
4147
- return (0, import_react_query46.useQuery)({
4427
+ return (0, import_react_query48.useQuery)({
4148
4428
  queryKey: ["behio", "reviews", productId, options?.page ?? 1],
4149
4429
  queryFn: () => unwrap(client.reviews.getProductReviews(productId, options?.page, options?.limit)),
4150
4430
  enabled: Boolean(productId) && (options?.enabled ?? true)
@@ -4152,30 +4432,30 @@ function useProductReviews(productId, options) {
4152
4432
  }
4153
4433
  function useSubmitReview() {
4154
4434
  const { client } = useBehio();
4155
- const qc = (0, import_react_query46.useQueryClient)();
4156
- return (0, import_react_query46.useMutation)({
4435
+ const qc = (0, import_react_query48.useQueryClient)();
4436
+ return (0, import_react_query48.useMutation)({
4157
4437
  mutationFn: (input) => unwrap(client.reviews.submit(input)),
4158
4438
  onSuccess: (_, input) => qc.invalidateQueries({ queryKey: ["behio", "reviews", input.productId] })
4159
4439
  });
4160
4440
  }
4161
4441
 
4162
4442
  // src/react/hooks/use-returns.ts
4163
- var import_react_query47 = require("@tanstack/react-query");
4443
+ var import_react_query49 = require("@tanstack/react-query");
4164
4444
  function useLookupReturnableOrder() {
4165
4445
  const { client } = useBehio();
4166
- return (0, import_react_query47.useMutation)({
4446
+ return (0, import_react_query49.useMutation)({
4167
4447
  mutationFn: ({ orderNumber, email }) => unwrap(client.returns.lookupOrder(orderNumber, email))
4168
4448
  });
4169
4449
  }
4170
4450
  function useSubmitReturn() {
4171
4451
  const { client } = useBehio();
4172
- return (0, import_react_query47.useMutation)({
4452
+ return (0, import_react_query49.useMutation)({
4173
4453
  mutationFn: (input) => unwrap(client.returns.submit(input))
4174
4454
  });
4175
4455
  }
4176
4456
  function useReturnStatus(returnId, email) {
4177
4457
  const { client } = useBehio();
4178
- return (0, import_react_query47.useQuery)({
4458
+ return (0, import_react_query49.useQuery)({
4179
4459
  queryKey: ["behio", "return-status", returnId],
4180
4460
  queryFn: () => unwrap(client.returns.getStatus(returnId, email)),
4181
4461
  enabled: Boolean(returnId && email)
@@ -4183,16 +4463,16 @@ function useReturnStatus(returnId, email) {
4183
4463
  }
4184
4464
 
4185
4465
  // src/react/hooks/use-quotes.ts
4186
- var import_react_query48 = require("@tanstack/react-query");
4466
+ var import_react_query50 = require("@tanstack/react-query");
4187
4467
  function useSubmitQuote() {
4188
4468
  const { client } = useBehio();
4189
- return (0, import_react_query48.useMutation)({
4469
+ return (0, import_react_query50.useMutation)({
4190
4470
  mutationFn: (input) => unwrap(client.quotes.submit(input))
4191
4471
  });
4192
4472
  }
4193
4473
  function useQuoteStatus(quoteId, email) {
4194
4474
  const { client } = useBehio();
4195
- return (0, import_react_query48.useQuery)({
4475
+ return (0, import_react_query50.useQuery)({
4196
4476
  queryKey: ["behio", "quote-status", quoteId],
4197
4477
  queryFn: () => unwrap(client.quotes.getStatus(quoteId, email)),
4198
4478
  enabled: Boolean(quoteId && email)
@@ -4200,10 +4480,10 @@ function useQuoteStatus(quoteId, email) {
4200
4480
  }
4201
4481
 
4202
4482
  // src/react/hooks/use-back-in-stock.ts
4203
- var import_react_query49 = require("@tanstack/react-query");
4483
+ var import_react_query51 = require("@tanstack/react-query");
4204
4484
  function useNotifyWhenAvailable() {
4205
4485
  const { client } = useBehio();
4206
- return (0, import_react_query49.useMutation)({
4486
+ return (0, import_react_query51.useMutation)({
4207
4487
  mutationFn: ({ productId, email }) => unwrap(client.catalog.notifyWhenAvailable(productId, email))
4208
4488
  });
4209
4489
  }
@@ -4340,6 +4620,9 @@ async function revokeAnalyticsConsent(client) {
4340
4620
  useAuth,
4341
4621
  useBehio,
4342
4622
  useBehioClient,
4623
+ useBlogPost,
4624
+ useBlogPosts,
4625
+ useBlogs,
4343
4626
  useBundle,
4344
4627
  useBundles,
4345
4628
  useCart,
@@ -4393,6 +4676,8 @@ async function revokeAnalyticsConsent(client) {
4393
4676
  useShopInfo,
4394
4677
  useShopScripts,
4395
4678
  useShopSeo,
4679
+ useSiteForm,
4680
+ useSiteFormSubmit,
4396
4681
  useSubmitQuote,
4397
4682
  useSubmitReturn,
4398
4683
  useSubmitReview,