@shopify/cli-hydrogen 8.0.4 → 8.1.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/{lib/setups/i18n/templates → assets/hydrogen/i18n}/domains.ts +1 -1
- package/dist/assets/hydrogen/i18n/mock-i18n-types.ts +3 -0
- package/dist/{lib/setups/i18n/templates → assets/hydrogen/i18n}/subdomains.ts +1 -1
- package/dist/{lib/setups/i18n/templates → assets/hydrogen/i18n}/subfolders.ts +1 -1
- package/dist/{generator-templates → assets/hydrogen}/starter/.eslintrc.cjs +1 -0
- package/dist/{generator-templates → assets/hydrogen}/starter/CHANGELOG.md +31 -0
- package/dist/assets/hydrogen/starter/app/components/Aside.tsx +76 -0
- package/dist/{generator-templates → assets/hydrogen}/starter/app/components/Cart.tsx +38 -14
- package/dist/{generator-templates → assets/hydrogen}/starter/app/components/Footer.tsx +30 -13
- package/dist/{generator-templates → assets/hydrogen}/starter/app/components/Header.tsx +52 -12
- package/dist/{generator-templates/starter/app/components/Layout.tsx → assets/hydrogen/starter/app/components/PageLayout.tsx} +38 -28
- package/dist/{generator-templates → assets/hydrogen}/starter/app/components/Search.tsx +5 -3
- package/dist/{generator-templates → assets/hydrogen}/starter/app/entry.server.tsx +8 -2
- package/dist/{generator-templates → assets/hydrogen}/starter/app/lib/fragments.ts +70 -0
- package/dist/assets/hydrogen/starter/app/root.tsx +204 -0
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/_index.tsx +62 -25
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account.addresses.tsx +0 -1
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account.orders.$id.tsx +2 -2
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account.profile.tsx +0 -1
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/api.predictive-search.tsx +6 -1
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/blogs.$blogHandle.$articleHandle.tsx +34 -8
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/blogs.$blogHandle._index.tsx +36 -10
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/blogs._index.tsx +35 -12
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/cart.tsx +7 -7
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/collections.$handle.tsx +49 -7
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/collections._index.tsx +32 -6
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/collections.all.tsx +31 -6
- package/dist/assets/hydrogen/starter/app/routes/pages.$handle.tsx +84 -0
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/products.$handle.tsx +82 -17
- package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/search.tsx +4 -1
- package/dist/{generator-templates → assets/hydrogen}/starter/app/styles/app.css +22 -4
- package/dist/{generator-templates → assets/hydrogen}/starter/env.d.ts +1 -0
- package/dist/{generator-templates → assets/hydrogen}/starter/package.json +10 -10
- package/dist/{generator-templates → assets/hydrogen}/starter/storefrontapi.generated.d.ts +3 -1
- package/dist/{generator-templates → assets/hydrogen}/starter/vite.config.ts +15 -0
- package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/routes/index.jsx +0 -10
- package/dist/{generator-templates/assets → assets/hydrogen}/vite/vite.config.js +15 -0
- package/dist/commands/hydrogen/build.js +119 -36
- package/dist/commands/hydrogen/debug/cpu.js +74 -64
- package/dist/commands/hydrogen/deploy.js +4 -4
- package/dist/commands/hydrogen/dev.js +133 -51
- package/dist/{init.d.ts → commands/hydrogen/init.d.ts} +5 -5
- package/dist/commands/hydrogen/init.js +17 -8
- package/dist/commands/hydrogen/preview.js +101 -13
- package/dist/commands/hydrogen/setup/vite.js +2 -2
- package/dist/commands/hydrogen/setup.js +1 -1
- package/dist/commands/hydrogen/upgrade.js +53 -50
- package/dist/index.d.ts +403 -0
- package/dist/index.js +61 -0
- package/dist/lib/build.js +48 -37
- package/dist/lib/bundle/analyzer.js +2 -4
- package/dist/lib/check-version.js +38 -18
- package/dist/lib/classic-compiler/build.js +11 -4
- package/dist/lib/classic-compiler/debug-cpu.js +52 -0
- package/dist/lib/classic-compiler/dev.js +12 -5
- package/dist/lib/codegen.js +34 -9
- package/dist/lib/cpu-profiler.js +29 -12
- package/dist/lib/defer.js +13 -7
- package/dist/lib/deps-optimizer.js +146 -0
- package/dist/lib/flags.js +2 -7
- package/dist/lib/format-code.js +1 -2
- package/dist/lib/import-utils.js +22 -0
- package/dist/lib/live-reload.js +15 -5
- package/dist/lib/log.js +24 -2
- package/dist/lib/mini-oxygen/index.js +6 -2
- package/dist/lib/mini-oxygen/node.js +18 -4
- package/dist/lib/mini-oxygen/workerd.js +18 -5
- package/dist/lib/onboarding/local.js +1 -1
- package/dist/lib/onboarding/setup-template.mocks.js +7 -11
- package/dist/lib/remix-config.js +11 -9
- package/dist/lib/remix-version-check.js +8 -13
- package/dist/lib/resource-cleanup.js +13 -0
- package/dist/lib/setups/css/assets.js +3 -3
- package/dist/lib/setups/css/css-modules.js +2 -2
- package/dist/lib/setups/css/postcss.js +2 -2
- package/dist/lib/setups/css/tailwind.js +2 -2
- package/dist/lib/setups/css/vanilla-extract.js +2 -2
- package/dist/lib/setups/i18n/index.js +3 -5
- package/dist/lib/setups/routes/generate.js +17 -16
- package/dist/lib/template-diff.js +120 -42
- package/dist/lib/template-downloader.js +6 -11
- package/dist/lib/transpile/morph/typedefs.js +17 -0
- package/dist/lib/virtual-routes.js +2 -2
- package/dist/lib/vite-config.js +2 -1
- package/oclif.manifest.json +89 -1
- package/package.json +13 -9
- package/dist/generator-templates/starter/app/components/Aside.tsx +0 -47
- package/dist/generator-templates/starter/app/lib/root-data.ts +0 -11
- package/dist/generator-templates/starter/app/root.tsx +0 -227
- package/dist/generator-templates/starter/app/routes/pages.$handle.tsx +0 -56
- package/dist/lib/setups/i18n/mock-i18n-types.js +0 -1
- package/dist/lib/setups/i18n/templates/domains.js +0 -14
- package/dist/lib/setups/i18n/templates/subdomains.js +0 -14
- package/dist/lib/setups/i18n/templates/subfolders.js +0 -13
- package/dist/lib/setups/routes/templates/locale-check.js +0 -9
- package/dist/virtual-routes/components/IconDiscord.jsx +0 -21
- /package/dist/{lib/bundle/bundle-analyzer.html → assets/hydrogen/bundle/analyzer.html} +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/css-modules/package.json +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/postcss/package.json +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/postcss/postcss.config.js +0 -0
- /package/dist/{lib/setups/routes/templates → assets/hydrogen/routes}/locale-check.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/.eslintignore +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/.graphqlrc.yml +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/README.md +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/assets/favicon.svg +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/entry.client.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/graphql/customer-account/CustomerAddressMutations.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/graphql/customer-account/CustomerOrderQuery.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/graphql/customer-account/CustomerOrdersQuery.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/graphql/customer-account/CustomerUpdateMutation.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/lib/search.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/lib/session.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/lib/variants.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/$.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/[robots.txt].tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/[sitemap.xml].tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account.$.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account._index.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account.orders._index.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account_.authorize.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account_.login.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/account_.logout.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/cart.$lines.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/discount.$code.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/policies.$handle.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/routes/policies._index.tsx +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/app/styles/reset.css +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/customer-accountapi.generated.d.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/public/.gitkeep +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/server.ts +0 -0
- /package/dist/{generator-templates → assets/hydrogen}/starter/tsconfig.json +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/tailwind/package.json +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/tailwind/postcss.config.js +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/tailwind/tailwind.config.js +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/tailwind/tailwind.css +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/vanilla-extract/package.json +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/assets/debug-network.css +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/assets/favicon-dark.svg +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/assets/favicon.svg +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/assets/inter-variable-font.woff2 +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/assets/jetbrainsmono-variable-font.woff2 +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/assets/styles.css +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/FlameChartWrapper.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/HydrogenLogoBaseBW.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/HydrogenLogoBaseColor.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/IconBanner.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/IconClose.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/IconDiscard.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/IconError.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/IconGithub.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/IconTwitter.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/Layout.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/RequestDetails.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/RequestTable.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/components/RequestWaterfall.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/lib/useDebugNetworkServer.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/routes/graphiql.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/routes/subrequest-profiler.jsx +0 -0
- /package/dist/{virtual-routes → assets/hydrogen/virtual-routes}/virtual-root.jsx +0 -0
- /package/dist/{generator-templates/assets → assets/hydrogen}/vite/package.json +0 -0
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# skeleton
|
|
2
2
|
|
|
3
|
+
## 2024.4.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix paths on Windows. ([#2243](https://github.com/Shopify/hydrogen/pull/2243)) by [@michenly](https://github.com/michenly)
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`31452380`](https://github.com/Shopify/hydrogen/commit/31452380340e079cd4ec1f8c10cdab5e5313e921)]:
|
|
10
|
+
- @shopify/hydrogen@2024.4.5
|
|
11
|
+
- @shopify/cli-hydrogen@8.1.1
|
|
12
|
+
|
|
13
|
+
## 2024.4.6
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`707afb96`](https://github.com/Shopify/hydrogen/commit/707afb96fd1ef64a59a14182f60ca61718b372d1)]:
|
|
18
|
+
- @shopify/hydrogen@2024.4.4
|
|
19
|
+
|
|
20
|
+
## 2024.4.5
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Update remix to v2.9.2 ([#2135](https://github.com/Shopify/hydrogen/pull/2135)) by [@michenly](https://github.com/michenly)
|
|
25
|
+
|
|
26
|
+
- `<Analytics>` and `useAnalytics` are now stable. ([#2141](https://github.com/Shopify/hydrogen/pull/2141)) by [@wizardlyhel](https://github.com/wizardlyhel)
|
|
27
|
+
|
|
28
|
+
- Update the skeleton template to use React state in the aside dialogs ([#2088](https://github.com/Shopify/hydrogen/pull/2088)) by [@blittle](https://github.com/blittle)
|
|
29
|
+
|
|
30
|
+
- Updated dependencies [[`fe82119f`](https://github.com/Shopify/hydrogen/commit/fe82119f5e75df5a0f727bab6a2186e679abc73d), [`32d4c33e`](https://github.com/Shopify/hydrogen/commit/32d4c33e4421a9c56f62a8c392f5417edddd0402), [`8eea75ec`](https://github.com/Shopify/hydrogen/commit/8eea75ec5ead4de98d7d1b2baedce8511029bcae), [`27e51abf`](https://github.com/Shopify/hydrogen/commit/27e51abfc1f5444afa952c503886bfa12fc55c7e), [`f29c9085`](https://github.com/Shopify/hydrogen/commit/f29c9085eb1adbde9e01226484eba8a85b5074ed), [`7b838beb`](https://github.com/Shopify/hydrogen/commit/7b838beb7c43380ffc9c32c2bb9f34291912fa42), [`d702aec2`](https://github.com/Shopify/hydrogen/commit/d702aec2214646a78cdafc2c25d510489db73f6d), [`ca4cf045`](https://github.com/Shopify/hydrogen/commit/ca4cf045f7fb72ad98b62af7bd172ff8cf553de2), [`5a554b2e`](https://github.com/Shopify/hydrogen/commit/5a554b2e9d91894c2db8032f0c29666dce1ea3f2), [`27e51abf`](https://github.com/Shopify/hydrogen/commit/27e51abfc1f5444afa952c503886bfa12fc55c7e), [`5d6465b3`](https://github.com/Shopify/hydrogen/commit/5d6465b32d90052e5580fcb81d98427bcb8ad528), [`608389d6`](https://github.com/Shopify/hydrogen/commit/608389d6d69c6a9801935d528507c165d1dd4ccf), [`9dfd1cfe`](https://github.com/Shopify/hydrogen/commit/9dfd1cfeb3e96c6d3426427a4b5d97ef475dab6d), [`7def3e9f`](https://github.com/Shopify/hydrogen/commit/7def3e9fa6e28f4fde7af43e2f346aa32267c38e), [`65239c76`](https://github.com/Shopify/hydrogen/commit/65239c76ca1d0b294b59b1ad53624485859c4da5), [`ca7f2888`](https://github.com/Shopify/hydrogen/commit/ca7f28887367a4882e57a67c4e248b0f0bba1c9b)]:
|
|
31
|
+
- @shopify/hydrogen@2024.4.3
|
|
32
|
+
- @shopify/cli-hydrogen@8.1.0
|
|
33
|
+
|
|
3
34
|
## 2024.4.4
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {createContext, type ReactNode, useContext, useState} from 'react';
|
|
2
|
+
|
|
3
|
+
type AsideType = 'search' | 'cart' | 'mobile' | 'closed';
|
|
4
|
+
type AsideContextValue = {
|
|
5
|
+
type: AsideType;
|
|
6
|
+
open: (mode: AsideType) => void;
|
|
7
|
+
close: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A side bar component with Overlay
|
|
12
|
+
* @example
|
|
13
|
+
* ```jsx
|
|
14
|
+
* <Aside type="search" heading="SEARCH">
|
|
15
|
+
* <input type="search" />
|
|
16
|
+
* ...
|
|
17
|
+
* </Aside>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function Aside({
|
|
21
|
+
children,
|
|
22
|
+
heading,
|
|
23
|
+
type,
|
|
24
|
+
}: {
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
type: AsideType;
|
|
27
|
+
heading: React.ReactNode;
|
|
28
|
+
}) {
|
|
29
|
+
const {type: activeType, close} = useAside();
|
|
30
|
+
const expanded = type === activeType;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
aria-modal
|
|
35
|
+
className={`overlay ${expanded ? 'expanded' : ''}`}
|
|
36
|
+
role="dialog"
|
|
37
|
+
>
|
|
38
|
+
<button className="close-outside" onClick={close} />
|
|
39
|
+
<aside>
|
|
40
|
+
<header>
|
|
41
|
+
<h3>{heading}</h3>
|
|
42
|
+
<button className="close reset" onClick={close}>
|
|
43
|
+
×
|
|
44
|
+
</button>
|
|
45
|
+
</header>
|
|
46
|
+
<main>{children}</main>
|
|
47
|
+
</aside>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const AsideContext = createContext<AsideContextValue | null>(null);
|
|
53
|
+
|
|
54
|
+
Aside.Provider = function AsideProvider({children}: {children: ReactNode}) {
|
|
55
|
+
const [type, setType] = useState<AsideType>('closed');
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<AsideContext.Provider
|
|
59
|
+
value={{
|
|
60
|
+
type,
|
|
61
|
+
open: setType,
|
|
62
|
+
close: () => setType('closed'),
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</AsideContext.Provider>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export function useAside() {
|
|
71
|
+
const aside = useContext(AsideContext);
|
|
72
|
+
if (!aside) {
|
|
73
|
+
throw new Error('useAside must be used within an AsideProvider');
|
|
74
|
+
}
|
|
75
|
+
return aside;
|
|
76
|
+
}
|
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CartForm,
|
|
3
|
+
Image,
|
|
4
|
+
Money,
|
|
5
|
+
useOptimisticCart,
|
|
6
|
+
type OptimisticCart,
|
|
7
|
+
} from '@shopify/hydrogen';
|
|
2
8
|
import type {CartLineUpdateInput} from '@shopify/hydrogen/storefront-api-types';
|
|
3
9
|
import {Link} from '@remix-run/react';
|
|
4
10
|
import type {CartApiQueryFragment} from 'storefrontapi.generated';
|
|
5
11
|
import {useVariantUrl} from '~/lib/variants';
|
|
6
12
|
|
|
7
|
-
type CartLine = CartApiQueryFragment['lines']['nodes'][0];
|
|
13
|
+
type CartLine = OptimisticCart<CartApiQueryFragment>['lines']['nodes'][0];
|
|
8
14
|
|
|
9
15
|
type CartMainProps = {
|
|
10
16
|
cart: CartApiQueryFragment | null;
|
|
11
17
|
layout: 'page' | 'aside';
|
|
12
18
|
};
|
|
13
19
|
|
|
14
|
-
export function CartMain({layout, cart}: CartMainProps) {
|
|
20
|
+
export function CartMain({layout, cart: originalCart}: CartMainProps) {
|
|
21
|
+
const cart = useOptimisticCart(originalCart);
|
|
22
|
+
|
|
15
23
|
const linesCount = Boolean(cart?.lines?.nodes?.length || 0);
|
|
16
24
|
const withDiscount =
|
|
17
25
|
cart &&
|
|
@@ -26,12 +34,18 @@ export function CartMain({layout, cart}: CartMainProps) {
|
|
|
26
34
|
);
|
|
27
35
|
}
|
|
28
36
|
|
|
29
|
-
function CartDetails({
|
|
37
|
+
function CartDetails({
|
|
38
|
+
layout,
|
|
39
|
+
cart,
|
|
40
|
+
}: {
|
|
41
|
+
cart: OptimisticCart<CartApiQueryFragment>;
|
|
42
|
+
layout: 'page' | 'aside';
|
|
43
|
+
}) {
|
|
30
44
|
const cartHasItems = !!cart && cart.totalQuantity > 0;
|
|
31
45
|
|
|
32
46
|
return (
|
|
33
47
|
<div className="cart-details">
|
|
34
|
-
<CartLines lines={cart?.lines} layout={layout} />
|
|
48
|
+
<CartLines lines={cart?.lines?.nodes} layout={layout} />
|
|
35
49
|
{cartHasItems && (
|
|
36
50
|
<CartSummary cost={cart.cost} layout={layout}>
|
|
37
51
|
<CartDiscounts discountCodes={cart.discountCodes} />
|
|
@@ -47,14 +61,14 @@ function CartLines({
|
|
|
47
61
|
layout,
|
|
48
62
|
}: {
|
|
49
63
|
layout: CartMainProps['layout'];
|
|
50
|
-
lines:
|
|
64
|
+
lines: CartLine[];
|
|
51
65
|
}) {
|
|
52
66
|
if (!lines) return null;
|
|
53
67
|
|
|
54
68
|
return (
|
|
55
69
|
<div aria-labelledby="cart-lines">
|
|
56
70
|
<ul>
|
|
57
|
-
{lines.
|
|
71
|
+
{lines.map((line) => (
|
|
58
72
|
<CartLineItem key={line.id} line={line} layout={layout} />
|
|
59
73
|
))}
|
|
60
74
|
</ul>
|
|
@@ -160,21 +174,29 @@ export function CartSummary({
|
|
|
160
174
|
);
|
|
161
175
|
}
|
|
162
176
|
|
|
163
|
-
function CartLineRemoveButton({
|
|
177
|
+
function CartLineRemoveButton({
|
|
178
|
+
lineIds,
|
|
179
|
+
disabled,
|
|
180
|
+
}: {
|
|
181
|
+
lineIds: string[];
|
|
182
|
+
disabled: boolean;
|
|
183
|
+
}) {
|
|
164
184
|
return (
|
|
165
185
|
<CartForm
|
|
166
186
|
route="/cart"
|
|
167
187
|
action={CartForm.ACTIONS.LinesRemove}
|
|
168
188
|
inputs={{lineIds}}
|
|
169
189
|
>
|
|
170
|
-
<button type="submit">
|
|
190
|
+
<button disabled={disabled} type="submit">
|
|
191
|
+
Remove
|
|
192
|
+
</button>
|
|
171
193
|
</CartForm>
|
|
172
194
|
);
|
|
173
195
|
}
|
|
174
196
|
|
|
175
197
|
function CartLineQuantity({line}: {line: CartLine}) {
|
|
176
198
|
if (!line || typeof line?.quantity === 'undefined') return null;
|
|
177
|
-
const {id: lineId, quantity} = line;
|
|
199
|
+
const {id: lineId, quantity, isOptimistic} = line;
|
|
178
200
|
const prevQuantity = Number(Math.max(0, quantity - 1).toFixed(0));
|
|
179
201
|
const nextQuantity = Number((quantity + 1).toFixed(0));
|
|
180
202
|
|
|
@@ -184,7 +206,7 @@ function CartLineQuantity({line}: {line: CartLine}) {
|
|
|
184
206
|
<CartLineUpdateButton lines={[{id: lineId, quantity: prevQuantity}]}>
|
|
185
207
|
<button
|
|
186
208
|
aria-label="Decrease quantity"
|
|
187
|
-
disabled={quantity <= 1}
|
|
209
|
+
disabled={quantity <= 1 || !!isOptimistic}
|
|
188
210
|
name="decrease-quantity"
|
|
189
211
|
value={prevQuantity}
|
|
190
212
|
>
|
|
@@ -197,12 +219,13 @@ function CartLineQuantity({line}: {line: CartLine}) {
|
|
|
197
219
|
aria-label="Increase quantity"
|
|
198
220
|
name="increase-quantity"
|
|
199
221
|
value={nextQuantity}
|
|
222
|
+
disabled={!!isOptimistic}
|
|
200
223
|
>
|
|
201
224
|
<span>+</span>
|
|
202
225
|
</button>
|
|
203
226
|
</CartLineUpdateButton>
|
|
204
227
|
|
|
205
|
-
<CartLineRemoveButton lineIds={[lineId]} />
|
|
228
|
+
<CartLineRemoveButton lineIds={[lineId]} disabled={!!isOptimistic} />
|
|
206
229
|
</div>
|
|
207
230
|
);
|
|
208
231
|
}
|
|
@@ -216,7 +239,8 @@ function CartLinePrice({
|
|
|
216
239
|
priceType?: 'regular' | 'compareAt';
|
|
217
240
|
[key: string]: any;
|
|
218
241
|
}) {
|
|
219
|
-
if (!line?.cost?.amountPerQuantity || !line?.cost?.totalAmount)
|
|
242
|
+
if (!line?.cost?.amountPerQuantity || !line?.cost?.totalAmount)
|
|
243
|
+
return <div style={{visibility: 'hidden'}}> </div>;
|
|
220
244
|
|
|
221
245
|
const moneyV2 =
|
|
222
246
|
priceType === 'regular'
|
|
@@ -224,7 +248,7 @@ function CartLinePrice({
|
|
|
224
248
|
: line.cost.compareAtAmountPerQuantity;
|
|
225
249
|
|
|
226
250
|
if (moneyV2 == null) {
|
|
227
|
-
return
|
|
251
|
+
return <div style={{visibility: 'hidden'}}> </div>;
|
|
228
252
|
}
|
|
229
253
|
|
|
230
254
|
return (
|
|
@@ -1,29 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {Suspense} from 'react';
|
|
2
|
+
import {Await, NavLink} from '@remix-run/react';
|
|
2
3
|
import type {FooterQuery, HeaderQuery} from 'storefrontapi.generated';
|
|
3
|
-
|
|
4
|
+
|
|
5
|
+
interface FooterProps {
|
|
6
|
+
footer: Promise<FooterQuery | null>;
|
|
7
|
+
header: HeaderQuery;
|
|
8
|
+
publicStoreDomain: string;
|
|
9
|
+
}
|
|
4
10
|
|
|
5
11
|
export function Footer({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
footer: footerPromise,
|
|
13
|
+
header,
|
|
14
|
+
publicStoreDomain,
|
|
15
|
+
}: FooterProps) {
|
|
9
16
|
return (
|
|
10
|
-
<
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
<Suspense>
|
|
18
|
+
<Await resolve={footerPromise}>
|
|
19
|
+
{(footer) => (
|
|
20
|
+
<footer className="footer">
|
|
21
|
+
{footer?.menu && header.shop.primaryDomain?.url && (
|
|
22
|
+
<FooterMenu
|
|
23
|
+
menu={footer.menu}
|
|
24
|
+
primaryDomainUrl={header.shop.primaryDomain.url}
|
|
25
|
+
publicStoreDomain={publicStoreDomain}
|
|
26
|
+
/>
|
|
27
|
+
)}
|
|
28
|
+
</footer>
|
|
29
|
+
)}
|
|
30
|
+
</Await>
|
|
31
|
+
</Suspense>
|
|
15
32
|
);
|
|
16
33
|
}
|
|
17
34
|
|
|
18
35
|
function FooterMenu({
|
|
19
36
|
menu,
|
|
20
37
|
primaryDomainUrl,
|
|
38
|
+
publicStoreDomain,
|
|
21
39
|
}: {
|
|
22
40
|
menu: FooterQuery['menu'];
|
|
23
|
-
primaryDomainUrl:
|
|
41
|
+
primaryDomainUrl: FooterProps['header']['shop']['primaryDomain']['url'];
|
|
42
|
+
publicStoreDomain: string;
|
|
24
43
|
}) {
|
|
25
|
-
const {publicStoreDomain} = useRootLoaderData();
|
|
26
|
-
|
|
27
44
|
return (
|
|
28
45
|
<nav className="footer-menu" role="navigation">
|
|
29
46
|
{(menu || FALLBACK_FOOTER_MENU).items.map((item) => {
|
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
import {Await, NavLink} from '@remix-run/react';
|
|
2
1
|
import {Suspense} from 'react';
|
|
3
|
-
import
|
|
4
|
-
import type
|
|
5
|
-
import {
|
|
2
|
+
import {Await, NavLink} from '@remix-run/react';
|
|
3
|
+
import {type CartViewPayload, useAnalytics} from '@shopify/hydrogen';
|
|
4
|
+
import type {HeaderQuery, CartApiQueryFragment} from 'storefrontapi.generated';
|
|
5
|
+
import {useAside} from '~/components/Aside';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
interface HeaderProps {
|
|
8
|
+
header: HeaderQuery;
|
|
9
|
+
cart: Promise<CartApiQueryFragment | null>;
|
|
10
|
+
isLoggedIn: Promise<boolean>;
|
|
11
|
+
publicStoreDomain: string;
|
|
12
|
+
}
|
|
8
13
|
|
|
9
14
|
type Viewport = 'desktop' | 'mobile';
|
|
10
15
|
|
|
11
|
-
export function Header({
|
|
16
|
+
export function Header({
|
|
17
|
+
header,
|
|
18
|
+
isLoggedIn,
|
|
19
|
+
cart,
|
|
20
|
+
publicStoreDomain,
|
|
21
|
+
}: HeaderProps) {
|
|
12
22
|
const {shop, menu} = header;
|
|
13
23
|
return (
|
|
14
24
|
<header className="header">
|
|
@@ -19,6 +29,7 @@ export function Header({header, isLoggedIn, cart}: HeaderProps) {
|
|
|
19
29
|
menu={menu}
|
|
20
30
|
viewport="desktop"
|
|
21
31
|
primaryDomainUrl={header.shop.primaryDomain.url}
|
|
32
|
+
publicStoreDomain={publicStoreDomain}
|
|
22
33
|
/>
|
|
23
34
|
<HeaderCtas isLoggedIn={isLoggedIn} cart={cart} />
|
|
24
35
|
</header>
|
|
@@ -29,12 +40,13 @@ export function HeaderMenu({
|
|
|
29
40
|
menu,
|
|
30
41
|
primaryDomainUrl,
|
|
31
42
|
viewport,
|
|
43
|
+
publicStoreDomain,
|
|
32
44
|
}: {
|
|
33
45
|
menu: HeaderProps['header']['menu'];
|
|
34
|
-
primaryDomainUrl:
|
|
46
|
+
primaryDomainUrl: HeaderProps['header']['shop']['primaryDomain']['url'];
|
|
35
47
|
viewport: Viewport;
|
|
48
|
+
publicStoreDomain: HeaderProps['publicStoreDomain'];
|
|
36
49
|
}) {
|
|
37
|
-
const {publicStoreDomain} = useRootLoaderData();
|
|
38
50
|
const className = `header-menu-${viewport}`;
|
|
39
51
|
|
|
40
52
|
function closeAside(event: React.MouseEvent<HTMLAnchorElement>) {
|
|
@@ -106,19 +118,47 @@ function HeaderCtas({
|
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
function HeaderMenuMobileToggle() {
|
|
121
|
+
const {open} = useAside();
|
|
109
122
|
return (
|
|
110
|
-
<
|
|
123
|
+
<button
|
|
124
|
+
className="header-menu-mobile-toggle reset"
|
|
125
|
+
onClick={() => open('mobile')}
|
|
126
|
+
>
|
|
111
127
|
<h3>☰</h3>
|
|
112
|
-
</
|
|
128
|
+
</button>
|
|
113
129
|
);
|
|
114
130
|
}
|
|
115
131
|
|
|
116
132
|
function SearchToggle() {
|
|
117
|
-
|
|
133
|
+
const {open} = useAside();
|
|
134
|
+
return (
|
|
135
|
+
<button className="reset" onClick={() => open('search')}>
|
|
136
|
+
Search
|
|
137
|
+
</button>
|
|
138
|
+
);
|
|
118
139
|
}
|
|
119
140
|
|
|
120
141
|
function CartBadge({count}: {count: number}) {
|
|
121
|
-
|
|
142
|
+
const {open} = useAside();
|
|
143
|
+
const {publish, shop, cart, prevCart} = useAnalytics();
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<a
|
|
147
|
+
href="/cart"
|
|
148
|
+
onClick={(e) => {
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
open('cart');
|
|
151
|
+
publish('cart_viewed', {
|
|
152
|
+
cart,
|
|
153
|
+
prevCart,
|
|
154
|
+
shop,
|
|
155
|
+
url: window.location.href || '',
|
|
156
|
+
} as CartViewPayload);
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
Cart {count}
|
|
160
|
+
</a>
|
|
161
|
+
);
|
|
122
162
|
}
|
|
123
163
|
|
|
124
164
|
function CartToggle({cart}: Pick<HeaderProps, 'cart'>) {
|
|
@@ -14,44 +14,53 @@ import {
|
|
|
14
14
|
PredictiveSearchResults,
|
|
15
15
|
} from '~/components/Search';
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
interface PageLayoutProps {
|
|
18
18
|
cart: Promise<CartApiQueryFragment | null>;
|
|
19
|
-
|
|
20
|
-
footer: Promise<FooterQuery>;
|
|
19
|
+
footer: Promise<FooterQuery | null>;
|
|
21
20
|
header: HeaderQuery;
|
|
22
21
|
isLoggedIn: Promise<boolean>;
|
|
23
|
-
|
|
22
|
+
publicStoreDomain: string;
|
|
23
|
+
children?: React.ReactNode;
|
|
24
|
+
}
|
|
24
25
|
|
|
25
|
-
export function
|
|
26
|
+
export function PageLayout({
|
|
26
27
|
cart,
|
|
27
28
|
children = null,
|
|
28
29
|
footer,
|
|
29
30
|
header,
|
|
30
31
|
isLoggedIn,
|
|
31
|
-
|
|
32
|
+
publicStoreDomain,
|
|
33
|
+
}: PageLayoutProps) {
|
|
32
34
|
return (
|
|
33
|
-
|
|
35
|
+
<Aside.Provider>
|
|
34
36
|
<CartAside cart={cart} />
|
|
35
37
|
<SearchAside />
|
|
36
|
-
<MobileMenuAside
|
|
37
|
-
{header &&
|
|
38
|
+
<MobileMenuAside header={header} publicStoreDomain={publicStoreDomain} />
|
|
39
|
+
{header && (
|
|
40
|
+
<Header
|
|
41
|
+
header={header}
|
|
42
|
+
cart={cart}
|
|
43
|
+
isLoggedIn={isLoggedIn}
|
|
44
|
+
publicStoreDomain={publicStoreDomain}
|
|
45
|
+
/>
|
|
46
|
+
)}
|
|
38
47
|
<main>{children}</main>
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
<Footer
|
|
49
|
+
footer={footer}
|
|
50
|
+
header={header}
|
|
51
|
+
publicStoreDomain={publicStoreDomain}
|
|
52
|
+
/>
|
|
53
|
+
</Aside.Provider>
|
|
45
54
|
);
|
|
46
55
|
}
|
|
47
56
|
|
|
48
|
-
function CartAside({cart}: {cart:
|
|
57
|
+
function CartAside({cart}: {cart: PageLayoutProps['cart']}) {
|
|
49
58
|
return (
|
|
50
|
-
<Aside
|
|
59
|
+
<Aside type="cart" heading="CART">
|
|
51
60
|
<Suspense fallback={<p>Loading cart ...</p>}>
|
|
52
61
|
<Await resolve={cart}>
|
|
53
62
|
{(cart) => {
|
|
54
|
-
return <CartMain cart={cart} layout="aside" />;
|
|
63
|
+
return <CartMain cart={cart!} layout="aside" />;
|
|
55
64
|
}}
|
|
56
65
|
</Await>
|
|
57
66
|
</Suspense>
|
|
@@ -61,7 +70,7 @@ function CartAside({cart}: {cart: LayoutProps['cart']}) {
|
|
|
61
70
|
|
|
62
71
|
function SearchAside() {
|
|
63
72
|
return (
|
|
64
|
-
<Aside
|
|
73
|
+
<Aside type="search" heading="SEARCH">
|
|
65
74
|
<div className="predictive-search">
|
|
66
75
|
<br />
|
|
67
76
|
<PredictiveSearchForm>
|
|
@@ -95,20 +104,21 @@ function SearchAside() {
|
|
|
95
104
|
}
|
|
96
105
|
|
|
97
106
|
function MobileMenuAside({
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
header,
|
|
108
|
+
publicStoreDomain,
|
|
100
109
|
}: {
|
|
101
|
-
|
|
102
|
-
|
|
110
|
+
header: PageLayoutProps['header'];
|
|
111
|
+
publicStoreDomain: PageLayoutProps['publicStoreDomain'];
|
|
103
112
|
}) {
|
|
104
113
|
return (
|
|
105
|
-
menu &&
|
|
106
|
-
shop
|
|
107
|
-
<Aside
|
|
114
|
+
header.menu &&
|
|
115
|
+
header.shop.primaryDomain?.url && (
|
|
116
|
+
<Aside type="mobile" heading="MENU">
|
|
108
117
|
<HeaderMenu
|
|
109
|
-
menu={menu}
|
|
118
|
+
menu={header.menu}
|
|
110
119
|
viewport="mobile"
|
|
111
|
-
primaryDomainUrl={shop.primaryDomain.url}
|
|
120
|
+
primaryDomainUrl={header.shop.primaryDomain.url}
|
|
121
|
+
publicStoreDomain={publicStoreDomain}
|
|
112
122
|
/>
|
|
113
123
|
</Aside>
|
|
114
124
|
)
|
|
@@ -16,6 +16,8 @@ import type {
|
|
|
16
16
|
SearchQuery,
|
|
17
17
|
} from 'storefrontapi.generated';
|
|
18
18
|
|
|
19
|
+
import type {PredictiveSearchAPILoader} from '../routes/api.predictive-search';
|
|
20
|
+
|
|
19
21
|
type PredicticeSearchResultItemImage =
|
|
20
22
|
| PredictiveCollectionFragment['image']
|
|
21
23
|
| PredictiveArticleFragment['image']
|
|
@@ -257,7 +259,7 @@ export function NoSearchResults() {
|
|
|
257
259
|
|
|
258
260
|
type ChildrenRenderProps = {
|
|
259
261
|
fetchResults: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
260
|
-
fetcher: ReturnType<typeof useFetcher<
|
|
262
|
+
fetcher: ReturnType<typeof useFetcher<PredictiveSearchAPILoader>>;
|
|
261
263
|
inputRef: React.MutableRefObject<HTMLInputElement | null>;
|
|
262
264
|
};
|
|
263
265
|
|
|
@@ -278,7 +280,7 @@ export function PredictiveSearchForm({
|
|
|
278
280
|
...props
|
|
279
281
|
}: SearchFromProps) {
|
|
280
282
|
const params = useParams();
|
|
281
|
-
const fetcher = useFetcher<
|
|
283
|
+
const fetcher = useFetcher<PredictiveSearchAPILoader>({
|
|
282
284
|
key: 'search',
|
|
283
285
|
});
|
|
284
286
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
@@ -456,7 +458,7 @@ function SearchResultItem({goToSearchResult, item}: SearchResultItemProps) {
|
|
|
456
458
|
type UseSearchReturn = NormalizedPredictiveSearch & {
|
|
457
459
|
searchInputRef: React.MutableRefObject<HTMLInputElement | null>;
|
|
458
460
|
searchTerm: React.MutableRefObject<string>;
|
|
459
|
-
state: ReturnType<typeof useFetcher
|
|
461
|
+
state: ReturnType<typeof useFetcher<PredictiveSearchAPILoader>>['state'];
|
|
460
462
|
};
|
|
461
463
|
|
|
462
464
|
function usePredictiveSearch(): UseSearchReturn {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {EntryContext} from '@shopify/remix-oxygen';
|
|
1
|
+
import type {EntryContext, AppLoadContext} from '@shopify/remix-oxygen';
|
|
2
2
|
import {RemixServer} from '@remix-run/react';
|
|
3
3
|
import isbot from 'isbot';
|
|
4
4
|
import {renderToReadableStream} from 'react-dom/server';
|
|
@@ -9,8 +9,14 @@ export default async function handleRequest(
|
|
|
9
9
|
responseStatusCode: number,
|
|
10
10
|
responseHeaders: Headers,
|
|
11
11
|
remixContext: EntryContext,
|
|
12
|
+
context: AppLoadContext,
|
|
12
13
|
) {
|
|
13
|
-
const {nonce, header, NonceProvider} = createContentSecurityPolicy(
|
|
14
|
+
const {nonce, header, NonceProvider} = createContentSecurityPolicy({
|
|
15
|
+
shop: {
|
|
16
|
+
checkoutDomain: context.env.PUBLIC_CHECKOUT_DOMAIN,
|
|
17
|
+
storeDomain: context.env.PUBLIC_STORE_DOMAIN,
|
|
18
|
+
}
|
|
19
|
+
});
|
|
14
20
|
|
|
15
21
|
const body = await renderToReadableStream(
|
|
16
22
|
<NonceProvider>
|