@shopify/hydrogen 0.25.0 → 0.26.1

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.
Files changed (128) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/dist/esnext/components/{CartEstimatedCost/CartEstimatedCost.client.d.ts → CartCost/CartCost.client.d.ts} +3 -3
  3. package/dist/esnext/components/{CartEstimatedCost/CartEstimatedCost.client.js → CartCost/CartCost.client.js} +7 -7
  4. package/dist/esnext/components/CartCost/index.d.ts +1 -0
  5. package/dist/esnext/components/CartCost/index.js +1 -0
  6. package/dist/esnext/components/CartLinePrice/CartLinePrice.client.js +2 -2
  7. package/dist/esnext/components/CartLineProvider/context.d.ts +3 -3
  8. package/dist/esnext/components/CartProvider/CartProvider.client.js +37 -27
  9. package/dist/esnext/components/CartProvider/cart-queries.d.ts +1 -1
  10. package/dist/esnext/components/CartProvider/cart-queries.js +3 -3
  11. package/dist/esnext/components/CartProvider/graphql/CartAttributesUpdateMutation.d.ts +5 -5
  12. package/dist/esnext/components/CartProvider/graphql/CartBuyerIdentityUpdateMutation.d.ts +5 -5
  13. package/dist/esnext/components/CartProvider/graphql/CartCreateMutation.d.ts +5 -5
  14. package/dist/esnext/components/CartProvider/graphql/CartDiscountCodesUpdateMutation.d.ts +5 -5
  15. package/dist/esnext/components/CartProvider/graphql/CartFragment.d.ts +5 -5
  16. package/dist/esnext/components/CartProvider/graphql/CartLineAddMutation.d.ts +5 -5
  17. package/dist/esnext/components/CartProvider/graphql/CartLineRemoveMutation.d.ts +5 -5
  18. package/dist/esnext/components/CartProvider/graphql/CartLineUpdateMutation.d.ts +5 -5
  19. package/dist/esnext/components/CartProvider/graphql/CartNoteUpdateMutation.d.ts +5 -5
  20. package/dist/esnext/components/CartProvider/graphql/CartQuery.d.ts +5 -5
  21. package/dist/esnext/components/CartProvider/hooks.client.d.ts +1 -1
  22. package/dist/esnext/components/CartProvider/hooks.client.js +16 -11
  23. package/dist/esnext/components/CartProvider/types.d.ts +3 -3
  24. package/dist/esnext/components/CartShopPayButton/CartShopPayButton.client.d.ts +1 -3
  25. package/dist/esnext/components/CartShopPayButton/CartShopPayButton.client.js +2 -4
  26. package/dist/esnext/components/Link/Link.client.d.ts +2 -0
  27. package/dist/esnext/components/Link/Link.client.js +14 -7
  28. package/dist/esnext/components/LocalizationProvider/LocalizationClientProvider.client.d.ts +2 -2
  29. package/dist/esnext/components/LocalizationProvider/LocalizationClientProvider.client.js +1 -1
  30. package/dist/esnext/components/LocalizationProvider/LocalizationContext.client.d.ts +6 -3
  31. package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.d.ts +8 -20
  32. package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.js +18 -33
  33. package/dist/esnext/components/LocalizationProvider/index.d.ts +0 -1
  34. package/dist/esnext/components/LocalizationProvider/index.js +0 -1
  35. package/dist/esnext/components/Metafield/Metafield.client.js +3 -3
  36. package/dist/esnext/components/Seo/DefaultPageSeo.client.js +3 -3
  37. package/dist/esnext/components/Seo/DescriptionSeo.client.js +1 -1
  38. package/dist/esnext/components/Seo/HomePageSeo.client.d.ts +1 -1
  39. package/dist/esnext/components/Seo/HomePageSeo.client.js +3 -3
  40. package/dist/esnext/components/Seo/ImageSeo.client.js +1 -1
  41. package/dist/esnext/components/Seo/NoIndexSeo.client.js +3 -3
  42. package/dist/esnext/components/Seo/ProductSeo.client.js +2 -2
  43. package/dist/esnext/components/Seo/Seo.client.js +1 -1
  44. package/dist/esnext/components/Seo/TitleSeo.client.js +1 -1
  45. package/dist/esnext/components/Seo/TwitterSeo.client.js +1 -1
  46. package/dist/esnext/components/Seo/seo-types.d.ts +1 -0
  47. package/dist/esnext/components/ShopPayButton/ShopPayButton.client.d.ts +3 -1
  48. package/dist/esnext/components/ShopPayButton/ShopPayButton.client.js +8 -3
  49. package/dist/esnext/components/index.d.ts +2 -2
  50. package/dist/esnext/components/index.js +2 -2
  51. package/dist/esnext/constants.d.ts +1 -1
  52. package/dist/esnext/constants.js +1 -1
  53. package/dist/esnext/entry-client.js +7 -5
  54. package/dist/esnext/entry-server.js +40 -40
  55. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetricsDebug.client.js +1 -1
  56. package/dist/esnext/foundation/Analytics/connectors/Shopify/ShopifyAnalytics.client.js +1 -1
  57. package/dist/esnext/foundation/FileRoutes/FileRoutes.server.js +1 -1
  58. package/dist/esnext/foundation/HydrogenRequest/HydrogenRequest.server.d.ts +9 -1
  59. package/dist/esnext/foundation/HydrogenRequest/HydrogenRequest.server.js +6 -0
  60. package/dist/esnext/foundation/Route/Route.server.js +1 -1
  61. package/dist/esnext/foundation/Router/BrowserRouter.client.d.ts +1 -1
  62. package/dist/esnext/foundation/Router/BrowserRouter.client.js +7 -5
  63. package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.d.ts +5 -4
  64. package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.js +9 -7
  65. package/dist/esnext/foundation/ShopifyProvider/ShopifyProvider.server.js +4 -0
  66. package/dist/esnext/foundation/ShopifyProvider/types.d.ts +1 -0
  67. package/dist/esnext/foundation/useNavigate/useNavigate.d.ts +2 -0
  68. package/dist/esnext/foundation/useNavigate/useNavigate.js +19 -0
  69. package/dist/esnext/foundation/useQuery/hooks.js +1 -4
  70. package/dist/esnext/foundation/useRouteParams/RouteParamsProvider.client.d.ts +3 -0
  71. package/dist/esnext/foundation/useRouteParams/RouteParamsProvider.client.js +8 -3
  72. package/dist/esnext/foundation/useUrl/useUrl.js +5 -3
  73. package/dist/esnext/framework/cache/in-memory.d.ts +12 -7
  74. package/dist/esnext/framework/cache/in-memory.js +49 -21
  75. package/dist/esnext/framework/load-config.d.ts +5 -0
  76. package/dist/esnext/framework/load-config.js +7 -0
  77. package/dist/esnext/framework/plugin.js +1 -1
  78. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-client-middleware.js +2 -3
  79. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +2 -2
  80. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-rsc.d.ts +2 -1
  81. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-rsc.js +2 -1
  82. package/dist/esnext/framework/types.d.ts +1 -0
  83. package/dist/esnext/framework/viteception.d.ts +2 -1
  84. package/dist/esnext/framework/viteception.js +2 -1
  85. package/dist/esnext/hooks/useCartLine/useCartLine.d.ts +3 -3
  86. package/dist/esnext/hooks/useLocalization/useLocalization.d.ts +4 -0
  87. package/dist/esnext/hooks/useLocalization/useLocalization.js +14 -0
  88. package/dist/esnext/hooks/useMeasurement/hooks.js +2 -2
  89. package/dist/esnext/hooks/useMoney/hooks.js +2 -2
  90. package/dist/esnext/index.d.ts +3 -0
  91. package/dist/esnext/index.js +1 -0
  92. package/dist/esnext/platforms/node.d.ts +1 -1
  93. package/dist/esnext/platforms/node.js +2 -1
  94. package/dist/esnext/storefront-api-types.d.ts +105 -3
  95. package/dist/esnext/storefront-api-types.js +8 -0
  96. package/dist/esnext/types.d.ts +10 -0
  97. package/dist/esnext/utilities/apiRoutes.d.ts +4 -3
  98. package/dist/esnext/utilities/image_size.js +11 -0
  99. package/dist/esnext/utilities/log/log-cache-api-status.js +3 -0
  100. package/dist/esnext/utilities/storefrontApi.d.ts +1 -0
  101. package/dist/esnext/utilities/storefrontApi.js +1 -1
  102. package/dist/esnext/version.d.ts +1 -1
  103. package/dist/esnext/version.js +1 -1
  104. package/dist/node/framework/cache/in-memory.d.ts +12 -7
  105. package/dist/node/framework/cache/in-memory.js +49 -21
  106. package/dist/node/framework/load-config.d.ts +5 -0
  107. package/dist/node/framework/load-config.js +11 -0
  108. package/dist/node/framework/plugin.js +1 -1
  109. package/dist/node/framework/plugins/vite-plugin-hydrogen-client-middleware.js +2 -3
  110. package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +2 -2
  111. package/dist/node/framework/plugins/vite-plugin-hydrogen-rsc.d.ts +2 -1
  112. package/dist/node/framework/plugins/vite-plugin-hydrogen-rsc.js +2 -1
  113. package/dist/node/framework/types.d.ts +1 -0
  114. package/dist/node/framework/viteception.d.ts +2 -1
  115. package/dist/node/framework/viteception.js +2 -1
  116. package/package.json +13 -3
  117. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +46 -17
  118. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite.development.js +18 -3
  119. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +2 -2
  120. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +2 -1
  121. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +46 -17
  122. package/vendor/react-server-dom-vite/esm/react-server-dom-vite.js +18 -3
  123. package/dist/esnext/components/CartEstimatedCost/index.d.ts +0 -1
  124. package/dist/esnext/components/CartEstimatedCost/index.js +0 -1
  125. package/dist/esnext/hooks/useCountry/index.d.ts +0 -1
  126. package/dist/esnext/hooks/useCountry/index.js +0 -1
  127. package/dist/esnext/hooks/useCountry/useCountry.d.ts +0 -7
  128. package/dist/esnext/hooks/useCountry/useCountry.js +0 -17
