@shopify/hydrogen 2026.4.6 → 2026.4.8

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.
@@ -1,4 +1,4 @@
1
- import { createContext, forwardRef, lazy, useContext, useRef, useState, useMemo, useEffect, useCallback, createElement, Fragment as Fragment$1, Suspense } from 'react';
1
+ import { createContext, forwardRef, lazy, useContext, useRef, useState, useMemo, useEffect, useCallback, startTransition, createElement, Fragment as Fragment$1, Suspense } from 'react';
2
2
  import { createContext as createContext$1, useRevalidator, useFetcher, useFetchers, RouterContextProvider, createRequestHandler as createRequestHandler$1, useNavigation, useLocation, useNavigate, Link, useMatches } from 'react-router';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useLoadScript, createStorefrontClient as createStorefrontClient$1, SHOPIFY_STOREFRONT_ID_HEADER, SHOPIFY_STOREFRONT_Y_HEADER, SHOPIFY_STOREFRONT_S_HEADER, SHOPIFY_UNIQUE_TOKEN_HEADER, SHOPIFY_VISIT_TOKEN_HEADER, flattenConnection, RichText as RichText$1, ShopPayButton as ShopPayButton$1, parseGid, getTrackingValues, sendShopifyAnalytics, AnalyticsEventName, AnalyticsPageType, getClientBrowserParameters } from '@shopify/hydrogen-react';
@@ -314,7 +314,7 @@ function getPrivacyBanner() {
314
314
  }
315
315
 
316
316
  // package.json
317
- var version = "2026.4.6";
317
+ var version = "2026.4.8";
318
318
 
319
319
  // src/analytics-manager/ShopifyAnalytics.tsx
320
320
  function getCustomerPrivacyRequired() {
@@ -816,6 +816,8 @@ function register(key) {
816
816
  }
817
817
  };
818
818
  }
819
+ var noopPublish = () => {
820
+ };
819
821
  function messageOnError(field, envVar) {
820
822
  return `[h2:error:Analytics.Provider] - ${field} is required. Make sure ${envVar} is defined in your environment variables. See https://h2o.fyi/analytics/consent to learn how to setup environment variables in the Shopify admin.`;
821
823
  }
@@ -830,11 +832,25 @@ function AnalyticsProvider({
830
832
  const { shop } = useShopAnalytics(shopProp);
831
833
  const [consentVersion, setConsentVersion] = useState(0);
832
834
  const [privacyReady, setPrivacyReady] = useState(false);
833
- const [carts, setCarts] = useState({ cart: null, prevCart: null });
835
+ const [carts, setCartsState] = useState({ cart: null, prevCart: null });
836
+ const setCarts = useCallback(
837
+ (update) => startTransition(() => setCartsState(update)),
838
+ []
839
+ );
834
840
  const canTrack = customCanTrack ?? hasAnalyticsConsent;
841
+ const canTrackRef = useRef(canTrack);
842
+ canTrackRef.current = canTrack;
843
+ const guardedPublish = useCallback(
844
+ (event, payload) => {
845
+ if (canTrackRef.current()) publish(event, payload);
846
+ },
847
+ []
848
+ );
835
849
  const onConsentChange = useCallback(() => {
836
- setPrivacyReady(true);
837
- setConsentVersion((version2) => version2 + 1);
850
+ startTransition(() => {
851
+ setPrivacyReady(true);
852
+ setConsentVersion((version2) => version2 + 1);
853
+ });
838
854
  }, []);
839
855
  if (!!shop) {
840
856
  if (/\/68817551382$/.test(shop.shopId)) {
@@ -872,8 +888,7 @@ function AnalyticsProvider({
872
888
  canTrack,
873
889
  ...carts,
874
890
  customData,
875
- publish: canTrack() ? publish : () => {
876
- },
891
+ publish: canTrack() ? guardedPublish : noopPublish,
877
892
  shop,
878
893
  subscribe,
879
894
  register,
@@ -886,7 +901,7 @@ function AnalyticsProvider({
886
901
  carts,
887
902
  carts.cart?.updatedAt,
888
903
  carts.prevCart,
889
- publish,
904
+ guardedPublish,
890
905
  subscribe,
891
906
  customData,
892
907
  shop,
@@ -915,7 +930,9 @@ function useAnalytics() {
915
930
  function useShopAnalytics(shopProp) {
916
931
  const [shop, setShop] = useState(null);
917
932
  useEffect(() => {
918
- Promise.resolve(shopProp).then(setShop);
933
+ Promise.resolve(shopProp).then((resolvedShop) => {
934
+ startTransition(() => setShop(resolvedShop));
935
+ });
919
936
  return () => {
920
937
  };
921
938
  }, [setShop, shopProp]);
@@ -1681,7 +1698,7 @@ function generateUUID() {
1681
1698
  }
1682
1699
 
1683
1700
  // src/version.ts
1684
- var LIB_VERSION = "2026.4.6";
1701
+ var LIB_VERSION = "2026.4.8";
1685
1702
 
1686
1703
  // src/utils/graphql.ts
1687
1704
  function minifyQuery(string) {
@@ -3365,7 +3382,7 @@ function useOptimisticCart(cart) {
3365
3382
  }
3366
3383
 
3367
3384
  // src/changelogHandler.ts
3368
- var DEFAULT_GITHUB_CHANGELOG_URL = "https://raw.githubusercontent.com/Shopify/hydrogen/main/docs/changelog.json";
3385
+ var DEFAULT_GITHUB_CHANGELOG_URL = "https://raw.githubusercontent.com/Shopify/hydrogen/2026-04/docs/changelog.json";
3369
3386
  async function changelogHandler({
3370
3387
  request,
3371
3388
  changelogUrl
@@ -3669,6 +3686,17 @@ function getRedirectUrl(requestUrl) {
3669
3686
  }
3670
3687
  }
3671
3688
  }
3689
+ function getSameOriginPath(target, origin) {
3690
+ if (!target) return void 0;
3691
+ try {
3692
+ const url = target.startsWith("/") ? new URL(target, origin) : new URL(target);
3693
+ if (url.origin !== origin) return void 0;
3694
+ const path = `${url.pathname}${url.search}${url.hash}`;
3695
+ return path.startsWith("//") ? void 0 : path;
3696
+ } catch {
3697
+ return void 0;
3698
+ }
3699
+ }
3672
3700
  function isLocalPath(requestUrl, redirectUrl) {
3673
3701
  try {
3674
3702
  return new URL(requestUrl).origin === new URL(redirectUrl, requestUrl).origin;
@@ -4007,7 +4035,9 @@ function createCustomerAccountClient({
4007
4035
  codeVerifier: verifier,
4008
4036
  state,
4009
4037
  nonce,
4010
- redirectPath: getRedirectUrl(request.url) || getHeader(request, "Referer") || defaultRedirectPath
4038
+ redirectPath: getRedirectUrl(request.url) || // The same HTTPS origin the OAuth `redirect_uri` uses, so an http
4039
+ // `request.url` still matches the https pages customers browse.
4040
+ getSameOriginPath(getHeader(request, "Referer"), httpsOrigin) || defaultRedirectPath
4011
4041
  });
4012
4042
  loginUrl.searchParams.append("code_challenge", challenge);
4013
4043
  loginUrl.searchParams.append("code_challenge_method", "S256");