@shopify/hydrogen 0.11.0-experimental.0 → 0.11.0-experimental.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.
- package/dist/esnext/client.d.ts +0 -1
- package/dist/esnext/client.js +0 -1
- package/dist/esnext/components/CartLines/CartLines.d.ts +3 -4
- package/dist/esnext/components/CartLines/CartLines.js +3 -5
- package/dist/esnext/components/CartShopPayButton/CartShopPayButton.client.js +6 -3
- package/dist/esnext/components/Link/Link.client.d.ts +18 -1
- package/dist/esnext/components/Link/Link.client.js +42 -4
- package/dist/esnext/components/Metafield/Metafield.client.d.ts +1 -1
- package/dist/esnext/components/Router/index.d.ts +1 -0
- package/dist/esnext/components/Router/index.js +1 -0
- package/dist/esnext/components/Seo/CollectionSeo.client.js +2 -2
- package/dist/esnext/components/Seo/ProductSeo.client.d.ts +1 -1
- package/dist/esnext/components/Seo/ProductSeo.client.js +4 -8
- package/dist/esnext/components/Seo/types.d.ts +2 -6
- package/dist/esnext/components/ShopPayButton/ShopPayButton.client.d.ts +22 -5
- package/dist/esnext/components/ShopPayButton/ShopPayButton.client.js +45 -12
- package/dist/esnext/components/UnitPrice/UnitPrice.client.d.ts +1 -6
- package/dist/esnext/components/UnitPrice/UnitPrice.client.js +3 -12
- package/dist/esnext/components/index.d.ts +2 -2
- package/dist/esnext/components/index.js +2 -48
- package/dist/esnext/constants.d.ts +1 -0
- package/dist/esnext/constants.js +1 -0
- package/dist/esnext/entry-client.js +3 -4
- package/dist/esnext/entry-server.js +2 -1
- package/dist/esnext/foundation/Helmet/Helmet.client.js +2 -6
- package/dist/esnext/foundation/Router/Router.client.d.ts +12 -0
- package/dist/esnext/foundation/Router/Router.client.js +44 -0
- package/dist/esnext/foundation/ssr-interop.d.ts +29 -0
- package/dist/esnext/foundation/ssr-interop.js +35 -0
- package/dist/esnext/foundation/useQuery/hooks.d.ts +1 -1
- package/dist/esnext/foundation/useQuery/hooks.js +1 -1
- package/dist/esnext/foundation/useServerState/use-server-state.d.ts +2 -1
- package/dist/esnext/foundation/useServerState/use-server-state.js +2 -2
- package/dist/esnext/foundation/useShop/use-shop.js +2 -6
- package/dist/esnext/foundation/useUrl/useUrl.d.ts +1 -1
- package/dist/esnext/foundation/useUrl/useUrl.js +5 -5
- package/dist/esnext/framework/Hydration/Html.js +13 -1
- package/dist/esnext/framework/Hydration/rsc.d.ts +1 -1
- package/dist/esnext/framework/Hydration/rsc.js +4 -4
- package/dist/esnext/framework/plugin.js +2 -0
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.js +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-ssr-interop.d.ts +3 -0
- package/dist/esnext/framework/plugins/vite-plugin-ssr-interop.js +13 -0
- package/dist/esnext/handle-event.js +2 -1
- package/dist/esnext/hooks/useNavigate/index.d.ts +1 -0
- package/dist/esnext/hooks/useNavigate/index.js +1 -0
- package/dist/esnext/hooks/useNavigate/useNavigate.d.ts +10 -0
- package/dist/esnext/hooks/useNavigate/useNavigate.js +11 -0
- package/dist/esnext/utilities/error.js +3 -12
- package/dist/esnext/utilities/fetch.js +8 -0
- package/dist/esnext/utilities/log/log.d.ts +4 -3
- package/dist/esnext/utilities/video_parameters.js +4 -0
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/node/constants.d.ts +1 -0
- package/dist/node/constants.js +4 -0
- package/dist/node/foundation/Helmet/Helmet.client.js +2 -6
- package/dist/node/foundation/ssr-interop.d.ts +29 -0
- package/dist/node/foundation/ssr-interop.js +39 -0
- package/dist/node/framework/Hydration/Html.js +13 -1
- package/dist/node/framework/Hydration/rsc.d.ts +1 -1
- package/dist/node/framework/Hydration/rsc.js +4 -4
- package/dist/node/framework/plugin.js +2 -0
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +1 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.js +1 -1
- package/dist/node/framework/plugins/vite-plugin-ssr-interop.d.ts +3 -0
- package/dist/node/framework/plugins/vite-plugin-ssr-interop.js +15 -0
- package/dist/node/handle-event.js +2 -1
- package/dist/node/utilities/log/log.d.ts +4 -3
- package/dist/worker/constants.d.ts +1 -0
- package/dist/worker/constants.js +1 -0
- package/dist/worker/foundation/Helmet/Helmet.client.js +2 -6
- package/dist/worker/foundation/ssr-interop.d.ts +29 -0
- package/dist/worker/foundation/ssr-interop.js +35 -0
- package/dist/worker/handle-event.js +2 -1
- package/dist/worker/utilities/log/log.d.ts +4 -3
- package/package.json +4 -5
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +1 -5
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +1 -0
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +1 -5
- package/dist/esnext/foundation/Router/ServerStateRouter.client.d.ts +0 -6
- package/dist/esnext/foundation/Router/ServerStateRouter.client.js +0 -30
- package/dist/esnext/utilities/meta-env-ssr.d.ts +0 -1
- package/dist/esnext/utilities/meta-env-ssr.js +0 -3
- package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.d.ts +0 -22
- package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.js +0 -92
- package/dist/node/foundation/ServerRequestProvider/index.d.ts +0 -1
- package/dist/node/foundation/ServerRequestProvider/index.js +0 -13
- package/dist/node/utilities/meta-env-ssr.d.ts +0 -1
- package/dist/node/utilities/meta-env-ssr.js +0 -6
- package/dist/worker/foundation/ServerRequestProvider/ServerRequestProvider.d.ts +0 -22
- package/dist/worker/foundation/ServerRequestProvider/ServerRequestProvider.js +0 -67
- package/dist/worker/foundation/ServerRequestProvider/index.d.ts +0 -1
- package/dist/worker/foundation/ServerRequestProvider/index.js +0 -1
- package/dist/worker/framework/cache.d.ts +0 -26
- package/dist/worker/framework/cache.js +0 -101
- package/dist/worker/utilities/meta-env-ssr.d.ts +0 -1
- package/dist/worker/utilities/meta-env-ssr.js +0 -3
package/dist/esnext/client.d.ts
CHANGED
|
@@ -3,6 +3,5 @@ export * from './hooks';
|
|
|
3
3
|
export * from './foundation/useServerState';
|
|
4
4
|
export * from './foundation/useShop';
|
|
5
5
|
export * from './foundation/ServerStateProvider';
|
|
6
|
-
export { ServerStateRouter } from './foundation/Router/ServerStateRouter.client';
|
|
7
6
|
export { Helmet } from './foundation/Helmet';
|
|
8
7
|
export * from './utilities';
|
package/dist/esnext/client.js
CHANGED
|
@@ -3,6 +3,5 @@ export * from './hooks';
|
|
|
3
3
|
export * from './foundation/useServerState';
|
|
4
4
|
export * from './foundation/useShop';
|
|
5
5
|
export * from './foundation/ServerStateProvider';
|
|
6
|
-
export { ServerStateRouter } from './foundation/Router/ServerStateRouter.client';
|
|
7
6
|
export { Helmet } from './foundation/Helmet';
|
|
8
7
|
export * from './utilities';
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { ReactNode, ElementType } from 'react';
|
|
2
|
-
import { Cart } from '../CartProvider';
|
|
3
2
|
import { Props } from '../types';
|
|
4
3
|
export interface CartLinesProps {
|
|
5
4
|
/** A `ReactNode` element. Valid values: `ul` or `undefined`. If `ul`, then each child will
|
|
6
5
|
* be wrapped with a `li` element.
|
|
7
6
|
*/
|
|
8
7
|
as?: 'ul';
|
|
9
|
-
/** A `ReactNode` element
|
|
10
|
-
children: ReactNode
|
|
8
|
+
/** A `ReactNode` element */
|
|
9
|
+
children: ReactNode;
|
|
11
10
|
}
|
|
12
11
|
/**
|
|
13
12
|
* The `CartLines` component iterates over each cart line and renders its `children` within
|
|
14
|
-
* a `CartLineProvider` for each cart line.
|
|
13
|
+
* a `CartLineProvider` for each cart line.
|
|
15
14
|
*/
|
|
16
15
|
export declare function CartLines<TTag extends ElementType>(props: Props<TTag> & CartLinesProps): JSX.Element;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { Fragment } from 'react';
|
|
2
2
|
import { useCart } from '../CartProvider';
|
|
3
3
|
import { CartLineProvider } from '../CartLineProvider';
|
|
4
4
|
/**
|
|
5
5
|
* The `CartLines` component iterates over each cart line and renders its `children` within
|
|
6
|
-
* a `CartLineProvider` for each cart line.
|
|
6
|
+
* a `CartLineProvider` for each cart line.
|
|
7
7
|
*/
|
|
8
8
|
export function CartLines(props) {
|
|
9
9
|
const { lines } = useCart();
|
|
@@ -12,8 +12,6 @@ export function CartLines(props) {
|
|
|
12
12
|
const ChildWrapper = Wrapper === 'ul' ? 'li' : Fragment;
|
|
13
13
|
return (React.createElement(Wrapper, { ...passthroughProps }, lines.map((line) => {
|
|
14
14
|
return (React.createElement(ChildWrapper, { key: line.id },
|
|
15
|
-
React.createElement(CartLineProvider, { line: line },
|
|
16
|
-
? cloneElement(children(line))
|
|
17
|
-
: children)));
|
|
15
|
+
React.createElement(CartLineProvider, { line: line }, children)));
|
|
18
16
|
})));
|
|
19
17
|
}
|
|
@@ -9,8 +9,11 @@ export function CartShopPayButton({
|
|
|
9
9
|
/** A string of classes to apply to the `div` that wraps the `shop-pay-button` web component. */
|
|
10
10
|
className, }) {
|
|
11
11
|
const { lines } = useCart();
|
|
12
|
-
const
|
|
13
|
-
return lines.map((line) =>
|
|
12
|
+
const idsAndQuantities = useMemo(() => {
|
|
13
|
+
return lines.map((line) => ({
|
|
14
|
+
id: line.merchandise.id,
|
|
15
|
+
quantity: line.quantity,
|
|
16
|
+
}));
|
|
14
17
|
}, [lines]);
|
|
15
|
-
return React.createElement(ShopPayButton, { className: className,
|
|
18
|
+
return (React.createElement(ShopPayButton, { className: className, variantIdsAndQuantities: idsAndQuantities }));
|
|
16
19
|
}
|
|
@@ -1 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface LinkProps
|
|
3
|
+
/** All properties available to an `<a>` element are available. See [anchor element documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attributes).*/
|
|
4
|
+
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
5
|
+
/** The destination URL that the link points to. This is the `href` attribute of the underlying `<a>` element. */
|
|
6
|
+
to: string;
|
|
7
|
+
/** Whether to update the state object or URL of the current history entry. Refer to the [history.replaceState documentation](https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState). */
|
|
8
|
+
replace?: boolean;
|
|
9
|
+
/** The custom client state with the navigation. */
|
|
10
|
+
clientState?: any;
|
|
11
|
+
/** Whether to reload the whole document on navigation. */
|
|
12
|
+
reloadDocument?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The `Link` component lets users navigate from one page to another.
|
|
16
|
+
* It renders an accessible `<a>` element.
|
|
17
|
+
*/
|
|
18
|
+
export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
|
|
@@ -1,5 +1,43 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { useRouter } from '../Router';
|
|
3
|
+
import { createPath } from 'history';
|
|
4
|
+
import { useNavigate } from '../../hooks/useNavigate';
|
|
5
|
+
/**
|
|
6
|
+
* The `Link` component lets users navigate from one page to another.
|
|
7
|
+
* It renders an accessible `<a>` element.
|
|
8
|
+
*/
|
|
9
|
+
export const Link = React.forwardRef(function Link(props, ref) {
|
|
10
|
+
const navigate = useNavigate();
|
|
11
|
+
const { location } = useRouter();
|
|
12
|
+
const { reloadDocument, target, replace: _replace, to, onClick, clientState, } = props;
|
|
13
|
+
const internalClick = useCallback((e) => {
|
|
14
|
+
if (onClick)
|
|
15
|
+
onClick(e);
|
|
16
|
+
if (!reloadDocument && // do regular browser stuff
|
|
17
|
+
e.button === 0 && // Ignore everything but left clicks
|
|
18
|
+
(!target || target === '_self') && // Let browser handle "target=_blank"
|
|
19
|
+
!isModifiedEvent(e) // Ignore modifier key clicks
|
|
20
|
+
) {
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
// If the URL hasn't changed, the regular <a> will do a replace
|
|
23
|
+
const replace = !!_replace || createPath(location) === createPath({ pathname: to });
|
|
24
|
+
navigate(props.to, {
|
|
25
|
+
replace,
|
|
26
|
+
clientState,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}, [reloadDocument, target, _replace, to, clientState, onClick, location]);
|
|
30
|
+
return (React.createElement("a", { ...without(props, ['to', 'replace', 'clientState', 'reloadDocument']), ref: ref, onClick: internalClick, href: props.to }, props.children));
|
|
31
|
+
});
|
|
32
|
+
function isModifiedEvent(event) {
|
|
33
|
+
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
|
|
34
|
+
}
|
|
35
|
+
function without(obj, props) {
|
|
36
|
+
const newObj = {};
|
|
37
|
+
for (const key of Object.keys(obj)) {
|
|
38
|
+
if (!props.includes(key)) {
|
|
39
|
+
newObj[key] = obj[key];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return newObj;
|
|
5
43
|
}
|
|
@@ -4,7 +4,7 @@ import { ParsedMetafield } from '../../types';
|
|
|
4
4
|
export interface MetafieldProps {
|
|
5
5
|
/** A [Metafield object](/api/storefront/reference/common-objects/metafield) from the Storefront API. */
|
|
6
6
|
metafield: ParsedMetafield;
|
|
7
|
-
/** An HTML tag to be rendered as the base element wrapper. The default value varies depending on [
|
|
7
|
+
/** An HTML tag to be rendered as the base element wrapper. The default value varies depending on [metafield.type](/apps/metafields/types). */
|
|
8
8
|
as?: ElementType;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Router, useRouter, useLocation, } from '../../foundation/Router/Router.client';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Router, useRouter, useLocation, } from '../../foundation/Router/Router.client';
|
|
@@ -5,8 +5,8 @@ import { TwitterSeo } from './TwitterSeo.client';
|
|
|
5
5
|
import { ImageSeo } from './ImageSeo.client';
|
|
6
6
|
export function CollectionSeo({ title, description, seo, image }) {
|
|
7
7
|
var _a, _b;
|
|
8
|
-
const seoTitle = (_a =
|
|
9
|
-
const seoDescription = (_b =
|
|
8
|
+
const seoTitle = (_a = seo.title) !== null && _a !== void 0 ? _a : title;
|
|
9
|
+
const seoDescription = (_b = seo.description) !== null && _b !== void 0 ? _b : description;
|
|
10
10
|
return (React.createElement(React.Fragment, null,
|
|
11
11
|
React.createElement(TitleSeo, { title: seoTitle }),
|
|
12
12
|
React.createElement(DescriptionSeo, { description: seoDescription }),
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Product } from './types';
|
|
2
|
-
export declare function ProductSeo({ url, title, description, seo, vendor,
|
|
2
|
+
export declare function ProductSeo({ url, title, description, seo, vendor, featuredImage, variants, }: Product): JSX.Element;
|
|
@@ -4,12 +4,11 @@ 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
|
-
export function ProductSeo({ url, title, description, seo, vendor,
|
|
8
|
-
var _a, _b
|
|
7
|
+
export function ProductSeo({ url, title, description, seo, vendor, featuredImage, variants, }) {
|
|
8
|
+
var _a, _b;
|
|
9
9
|
const seoTitle = (_a = seo === null || seo === void 0 ? void 0 : seo.title) !== null && _a !== void 0 ? _a : title;
|
|
10
10
|
const seoDescription = (_b = seo === null || seo === void 0 ? void 0 : seo.description) !== null && _b !== void 0 ? _b : description;
|
|
11
11
|
let firstVariantPrice;
|
|
12
|
-
let firstImage;
|
|
13
12
|
const productSchema = {
|
|
14
13
|
'@context': 'http://schema.org/',
|
|
15
14
|
'@type': 'Product',
|
|
@@ -21,10 +20,7 @@ export function ProductSeo({ url, title, description, seo, vendor, images, varia
|
|
|
21
20
|
},
|
|
22
21
|
url,
|
|
23
22
|
};
|
|
24
|
-
|
|
25
|
-
firstImage = (_c = images.edges[0]) === null || _c === void 0 ? void 0 : _c.node;
|
|
26
|
-
productSchema.image = firstImage.url;
|
|
27
|
-
}
|
|
23
|
+
productSchema.image = featuredImage.url;
|
|
28
24
|
if (variants.edges.length > 0) {
|
|
29
25
|
const firstVariant = variants.edges[0].node;
|
|
30
26
|
firstVariantPrice = firstVariant.priceV2;
|
|
@@ -56,5 +52,5 @@ export function ProductSeo({ url, title, description, seo, vendor, images, varia
|
|
|
56
52
|
React.createElement(TitleSeo, { title: seoTitle }),
|
|
57
53
|
React.createElement(DescriptionSeo, { description: seoDescription }),
|
|
58
54
|
React.createElement(TwitterSeo, { title: seoTitle, description: seoDescription }),
|
|
59
|
-
|
|
55
|
+
featuredImage && React.createElement(ImageSeo, { ...featuredImage })));
|
|
60
56
|
}
|
|
@@ -32,11 +32,7 @@ export interface Product {
|
|
|
32
32
|
description?: Description;
|
|
33
33
|
};
|
|
34
34
|
vendor: string;
|
|
35
|
-
|
|
36
|
-
edges: {
|
|
37
|
-
node: Image;
|
|
38
|
-
}[];
|
|
39
|
-
};
|
|
35
|
+
featuredImage: Image;
|
|
40
36
|
variants: {
|
|
41
37
|
edges: {
|
|
42
38
|
node: {
|
|
@@ -56,7 +52,7 @@ export interface Product {
|
|
|
56
52
|
export interface Collection {
|
|
57
53
|
title: Title;
|
|
58
54
|
description: Description;
|
|
59
|
-
seo
|
|
55
|
+
seo: {
|
|
60
56
|
title?: Title;
|
|
61
57
|
description?: Description;
|
|
62
58
|
};
|
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
export
|
|
2
|
-
/** An array of IDs of the variants to purchase with Shop Pay. */
|
|
3
|
-
variantIds: string[];
|
|
1
|
+
export declare type ShopPayButtonProps = {
|
|
4
2
|
/** A string of classes to apply to the `div` that wraps the Shop Pay button. */
|
|
5
3
|
className?: string;
|
|
6
|
-
}
|
|
4
|
+
} & ({
|
|
5
|
+
/** 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
|
+
variantIds: string[];
|
|
7
|
+
/** An array of variant IDs and quantities to purchase with Shop Pay. */
|
|
8
|
+
variantIdsAndQuantities?: never;
|
|
9
|
+
} | {
|
|
10
|
+
/** 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'. */
|
|
11
|
+
variantIds?: never;
|
|
12
|
+
/** An array of variant IDs and quantities to purchase with Shop Pay. */
|
|
13
|
+
variantIdsAndQuantities: Array<{
|
|
14
|
+
id: string;
|
|
15
|
+
quantity: number;
|
|
16
|
+
}>;
|
|
17
|
+
});
|
|
7
18
|
declare global {
|
|
8
19
|
namespace JSX {
|
|
9
20
|
interface IntrinsicElements {
|
|
@@ -17,4 +28,10 @@ declare global {
|
|
|
17
28
|
/**
|
|
18
29
|
* The `ShopPayButton` component renders a button that redirects to the Shop Pay checkout.
|
|
19
30
|
*/
|
|
20
|
-
export declare function ShopPayButton({ variantIds, className }: ShopPayButtonProps): JSX.Element;
|
|
31
|
+
export declare function ShopPayButton({ variantIds, className, variantIdsAndQuantities, }: ShopPayButtonProps): JSX.Element;
|
|
32
|
+
/**
|
|
33
|
+
* Takes a string in the format of "gid://shopify/ProductVariant/41007289630776" and returns a string of the ID part at the end: "41007289630776"
|
|
34
|
+
*/
|
|
35
|
+
export declare function getIdFromGid(id?: string): string | undefined;
|
|
36
|
+
export declare const MissingPropsErrorMessage = "You must pass in either \"variantIds\" or \"variantIdsAndQuantities\" to ShopPayButton";
|
|
37
|
+
export declare const DoublePropsErrorMessage = "You must provide either a variantIds or variantIdsAndQuantities prop, but not both in the ShopPayButton component";
|
|
@@ -1,23 +1,56 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { useShop } from '../../foundation/useShop';
|
|
3
3
|
import { useLoadScript } from '../../hooks/useLoadScript/useLoadScript';
|
|
4
|
-
const URL = 'https://cdn.shopify.com/shopifycloud/shop-js/v0.
|
|
4
|
+
const URL = 'https://cdn.shopify.com/shopifycloud/shop-js/v0.8/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 }) {
|
|
9
|
-
const [ids, setIds] = useState([]);
|
|
8
|
+
export function ShopPayButton({ variantIds, className, variantIdsAndQuantities, }) {
|
|
10
9
|
const { storeDomain } = useShop();
|
|
11
10
|
const shopPayLoadedStatus = useLoadScript(URL);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
let ids;
|
|
12
|
+
if (variantIds && variantIdsAndQuantities) {
|
|
13
|
+
throw new Error(DoublePropsErrorMessage);
|
|
14
|
+
}
|
|
15
|
+
if (variantIds) {
|
|
16
|
+
ids = variantIds.reduce((prev, curr) => {
|
|
17
|
+
const bareId = getIdFromGid(curr);
|
|
18
|
+
if (bareId) {
|
|
19
|
+
prev.push(bareId);
|
|
17
20
|
}
|
|
18
|
-
return
|
|
21
|
+
return prev;
|
|
19
22
|
}, []);
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
}
|
|
24
|
+
else if (variantIdsAndQuantities) {
|
|
25
|
+
ids = variantIdsAndQuantities.reduce((prev, curr) => {
|
|
26
|
+
var _a;
|
|
27
|
+
const bareId = getIdFromGid(curr === null || curr === void 0 ? void 0 : curr.id);
|
|
28
|
+
if (bareId) {
|
|
29
|
+
prev.push(`${bareId}:${(_a = curr === null || curr === void 0 ? void 0 : curr.quantity) !== null && _a !== void 0 ? _a : 1}`);
|
|
30
|
+
}
|
|
31
|
+
return prev;
|
|
32
|
+
}, []);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new Error(MissingPropsErrorMessage);
|
|
36
|
+
}
|
|
22
37
|
return (React.createElement("div", { className: className, tabIndex: 1 }, shopPayLoadedStatus === 'done' && (React.createElement("shop-pay-button", { "store-url": `https://${storeDomain}`, variants: ids.join(',') }))));
|
|
23
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Takes a string in the format of "gid://shopify/ProductVariant/41007289630776" and returns a string of the ID part at the end: "41007289630776"
|
|
41
|
+
*/
|
|
42
|
+
export function getIdFromGid(id) {
|
|
43
|
+
if (!id)
|
|
44
|
+
return;
|
|
45
|
+
let gid;
|
|
46
|
+
// atob() / Buffer required for SFAPI 2022-01. Remove atob() when upgrading to 2022-04
|
|
47
|
+
if (typeof (window === null || window === void 0 ? void 0 : window.atob) !== 'undefined') {
|
|
48
|
+
gid = window.atob(id);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
gid = Buffer.from(id, 'base64').toString('ascii');
|
|
52
|
+
}
|
|
53
|
+
return gid.split('/').pop();
|
|
54
|
+
}
|
|
55
|
+
export const MissingPropsErrorMessage = `You must pass in either "variantIds" or "variantIdsAndQuantities" to ShopPayButton`;
|
|
56
|
+
export const DoublePropsErrorMessage = `You must provide either a variantIds or variantIdsAndQuantities prop, but not both in the ShopPayButton component`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ElementType
|
|
1
|
+
import { ElementType } from 'react';
|
|
2
2
|
import { Props } from '../types';
|
|
3
3
|
import { UnitPriceMeasurement, MoneyV2 } from '../../graphql/types/types';
|
|
4
4
|
export interface UnitPriceProps {
|
|
@@ -6,17 +6,12 @@ export interface UnitPriceProps {
|
|
|
6
6
|
unitPrice: MoneyV2;
|
|
7
7
|
/** A [`UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement). */
|
|
8
8
|
unitPriceMeasurement: UnitPriceMeasurement;
|
|
9
|
-
/** A function that takes an object returned by the `UnitPrice` component and returns a `ReactNode`. */
|
|
10
|
-
children?: ReactNode;
|
|
11
9
|
/** An HTML tag to be rendered as the base element wrapper. The default is `div`. */
|
|
12
10
|
as?: ElementType;
|
|
13
11
|
}
|
|
14
12
|
/**
|
|
15
13
|
* The `UnitPrice` component renders a string with a [UnitPrice](/themes/pricing-payments/unit-pricing) as the
|
|
16
14
|
* [Storefront API's `MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) with a reference unit from the [Storefront API's `UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement).
|
|
17
|
-
*
|
|
18
|
-
* If `children` is a function, then it will provide render props for the `children` corresponding to the object
|
|
19
|
-
* returned by the `useMoney` hook and the `UnitPriceMeasurement` object.
|
|
20
15
|
*/
|
|
21
16
|
export declare function UnitPrice<TTag extends ElementType>(props: Props<TTag> & UnitPriceProps): JSX.Element;
|
|
22
17
|
export declare namespace UnitPrice {
|
|
@@ -1,26 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useMoney } from '../../hooks';
|
|
3
2
|
import { Money } from '../Money';
|
|
4
3
|
import { UnitPriceFragment as Fragment } from '../../graphql/graphql-constants';
|
|
5
4
|
/**
|
|
6
5
|
* The `UnitPrice` component renders a string with a [UnitPrice](/themes/pricing-payments/unit-pricing) as the
|
|
7
6
|
* [Storefront API's `MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) with a reference unit from the [Storefront API's `UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement).
|
|
8
|
-
*
|
|
9
|
-
* If `children` is a function, then it will provide render props for the `children` corresponding to the object
|
|
10
|
-
* returned by the `useMoney` hook and the `UnitPriceMeasurement` object.
|
|
11
7
|
*/
|
|
12
8
|
export function UnitPrice(props) {
|
|
13
|
-
const { unitPrice, unitPriceMeasurement,
|
|
9
|
+
const { unitPrice, unitPriceMeasurement, as, ...passthroughProps } = props;
|
|
14
10
|
const Wrapper = as !== null && as !== void 0 ? as : 'div';
|
|
15
|
-
|
|
16
|
-
const unitPriceAndMeasurementObject = {
|
|
17
|
-
...unitPriceMoneyObject,
|
|
18
|
-
...unitPriceMeasurement,
|
|
19
|
-
};
|
|
20
|
-
return (React.createElement(Wrapper, { ...passthroughProps }, typeof children === 'function' ? (children(unitPriceAndMeasurementObject)) : (React.createElement(React.Fragment, null,
|
|
11
|
+
return (React.createElement(Wrapper, { ...passthroughProps },
|
|
21
12
|
React.createElement(Money, { money: unitPrice }),
|
|
22
13
|
"/",
|
|
23
|
-
unitPriceMeasurement.referenceUnit))
|
|
14
|
+
unitPriceMeasurement.referenceUnit));
|
|
24
15
|
}
|
|
25
16
|
UnitPrice.Fragment = Fragment;
|
|
26
17
|
export const UnitPriceFragment = Fragment;
|
|
@@ -41,12 +41,12 @@ export { SelectedVariantAddToCartButton } from './SelectedVariantAddToCartButton
|
|
|
41
41
|
export { SelectedVariantBuyNowButton } from './SelectedVariantBuyNowButton';
|
|
42
42
|
export { SelectedVariantShopPayButton } from './SelectedVariantShopPayButton';
|
|
43
43
|
export { SelectedVariantImage } from './SelectedVariantImage';
|
|
44
|
+
export { SelectedVariantUnitPrice } from './SelectedVariantUnitPrice';
|
|
44
45
|
export type { BuyNowButtonProps, BuyNowButtonPropsWeControl, } from './BuyNowButton';
|
|
45
46
|
export { BuyNowButton } from './BuyNowButton';
|
|
46
47
|
export type { ShopPayButtonProps } from './ShopPayButton';
|
|
47
48
|
export { ShopPayButton } from './ShopPayButton';
|
|
48
49
|
export { useAvailableCountries } from '../hooks/useAvailableCountries';
|
|
49
50
|
export { useCountry } from '../hooks/useCountry';
|
|
50
|
-
export declare const Product: Function & Record<string, any>;
|
|
51
|
-
export declare const CartLine: Function & Record<string, any>;
|
|
52
51
|
export { Seo } from './Seo';
|
|
52
|
+
export { useNavigate } from '../hooks/useNavigate';
|
|
@@ -31,56 +31,10 @@ export { SelectedVariantAddToCartButton } from './SelectedVariantAddToCartButton
|
|
|
31
31
|
export { SelectedVariantBuyNowButton } from './SelectedVariantBuyNowButton';
|
|
32
32
|
export { SelectedVariantShopPayButton } from './SelectedVariantShopPayButton';
|
|
33
33
|
export { SelectedVariantImage } from './SelectedVariantImage';
|
|
34
|
+
export { SelectedVariantUnitPrice } from './SelectedVariantUnitPrice';
|
|
34
35
|
export { BuyNowButton } from './BuyNowButton';
|
|
35
36
|
export { ShopPayButton } from './ShopPayButton';
|
|
36
37
|
export { useAvailableCountries } from '../hooks/useAvailableCountries';
|
|
37
38
|
export { useCountry } from '../hooks/useCountry';
|
|
38
|
-
/**
|
|
39
|
-
* Provide namespaced aliases for the `Product` group.
|
|
40
|
-
*/
|
|
41
|
-
import { ProductProvider } from './ProductProvider';
|
|
42
|
-
import { ProductPrice } from './ProductPrice';
|
|
43
|
-
import { ProductDescription } from './ProductDescription';
|
|
44
|
-
import { ProductTitle } from './ProductTitle';
|
|
45
|
-
import { ProductMetafield } from './ProductMetafield';
|
|
46
|
-
import { SelectedVariantAddToCartButton } from './SelectedVariantAddToCartButton';
|
|
47
|
-
import { SelectedVariantBuyNowButton } from './SelectedVariantBuyNowButton';
|
|
48
|
-
import { SelectedVariantShopPayButton } from './SelectedVariantShopPayButton';
|
|
49
|
-
import { SelectedVariantImage } from './SelectedVariantImage';
|
|
50
|
-
import { SelectedVariantPrice } from './SelectedVariantPrice';
|
|
51
|
-
import { SelectedVariantUnitPrice } from './SelectedVariantUnitPrice';
|
|
52
|
-
import { SelectedVariantMetafield } from './SelectedVariantMetafield';
|
|
53
|
-
export const Product = ProductProvider;
|
|
54
|
-
Product.Description = ProductDescription;
|
|
55
|
-
Product.Price = ProductPrice;
|
|
56
|
-
Product.Title = ProductTitle;
|
|
57
|
-
Product.Metafield = ProductMetafield;
|
|
58
|
-
Product.SelectedVariant = {
|
|
59
|
-
AddToCartButton: SelectedVariantAddToCartButton,
|
|
60
|
-
BuyNowButton: SelectedVariantBuyNowButton,
|
|
61
|
-
ShopPayButton: SelectedVariantShopPayButton,
|
|
62
|
-
Price: SelectedVariantPrice,
|
|
63
|
-
Image: SelectedVariantImage,
|
|
64
|
-
UnitPrice: SelectedVariantUnitPrice,
|
|
65
|
-
Metafield: SelectedVariantMetafield,
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Provide namespaced aliases for the `CartLine` group.
|
|
69
|
-
*/
|
|
70
|
-
import { CartLineProvider } from './CartLineProvider';
|
|
71
|
-
import { CartLineImage } from './CartLineImage';
|
|
72
|
-
import { CartLinePrice } from './CartLinePrice';
|
|
73
|
-
import { CartLineProductTitle } from './CartLineProductTitle';
|
|
74
|
-
import { CartLineQuantity } from './CartLineQuantity';
|
|
75
|
-
import { CartLineQuantityAdjustButton } from './CartLineQuantityAdjustButton';
|
|
76
|
-
import { CartLineSelectedOptions } from './CartLineSelectedOptions';
|
|
77
|
-
import { CartLineAttributes } from './CartLineAttributes';
|
|
78
|
-
export const CartLine = CartLineProvider;
|
|
79
|
-
CartLine.Image = CartLineImage;
|
|
80
|
-
CartLine.Price = CartLinePrice;
|
|
81
|
-
CartLine.ProductTitle = CartLineProductTitle;
|
|
82
|
-
CartLine.Quantity = CartLineQuantity;
|
|
83
|
-
CartLine.QuantityAdjustButton = CartLineQuantityAdjustButton;
|
|
84
|
-
CartLine.SelectedOptions = CartLineSelectedOptions;
|
|
85
|
-
CartLine.Attributes = CartLineAttributes;
|
|
86
39
|
export { Seo } from './Seo';
|
|
40
|
+
export { useNavigate } from '../hooks/useNavigate';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const RSC_PATHNAME = "/__rsc";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const RSC_PATHNAME = '/__rsc';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { Suspense, useState } from 'react';
|
|
2
2
|
// @ts-ignore
|
|
3
3
|
import { hydrateRoot } from 'react-dom';
|
|
4
|
-
import { BrowserRouter } from 'react-router-dom';
|
|
5
4
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
6
5
|
import { useServerResponse } from './framework/Hydration/rsc';
|
|
7
|
-
import { ServerStateProvider
|
|
6
|
+
import { ServerStateProvider } from './client';
|
|
7
|
+
import { Router } from './foundation/Router/Router.client';
|
|
8
8
|
const renderHydrogen = async (ClientWrapper) => {
|
|
9
9
|
const root = document.getElementById('root');
|
|
10
10
|
if (!root) {
|
|
@@ -23,8 +23,7 @@ function Content({ clientWrapper: ClientWrapper }) {
|
|
|
23
23
|
});
|
|
24
24
|
const response = useServerResponse(serverState);
|
|
25
25
|
return (React.createElement(ServerStateProvider, { serverState: serverState, setServerState: setServerState },
|
|
26
|
-
React.createElement(
|
|
27
|
-
React.createElement(ServerStateRouter, null),
|
|
26
|
+
React.createElement(Router, null,
|
|
28
27
|
React.createElement(ClientWrapper, null, response.readRoot()))));
|
|
29
28
|
}
|
|
30
29
|
function Error({ error }) {
|
|
@@ -9,6 +9,7 @@ import { ServerRequestProvider } from './foundation/ServerRequestProvider';
|
|
|
9
9
|
import { getApiRouteFromURL, getApiRoutesFromPages } from './utilities/apiRoutes';
|
|
10
10
|
import { ServerStateProvider } from './foundation/ServerStateProvider';
|
|
11
11
|
import { ssrRenderToPipeableStream, ssrRenderToReadableStream, rscRenderToReadableStream, createFromReadableStream, } from './streaming.server';
|
|
12
|
+
import { RSC_PATHNAME } from './constants';
|
|
12
13
|
/**
|
|
13
14
|
* If a query is taking too long, or something else went wrong,
|
|
14
15
|
* send back a response containing the Suspense fallback and rely
|
|
@@ -528,7 +529,7 @@ async function isStreamingSupported() {
|
|
|
528
529
|
}
|
|
529
530
|
function setupCurrentRequest(url, request) {
|
|
530
531
|
const log = getLoggerFromContext(request);
|
|
531
|
-
const state = url.pathname ===
|
|
532
|
+
const state = url.pathname === RSC_PATHNAME
|
|
532
533
|
? JSON.parse(url.searchParams.get('state') || '{}')
|
|
533
534
|
: { pathname: url.pathname, search: url.search };
|
|
534
535
|
const componentResponse = new ServerComponentResponse();
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Helmet as ActualHelmet, HelmetData, } from 'react-helmet-async';
|
|
3
|
-
import {
|
|
4
|
-
import { META_ENV_SSR } from '../../utilities/meta-env-ssr';
|
|
3
|
+
import { useEnvContext } from '../ssr-interop';
|
|
5
4
|
const clientHelmetData = new HelmetData({});
|
|
6
5
|
export function Helmet({ children, ...props }) {
|
|
7
|
-
|
|
8
|
-
const helmetData = META_ENV_SSR
|
|
9
|
-
? useServerRequest().ctx.helmet
|
|
10
|
-
: clientHelmetData;
|
|
6
|
+
const helmetData = useEnvContext((req) => req.ctx.helmet, clientHelmetData);
|
|
11
7
|
return (
|
|
12
8
|
// @ts-ignore
|
|
13
9
|
React.createElement(ActualHelmet, { ...props, helmetData: helmetData }, children));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BrowserHistory, Location } from 'history';
|
|
2
|
+
import { FC } from 'react';
|
|
3
|
+
declare type RouterContextValue = {
|
|
4
|
+
history: BrowserHistory;
|
|
5
|
+
location: Location;
|
|
6
|
+
};
|
|
7
|
+
export declare const Router: FC<{
|
|
8
|
+
history?: BrowserHistory;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function useRouter(): RouterContextValue;
|
|
11
|
+
export declare function useLocation(): Location;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createBrowserHistory } from 'history';
|
|
2
|
+
import React, { createContext, useContext, useMemo, useState, useEffect, } from 'react';
|
|
3
|
+
import { META_ENV_SSR } from '../ssr-interop';
|
|
4
|
+
import { useServerState } from '../useServerState';
|
|
5
|
+
const RouterContext = createContext({});
|
|
6
|
+
export const Router = ({ history: pHistory, children, }) => {
|
|
7
|
+
const history = useMemo(() => pHistory || createBrowserHistory(), [pHistory]);
|
|
8
|
+
const [firstLoad, setFirstLoad] = useState(true);
|
|
9
|
+
const [location, setLocation] = useState(history.location);
|
|
10
|
+
const { pending, setServerState } = useServerState();
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
// The app has just loaded
|
|
13
|
+
if (firstLoad)
|
|
14
|
+
setFirstLoad(false);
|
|
15
|
+
// A navigation event has just happened
|
|
16
|
+
else if (!pending) {
|
|
17
|
+
window.scrollTo(0, 0);
|
|
18
|
+
}
|
|
19
|
+
}, [pending]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const unlisten = history.listen(({ location: newLocation }) => {
|
|
22
|
+
setServerState({
|
|
23
|
+
pathname: newLocation.pathname,
|
|
24
|
+
search: location.search || undefined,
|
|
25
|
+
});
|
|
26
|
+
setLocation(newLocation);
|
|
27
|
+
});
|
|
28
|
+
return () => unlisten();
|
|
29
|
+
}, [history]);
|
|
30
|
+
return (React.createElement(RouterContext.Provider, { value: {
|
|
31
|
+
history,
|
|
32
|
+
location,
|
|
33
|
+
} }, children));
|
|
34
|
+
};
|
|
35
|
+
export function useRouter() {
|
|
36
|
+
const router = useContext(RouterContext);
|
|
37
|
+
if (!router && META_ENV_SSR) {
|
|
38
|
+
throw new Error('useRouter must be used within a <Router> component');
|
|
39
|
+
}
|
|
40
|
+
return router;
|
|
41
|
+
}
|
|
42
|
+
export function useLocation() {
|
|
43
|
+
return useRouter().location;
|
|
44
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is used for compatibility between browser and server environments.
|
|
3
|
+
* The browser loads this file as is, without leaking server logic.
|
|
4
|
+
* In the server, this file is transformed by Vite to inject server logic.
|
|
5
|
+
* NOTE: Do not remove SSR-prefixed comments in this file.
|
|
6
|
+
*/
|
|
7
|
+
import type { ServerComponentRequest } from '../framework/Hydration/ServerComponentRequest.server';
|
|
8
|
+
export declare const META_ENV_SSR = false;
|
|
9
|
+
declare type ServerGetter<T> = (request: ServerComponentRequest) => T;
|
|
10
|
+
/**
|
|
11
|
+
* Isomorphic hook to access context data. It gives access to the current request
|
|
12
|
+
* when running on the server, and returns the provided client fallback in the browser.
|
|
13
|
+
* This can be used in server components (RSC) as a Context/Provider replacement. In client
|
|
14
|
+
* components, it uses the server getter in SSR and the client fallback in the browser.
|
|
15
|
+
* @param serverGetter - A function that gets the current server request and returns any
|
|
16
|
+
* desired request property. It only runs in the server (both in RSC and SSR).
|
|
17
|
+
* @param clientFallback - An optional raw value or a React.Context to be consumed that will be
|
|
18
|
+
* returned if the current environment is not the server. Note that, if this is a React.Context,
|
|
19
|
+
* there must be a React.Provider parent in the app tree.
|
|
20
|
+
* @returns A value retrieved from the current server request or a fallback value in the client.
|
|
21
|
+
* The returned type depends on what the server getter returns.
|
|
22
|
+
* @example
|
|
23
|
+
* ```js
|
|
24
|
+
* import {MyClientContext} from './my-client-react-context-provider';
|
|
25
|
+
* useEnvContext(req => req.ctx.myServerContext, MyClientContext)
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function useEnvContext<T>(serverGetter: ServerGetter<T>, clientFallback?: any): T;
|
|
29
|
+
export {};
|