@@ -37,13 +37,13 @@ export declare type CartLineUpdateMutation = {
37
37
  attributes: Array<{
38
38
  __typename?: 'Attribute';
39
39
  } & Pick<Types.Attribute, 'key' | 'value'>>;
40
- estimatedCost: {
41
- __typename?: 'CartLineEstimatedCost';
40
+ cost: {
41
+ __typename?: 'CartLineCost';
42
42
  } & {
43
43
  totalAmount: {
44
44
  __typename?: 'MoneyV2';
45
45
  } & Pick<Types.MoneyV2, 'amount' | 'currencyCode'>;
46
- compareAtAmount?: Types.Maybe<{
46
+ compareAtAmountPerQuantity?: Types.Maybe<{
47
47
  __typename?: 'MoneyV2';
48
48
  } & Pick<Types.MoneyV2, 'amount' | 'currencyCode'>>;
49
49
  };
@@ -69,8 +69,8 @@ export declare type CartLineUpdateMutation = {
69
69
  };
70
70
  }>;
71
71
  };
72
- estimatedCost: {
73
- __typename?: 'CartEstimatedCost';
72
+ cost: {
73
+ __typename?: 'CartCost';
74
74
  } & {
75
75
  subtotalAmount: {
76
76
  __typename?: 'MoneyV2';
@@ -37,13 +37,13 @@ export declare type CartNoteUpdateMutation = {
37
37
  attributes: Array<{
38
38
  __typename?: 'Attribute';
39
39
  } & Pick<Types.Attribute, 'key' | 'value'>>;
40
- estimatedCost: {
41
- __typename?: 'CartLineEstimatedCost';
40
+ cost: {
41
+ __typename?: 'CartLineCost';
42
42
  } & {
43
43
  totalAmount: {
44
44
  __typename?: 'MoneyV2';
45
45
  } & Pick<Types.MoneyV2, 'amount' | 'currencyCode'>;
46
- compareAtAmount?: Types.Maybe<{
46
+ compareAtAmountPerQuantity?: Types.Maybe<{
47
47
  __typename?: 'MoneyV2';
48
48
  } & Pick<Types.MoneyV2, 'amount' | 'currencyCode'>>;
49
49
  };
@@ -69,8 +69,8 @@ export declare type CartNoteUpdateMutation = {
69
69
  };
70
70
  }>;
71
71
  };
72
- estimatedCost: {
73
- __typename?: 'CartEstimatedCost';
72
+ cost: {
73
+ __typename?: 'CartCost';
74
74
  } & {
75
75
  subtotalAmount: {
76
76
  __typename?: 'MoneyV2';
@@ -33,13 +33,13 @@ export declare type CartQueryQuery = {
33
33
  attributes: Array<{
34
34
  __typename?: 'Attribute';
35
35
  } & Pick<Types.Attribute, 'key' | 'value'>>;
36
- estimatedCost: {
37
- __typename?: 'CartLineEstimatedCost';
36
+ cost: {
37
+ __typename?: 'CartLineCost';
38
38
  } & {
39
39
  totalAmount: {
40
40
  __typename?: 'MoneyV2';
41
41
  } & Pick<Types.MoneyV2, 'amount' | 'currencyCode'>;
42
- compareAtAmount?: Types.Maybe<{
42
+ compareAtAmountPerQuantity?: Types.Maybe<{
43
43
  __typename?: 'MoneyV2';
44
44
  } & Pick<Types.MoneyV2, 'amount' | 'currencyCode'>>;
45
45
  };
@@ -65,8 +65,8 @@ export declare type CartQueryQuery = {
65
65
  };
66
66
  }>;
67
67
  };
68
- estimatedCost: {
69
- __typename?: 'CartEstimatedCost';
68
+ cost: {
69
+ __typename?: 'CartCost';
70
70
  } & {
71
71
  subtotalAmount: {
72
72
  __typename?: 'MoneyV2';
@@ -5,7 +5,7 @@ export declare function useCartFetch(): <T, K>({ query, variables, }: {
5
5
  variables: T;
6
6
  }) => Promise<{
7
7
  data: K | undefined;
8
- error: any;
8
+ errors: any;
9
9
  }>;
10
10
  export declare function useInstantCheckout(): {
11
11
  cart: Cart | undefined;
@@ -2,17 +2,22 @@ import React, { useState } from 'react';
2
2
  import { useShop } from '../../foundation';
3
3
  import { flattenConnection } from '../../utilities';
4
4
  import { CartCreate, defaultCartFragment } from './cart-queries';
5
+ import { SHOPIFY_STOREFRONT_ID_HEADER, STOREFRONT_API_PUBLIC_TOKEN_HEADER, } from '../../constants';
5
6
  export function useCartFetch() {
6
- const { storeDomain, storefrontApiVersion, storefrontToken } = useShop();
7
+ const { storeDomain, storefrontApiVersion, storefrontToken, storefrontId } = useShop();
7
8
  return React.useCallback(({ query, variables, }) => {
9
+ const headers = {
10
+ 'Content-Type': 'application/json',
11
+ 'X-SDK-Variant': 'hydrogen',
12
+ 'X-SDK-Version': storefrontApiVersion,
13
+ [STOREFRONT_API_PUBLIC_TOKEN_HEADER]: storefrontToken,
14
+ };
15
+ if (storefrontId) {
16
+ headers[SHOPIFY_STOREFRONT_ID_HEADER] = storefrontId;
17
+ }
8
18
  return fetch(`https://${storeDomain}/api/${storefrontApiVersion}/graphql.json`, {
9
19
  method: 'POST',
10
- headers: {
11
- 'Content-Type': 'application/json',
12
- 'X-SDK-Variant': 'hydrogen',
13
- 'X-SDK-Version': storefrontApiVersion,
14
- 'X-Shopify-Storefront-Access-Token': storefrontToken,
15
- },
20
+ headers,
16
21
  body: JSON.stringify({
17
22
  query: query.toString(),
18
23
  variables,
@@ -25,7 +30,7 @@ export function useCartFetch() {
25
30
  error: error.toString(),
26
31
  };
27
32
  });
28
- }, [storeDomain, storefrontApiVersion, storefrontToken]);
33
+ }, [storeDomain, storefrontApiVersion, storefrontToken, storefrontId]);
29
34
  }
30
35
  export function useInstantCheckout() {
31
36
  const [cart, updateCart] = useState();
@@ -33,14 +38,14 @@ export function useInstantCheckout() {
33
38
  const [error, updateError] = useState();
34
39
  const fetch = useCartFetch();
35
40
  const createInstantCheckout = React.useCallback(async (cartInput) => {
36
- const { data, error } = await fetch({
41
+ const { data, errors } = await fetch({
37
42
  query: CartCreate(defaultCartFragment),
38
43
  variables: {
39
44
  input: cartInput,
40
45
  },
41
46
  });
42
- if (error) {
43
- updateError(error);
47
+ if (errors) {
48
+ updateError(errors);
44
49
  updateCart(undefined);
45
50
  updateCheckoutUrl(undefined);
46
51
  }
@@ -16,8 +16,8 @@ export interface Cart {
16
16
  attributes: CartFragmentFragment['attributes'];
17
17
  /** The discount codes applied to the cart. */
18
18
  discountCodes?: CartFragmentFragment['discountCodes'];
19
- /** The estimate cost for the cart, including the subtotal, total, taxes, and duties. */
20
- estimatedCost?: CartFragmentFragment['estimatedCost'];
19
+ /** The cost for the cart, including the subtotal, total, taxes, and duties. */
20
+ cost?: CartFragmentFragment['cost'];
21
21
  /** The total number of items in the cart, across all lines. If there are no lines, then the value is 0. */
22
22
  totalQuantity: number;
23
23
  }
@@ -98,7 +98,7 @@ export declare type CartAction = {
98
98
  cart: Cart;
99
99
  } | {
100
100
  type: 'reject';
101
- error: string;
101
+ errors: any;
102
102
  } | {
103
103
  type: 'resetCart';
104
104
  };
@@ -4,6 +4,4 @@ import { ShopPayButton } from '../ShopPayButton';
4
4
  * The `CartShopPayButton` component renders a `ShopPayButton` for the items in the cart.
5
5
  * It must be a descendent of a `CartProvider` component.
6
6
  */
7
- export declare function CartShopPayButton({
8
- /** A string of classes to apply to the `div` that wraps the `shop-pay-button` web component. */
9
- className, }: Omit<React.ComponentProps<typeof ShopPayButton>, 'variantIds'>): JSX.Element;
7
+ export declare function CartShopPayButton(props: Omit<React.ComponentProps<typeof ShopPayButton>, 'variantIds'>): JSX.Element;
@@ -5,9 +5,7 @@ import { ShopPayButton } from '../ShopPayButton';
5
5
  * The `CartShopPayButton` component renders a `ShopPayButton` for the items in the cart.
6
6
  * It must be a descendent of a `CartProvider` component.
7
7
  */
8
- export function CartShopPayButton({
9
- /** A string of classes to apply to the `div` that wraps the `shop-pay-button` web component. */
10
- className, }) {
8
+ export function CartShopPayButton(props) {
11
9
  const { lines } = useCart();
12
10
  const idsAndQuantities = useMemo(() => {
13
11
  return lines.map((line) => ({
@@ -15,5 +13,5 @@ className, }) {
15
13
  quantity: line.quantity,
16
14
  }));
17
15
  }, [lines]);
18
- return (React.createElement(ShopPayButton, { className: className, variantIdsAndQuantities: idsAndQuantities }));
16
+ return (React.createElement(ShopPayButton, { variantIdsAndQuantities: idsAndQuantities, ...props }));
19
17
  }
@@ -12,6 +12,8 @@ export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEle
12
12
  prefetch?: boolean;
13
13
  /** Whether to emulate natural browser behavior and restore scroll position on navigation. Defaults to `true`. */
14
14
  scroll?: boolean;
15
+ /** Override the `basePath` inherited from the Route */
16
+ basePath?: string;
15
17
  }
16
18
  /**
17
19
  * The `Link` component is used to navigate between routes. Because it renders an underlying `<a>` element, all
@@ -1,9 +1,10 @@
1
1
  import React, { useCallback, useEffect, useState } from 'react';
2
- import { useRouter } from '../../foundation/Router/BrowserRouter.client';
2
+ import { useLocation } from '../../foundation/Router/BrowserRouter.client';
3
3
  import { createPath } from 'history';
4
- import { useNavigate } from '../../foundation/useNavigate/useNavigate';
4
+ import { buildPath, useNavigate } from '../../foundation/useNavigate/useNavigate';
5
5
  import { RSC_PATHNAME } from '../../constants';
6
6
  import { useInternalServerProps } from '../../foundation/useServerProps/use-server-props';
7
+ import { useBasePath } from '../../foundation/useRouteParams/RouteParamsProvider.client';
7
8
  /**
8
9
  * The `Link` component is used to navigate between routes. Because it renders an underlying `<a>` element, all
9
10
  * properties available to the `<a>` element are also available to the `Link` component.
@@ -11,14 +12,16 @@ import { useInternalServerProps } from '../../foundation/useServerProps/use-serv
11
12
  */
12
13
  export const Link = React.forwardRef(function Link(props, ref) {
13
14
  const navigate = useNavigate();
14
- const { location } = useRouter();
15
+ const location = useLocation();
15
16
  const [_, startTransition] = React.useTransition();
17
+ const routeBasePath = useBasePath();
16
18
  /**
17
19
  * Inspired by Remix's Link component
18
20
  */
19
21
  const [shouldPrefetch, setShouldPrefetch] = useState(false);
20
22
  const [maybePrefetch, setMaybePrefetch] = useState(false);
21
- const { reloadDocument, target, replace: _replace, to, onClick, clientState, prefetch = true, scroll = true, } = props;
23
+ const { reloadDocument, target, replace: _replace, onClick, clientState, prefetch = true, scroll = true, } = props;
24
+ const to = buildPath(props.basePath ?? routeBasePath, props.to);
22
25
  const internalClick = useCallback((e) => {
23
26
  if (onClick)
24
27
  onClick(e);
@@ -34,6 +37,7 @@ export const Link = React.forwardRef(function Link(props, ref) {
34
37
  replace,
35
38
  scroll,
36
39
  clientState,
40
+ basePath: '/', // path was already resolved with the base
37
41
  });
38
42
  }
39
43
  }, [
@@ -52,7 +56,7 @@ export const Link = React.forwardRef(function Link(props, ref) {
52
56
  * startTransition to yield to more important updates
53
57
  */
54
58
  startTransition(() => {
55
- if (prefetch) {
59
+ if (prefetch && !!to) {
56
60
  setMaybePrefetch(true);
57
61
  }
58
62
  });
@@ -94,12 +98,15 @@ export const Link = React.forwardRef(function Link(props, ref) {
94
98
  'reloadDocument',
95
99
  'prefetch',
96
100
  'scroll',
97
- ]), ref: ref, onClick: internalClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onFocus: onFocus, onBlur: onBlur, onTouchStart: onTouchStart, href: props.to }, props.children),
101
+ ]), ref: ref, rel: props.rel ??
102
+ (to.startsWith('http') || to.startsWith('//')
103
+ ? 'noreferrer noopener'
104
+ : undefined), onClick: internalClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onFocus: onFocus, onBlur: onBlur, onTouchStart: onTouchStart, href: to }, props.children),
98
105
  shouldPrefetch && React.createElement(Prefetch, { pathname: to })));
99
106
  });
100
107
  function Prefetch({ pathname }) {
101
108
  const { getProposedLocationServerProps } = useInternalServerProps();
102
- const { location } = useRouter();
109
+ const location = useLocation();
103
110
  const newPath = createPath({ pathname });
104
111
  if (pathname.startsWith('http') || newPath === createPath(location)) {
105
112
  return null;
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- import { Localization } from './LocalizationContext.client';
2
+ import { LocalizationContextValue } from './LocalizationContext.client';
3
3
  export default function LocalizationClientProvider({ localization, children, }: {
4
4
  children: ReactNode;
5
- localization: Localization;
5
+ localization: LocalizationContextValue;
6
6
  }): JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { LocalizationContext } from './LocalizationContext.client';
2
+ import { LocalizationContext, } from './LocalizationContext.client';
3
3
  export default function LocalizationClientProvider({ localization, children, }) {
4
4
  return (React.createElement(LocalizationContext.Provider, { value: localization }, children));
5
5
  }
@@ -1,6 +1,9 @@
1
- import type { LocalizationQuery } from './LocalizationProvider.server';
2
- export declare type Localization = LocalizationQuery['localization'];
3
1
  export interface LocalizationContextValue {
4
- country?: Localization['country'];
2
+ country: {
3
+ isoCode: string;
4
+ };
5
+ language: {
6
+ isoCode: string;
7
+ };
5
8
  }
6
9
  export declare const LocalizationContext: import("react").Context<LocalizationContextValue | null>;
@@ -1,33 +1,21 @@
1
1
  import { ReactNode } from 'react';
2
- import { PreloadOptions } from '../../types';
3
- import { Country } from '../../storefront-api-types';
4
2
  export interface LocalizationProviderProps {
5
3
  /** A `ReactNode` element. */
6
4
  children: ReactNode;
7
- /** Whether to preload the query. Defaults to `false`. Specify `true` to
8
- * [preload the query](https://shopify.dev/custom-storefronts/hydrogen/framework/preloaded-queries) for the URL
9
- * or `'*'` to preload the query for all requests.
5
+ /**
6
+ * Override the `isoCode` to define the active country
10
7
  */
11
- preload: PreloadOptions;
8
+ countryCode?: string;
9
+ /**
10
+ * Override the `languageCode` to define the active language
11
+ */
12
+ languageCode?: string;
12
13
  }
13
14
  /**
14
15
  * The `LocalizationProvider` component automatically queries the Storefront API's
15
16
  * [`localization`](https://shopify.dev/api/storefront/reference/common-objects/queryroot) field
16
17
  * for the `isoCode` and `name` of the `country` and keeps this information in a context.
17
18
  *
18
- * Any descendents of this provider can use the `useCountry` hook.
19
- * The `isoCode` of the `country` can be used in the Storefront API's
20
- * `@inContext` directive as the `country` value.
19
+ * Any descendents of this provider can use the `useLocalization` hook.
21
20
  */
22
21
  export declare function LocalizationProvider(props: LocalizationProviderProps): JSX.Element;
23
- export declare type LocalizationQuery = {
24
- __typename?: 'QueryRoot';
25
- } & {
26
- localization: {
27
- __typename?: 'Localization';
28
- } & {
29
- country: {
30
- __typename?: 'Country';
31
- } & Pick<Country, 'isoCode' | 'name'>;
32
- };
33
- };
@@ -1,44 +1,29 @@
1
1
  import React from 'react';
2
2
  import LocalizationClientProvider from './LocalizationClientProvider.client';
3
3
  import { useShop } from '../../foundation/useShop';
4
- import { useShopQuery } from '../../hooks/useShopQuery';
5
- import { CacheLong } from '../../foundation/Cache/strategies';
6
- import { useSession } from '../../foundation/useSession/useSession';
4
+ import { useServerRequest } from '../../foundation/ServerRequestProvider';
5
+ import { CountryCode } from '../../storefront-api-types';
7
6
  /**
8
7
  * The `LocalizationProvider` component automatically queries the Storefront API's
9
8
  * [`localization`](https://shopify.dev/api/storefront/reference/common-objects/queryroot) field
10
9
  * for the `isoCode` and `name` of the `country` and keeps this information in a context.
11
10
  *
12
- * Any descendents of this provider can use the `useCountry` hook.
13
- * The `isoCode` of the `country` can be used in the Storefront API's
14
- * `@inContext` directive as the `country` value.
11
+ * Any descendents of this provider can use the `useLocalization` hook.
15
12
  */
16
13
  export function LocalizationProvider(props) {
17
- const { languageCode } = useShop();
18
- const { countryCode, countryName } = useSession();
19
- const { data: { localization }, } = useShopQuery({
20
- query,
21
- variables: { language: languageCode },
22
- cache: CacheLong(),
23
- preload: props.preload,
24
- });
25
- return (React.createElement(LocalizationClientProvider, { localization: countryCode
26
- ? {
27
- country: {
28
- name: countryName,
29
- isoCode: countryCode,
30
- },
31
- }
32
- : localization }, props.children));
14
+ const { languageCode: defaultLanguageCode, locale } = useShop();
15
+ const defaultCountryCode = locale.split(/[-_]/)[1] || CountryCode.Us;
16
+ const languageCode = (props.languageCode ?? defaultLanguageCode).toUpperCase();
17
+ const countryCode = (props.countryCode ?? defaultCountryCode).toUpperCase();
18
+ const request = useServerRequest();
19
+ const localization = {
20
+ country: {
21
+ isoCode: countryCode,
22
+ },
23
+ language: {
24
+ isoCode: languageCode,
25
+ },
26
+ };
27
+ request.ctx.localization = localization;
28
+ return (React.createElement(LocalizationClientProvider, { localization: localization }, props.children));
33
29
  }
34
- const query = `
35
- query Localization($language: LanguageCode)
36
- @inContext(language: $language) {
37
- localization {
38
- country {
39
- isoCode
40
- name
41
- }
42
- }
43
- }
44
- `;
@@ -1,2 +1 @@
1
1
  export { LocalizationProvider } from './LocalizationProvider.server';
2
- export { useCountry } from '../../hooks/useCountry/useCountry';
@@ -1,2 +1 @@
1
1
  export { LocalizationProvider } from './LocalizationProvider.server';
2
- export { useCountry } from '../../hooks/useCountry/useCountry';
@@ -1,6 +1,6 @@
1
1
  import React, { useMemo } from 'react';
2
- import { useShop } from '../../foundation';
3
- import { getMeasurementAsString } from '../../utilities';
2
+ import { useLocalization } from '../../hooks/useLocalization/useLocalization';
3
+ import { getMeasurementAsString } from '../../utilities/measurement';
4
4
  import { Image } from '../Image';
5
5
  import { Video } from '../Video';
6
6
  import { flattenConnection } from '../../utilities/flattenConnection/index';
@@ -13,7 +13,7 @@ import { parseMetafield } from '../../utilities/parseMetafield/index';
13
13
  */
14
14
  export function Metafield(props) {
15
15
  const { data, children, as, ...passthroughProps } = props;
16
- const { locale } = useShop();
16
+ const { locale } = useLocalization();
17
17
  const parsedMetafield = useMemo(() => parseMetafield(data), [data]);
18
18
  if (!parsedMetafield) {
19
19
  if (__HYDROGEN_DEV__) {
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
- import { useShop } from '../../foundation';
3
- import { Head } from '../../client';
2
+ import { Head } from '../../foundation/Head';
3
+ import { useLocalization } from '../../hooks/useLocalization/useLocalization';
4
4
  import { TitleSeo } from './TitleSeo.client';
5
5
  import { DescriptionSeo } from './DescriptionSeo.client';
6
6
  import { TwitterSeo } from './TwitterSeo.client';
7
7
  export function DefaultPageSeo({ title, description, url, titleTemplate, lang, }) {
8
- const { languageCode: fallBacklang } = useShop();
8
+ const { language: { isoCode: fallBacklang }, } = useLocalization();
9
9
  return (React.createElement(React.Fragment, null,
10
10
  React.createElement(Head, { defaultTitle: title ?? '', titleTemplate: titleTemplate ?? `%s - ${title}` },
11
11
  React.createElement("html", { lang: lang ?? fallBacklang }),
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Head } from '../../client';
2
+ import { Head } from '../../foundation/Head';
3
3
  export function DescriptionSeo({ description, }) {
4
4
  if (!description) {
5
5
  return null;
@@ -1,2 +1,2 @@
1
1
  import type { HomePage } from './seo-types';
2
- export declare function HomePageSeo({ title, description, url }: HomePage): JSX.Element;
2
+ export declare function HomePageSeo({ title, description, url, titleTemplate, }: HomePage): JSX.Element;
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
- import { Head } from '../../client';
2
+ import { Head } from '../../foundation/Head';
3
3
  import { TitleSeo } from './TitleSeo.client';
4
4
  import { DescriptionSeo } from './DescriptionSeo.client';
5
- export function HomePageSeo({ title, description, url }) {
5
+ export function HomePageSeo({ title, description, url, titleTemplate, }) {
6
6
  const organizationSchema = {
7
7
  '@context': 'http://schema.org',
8
8
  '@type': 'Organization',
@@ -16,7 +16,7 @@ export function HomePageSeo({ title, description, url }) {
16
16
  url,
17
17
  };
18
18
  return (React.createElement(React.Fragment, null,
19
- React.createElement(Head, null,
19
+ React.createElement(Head, { defaultTitle: title ?? '', titleTemplate: titleTemplate ?? `%s` },
20
20
  React.createElement("meta", { property: "og:url", content: url }),
21
21
  React.createElement("script", { type: "application/ld+json" }, JSON.stringify(organizationSchema)),
22
22
  React.createElement("script", { type: "application/ld+json" }, JSON.stringify(webSiteSchema))),
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Head } from '../../client';
2
+ import { Head } from '../../foundation/Head';
3
3
  export function ImageSeo({ url, width, height, altText }) {
4
4
  return (React.createElement(Head, null,
5
5
  url && React.createElement("meta", { property: "og:image", content: url }),
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
- import { useShop } from '../../foundation';
3
- import { Head } from '../../client';
2
+ import { useLocalization } from '../../hooks/useLocalization/useLocalization';
3
+ import { Head } from '../../foundation/Head/Head.client';
4
4
  export function NoIndexPageSeo({ title, titleTemplate, lang, }) {
5
- const { languageCode: fallBacklang } = useShop();
5
+ const { language: { isoCode: fallBacklang }, } = useLocalization();
6
6
  return (React.createElement(React.Fragment, null,
7
7
  React.createElement(Head, { defaultTitle: title ?? '', titleTemplate: titleTemplate ?? `%s - ${title}` },
8
8
  React.createElement("html", { lang: lang ?? fallBacklang }),
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
- import { Head } from '../../client';
2
+ import { Head } from '../../foundation/Head';
3
3
  import { TitleSeo } from './TitleSeo.client';
4
4
  import { DescriptionSeo } from './DescriptionSeo.client';
5
5
  import { TwitterSeo } from './TwitterSeo.client';
6
6
  import { ImageSeo } from './ImageSeo.client';
7
- import { flattenConnection } from '../../utilities';
7
+ import { flattenConnection } from '../../utilities/flattenConnection';
8
8
  export function ProductSeo({ url, title, description, seo, vendor, featuredImage, variants, }) {
9
9
  const seoTitle = seo?.title ?? title;
10
10
  const seoDescription = seo?.description ?? description;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { useUrl } from '../../foundation';
2
+ import { useUrl } from '../../foundation/useUrl';
3
3
  import { DefaultPageSeo } from './DefaultPageSeo.client';
4
4
  import { HomePageSeo } from './HomePageSeo.client';
5
5
  import { ProductSeo } from './ProductSeo.client';
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Head } from '../../client';
2
+ import { Head } from '../../foundation/Head';
3
3
  export function TitleSeo({ title }) {
4
4
  if (!title) {
5
5
  return null;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Head } from '../../client';
2
+ import { Head } from '../../foundation/Head';
3
3
  export function TwitterSeo({ site, title, description }) {
4
4
  return (React.createElement(Head, null,
5
5
  React.createElement("meta", { name: "twitter:card", content: "summary_large_image" }),
@@ -8,6 +8,7 @@ export interface HomePage {
8
8
  description: ShopType['description'];
9
9
  title: ShopType['name'];
10
10
  url: Scalars['URL'];
11
+ titleTemplate?: string;
11
12
  }
12
13
  export interface DefaultPage extends ShopType {
13
14
  title: ShopType['name'];
@@ -1,6 +1,8 @@
1
1
  declare type ShopPayButtonProps = {
2
2
  /** A string of classes to apply to the `div` that wraps the Shop Pay button. */
3
3
  className?: string;
4
+ /** A string that's applied to the [CSS custom property (variable)](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) `--shop-pay-button-width` for the [Buy with Shop Pay component](https://shopify.dev/custom-storefronts/tools/web-components#buy-with-shop-pay-component). */
5
+ width?: string;
4
6
  } & ({
5
7
  /** An array of IDs of the variants to purchase with Shop Pay. This will only ever have a quantity of 1 for each variant. If you want to use other quantities, then use 'variantIdsAndQuantities'. */
6
8
  variantIds: string[];
@@ -28,7 +30,7 @@ declare global {
28
30
  /**
29
31
  * The `ShopPayButton` component renders a button that redirects to the Shop Pay checkout.
30
32
  */
31
- export declare function ShopPayButton({ variantIds, className, variantIdsAndQuantities, }: ShopPayButtonProps): JSX.Element;
33
+ export declare function ShopPayButton({ variantIds, className, variantIdsAndQuantities, width, }: ShopPayButtonProps): JSX.Element;
32
34
  /**
33
35
  * Takes a string in the format of "gid://shopify/ProductVariant/41007289630776" and returns a string of the ID part at the end: "41007289630776"
34
36
  */
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import { useShop } from '../../foundation/useShop';
3
3
  import { useLoadScript } from '../../hooks/useLoadScript/useLoadScript.client';
4
- const URL = 'https://cdn.shopify.com/shopifycloud/shop-js/v0.8/client.js';
4
+ const URL = 'https://cdn.shopify.com/shopifycloud/shop-js/v1.0/client.js';
5
5
  /**
6
6
  * The `ShopPayButton` component renders a button that redirects to the Shop Pay checkout.
7
7
  */
8
- export function ShopPayButton({ variantIds, className, variantIdsAndQuantities, }) {
8
+ export function ShopPayButton({ variantIds, className, variantIdsAndQuantities, width, }) {
9
9
  const { storeDomain } = useShop();
10
10
  const shopPayLoadedStatus = useLoadScript(URL);
11
11
  let ids;
@@ -33,9 +33,14 @@ export function ShopPayButton({ variantIds, className, variantIdsAndQuantities,
33
33
  else {
34
34
  throw new Error(MissingPropsErrorMessage);
35
35
  }
36
+ const style = width
37
+ ? {
38
+ '--shop-pay-button-width': width,
39
+ }
40
+ : undefined;
36
41
  return (
37
42
  /* eslint-disable jsx-a11y/no-noninteractive-tabindex */
38
- React.createElement("div", { className: className, tabIndex: 0 }, shopPayLoadedStatus === 'done' && (React.createElement("shop-pay-button", { "store-url": `https://${storeDomain}`, variants: ids.join(',') })))
43
+ React.createElement("div", { className: className, tabIndex: 0, style: style }, shopPayLoadedStatus === 'done' && (React.createElement("shop-pay-button", { "store-url": `https://${storeDomain}`, variants: ids.join(',') })))
39
44
  /* eslint-enable jsx-a11y/no-noninteractive-tabindex */
40
45
  );
41
46
  }
@@ -17,12 +17,12 @@ export { CartLineQuantityAdjustButton } from './CartLineQuantityAdjustButton';
17
17
  export { CartLines } from './CartLines';
18
18
  export { CartCheckoutButton } from './CartCheckoutButton';
19
19
  export { CartShopPayButton } from './CartShopPayButton';
20
- export { CartEstimatedCost } from './CartEstimatedCost';
20
+ export { CartCost } from './CartCost';
21
21
  export { CartProvider, useCart, useInstantCheckout } from './CartProvider';
22
22
  export type { State, Status, Cart, CartWithActions, CartAction, } from './CartProvider';
23
23
  export { ProductOptionsProvider, useProductOptions, } from './ProductOptionsProvider';
24
24
  export { ProductPrice } from './ProductPrice';
25
25
  export { BuyNowButton } from './BuyNowButton';
26
26
  export { ShopPayButton } from './ShopPayButton';
27
- export { useCountry } from '../hooks/useCountry';
27
+ export { useLocalization } from '../hooks/useLocalization/useLocalization';
28
28
  export { Seo } from './Seo';