diff --git a/README.md b/README.md index 1af8bbf35..d93068f06 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fcommerce&project-name=commerce&repo-name=commerce&demo-title=Next.js%20Commerce&demo-description=An%20all-in-one%20starter%20kit%20for%20high-performance%20e-commerce%20sites.&demo-url=https%3A%2F%2Fdemo.vercel.store&demo-image=https%3A%2F%2Fbigcommerce-demo-asset-ksvtgfvnd.vercel.app%2Fbigcommerce.png&integration-ids=oac_MuWZiE4jtmQ2ejZQaQ7ncuDT) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fcommerce&project-name=commerce&repo-name=commerce&demo-title=Next.js%20Commerce&demo-description=An%20all-in-one%20starter%20kit%20for%20high-performance%20e-commerce%20sites.&demo-url=https%3A%2F%2Fdemo.vercel.store&demo-image=https%3A%2F%2Fbigcommerce-demo-asset-ksvtgfvnd.vercel.app%2Fbigcommerce.png&integration-ids=oac_MuWZiE4jtmQ2ejZQaQ7ncuDT,oac_9HSKtXld74NG0srzdxSiBGty&skippable-integrations=1&root-directory=site&build-command=cd%20..%20%26%26%20yarn%20build) # Next.js Commerce @@ -49,7 +49,7 @@ Open `site/.env.local` and change the value of `COMMERCE_PROVIDER` to the provid The setup for Shopify would look like this for example: ``` -COMMERCE_PROVIDER=shopify +COMMERCE_PROVIDER=@vercel/commerce-shopify NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxx NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN=xxxxxxx.myshopify.com ``` @@ -147,3 +147,40 @@ After Email confirmation, Checkout should be manually enabled through BigCommerc
BigCommerce team has been notified and they plan to add more details about this subject. + +
+When run locally I get `Error: Cannot find module '...@vercel/commerce/dist/config'` + +```bash +commerce/site +❯ yarn dev +yarn run v1.22.17 +$ next dev +ready - started server on 0.0.0.0:3000, url: http://localhost:3000 +info - Loaded env from /commerce/site/.env.local +error - Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error +Error: Cannot find module '/Users/dom/work/vercel/commerce/node_modules/@vercel/commerce/dist/config.cjs' + at createEsmNotFoundErr (node:internal/modules/cjs/loader:960:15) + at finalizeEsmResolution (node:internal/modules/cjs/loader:953:15) + at resolveExports (node:internal/modules/cjs/loader:482:14) + at Function.Module._findPath (node:internal/modules/cjs/loader:522:31) + at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27) + at Function.mod._resolveFilename (/Users/dom/work/vercel/commerce/node_modules/next/dist/build/webpack/require-hook.js:179:28) + at Function.Module._load (node:internal/modules/cjs/loader:778:27) + at Module.require (node:internal/modules/cjs/loader:1005:19) + at require (node:internal/modules/cjs/helpers:102:18) + at Object. (/Users/dom/work/vercel/commerce/site/commerce-config.js:9:14) { + code: 'MODULE_NOT_FOUND', + path: '/Users/dom/work/vercel/commerce/node_modules/@vercel/commerce/package.json' +} +error Command failed with exit code 1. +info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. +``` + +The error usually occurs when running yarn dev inside of the `/site/` folder after installing a fresh repository. + +In order to fix this, run `yarn dev` in the monorepo root folder first. + +> Using `yarn dev` from the root is recommended for developing, which will run watch mode on all packages. + +
diff --git a/package.json b/package.json index 2854cf992..fc97f30b9 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "build": "turbo run build --scope=next-commerce --include-dependencies --no-deps", "dev": "turbo run dev", "start": "turbo run start", + "types": "turbo run types", "prettier-fix": "prettier --write ." }, "devDependencies": { diff --git a/packages/bigcommerce/src/api/endpoints/wishlist/add-item.ts b/packages/bigcommerce/src/api/endpoints/wishlist/add-item.ts index bf449cb11..734a64402 100644 --- a/packages/bigcommerce/src/api/endpoints/wishlist/add-item.ts +++ b/packages/bigcommerce/src/api/endpoints/wishlist/add-item.ts @@ -3,7 +3,6 @@ import { parseWishlistItem } from '../../utils/parse-item' import getCustomerId from '../../utils/get-customer-id' import type { WishlistEndpoint } from '.' -// Return wishlist info const addItem: WishlistEndpoint['handlers']['addItem'] = async ({ res, body: { customerToken, item }, @@ -17,41 +16,52 @@ const addItem: WishlistEndpoint['handlers']['addItem'] = async ({ }) } - const customerId = - customerToken && (await getCustomerId({ customerToken, config })) + try { + const customerId = + customerToken && (await getCustomerId({ customerToken, config })) - if (!customerId) { - return res.status(400).json({ + if (!customerId) { + throw new Error('Invalid request. No CustomerId') + } + + let { wishlist } = await commerce.getCustomerWishlist({ + variables: { customerId }, + config, + }) + + if (!wishlist) { + // If user has no wishlist, then let's create one with new item + const { data } = await config.storeApiFetch('/v3/wishlists', { + method: 'POST', + body: JSON.stringify({ + name: 'Next.js Commerce Wishlist', + is_public: false, + customer_id: Number(customerId), + items: [parseWishlistItem(item)], + }), + }) + return res.status(200).json(data) + } + + // Existing Wishlist, let's add Item to Wishlist + const { data } = await config.storeApiFetch( + `/v3/wishlists/${wishlist.id}/items`, + { + method: 'POST', + body: JSON.stringify({ + items: [parseWishlistItem(item)], + }), + } + ) + + // Returns Wishlist + return res.status(200).json(data) + } catch (err: any) { + res.status(500).json({ data: null, - errors: [{ message: 'Invalid request' }], + errors: [{ message: err.message }], }) } - - const { wishlist } = await commerce.getCustomerWishlist({ - variables: { customerId }, - config, - }) - const options = { - method: 'POST', - body: JSON.stringify( - wishlist - ? { - items: [parseWishlistItem(item)], - } - : { - name: 'Wishlist', - customer_id: customerId, - items: [parseWishlistItem(item)], - is_public: false, - } - ), - } - - const { data } = wishlist - ? await config.storeApiFetch(`/v3/wishlists/${wishlist.id}/items`, options) - : await config.storeApiFetch('/v3/wishlists', options) - - res.status(200).json({ data }) } export default addItem diff --git a/packages/bigcommerce/src/api/fragments/product.ts b/packages/bigcommerce/src/api/fragments/product.ts index d266b8c92..734e0ab63 100644 --- a/packages/bigcommerce/src/api/fragments/product.ts +++ b/packages/bigcommerce/src/api/fragments/product.ts @@ -58,7 +58,7 @@ export const productInfoFragment = /* GraphQL */ ` } } } - variants { + variants(first: 250) { edges { node { entityId diff --git a/packages/bigcommerce/src/api/index.ts b/packages/bigcommerce/src/api/index.ts index b4999642b..bd5fcb3b7 100644 --- a/packages/bigcommerce/src/api/index.ts +++ b/packages/bigcommerce/src/api/index.ts @@ -38,9 +38,9 @@ export interface BigcommerceConfig extends CommerceAPIConfig { storeApiFetch(endpoint: string, options?: RequestInit): Promise } -const API_URL = process.env.BIGCOMMERCE_STOREFRONT_API_URL +const API_URL = process.env.BIGCOMMERCE_STOREFRONT_API_URL // GraphAPI const API_TOKEN = process.env.BIGCOMMERCE_STOREFRONT_API_TOKEN -const STORE_API_URL = process.env.BIGCOMMERCE_STORE_API_URL +const STORE_API_URL = process.env.BIGCOMMERCE_STORE_API_URL // REST API const STORE_API_TOKEN = process.env.BIGCOMMERCE_STORE_API_TOKEN const STORE_API_CLIENT_ID = process.env.BIGCOMMERCE_STORE_API_CLIENT_ID const STORE_CHANNEL_ID = process.env.BIGCOMMERCE_CHANNEL_ID diff --git a/packages/bigcommerce/src/api/operations/get-customer-wishlist.ts b/packages/bigcommerce/src/api/operations/get-customer-wishlist.ts index dc0dd0d9a..25e2157e1 100644 --- a/packages/bigcommerce/src/api/operations/get-customer-wishlist.ts +++ b/packages/bigcommerce/src/api/operations/get-customer-wishlist.ts @@ -44,6 +44,7 @@ export default function getCustomerWishlistOperation({ const { data = [] } = await config.storeApiFetch< RecursivePartial<{ data: Wishlist[] }> >(`/v3/wishlists?customer_id=${variables.customerId}`) + const wishlist = data[0] if (includeProducts && wishlist?.items?.length) { diff --git a/packages/bigcommerce/src/api/operations/get-product.ts b/packages/bigcommerce/src/api/operations/get-product.ts index b2f9c9677..c7457de2a 100644 --- a/packages/bigcommerce/src/api/operations/get-product.ts +++ b/packages/bigcommerce/src/api/operations/get-product.ts @@ -21,7 +21,7 @@ export const getProductQuery = /* GraphQL */ ` __typename ... on Product { ...productInfo - variants { + variants(first: 250) { edges { node { entityId diff --git a/packages/bigcommerce/src/wishlist/use-wishlist.tsx b/packages/bigcommerce/src/wishlist/use-wishlist.tsx index e77d6885b..7882233f5 100644 --- a/packages/bigcommerce/src/wishlist/use-wishlist.tsx +++ b/packages/bigcommerce/src/wishlist/use-wishlist.tsx @@ -1,11 +1,13 @@ import { useMemo } from 'react' import { SWRHook } from '@vercel/commerce/utils/types' -import useWishlist, { UseWishlist } from '@vercel/commerce/wishlist/use-wishlist' -import type { GetWishlistHook } from '../types/wishlist' +import useWishlist, { + UseWishlist, +} from '@vercel/commerce/wishlist/use-wishlist' import useCustomer from '../customer/use-customer' -export default useWishlist as UseWishlist +import type { GetWishlistHook } from '../types/wishlist' +export default useWishlist as UseWishlist export const handler: SWRHook = { fetchOptions: { url: '/api/wishlist', diff --git a/packages/commerce/src/config.cjs b/packages/commerce/src/config.cjs index aabc16e0c..add0061a9 100644 --- a/packages/commerce/src/config.cjs +++ b/packages/commerce/src/config.cjs @@ -18,10 +18,14 @@ function withCommerceConfig(nextConfig = {}) { const commerceNextConfig = importCwd(path.join(provider, 'next.config')) const config = merge(nextConfig, commerceNextConfig) + const features = merge( + config.commerce.features, + config.commerce[provider]?.features ?? {} + ) config.env = config.env || {} - Object.entries(config.commerce.features).forEach(([k, v]) => { + Object.entries(features).forEach(([k, v]) => { if (v) config.env[`COMMERCE_${k.toUpperCase()}_ENABLED`] = true }) diff --git a/packages/commerce/src/types/product.ts b/packages/commerce/src/types/product.ts index 400ac4160..5e63d6e98 100644 --- a/packages/commerce/src/types/product.ts +++ b/packages/commerce/src/types/product.ts @@ -43,6 +43,7 @@ export type Product = { variants: ProductVariant[] price: ProductPrice options: ProductOption[] + vendor?: string } export type SearchProductsBody = { diff --git a/packages/vendure/src/next.config.cjs b/packages/vendure/src/next.config.cjs index 96153ad1e..2e6842f00 100644 --- a/packages/vendure/src/next.config.cjs +++ b/packages/vendure/src/next.config.cjs @@ -3,6 +3,6 @@ const commerce = require('./commerce.config.json') module.exports = { commerce, images: { - domains: ['localhost', 'demo.vendure.io'], + domains: ['localhost', 'demo.vendure.io','readonlydemo.vendure.io'], }, } diff --git a/site/assets/base.css b/site/assets/base.css index 05a234a73..37e14196c 100644 --- a/site/assets/base.css +++ b/site/assets/base.css @@ -4,11 +4,9 @@ --secondary: #000000; --secondary-2: #111; --selection: var(--cyan); - --text-base: #000000; --text-primary: #000000; --text-secondary: white; - --hover: rgba(0, 0, 0, 0.075); --hover-1: rgba(0, 0, 0, 0.15); --hover-2: rgba(0, 0, 0, 0.25); @@ -17,15 +15,11 @@ --red: #da3c3c; --purple: #f81ce5; --blue: #0070f3; - --pink: #ff0080; --pink-light: #ff379c; - --magenta: #eb367f; - --violet: #7928ca; --violet-dark: #4c2889; - --accent-0: #fff; --accent-1: #fafafa; --accent-2: #eaeaea; @@ -36,7 +30,6 @@ --accent-7: #333333; --accent-8: #111111; --accent-9: #000; - --font-sans: -apple-system, system-ui, BlinkMacSystemFont, 'Helvetica Neue', 'Helvetica', sans-serif; } @@ -50,11 +43,9 @@ --hover-1: rgba(255, 255, 255, 0.15); --hover-2: rgba(255, 255, 255, 0.25); --selection: var(--purple); - --text-base: white; --text-primary: white; --text-secondary: black; - --accent-9: #fff; --accent-8: #fafafa; --accent-7: #eaeaea; @@ -73,17 +64,11 @@ box-sizing: inherit; } -html { +html, +body { height: 100%; box-sizing: border-box; touch-action: manipulation; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -html, -body { font-family: var(--font-sans); text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; @@ -104,15 +89,15 @@ a { } .animated { - -webkit-animation-duration: 1s; animation-duration: 1s; - -webkit-animation-fill-mode: both; animation-fill-mode: both; + -webkit-animation-duration: 1s; + -webkit-animation-fill-mode: both; } .fadeIn { - -webkit-animation-name: fadeIn; animation-name: fadeIn; + -webkit-animation-name: fadeIn; } @-webkit-keyframes fadeIn { diff --git a/site/components/common/Head/Head.tsx b/site/components/common/Head/Head.tsx index b2c0c997b..ed43c0d39 100644 --- a/site/components/common/Head/Head.tsx +++ b/site/components/common/Head/Head.tsx @@ -1,17 +1,16 @@ -import { FC } from 'react' -import NextHead from 'next/head' -import { DefaultSeo } from 'next-seo' -import config from '@config/seo.json' +import type { VFC } from 'react' +import { SEO } from '@components/common' -const Head: FC = () => { +const Head: VFC = () => { return ( - <> - - - - - - + + + + ) } diff --git a/site/components/common/Layout/Layout.tsx b/site/components/common/Layout/Layout.tsx index 5c936a09f..6dda880e4 100644 --- a/site/components/common/Layout/Layout.tsx +++ b/site/components/common/Layout/Layout.tsx @@ -1,12 +1,11 @@ import cn from 'clsx' -import React, { FC } from 'react' +import s from './Layout.module.css' import dynamic from 'next/dynamic' import { useRouter } from 'next/router' import { CommerceProvider } from '@framework' +import LoginView from '@components/auth/LoginView' import { useUI } from '@components/ui/context' -import type { Page } from '@commerce/types/page' import { Navbar, Footer } from '@components/common' -import type { Category } from '@commerce/types/site' import ShippingView from '@components/checkout/ShippingView' import CartSidebarView from '@components/cart/CartSidebarView' import { useAcceptCookies } from '@lib/hooks/useAcceptCookies' @@ -14,10 +13,10 @@ import { Sidebar, Button, LoadingDots } from '@components/ui' import PaymentMethodView from '@components/checkout/PaymentMethodView' import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView' import { CheckoutProvider } from '@components/checkout/context' -import MenuSidebarView, { Link } from '../UserNav/MenuSidebarView' - -import LoginView from '@components/auth/LoginView' -import s from './Layout.module.css' +import { MenuSidebarView } from '@components/common/UserNav' +import type { Page } from '@commerce/types/page' +import type { Category } from '@commerce/types/site' +import type { Link as LinkProps } from '../UserNav/MenuSidebarView' const Loading = () => (
@@ -29,35 +28,26 @@ const dynamicProps = { loading: Loading, } -const SignUpView = dynamic( - () => import('@components/auth/SignUpView'), - { - ...dynamicProps - } -) +const SignUpView = dynamic(() => import('@components/auth/SignUpView'), { + ...dynamicProps, +}) const ForgotPassword = dynamic( () => import('@components/auth/ForgotPassword'), - { - ...dynamicProps - } -) - -const FeatureBar = dynamic( - () => import('@components/common/FeatureBar'), - { - ...dynamicProps - } -) - -const Modal = dynamic( - () => import('@components/ui/Modal'), { ...dynamicProps, - ssr: false } ) +const FeatureBar = dynamic(() => import('@components/common/FeatureBar'), { + ...dynamicProps, +}) + +const Modal = dynamic(() => import('@components/ui/Modal'), { + ...dynamicProps, + ssr: false, +}) + interface Props { pageProps: { pages?: Page[] @@ -65,7 +55,7 @@ interface Props { } } -const ModalView: FC<{ modalView: string; closeModal(): any }> = ({ +const ModalView: React.FC<{ modalView: string; closeModal(): any }> = ({ modalView, closeModal, }) => { @@ -78,41 +68,41 @@ const ModalView: FC<{ modalView: string; closeModal(): any }> = ({ ) } -const ModalUI: FC = () => { +const ModalUI: React.FC = () => { const { displayModal, closeModal, modalView } = useUI() return displayModal ? ( ) : null } -const SidebarView: FC<{ +const SidebarView: React.FC<{ sidebarView: string closeSidebar(): any - links: Link[] + links: LinkProps[] }> = ({ sidebarView, closeSidebar, links }) => { return ( - {sidebarView === 'MOBILEMENU_VIEW' && } {sidebarView === 'CART_VIEW' && } - {sidebarView === 'CHECKOUT_VIEW' && } - {sidebarView === 'PAYMENT_VIEW' && } {sidebarView === 'SHIPPING_VIEW' && } + {sidebarView === 'PAYMENT_VIEW' && } + {sidebarView === 'CHECKOUT_VIEW' && } + {sidebarView === 'MOBILE_MENU_VIEW' && } ) } -const SidebarUI: FC<{ links: any }> = ({ links }) => { +const SidebarUI: React.FC<{ links: LinkProps[] }> = ({ links }) => { const { displaySidebar, closeSidebar, sidebarView } = useUI() return displaySidebar ? ( ) : null } -const Layout: FC = ({ +const Layout: React.FC = ({ children, pageProps: { categories = [], ...pageProps }, }) => { diff --git a/site/components/common/Navbar/Navbar.tsx b/site/components/common/Navbar/Navbar.tsx index bc1969a91..9286ef160 100644 --- a/site/components/common/Navbar/Navbar.tsx +++ b/site/components/common/Navbar/Navbar.tsx @@ -16,7 +16,7 @@ interface NavbarProps { const Navbar: FC = ({ links }) => ( - +
diff --git a/site/components/common/SEO/SEO.tsx b/site/components/common/SEO/SEO.tsx new file mode 100644 index 000000000..b5e3ad23b --- /dev/null +++ b/site/components/common/SEO/SEO.tsx @@ -0,0 +1,157 @@ +import Head from 'next/head' +import { FC, Fragment, ReactNode } from 'react' +import config from '@config/seo_meta.json' + +const storeUrl = + process.env.NEXT_PUBLIC_STORE_URL || process.env.NEXT_PUBLIC_VERCEL_URL +const storeBaseUrl = storeUrl ? `https://${storeUrl}` : null + +interface OgImage { + url?: string + width?: string + height?: string + alt?: string +} + +interface Props { + title?: string + description?: string + robots?: string + openGraph?: { + title?: string + type?: string + locale?: string + description?: string + site_name?: string + url?: string + images?: OgImage[] + } + children?: ReactNode +} + +const ogImage = ({ url, width, height, alt }: OgImage, index: number) => { + // generate full URL for OG image url with store base URL + const imgUrl = storeBaseUrl ? new URL(url!, storeBaseUrl).toString() : url + return ( + + + + + + + ) +} + +const SEO: FC = ({ + title, + description, + openGraph, + robots, + children, +}) => { + /** + * @see https://nextjs.org/docs/api-reference/next/head + * + * meta or any other elements need to be contained as direct children of the Head element, + * or wrapped into maximum one level of or arrays + * otherwise the tags won't be correctly picked up on client-side navigations. + * + * The `key` property makes the tag is only rendered once, + */ + return ( + + + {title ? `${config.titleTemplate.replace(/%s/g, title)}` : config.title} + + + + + + + + {openGraph?.locale && ( + + )} + {openGraph?.images?.length + ? openGraph.images.map((img, index) => ogImage(img, index)) + : ogImage(config.openGraph.images[0], 0)} + {config.twitter.cardType && ( + + )} + {config.twitter.site && ( + + )} + {config.twitter.handle && ( + + )} + + + {children} + + ) +} + +export default SEO diff --git a/site/components/common/SEO/index.ts b/site/components/common/SEO/index.ts new file mode 100644 index 000000000..e20ec8600 --- /dev/null +++ b/site/components/common/SEO/index.ts @@ -0,0 +1 @@ +export { default } from './SEO' diff --git a/site/components/common/SidebarLayout/SidebarLayout.tsx b/site/components/common/SidebarLayout/SidebarLayout.tsx index 407a938ea..b291e8a68 100644 --- a/site/components/common/SidebarLayout/SidebarLayout.tsx +++ b/site/components/common/SidebarLayout/SidebarLayout.tsx @@ -12,8 +12,8 @@ type ComponentProps = { className?: string } & ( const SidebarLayout: FC = ({ children, className, - handleClose, handleBack, + handleClose, }) => { return (
@@ -38,9 +38,8 @@ const SidebarLayout: FC = ({ Back )} - - - + +
{children}
diff --git a/site/components/common/UserNav/CustomerMenuContent/CustomerMenuContent.module.css b/site/components/common/UserNav/CustomerMenuContent/CustomerMenuContent.module.css new file mode 100644 index 000000000..93a183a2b --- /dev/null +++ b/site/components/common/UserNav/CustomerMenuContent/CustomerMenuContent.module.css @@ -0,0 +1,31 @@ +.root { + @apply inset-0 fixed; + left: 72px; + z-index: 10; + height: 100vh; + min-width: 100vw; + transition: none; +} + +@media screen(lg) { + .root { + @apply static; + min-width: inherit; + height: inherit; + } +} + +.link { + @apply text-primary flex cursor-pointer px-6 py-3 + transition ease-in-out duration-150 leading-6 + font-medium items-center capitalize w-full box-border + outline-0; +} + +.link:hover { + @apply bg-accent-1 outline-none; +} + +.link.active { + @apply font-bold bg-accent-2; +} diff --git a/site/components/common/UserNav/CustomerMenuContent/CustomerMenuContent.tsx b/site/components/common/UserNav/CustomerMenuContent/CustomerMenuContent.tsx new file mode 100644 index 000000000..992d17178 --- /dev/null +++ b/site/components/common/UserNav/CustomerMenuContent/CustomerMenuContent.tsx @@ -0,0 +1,86 @@ +import cn from 'clsx' +import { useTheme } from 'next-themes' +import { useRouter } from 'next/router' +import { Moon, Sun } from '@components/icons' +import s from './CustomerMenuContent.module.css' +import useLogout from '@framework/auth/use-logout' +import { + DropdownContent, + DropdownMenuItem, +} from '@components/ui/Dropdown/Dropdown' + +const LINKS = [ + { + name: 'My Orders', + href: '/orders', + }, + { + name: 'My Profile', + href: '/profile', + }, + { + name: 'My Cart', + href: '/cart', + }, +] + +export default function CustomerMenuContent() { + const router = useRouter() + const logout = useLogout() + const { pathname } = useRouter() + const { theme, setTheme } = useTheme() + + function handleClick(_: React.MouseEvent, href: string) { + router.push(href) + } + + return ( + + {LINKS.map(({ name, href }) => ( + + handleClick(e, href)} + > + {name} + + + ))} + + { + setTheme(theme === 'dark' ? 'light' : 'dark') + }} + > +
+ Theme: {theme}{' '} +
+
+ {theme == 'dark' ? ( + + ) : ( + + )} +
+
+
+ + logout()} + > + Logout + + +
+ ) +} diff --git a/site/components/common/UserNav/CustomerMenuContent/index.ts b/site/components/common/UserNav/CustomerMenuContent/index.ts new file mode 100644 index 000000000..b465e81d6 --- /dev/null +++ b/site/components/common/UserNav/CustomerMenuContent/index.ts @@ -0,0 +1 @@ +export { default } from './CustomerMenuContent' diff --git a/site/components/common/UserNav/DropdownMenu.module.css b/site/components/common/UserNav/DropdownMenu.module.css deleted file mode 100644 index 8c4d9eb98..000000000 --- a/site/components/common/UserNav/DropdownMenu.module.css +++ /dev/null @@ -1,26 +0,0 @@ -@screen lg { - .dropdownMenu { - @apply absolute top-10 border border-accent-1 shadow-lg w-56 h-auto; - } -} - -.dropdownMenu { - @apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full; -} - -.link { - @apply text-primary flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 leading-6 font-medium items-center; - text-transform: capitalize; -} - -.link:hover { - @apply bg-accent-1; -} - -.link.active { - @apply font-bold bg-accent-2; -} - -.off { - @apply hidden; -} diff --git a/site/components/common/UserNav/DropdownMenu.tsx b/site/components/common/UserNav/DropdownMenu.tsx deleted file mode 100644 index 9a73003dc..000000000 --- a/site/components/common/UserNav/DropdownMenu.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import cn from 'clsx' -import Link from 'next/link' -import { FC, useRef, useState, useEffect } from 'react' -import { useTheme } from 'next-themes' -import { useRouter } from 'next/router' -import s from './DropdownMenu.module.css' -import { Avatar } from '@components/common' -import { Moon, Sun } from '@components/icons' -import { useUI } from '@components/ui/context' -import ClickOutside from '@lib/click-outside' -import useLogout from '@framework/auth/use-logout' - -import { - disableBodyScroll, - enableBodyScroll, - clearAllBodyScrollLocks, -} from 'body-scroll-lock' - -interface DropdownMenuProps { - open?: boolean -} - -const LINKS = [ - { - name: 'My Orders', - href: '/orders', - }, - { - name: 'My Profile', - href: '/profile', - }, - { - name: 'My Cart', - href: '/cart', - }, -] - -const DropdownMenu: FC = ({ open = false }) => { - const logout = useLogout() - const { pathname } = useRouter() - const { theme, setTheme } = useTheme() - const [display, setDisplay] = useState(false) - const { closeSidebarIfPresent } = useUI() - const ref = useRef() as React.MutableRefObject - - useEffect(() => { - if (ref.current) { - if (display) { - disableBodyScroll(ref.current) - } else { - enableBodyScroll(ref.current) - } - } - return () => { - clearAllBodyScrollLocks() - } - }, [display]) - - return ( - setDisplay(false)}> - - - ) -} - -export default DropdownMenu diff --git a/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.module.css b/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.module.css index 26469d6b6..6c05b013e 100644 --- a/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.module.css +++ b/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.module.css @@ -3,5 +3,5 @@ } .item { - @apply text-2xl font-bold; -} \ No newline at end of file + @apply text-xl font-bold py-2; +} diff --git a/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.tsx b/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.tsx index 334b8de9e..a4ed5b51b 100644 --- a/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.tsx +++ b/site/components/common/UserNav/MenuSidebarView/MenuSidebarView.tsx @@ -1,31 +1,32 @@ import Link from 'next/link' import s from './MenuSidebarView.module.css' -import { FC } from 'react' import { useUI } from '@components/ui/context' import SidebarLayout from '@components/common/SidebarLayout' -import { Link as LinkProps} from '.' +import type { Link as LinkProps } from './index' - -interface MenuProps { +export default function MenuSidebarView({ + links = [], +}: { links?: LinkProps[] -} - -const MenuSidebarView: FC = (props) => { +}) { const { closeSidebar } = useUI() - const handleClose = () => closeSidebar() return ( - + closeSidebar()}>
- = ({ product, relatedProducts }) => { images: [ { url: product.images[0]?.url!, - width: 800, - height: 600, + width: '800', + height: '600', alt: product.name, }, ], diff --git a/site/components/ui/Container/Container.tsx b/site/components/ui/Container/Container.tsx index 095d4f9d4..d8425f3b3 100644 --- a/site/components/ui/Container/Container.tsx +++ b/site/components/ui/Container/Container.tsx @@ -12,10 +12,10 @@ const Container: FC = ({ children, className, el = 'div', - clean, + clean = false, // Full Width Screen }) => { const rootClassName = cn(className, { - 'mx-auto max-w-8xl px-6': !clean, + 'mx-auto max-w-7xl px-6 w-full': !clean, }) let Component: React.ComponentType> = diff --git a/site/components/ui/Dropdown/Dropdown.module.css b/site/components/ui/Dropdown/Dropdown.module.css new file mode 100644 index 000000000..46b2469cb --- /dev/null +++ b/site/components/ui/Dropdown/Dropdown.module.css @@ -0,0 +1,32 @@ +.root { + @apply bg-accent-0; + animation: none; + transition: none; + min-width: 100%; +} + +@media screen(lg) { + .root { + @apply bg-accent-0; + box-shadow: hsl(206 22% 7% / 45%) 0px 10px 38px -10px, + hsl(206 22% 7% / 20%) 0px 10px 20px -15px; + min-width: 14rem; + will-change: transform, opacity; + animation-duration: 600ms; + animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); + animation-fill-mode: forwards; + transform-origin: var(--radix-dropdown-menu-content-transform-origin); + animation-name: slideIn; + } +} + +@keyframes slideIn { + 0% { + opacity: 0; + transform: translateY(2px); + } + 100% { + opacity: 1; + transform: translateY(0px); + } +} diff --git a/site/components/ui/Dropdown/Dropdown.tsx b/site/components/ui/Dropdown/Dropdown.tsx new file mode 100644 index 000000000..566b962d6 --- /dev/null +++ b/site/components/ui/Dropdown/Dropdown.tsx @@ -0,0 +1,22 @@ +import cn from 'clsx' +import React from 'react' +import s from './Dropdown.module.css' +import * as DropdownMenu from '@radix-ui/react-dropdown-menu' + +export const Dropdown = DropdownMenu.Root +export const DropdownMenuItem = DropdownMenu.Item +export const DropdownTrigger = DropdownMenu.Trigger +export const DropdownMenuLabel = DropdownMenu.Label +export const DropdownMenuGroup = DropdownMenu.Group + +export const DropdownContent = React.forwardRef< + HTMLDivElement, + { children: React.ReactNode } & DropdownMenu.DropdownMenuContentProps & + React.RefAttributes +>(function DropdownContent({ children, className, ...props }, forwardedRef) { + return ( + +
{children}
+
+ ) +}) diff --git a/site/components/ui/Sidebar/Sidebar.tsx b/site/components/ui/Sidebar/Sidebar.tsx index fd0ce9057..3c01cbd53 100644 --- a/site/components/ui/Sidebar/Sidebar.tsx +++ b/site/components/ui/Sidebar/Sidebar.tsx @@ -1,14 +1,13 @@ -import { FC, useEffect, useRef } from 'react' -import s from './Sidebar.module.css' import cn from 'clsx' +import s from './Sidebar.module.css' +import { useEffect, useRef } from 'react' import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock' - interface SidebarProps { children: any onClose: () => void } -const Sidebar: FC = ({ children, onClose }) => { +const Sidebar: React.FC = ({ children, onClose }) => { const sidebarRef = useRef() as React.MutableRefObject const contentRef = useRef() as React.MutableRefObject diff --git a/site/components/ui/index.ts b/site/components/ui/index.ts index 47bdbd9ff..e4b37affb 100644 --- a/site/components/ui/index.ts +++ b/site/components/ui/index.ts @@ -13,4 +13,5 @@ export { default as Input } from './Input' export { default as Collapse } from './Collapse' export { default as Quantity } from './Quantity' export { default as Rating } from './Rating' +export * from './Dropdown/Dropdown' export { useUI } from './context' diff --git a/site/components/wishlist/WishlistButton/WishlistButton.tsx b/site/components/wishlist/WishlistButton/WishlistButton.tsx index 419d271a5..f4e0fb31f 100644 --- a/site/components/wishlist/WishlistButton/WishlistButton.tsx +++ b/site/components/wishlist/WishlistButton/WishlistButton.tsx @@ -31,8 +31,8 @@ const WishlistButton: FC = ({ const itemInWishlist = data?.items?.find( // @ts-ignore Wishlist is not always enabled (item) => - item.product_id === productId && - item.variant_id === variant.id + item.product_id === Number(productId) && + item.variant_id === Number(variant.id) ) const handleWishlistChange = async (e: any) => { diff --git a/site/components/wishlist/WishlistCard/WishlistCard.module.css b/site/components/wishlist/WishlistCard/WishlistCard.module.css index cd0237d3b..fb2d026b3 100644 --- a/site/components/wishlist/WishlistCard/WishlistCard.module.css +++ b/site/components/wishlist/WishlistCard/WishlistCard.module.css @@ -1,21 +1,38 @@ .root { - @apply grid grid-cols-12 w-full gap-6 px-3 py-6 border-b border-accent-2 transition duration-100 ease-in-out; + @apply relative grid sm:grid-cols-1 lg:grid-cols-12 + w-full gap-6 px-3 py-6 border-b border-accent-2 + transition duration-100 ease-in-out; +} - &:nth-child(3n + 1) { - & .productBg { - @apply bg-violet; - } - } +.root:nth-child(3n + 1) .imageWrapper { + @apply bg-violet; +} - &:nth-child(3n + 2) { - & .productBg { - @apply bg-pink; - } - } +.root:nth-child(3n + 2) .imageWrapper { + @apply bg-pink; +} - &:nth-child(3n + 3) { - & .productBg { - @apply bg-blue; - } +.root:nth-child(3n + 3) .imageWrapper { + @apply bg-blue; +} + +.imageWrapper { + @apply col-span-3; + min-width: 230px; + width: 230px; + height: 230px; +} + +.description { + @apply col-span-7 flex flex-col; +} + +.actions { + @apply absolute bg-accent-0 p-3 top-0 right-4; +} + +@media screen(lg) { + .actions { + @apply static col-span-2 flex flex-col justify-between space-y-4; } } diff --git a/site/components/wishlist/WishlistCard/WishlistCard.tsx b/site/components/wishlist/WishlistCard/WishlistCard.tsx index 7d0c6710a..6af6c914e 100644 --- a/site/components/wishlist/WishlistCard/WishlistCard.tsx +++ b/site/components/wishlist/WishlistCard/WishlistCard.tsx @@ -13,13 +13,11 @@ import useAddItem from '@framework/cart/use-add-item' import useRemoveItem from '@framework/wishlist/use-remove-item' import type { Wishlist } from '@commerce/types/wishlist' -interface Props { - item: Wishlist -} - const placeholderImg = '/product-img-placeholder.svg' -const WishlistCard: FC = ({ item }) => { +const WishlistCard: React.FC<{ + item: Wishlist +}> = ({ item }) => { const product: Product = item.product const { price } = usePrice({ amount: product.price?.value, @@ -63,41 +61,41 @@ const WishlistCard: FC = ({ item }) => { return (
-
-
- {product.images[0]?.alt -
+
+ {product.images[0]?.alt
-
-

- - {product.name} - -

-
- +
+
+

+ + {product.name} + +

+
+ +
+
+
+
-
-
+
{price}
-
+
diff --git a/site/config/seo.json b/site/config/seo_meta.json similarity index 90% rename from site/config/seo.json rename to site/config/seo_meta.json index 82520cf9b..c9c5fc226 100644 --- a/site/config/seo.json +++ b/site/config/seo_meta.json @@ -6,14 +6,13 @@ "title": "ACME Storefront | Powered by Next.js Commerce", "description": "Next.js Commerce - https://www.nextjs.org/commerce", "type": "website", - "locale": "en_IE", "url": "https://nextjs.org/commerce", "site_name": "Next.js Commerce", "images": [ { "url": "/card.png", - "width": 800, - "height": 600, + "width": "800", + "height": "600", "alt": "Next.js Commerce" } ] diff --git a/site/package.json b/site/package.json index 7a28e7e7b..efddd9a7b 100644 --- a/site/package.json +++ b/site/package.json @@ -13,6 +13,7 @@ }, "sideEffects": false, "dependencies": { + "@radix-ui/react-dropdown-menu": "^0.1.6", "@react-spring/web": "^9.4.1", "@vercel/commerce": "^0.0.1", "@vercel/commerce-bigcommerce": "^0.0.1", @@ -34,7 +35,6 @@ "lodash.random": "^3.2.0", "lodash.throttle": "^4.1.1", "next": "^12.0.8", - "next-seo": "^4.28.1", "next-themes": "^0.0.15", "postcss": "^8.3.5", "postcss-nesting": "^8.0.1", diff --git a/site/pages/cart.tsx b/site/pages/cart.tsx index 09a2227a2..6823f7b62 100644 --- a/site/pages/cart.tsx +++ b/site/pages/cart.tsx @@ -3,7 +3,7 @@ import useCart from '@framework/cart/use-cart' import usePrice from '@framework/product/use-price' import commerce from '@lib/api/commerce' import { Layout } from '@components/common' -import { Button, Text } from '@components/ui' +import { Button, Text, Container } from '@components/ui' import { Bag, Cross, Check, MapPin, CreditCard } from '@components/icons' import { CartItem } from '@components/cart' import { useUI } from '@components/ui/context' @@ -48,8 +48,8 @@ export default function Cart() { } return ( -
-
+ +
{isLoading || isEmpty ? (
@@ -82,7 +82,7 @@ export default function Cart() {
) : ( -
+
My Cart Review your Order
    @@ -111,7 +111,7 @@ export default function Cart() {
)}
-
+
{process.env.COMMERCE_CUSTOMCHECKOUT_ENABLED && ( <> @@ -185,7 +185,7 @@ export default function Cart() {
-
+
) } diff --git a/site/pages/orders.tsx b/site/pages/orders.tsx index b8b10814b..58f444507 100644 --- a/site/pages/orders.tsx +++ b/site/pages/orders.tsx @@ -22,7 +22,7 @@ export async function getStaticProps({ export default function Orders() { return ( - + My Orders
diff --git a/site/pages/profile.tsx b/site/pages/profile.tsx index eb54004ee..4c883059d 100644 --- a/site/pages/profile.tsx +++ b/site/pages/profile.tsx @@ -23,24 +23,28 @@ export async function getStaticProps({ export default function Profile() { const { data } = useCustomer() return ( - + My Profile - {data && ( -
-
-
- Full Name +
+ {data && ( +
+
+ + Full Name + {data.firstName} {data.lastName}
-
- Email +
+ + Email + {data.email}
-
- )} + )} +
) } diff --git a/site/pages/wishlist.tsx b/site/pages/wishlist.tsx index 389e7aaab..1b8edb31f 100644 --- a/site/pages/wishlist.tsx +++ b/site/pages/wishlist.tsx @@ -40,8 +40,8 @@ export default function Wishlist() { const { data, isLoading, isEmpty } = useWishlist({ includeProducts: true }) return ( - -
+ +
My Wishlist
{isLoading ? ( @@ -65,9 +65,9 @@ export default function Wishlist() {

) : ( -
+
{data && - // @ts-ignore Shopify - Fix this types + // @ts-ignore - Wishlist Item Type data.items?.map((item) => ( ))} diff --git a/turbo.json b/turbo.json index ccd7d3567..8e38ccddc 100644 --- a/turbo.json +++ b/turbo.json @@ -6,7 +6,13 @@ "outputs": ["dist/**"] }, "next-commerce#build": { - "dependsOn": ["^build", "$COMMERCE_PROVIDER"], + "dependsOn": [ + "^build", + "$COMMERCE_PROVIDER", + "$BIGCOMMERCE_STOREFRONT_API_URL", + "$NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN", + "$NEXT_PUBLIC_SWELL_STORE_ID" + ], "outputs": [".next/**"] }, "test": { @@ -24,6 +30,9 @@ }, "start": { "cache": false + }, + "types": { + "outputs": ["dist/**/*.d.ts"] } } } diff --git a/yarn.lock b/yarn.lock index 1c1a7fc7b..fc850a7a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -444,6 +444,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.13.10": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" @@ -982,6 +989,261 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== +"@radix-ui/popper@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/popper/-/popper-0.1.0.tgz#c387a38f31b7799e1ea0d2bb1ca0c91c2931b063" + integrity sha512-uzYeElL3w7SeNMuQpXiFlBhTT+JyaNMCwDfjKkrzugEcYrf5n52PHqncNdQPUtR42hJh8V9FsqyEDbDxkeNjJQ== + dependencies: + "@babel/runtime" "^7.13.10" + csstype "^3.0.4" + +"@radix-ui/primitive@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-0.1.0.tgz#6206b97d379994f0d1929809db035733b337e543" + integrity sha512-tqxZKybwN5Fa3VzZry4G6mXAAb9aAqKmPtnVbZpL0vsBwvOHTBwsjHVPXylocYLwEtBY9SCe665bYnNB515uoA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-arrow@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-0.1.4.tgz#a871448a418cd3507d83840fdd47558cb961672b" + integrity sha512-BB6XzAb7Ml7+wwpFdYVtZpK1BlMgqyafSQNGzhIpSZ4uXvXOHPlR5GP8M449JkeQzgQjv9Mp1AsJxFC0KuOtuA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "0.1.4" + +"@radix-ui/react-collection@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-0.1.4.tgz#734061ffd5bb93e88889d49b87391a73a63824c9" + integrity sha512-3muGI15IdgaDFjOcO7xX8a35HQRBRF6LH9pS6UCeZeRmbslkVeHyJRQr2rzICBUoX7zgIA0kXyMDbpQnJGyJTA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-slot" "0.1.2" + +"@radix-ui/react-compose-refs@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.1.0.tgz#cff6e780a0f73778b976acff2c2a5b6551caab95" + integrity sha512-eyclbh+b77k+69Dk72q3694OHrn9B3QsoIRx7ywX341U9RK1ThgQjMFZoPtmZNQTksXHLNEiefR8hGVeFyInGg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-context@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-0.1.1.tgz#06996829ea124d9a1bc1dbe3e51f33588fab0875" + integrity sha512-PkyVX1JsLBioeu0jB9WvRpDBBLtLZohVDT3BB5CTSJqActma8S8030P57mWZb4baZifMvN7KKWPAA40UmWKkQg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-dismissable-layer@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-0.1.5.tgz#9379032351e79028d472733a5cc8ba4a0ea43314" + integrity sha512-J+fYWijkX4M4QKwf9dtu1oC0U6e6CEl8WhBp3Ad23yz2Hia0XCo6Pk/mp5CAFy4QBtQedTSkhW05AdtSOEoajQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "0.1.0" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-use-body-pointer-events" "0.1.1" + "@radix-ui/react-use-callback-ref" "0.1.0" + "@radix-ui/react-use-escape-keydown" "0.1.0" + +"@radix-ui/react-dropdown-menu@^0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-0.1.6.tgz#3203229788cd57e552c9f19dcc7008e2b545919c" + integrity sha512-RZhtzjWwJ4ZBN7D8ek4Zn+ilHzYuYta9yIxFnbC0pfqMnSi67IQNONo1tuuNqtFh9SRHacPKc65zo+kBBlxtdg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "0.1.0" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-id" "0.1.5" + "@radix-ui/react-menu" "0.1.6" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-use-controllable-state" "0.1.0" + +"@radix-ui/react-focus-guards@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-0.1.0.tgz#ba3b6f902cba7826569f8edc21ff8223dece7def" + integrity sha512-kRx/swAjEfBpQ3ns7J3H4uxpXuWCqN7MpALiSDOXiyo2vkWv0L9sxvbpZeTulINuE3CGMzicVMuNc/VWXjFKOg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-focus-scope@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-0.1.4.tgz#c830724e212d42ffaaa81aee49533213d09b47df" + integrity sha512-fbA4ES3H4Wkxp+OeLhvN6SwL7mXNn/aBtUf7DRYxY9+Akrf7dRxl2ck4lgcpPsSg3zSDsEwLcY+h5cmj5yvlug== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-use-callback-ref" "0.1.0" + +"@radix-ui/react-id@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-0.1.5.tgz#010d311bedd5a2884c1e9bb6aaaa4e6cc1d1d3b8" + integrity sha512-IPc4H/63bes0IZ1GJJozSEkSWcDyhNGtKFWUpJ+XtaLyQ1X3x7Mf6fWwWhDcpqlYEP+5WtAvfqcyEsyjP+ZhBQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "0.1.0" + +"@radix-ui/react-menu@0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-0.1.6.tgz#7f9521a10f6a9cd819b33b33d5ed9538d79b2e75" + integrity sha512-ho3+bhpr3oAFkOBJ8VkUb1BcGoiZBB3OmcWPqa6i5RTUKrzNX/d6rauochu2xDlWjiRtpVuiAcsTVOeIC4FbYQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "0.1.0" + "@radix-ui/react-collection" "0.1.4" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-dismissable-layer" "0.1.5" + "@radix-ui/react-focus-guards" "0.1.0" + "@radix-ui/react-focus-scope" "0.1.4" + "@radix-ui/react-id" "0.1.5" + "@radix-ui/react-popper" "0.1.4" + "@radix-ui/react-portal" "0.1.4" + "@radix-ui/react-presence" "0.1.2" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-roving-focus" "0.1.5" + "@radix-ui/react-use-callback-ref" "0.1.0" + "@radix-ui/react-use-direction" "0.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "^2.4.0" + +"@radix-ui/react-popper@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-0.1.4.tgz#dfc055dcd7dfae6a2eff7a70d333141d15a5d029" + integrity sha512-18gDYof97t8UQa7zwklG1Dr8jIdj3u+rVOQLzPi9f5i1YQak/pVGkaqw8aY+iDUknKKuZniTk/7jbAJUYlKyOw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/popper" "0.1.0" + "@radix-ui/react-arrow" "0.1.4" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-use-rect" "0.1.1" + "@radix-ui/react-use-size" "0.1.1" + "@radix-ui/rect" "0.1.1" + +"@radix-ui/react-portal@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-0.1.4.tgz#17bdce3d7f1a9a0b35cb5e935ab8bc562441a7d2" + integrity sha512-MO0wRy2eYRTZ/CyOri9NANCAtAtq89DEtg90gicaTlkCfdqCLEBsLb+/q66BZQTr3xX/Vq01nnVfc/TkCqoqvw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-use-layout-effect" "0.1.0" + +"@radix-ui/react-presence@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.1.2.tgz#9f11cce3df73cf65bc348e8b76d891f0d54c1fe3" + integrity sha512-3BRlFZraooIUfRlyN+b/Xs5hq1lanOOo/+3h6Pwu2GMFjkGKKa4Rd51fcqGqnVlbr3jYg+WLuGyAV4KlgqwrQw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-use-layout-effect" "0.1.0" + +"@radix-ui/react-primitive@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-0.1.4.tgz#6c233cf08b0cb87fecd107e9efecb3f21861edc1" + integrity sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "0.1.2" + +"@radix-ui/react-roving-focus@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-0.1.5.tgz#cc48d17a36b56f253d54905b0fd60ee134cb97ee" + integrity sha512-ClwKPS5JZE+PaHCoW7eu1onvE61pDv4kO8W4t5Ra3qMFQiTJLZMdpBQUhksN//DaVygoLirz4Samdr5Y1x1FSA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "0.1.0" + "@radix-ui/react-collection" "0.1.4" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-id" "0.1.5" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-use-callback-ref" "0.1.0" + "@radix-ui/react-use-controllable-state" "0.1.0" + +"@radix-ui/react-slot@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-0.1.2.tgz#e6f7ad9caa8ce81cc8d532c854c56f9b8b6307c8" + integrity sha512-ADkqfL+agEzEguU3yS26jfB50hRrwf7U4VTwAOZEmi/g+ITcBWe12yM46ueS/UCIMI9Py+gFUaAdxgxafFvY2Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "0.1.0" + +"@radix-ui/react-use-body-pointer-events@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.1.tgz#63e7fd81ca7ffd30841deb584cd2b7f460df2597" + integrity sha512-R8leV2AWmJokTmERM8cMXFHWSiv/fzOLhG/JLmRBhLTAzOj37EQizssq4oW0Z29VcZy2tODMi9Pk/htxwb+xpA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "0.1.0" + +"@radix-ui/react-use-callback-ref@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-0.1.0.tgz#934b6e123330f5b3a6b116460e6662cbc663493f" + integrity sha512-Va041McOFFl+aV+sejvl0BS2aeHx86ND9X/rVFmEFQKTXCp6xgUK0NGUAGcgBlIjnJSbMYPGEk1xKSSlVcN2Aw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-controllable-state@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-0.1.0.tgz#4fced164acfc69a4e34fb9d193afdab973a55de1" + integrity sha512-zv7CX/PgsRl46a52Tl45TwqwVJdmqnlQEQhaYMz/yBOD2sx2gCkCFSoF/z9mpnYWmS6DTLNTg5lIps3fV6EnXg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "0.1.0" + +"@radix-ui/react-use-direction@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-direction/-/react-use-direction-0.1.0.tgz#97ac1d52e497c974389e7988f809238ed72e7df7" + integrity sha512-NajpY/An9TCPSfOVkgWIdXJV+VuWl67PxB6kOKYmtNAFHvObzIoh8o0n9sAuwSAyFCZVq211FEf9gvVDRhOyiA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-escape-keydown@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-0.1.0.tgz#dc80cb3753e9d1bd992adbad9a149fb6ea941874" + integrity sha512-tDLZbTGFmvXaazUXXv8kYbiCcbAE8yKgng9s95d8fCO+Eundv0Jngbn/hKPhDDs4jj9ChwRX5cDDnlaN+ugYYQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "0.1.0" + +"@radix-ui/react-use-layout-effect@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.1.0.tgz#ebf71bd6d2825de8f1fbb984abf2293823f0f223" + integrity sha512-+wdeS51Y+E1q1Wmd+1xSSbesZkpVj4jsg0BojCbopWvgq5iBvixw5vgemscdh58ep98BwUbsFYnrywFhV9yrVg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-rect@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-0.1.1.tgz#6c15384beee59c086e75b89a7e66f3d2e583a856" + integrity sha512-kHNNXAsP3/PeszEmM/nxBBS9Jbo93sO+xuMTcRfwzXsmxT5gDXQzAiKbZQ0EecCPtJIzqvr7dlaQi/aP1PKYqQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/rect" "0.1.1" + +"@radix-ui/react-use-size@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-0.1.1.tgz#f6b75272a5d41c3089ca78c8a2e48e5f204ef90f" + integrity sha512-pTgWM5qKBu6C7kfKxrKPoBI2zZYZmp2cSXzpUiGM3qEBQlMLtYhaY2JXdXUCxz+XmD1YEjc8oRwvyfsD4AG4WA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/rect@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.1.1.tgz#95b5ba51f469bea6b1b841e2d427e17e37d38419" + integrity sha512-g3hnE/UcOg7REdewduRPAK88EPuLZtaq7sA9ouu8S+YEtnyFRI16jgv6GZYe3VMoQLL1T171ebmEPtDjyxWLzw== + dependencies: + "@babel/runtime" "^7.13.10" + "@react-spring/animated@~9.4.0": version "9.4.2" resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.4.2.tgz#1dc107233ce4a44b023abac829f3b2ea8327a128" @@ -1556,6 +1818,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-hidden@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254" + integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA== + dependencies: + tslib "^1.0.0" + aria-query@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" @@ -2392,6 +2661,11 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== +csstype@^3.0.4: + version "3.0.11" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" + integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== + damerau-levenshtein@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -2533,6 +2807,11 @@ detect-indent@^6.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + detective@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" @@ -3283,6 +3562,11 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4763,11 +5047,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -next-seo@^4.28.1: - version "4.29.0" - resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-4.29.0.tgz#d281e95ba47914117cc99e9e468599f0547d9b9b" - integrity sha512-xmwzcz4uHaYJ8glbuhs6FSBQ7z3irmdPYdJJ5saWm72Uy3o+mPKGaPCXQetTCE6/xxVnpoDV4yFtFlEjUcljSg== - next-themes@^0.0.15: version "0.0.15" resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.0.15.tgz#ab0cee69cd763b77d41211f631e108beab39bf7d" @@ -5641,6 +5920,34 @@ react-refresh@0.8.3: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== +react-remove-scroll-bar@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.2.0.tgz#d4d545a7df024f75d67e151499a6ab5ac97c8cdd" + integrity sha512-UU9ZBP1wdMR8qoUs7owiVcpaPwsQxUDC2lypP6mmixaGlARZa7ZIBx1jcuObLdhMOvCsnZcvetOho0wzPa9PYg== + dependencies: + react-style-singleton "^2.1.0" + tslib "^1.0.0" + +react-remove-scroll@^2.4.0: + version "2.4.4" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.4.tgz#2dfff377cf17efc00de39dad51c143fc7a1b9e3e" + integrity sha512-EyC5ohYhaeKbThMSQxuN2i+QC5HqV3AJvNZKEdiATITexu0gHm00+5ko0ltNS1ajYJVeDgVG2baRSCei0AUWlQ== + dependencies: + react-remove-scroll-bar "^2.1.0" + react-style-singleton "^2.1.0" + tslib "^1.0.0" + use-callback-ref "^1.2.3" + use-sidecar "^1.0.1" + +react-style-singleton@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.1.1.tgz#ce7f90b67618be2b6b94902a30aaea152ce52e66" + integrity sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA== + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^1.0.0" + react-use-measure@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/react-use-measure/-/react-use-measure-2.1.1.tgz#5824537f4ee01c9469c45d5f7a8446177c6cc4ba" @@ -6622,7 +6929,7 @@ tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -6827,6 +7134,19 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" +use-callback-ref@^1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.5.tgz#6115ed242cfbaed5915499c0a9842ca2912f38a5" + integrity sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg== + +use-sidecar@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.5.tgz#ffff2a17c1df42e348624b699ba6e5c220527f2b" + integrity sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA== + dependencies: + detect-node-es "^1.1.0" + tslib "^1.9.3" + use-subscription@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"