diff --git a/app/[locale]/[[...slug]]/category-page.tsx b/app/[locale]/[[...slug]]/category-page.tsx
index 045aa315f..7cc1cfdc5 100644
--- a/app/[locale]/[[...slug]]/category-page.tsx
+++ b/app/[locale]/[[...slug]]/category-page.tsx
@@ -7,7 +7,6 @@ interface CategoryPageProps {
// has access to state and effects just like Page components
// in the `pages` directory.
export default function ProductPage({data }: CategoryPageProps) {
- console.log(data);
return (
<>Category page>
diff --git a/app/[locale]/[[...slug]]/page.tsx b/app/[locale]/[[...slug]]/page.tsx
index ad523a414..99f208150 100644
--- a/app/[locale]/[[...slug]]/page.tsx
+++ b/app/[locale]/[[...slug]]/page.tsx
@@ -14,8 +14,6 @@ export async function generateStaticParams() {
next: { revalidate: 10 },
})
- // console.log(paths)
-
return paths.map((path: {
slug: string,
locale: string
@@ -52,7 +50,7 @@ export default async function Page({
}) {
const { slug, locale } = params;
- const { query, queryParams, docType } = getQueryFromSlug(slug, locale)
+ const { query = '', queryParams, docType } = getQueryFromSlug(slug, locale)
const pageData = await client.fetch(query, queryParams)
diff --git a/app/[locale]/[[...slug]]/product-page.tsx b/app/[locale]/[[...slug]]/product-page.tsx
index 8745d689d..1e1e69d71 100644
--- a/app/[locale]/[[...slug]]/product-page.tsx
+++ b/app/[locale]/[[...slug]]/product-page.tsx
@@ -1,4 +1,5 @@
import ProductView from "components/product/product-view";
+import { notFound } from "next/navigation";
interface ProductPageProps {
data: object | any
@@ -8,6 +9,10 @@ interface ProductPageProps {
// has access to state and effects just like Page components
// in the `pages` directory.
export default function ProductPage({data }: ProductPageProps) {
+ if (!data) {
+ return notFound();
+ }
+
const { product } = data;
return (
diff --git a/app/[locale]/globals.css b/app/[locale]/globals.css
index 71647370b..7a899dedd 100644
--- a/app/[locale]/globals.css
+++ b/app/[locale]/globals.css
@@ -39,6 +39,15 @@ body {
}
/* COMPONENTS */
+.glider {
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+}
+
+.glider::-webkit-scrollbar {
+ display: none;
+}
+
.glider-dots {
@apply flex !space-x-[2px] !mt-8;
}
diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx
index e0c00f19d..751c98bc8 100644
--- a/app/[locale]/layout.tsx
+++ b/app/[locale]/layout.tsx
@@ -57,7 +57,9 @@ export default async function LocaleLayout({children, params: {locale}}: LocaleL
- {children}
+
+ {children}
+
diff --git a/app/[locale]/product/[handle]/page.tsx b/app/[locale]/product/[handle]/page.tsx
deleted file mode 100644
index 612cd0236..000000000
--- a/app/[locale]/product/[handle]/page.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import type { Metadata } from 'next';
-import { notFound } from 'next/navigation';
-import { Suspense } from 'react';
-
-import Grid from 'components/grid';
-import Footer from 'components/layout/footer';
-import ProductGridItems from 'components/layout/product-grid-items';
-import { AddToCart } from 'components/product/add-to-cart';
-import { Gallery } from 'components/product/gallery';
-import { VariantSelector } from 'components/product/variant-selector';
-import Prose from 'components/prose';
-import { HIDDEN_PRODUCT_TAG } from 'lib/constants';
-import { getProduct, getProductRecommendations } from 'lib/shopify';
-import { Image } from 'lib/shopify/types';
-
-export const runtime = 'edge';
-
-export async function generateMetadata({
- params
-}: {
- params: { handle: string };
-}): Promise {
- const product = await getProduct(params.handle);
-
- if (!product) return notFound();
-
- const { url, width, height, altText: alt } = product.featuredImage || {};
- const hide = !product.tags.includes(HIDDEN_PRODUCT_TAG);
-
- return {
- title: product.seo.title || product.title,
- description: product.seo.description || product.description,
- robots: {
- index: hide,
- follow: hide,
- googleBot: {
- index: hide,
- follow: hide
- }
- },
- openGraph: url
- ? {
- images: [
- {
- url,
- width,
- height,
- alt
- }
- ]
- }
- : null
- };
-}
-
-export default async function ProductPage({ params }: { params: { handle: string } }) {
- const product = await getProduct(params.handle);
-
- if (!product) return notFound();
-
- return (
-
-
-
- ({
- src: image.url,
- altText: image.altText
- }))}
- />
-
-
-
- {/* @ts-expect-error Server Component */}
-
-
- {product.descriptionHtml ? (
-
- ) : null}
-
-
-
-
-
- {/* @ts-expect-error Server Component */}
-
-
- {/* @ts-expect-error Server Component */}
-
-
-
-
- );
-}
-
-async function RelatedProducts({ id }: { id: string }) {
- const relatedProducts = await getProductRecommendations(id);
-
- if (!relatedProducts.length) return null;
-
- return (
-
-
Related Products
-
-
-
-
- );
-}
diff --git a/app/sitemap.ts b/app/sitemap.ts
index 1a0fd8232..cc202216e 100644
--- a/app/sitemap.ts
+++ b/app/sitemap.ts
@@ -1,4 +1,3 @@
-import { getCollections, getPages, getProducts } from 'lib/shopify';
import { MetadataRoute } from 'next';
const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL
@@ -11,23 +10,5 @@ export default async function sitemap(): Promise ({
- url: `${baseUrl}${collection.path}`,
- lastModified: collection.updatedAt
- }));
-
- const products = await getProducts({});
- const productsMap = products.map((product) => ({
- url: `${baseUrl}/product/${product.handle}`,
- lastModified: product.updatedAt
- }));
-
- const pages = await getPages();
- const pagesMap = pages.map((page) => ({
- url: `${baseUrl}/${page.handle}`,
- lastModified: page.updatedAt
- }));
-
- return [...routesMap, ...collectionsMap, ...productsMap, ...pagesMap];
+ return [...routesMap];
}
diff --git a/components/cart/delete-item-button.tsx b/components/cart/delete-item-button.tsx
index 789a87754..0d191aba6 100644
--- a/components/cart/delete-item-button.tsx
+++ b/components/cart/delete-item-button.tsx
@@ -1,5 +1,5 @@
import CloseIcon from 'components/icons/close';
-import LoadingDots from 'components/loading-dots';
+import LoadingDots from 'components/ui/loading-dots';
import { useRouter } from 'next/navigation';
import { startTransition, useState } from 'react';
diff --git a/components/layout/navbar/index.tsx b/components/layout/navbar/index.tsx
deleted file mode 100644
index 92489e8c9..000000000
--- a/components/layout/navbar/index.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import Link from 'next/link';
-
-import LogoIcon from 'components/icons/logo';
-// import { getMenu } from 'lib/shopify';
-// import { Menu } from 'lib/shopify/types';
-// import MobileMenu from './mobile-menu';
-// import Search from './search';
-
-export default async function Navbar() {
- // const menu = await getMenu('next-js-frontend-header-menu');
-
- return (
-
- );
-}
diff --git a/components/layout/navbar/mobile-menu.tsx b/components/layout/navbar/mobile-menu.tsx
deleted file mode 100644
index c960d5218..000000000
--- a/components/layout/navbar/mobile-menu.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-'use client';
-
-import { Dialog } from '@headlessui/react';
-import { motion } from 'framer-motion';
-import Link from 'next/link';
-import { usePathname, useSearchParams } from 'next/navigation';
-import { useEffect, useState } from 'react';
-
-import CloseIcon from 'components/icons/close';
-import MenuIcon from 'components/icons/menu';
-import { Menu } from 'lib/shopify/types';
-import Search from './search';
-
-export default function MobileMenu({ menu }: { menu: Menu[] }) {
- const pathname = usePathname();
- const searchParams = useSearchParams();
- const [mobileMenuIsOpen, setMobileMenuIsOpen] = useState(false);
-
- useEffect(() => {
- const handleResize = () => {
- if (window.innerWidth > 768) {
- setMobileMenuIsOpen(false);
- }
- };
- window.addEventListener('resize', handleResize);
- return () => window.removeEventListener('resize', handleResize);
- }, [mobileMenuIsOpen]);
-
- useEffect(() => {
- setMobileMenuIsOpen(false);
- }, [pathname, searchParams]);
-
- return (
- <>
-
-
- >
- );
-}
diff --git a/components/layout/navbar/search.tsx b/components/layout/navbar/search.tsx
deleted file mode 100644
index b3ff9a6bb..000000000
--- a/components/layout/navbar/search.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-'use client';
-
-import { useRouter, useSearchParams } from 'next/navigation';
-
-import SearchIcon from 'components/icons/search';
-
-export default function Search() {
- const router = useRouter();
- const searchParams = useSearchParams();
-
- function onSubmit(e: React.FormEvent) {
- e.preventDefault();
-
- const val = e.target as HTMLFormElement;
- const search = val.search as HTMLInputElement;
-
- if (search.value) {
- router.push(`/search?q=${search.value}`);
- } else {
- router.push(`/search`);
- }
- }
-
- return (
-
- );
-}
diff --git a/components/layout/search/collections.tsx b/components/layout/search/collections.tsx
deleted file mode 100644
index e4abb8d4a..000000000
--- a/components/layout/search/collections.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import clsx from 'clsx';
-import { Suspense } from 'react';
-
-import { getCollections } from 'lib/shopify';
-import FilterList from './filter';
-
-async function CollectionList() {
- const collections = await getCollections();
- return ;
-}
-
-const skeleton = 'mb-3 h-4 w-5/6 animate-pulse rounded';
-const activeAndTitles = 'bg-gray-800 dark:bg-gray-300';
-const items = 'bg-gray-400 dark:bg-gray-700';
-
-export default function Collections() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- }
- >
- {/* @ts-expect-error Server Component */}
-
-
- );
-}
diff --git a/components/layout/search/filter/dropdown.tsx b/components/layout/search/filter/dropdown.tsx
deleted file mode 100644
index 6f3e37f26..000000000
--- a/components/layout/search/filter/dropdown.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-'use client';
-
-import { usePathname, useSearchParams } from 'next/navigation';
-import { useEffect, useRef, useState } from 'react';
-
-import Caret from 'components/icons/caret-right';
-import type { ListItem } from '.';
-import { FilterItem } from './item';
-
-export default function FilterItemDropdown({ list }: { list: ListItem[] }) {
- const pathname = usePathname();
- const searchParams = useSearchParams();
- const [active, setActive] = useState('');
- const [openSelect, setOpenSelect] = useState(false);
- const ref = useRef(null);
-
- useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- if (ref.current && !ref.current.contains(event.target as Node)) {
- setOpenSelect(false);
- }
- };
-
- window.addEventListener('click', handleClickOutside);
- return () => window.removeEventListener('click', handleClickOutside);
- }, []);
-
- useEffect(() => {
- list.forEach((listItem: ListItem) => {
- if (
- ('path' in listItem && pathname === listItem.path) ||
- ('slug' in listItem && searchParams.get('sort') === listItem.slug)
- ) {
- setActive(listItem.title);
- }
- });
- }, [pathname, list, searchParams]);
-
- return (
-
-
{
- setOpenSelect(!openSelect);
- }}
- className="flex w-full items-center justify-between rounded border border-black/30 px-4 py-2 text-sm dark:border-white/30"
- >
-
{active}
-
-
- {openSelect && (
-
{
- setOpenSelect(false);
- }}
- className="absolute z-40 w-full rounded-b-md bg-white p-4 shadow-md dark:bg-black"
- >
- {list.map((item: ListItem, i) => (
-
- ))}
-
- )}
-
- );
-}
diff --git a/components/layout/search/filter/index.tsx b/components/layout/search/filter/index.tsx
deleted file mode 100644
index d740faeaa..000000000
--- a/components/layout/search/filter/index.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import { SortFilterItem } from 'lib/constants';
-import FilterItemDropdown from './dropdown';
-import { FilterItem } from './item';
-
-export type ListItem = SortFilterItem | PathFilterItem;
-export type PathFilterItem = { title: string; path: string };
-
-function FilterItemList({ list }: { list: ListItem[] }) {
- return (
-
- {list.map((item: ListItem, i) => (
-
- ))}
-
- );
-}
-
-export default function FilterList({ list, title }: { list: ListItem[]; title?: string }) {
- return (
- <>
-
- >
- );
-}
diff --git a/components/layout/search/filter/item.tsx b/components/layout/search/filter/item.tsx
deleted file mode 100644
index f56d6114b..000000000
--- a/components/layout/search/filter/item.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-'use client';
-
-import clsx from 'clsx';
-import { SortFilterItem } from 'lib/constants';
-import { createUrl } from 'lib/utils';
-import Link from 'next/link';
-import { usePathname, useSearchParams } from 'next/navigation';
-import { useEffect, useState } from 'react';
-import type { ListItem, PathFilterItem } from '.';
-
-function PathFilterItem({ item }: { item: PathFilterItem }) {
- const pathname = usePathname();
- const searchParams = useSearchParams();
- const [active, setActive] = useState(pathname === item.path);
-
- useEffect(() => {
- setActive(pathname === item.path);
- }, [pathname, item.path]);
-
- return (
-
-
- {item.title}
-
-
- );
-}
-
-function SortFilterItem({ item }: { item: SortFilterItem }) {
- const pathname = usePathname();
- const searchParams = useSearchParams();
- const [active, setActive] = useState(searchParams.get('sort') === item.slug);
-
- useEffect(() => {
- setActive(searchParams.get('sort') === item.slug);
- }, [searchParams, item.slug]);
-
- const href =
- item.slug && item.slug.length
- ? createUrl(pathname, new URLSearchParams({ sort: item.slug }))
- : pathname;
-
- return (
-
-
- {item.title}
-
-
- );
-}
-
-export function FilterItem({ item }: { item: ListItem }) {
- return 'path' in item ? : ;
-}
diff --git a/components/modules/blurb-section/blurb-section.tsx b/components/modules/blurb-section/blurb-section.tsx
index d36d31c1e..ee5241d4e 100644
--- a/components/modules/blurb-section/blurb-section.tsx
+++ b/components/modules/blurb-section/blurb-section.tsx
@@ -1,14 +1,6 @@
-import {
- CarouselItemProps as ItemProps,
- CarouselProps as Props,
-} from 'components/modules/carousel/carousel'
import dynamic from 'next/dynamic'
-const Carousel = dynamic(() =>
- import('components/modules/carousel/carousel').then((mod) => mod.Carousel)
-)
-const CarouselItem = dynamic(() =>
- import('components/modules/carousel/carousel').then((mod) => mod.CarouselItem)
-)
+
+import { Carousel, CarouselItem } from 'components/modules/carousel/carousel'
const Card = dynamic(() => import('components/ui/card'))
import Text from 'components/ui/text'
@@ -83,7 +75,6 @@ const BlurbSection = ({
{blurbs && (
(() =>
- import('components/modules/carousel/carousel').then((mod) => mod.Carousel)
-)
-const CarouselItem = dynamic(() =>
- import('components/modules/carousel/carousel').then((mod) => mod.CarouselItem)
-)
+
+import { Carousel, CarouselItem } from 'components/modules/carousel/carousel'
+
const ProductCard = dynamic(() => import('components/ui/product-card'))
const CategoryCard = dynamic(() => import('components/ui/category-card'))
diff --git a/components/product/product-view.tsx b/components/product/product-view.tsx
index ad752d2c6..a166cf96e 100644
--- a/components/product/product-view.tsx
+++ b/components/product/product-view.tsx
@@ -1,21 +1,12 @@
'use client'
-import {
- CarouselItemProps as ItemProps,
- CarouselProps as Props,
-} from 'components/modules/carousel/carousel'
+import { Carousel, CarouselItem } from 'components/modules/carousel/carousel'
import SanityImage from 'components/ui/sanity-image'
import { Product } from "lib/storm/types/product"
import { cn } from 'lib/utils'
import { useTranslations } from 'next-intl'
import dynamic from "next/dynamic"
const ProductCard = dynamic(() => import('components/ui/product-card'))
-const Carousel = dynamic(() =>
- import('components/modules/carousel/carousel').then((mod) => mod.Carousel)
-)
-const CarouselItem = dynamic(() =>
- import('components/modules/carousel/carousel').then((mod) => mod.CarouselItem)
-)
const Text = dynamic(() => import('components/ui/text'))
interface ProductViewProps {
product: Product
@@ -78,7 +69,9 @@ export default function ProductView({product, relatedProducts }: ProductViewProp
- {product.name}
+
+ {product.name}
+
diff --git a/components/ui/locale-switcher/index.ts b/components/ui/locale-switcher/index.ts
index 46525c3d4..b4fa2d7d1 100644
--- a/components/ui/locale-switcher/index.ts
+++ b/components/ui/locale-switcher/index.ts
@@ -1 +1,2 @@
-export { default } from './I18nWidget'
+export { default } from './locale-switcher';
+
diff --git a/components/ui/text/text.tsx b/components/ui/text/text.tsx
index 54220011a..4eb263146 100644
--- a/components/ui/text/text.tsx
+++ b/components/ui/text/text.tsx
@@ -20,6 +20,7 @@ type Variant =
| 'heading'
| 'body'
| 'pageHeading'
+ | 'productHeading'
| 'sectionHeading'
| 'label'
| 'paragraph'
@@ -39,6 +40,7 @@ const Text: FunctionComponent = ({
body: 'div',
heading: 'h1',
pageHeading: 'h1',
+ productHeading: 'h1',
sectionHeading: 'h2',
listChildHeading: 'h3',
label: 'div',
@@ -67,8 +69,10 @@ const Text: FunctionComponent = ({
variant === 'heading',
['max-w-prose text-3xl font-display font-bold leading-none md:text-4xl md:leading-none lg:leading-none lg:text-5xl']:
variant === 'pageHeading',
+ ['max-w-prose text-2xl font-display leading-none md:text-3xl md:leading-none lg:leading-none lg:text-4xl']:
+ variant === 'productHeading',
['max-w-prose text-2xl font-display font-bold leading-none md:text-3xl md:leading-none lg:leading-none lg:text-4xl']:
- variant === 'sectionHeading',
+ variant === 'sectionHeading',
['text-sm font-semibold leading-tight lg:text-base']:
variant === 'listChildHeading',
['text-sm max-w-prose lg:text-base 2xl:text-lg']: variant === 'label',
diff --git a/helpers/getQueryFromSlug.ts b/helpers/getQueryFromSlug.ts
index 30f5ddf0a..6f079c5e6 100644
--- a/helpers/getQueryFromSlug.ts
+++ b/helpers/getQueryFromSlug.ts
@@ -7,11 +7,11 @@ import {
} from '../lib/sanity/queries'
const getQueryFromSlug = (slugArray: string[], locale: string) => {
- const docQuery = {
- homePage: groq`${homePageQuery}`,
- product: groq`${productQuery}`,
- category: groq`${categoryQuery}`,
- page: groq`${pageQuery}`,
+ const docQuery: { [index: string]: string } = {
+ 'homePage': groq`${homePageQuery}`,
+ 'product': groq`${productQuery}`,
+ 'category': groq`${categoryQuery}`,
+ 'page': groq`${pageQuery}`,
}
let docType = ''
diff --git a/middleware.ts b/middleware.ts
index e87f1c361..b1849e5c5 100644
--- a/middleware.ts
+++ b/middleware.ts
@@ -5,7 +5,10 @@ export default createMiddleware({
locales: ['sv', 'en', 'nn'],
// If this locale is matched, pathnames work without a prefix (e.g. `/about`)
- defaultLocale: 'sv'
+ defaultLocale: 'sv',
+
+ // Don't automatically detect locale, sv is default.
+ localeDetection: false
});
export const config = {
diff --git a/next.config.js b/next.config.js
index 5e4ed1c56..8e03cd0b2 100644
--- a/next.config.js
+++ b/next.config.js
@@ -10,7 +10,6 @@ module.exports = withBundleAnalyzer(
ignoreDuringBuilds: true
},
experimental: {
- appDir: true,
scrollRestoration: true,
},
images: {
diff --git a/package.json b/package.json
index 8a739d543..4b5cc1e39 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
"framer-motion": "^8.4.0",
"is-empty-iterable": "^3.0.0",
"lucide-react": "^0.194.0",
- "next": "13.3.4",
+ "next": "13.4.0",
"next-intl": "^2.13.1",
"next-sanity": "^4.2.0",
"react": "18.2.0",
@@ -62,7 +62,7 @@
"@vercel/git-hooks": "^1.0.0",
"autoprefixer": "^10.4.13",
"eslint": "^8.35.0",
- "eslint-config-next": "^13.3.4",
+ "eslint-config-next": "^13.4.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-unicorn": "^45.0.2",
"lint-staged": "^13.1.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 499e3d053..7bf872351 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -24,14 +24,14 @@ specifiers:
class-variance-authority: ^0.6.0
clsx: ^1.2.1
eslint: ^8.35.0
- eslint-config-next: ^13.3.4
+ eslint-config-next: ^13.4.0
eslint-config-prettier: ^8.6.0
eslint-plugin-unicorn: ^45.0.2
framer-motion: ^8.4.0
is-empty-iterable: ^3.0.0
lint-staged: ^13.1.1
lucide-react: ^0.194.0
- next: 13.3.4
+ next: 13.4.0
next-intl: ^2.13.1
next-sanity: ^4.2.0
postcss: ^8.4.21
@@ -66,9 +66,9 @@ dependencies:
framer-motion: 8.5.5_biqbaboplfbrettd7655fr4n2y
is-empty-iterable: 3.0.0
lucide-react: 0.194.0_react@18.2.0
- next: 13.3.4_5lnmxaau2bs7vcvowl2iwadrxa
- next-intl: 2.13.1_next@13.3.4+react@18.2.0
- next-sanity: 4.2.0_ng6tx5vtrrzblbayibx5wevyra
+ next: 13.4.0_5lnmxaau2bs7vcvowl2iwadrxa
+ next-intl: 2.13.1_next@13.4.0+react@18.2.0
+ next-sanity: 4.2.0_aehsfoaj4shzjn3qi6ffpl7sie
react: 18.2.0
react-cookie: 4.1.1_react@18.2.0
react-dom: 18.2.0_react@18.2.0
@@ -88,7 +88,7 @@ devDependencies:
'@vercel/git-hooks': 1.0.0
autoprefixer: 10.4.14_postcss@8.4.22
eslint: 8.38.0
- eslint-config-next: 13.3.4_ze6bmax3gcsfve3yrzu6npguhe
+ eslint-config-next: 13.4.0_ze6bmax3gcsfve3yrzu6npguhe
eslint-config-prettier: 8.8.0_eslint@8.38.0
eslint-plugin-unicorn: 45.0.2_eslint@8.38.0
lint-staged: 13.2.1
@@ -1091,18 +1091,18 @@ packages:
- utf-8-validate
dev: false
- /@next/env/13.3.4:
- resolution: {integrity: sha512-oTK/wRV2qga86m/4VdrR1+/56UA6U1Qv3sIgowB+bZjahniZLEG5BmmQjfoGv7ZuLXBZ8Eec6hkL9BqJcrEL2g==}
+ /@next/env/13.4.0:
+ resolution: {integrity: sha512-LKofmUuxwGXk2OZJSSJ2SlJE62s6z+56aRsze7chc5TPoVouLR9liTiSWxzYuVzuxk0ui2wtIjyR2tcgS1dIyw==}
dev: false
- /@next/eslint-plugin-next/13.3.4:
- resolution: {integrity: sha512-mvS+HafOPy31oJbAi920WJXMdjbyb4v5FAMr9PeGZfRIdEcsLkA3mU/ZvmwzovJgP3nAWw2e2yM8iIFW8VpvIA==}
+ /@next/eslint-plugin-next/13.4.0:
+ resolution: {integrity: sha512-ZqQi1slguDavpuNUcl9va8+WtHHpgymIW2g+4Gs9FdI+5rjAvrUqqjfCec2hi3Cjbbp7zULFQuAiPwASKHbrxw==}
dependencies:
glob: 7.1.7
dev: true
- /@next/swc-darwin-arm64/13.3.4:
- resolution: {integrity: sha512-vux7RWfzxy1lD21CMwZsy9Ej+0+LZdIIj1gEhVmzOQqQZ5N56h8JamrjIVCfDL+Lpj8KwOmFZbPHE8qaYnL2pg==}
+ /@next/swc-darwin-arm64/13.4.0:
+ resolution: {integrity: sha512-C39AGL3ANXA+P3cFclQjFZaJ4RHPmuBhskmyy0N3VyCntDmRrNkS4aXeNY4Xwure9IL1nuw02D8bM55I+FsbuQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@@ -1110,8 +1110,8 @@ packages:
dev: false
optional: true
- /@next/swc-darwin-x64/13.3.4:
- resolution: {integrity: sha512-1tb+6JT98+t7UIhVQpKL7zegKnCs9RKU6cKNyj+DYKuC/NVl49/JaIlmwCwK8Ibl+RXxJrK7uSXSIO71feXsgw==}
+ /@next/swc-darwin-x64/13.4.0:
+ resolution: {integrity: sha512-nj6nx6o7rnBXjo1woZFWLk7OUs7y0SQ0k65SX62kc88GqXtYi3BCqbBznjOX8qtrO//NmtAde/Jd5qkjSgINUQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@@ -1119,8 +1119,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-arm64-gnu/13.3.4:
- resolution: {integrity: sha512-UqcKkYTKslf5YAJNtZ5XV1D5MQJIkVtDHL8OehDZERHzqOe7jvy41HFto33IDPPU8gJiP5eJb3V9U26uifqHjw==}
+ /@next/swc-linux-arm64-gnu/13.4.0:
+ resolution: {integrity: sha512-FBYL7kpzI2KG3lv8gO4xVYmWcFohptjzD9RCLdXsAz+Kqz5VCJILF21DoRcz4Nwj/jMe0SO7l5kBVW4POl4EaQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -1128,8 +1128,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-arm64-musl/13.3.4:
- resolution: {integrity: sha512-HE/FmE8VvstAfehyo/XsrhGgz97cEr7uf9IfkgJ/unqSXE0CDshDn/4as6rRid74eDR8/exi7c2tdo49Tuqxrw==}
+ /@next/swc-linux-arm64-musl/13.4.0:
+ resolution: {integrity: sha512-S3htBbcovnLMgVn0z1ThrP1iAeEM43fw8B7S3KyHTAGe0I21ww4rvUkLdgPCqLNvMpv899lmG7NU5rs6rTkGvg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -1137,8 +1137,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-x64-gnu/13.3.4:
- resolution: {integrity: sha512-xU+ugaupGA4SL5aK1ZYEqVHrW3TPOhxVcpaJLfpANm2443J4GfxCmOacu9XcSgy5c51Mq7C9uZ1LODKHfZosRQ==}
+ /@next/swc-linux-x64-gnu/13.4.0:
+ resolution: {integrity: sha512-H8GhCgQwFl6iWJ6azQ2tG/GY8BUg1nhPtg4Tp2kIPljdyQypTGJe8oRnPDx0N48WWvB2fNeA7LNEwzVuSidH2w==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -1146,8 +1146,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-x64-musl/13.3.4:
- resolution: {integrity: sha512-cZvmf5KcYeTfIK6bCypfmxGUjme53Ep7hx94JJtGrYgCA1VwEuYdh+KouubJaQCH3aqnNE7+zGnVEupEKfoaaA==}
+ /@next/swc-linux-x64-musl/13.4.0:
+ resolution: {integrity: sha512-mztVybRPY39NfPOA3QrRQKzYuw7A/D8ElR6ruvM1cBsXMEfF5xTzdZqfTtrE/gNTPUFug9FJPpiRpkZ4mDUl8w==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -1155,8 +1155,8 @@ packages:
dev: false
optional: true
- /@next/swc-win32-arm64-msvc/13.3.4:
- resolution: {integrity: sha512-7dL+CAUAjmgnVbjXPIpdj7/AQKFqEUL3bKtaOIE1JzJ5UMHHAXCPwzQtibrsvQpf9MwcAmiv8aburD3xH1xf8w==}
+ /@next/swc-win32-arm64-msvc/13.4.0:
+ resolution: {integrity: sha512-mdVh/n0QqT2uXqn8kaTywUoLxY1OYqTpiKbt5b51pDwOStqgbIbqBqG0A7XDaiqWa7RKwllOYxPlPm16EDfWUA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
@@ -1164,8 +1164,8 @@ packages:
dev: false
optional: true
- /@next/swc-win32-ia32-msvc/13.3.4:
- resolution: {integrity: sha512-qplTyzEl1vPkS+/DRK3pKSL0HeXrPHkYsV7U6gboHYpfqoHY+bcLUj3gwVUa9PEHRIoq4vXvPzx/WtzE6q52ng==}
+ /@next/swc-win32-ia32-msvc/13.4.0:
+ resolution: {integrity: sha512-GNRqT2mqxxH0x9VthFqziBj8X8HsoBUougmLe3kOouRq/jF73LpKXG0Qs2MYkylqvv/Wg31EYjFNcJnBi1Nimg==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@@ -1173,8 +1173,8 @@ packages:
dev: false
optional: true
- /@next/swc-win32-x64-msvc/13.3.4:
- resolution: {integrity: sha512-usdvZT7JHrTuXC+4OKN5mCzUkviFkCyJJTkEz8jhBpucg+T7s83e7owm3oNFzmj5iKfvxU2St6VkcnSgpFvEYA==}
+ /@next/swc-win32-x64-msvc/13.4.0:
+ resolution: {integrity: sha512-0AkvhUBUqeb4WKN75IW1KjPkN3HazQFA0OpMuTK+6ptJUXMaMwDDcF3sIPCI741BJ2fpODB7BPM4C63hXWEypg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -3419,8 +3419,8 @@ packages:
source-map: 0.6.1
dev: false
- /eslint-config-next/13.3.4_ze6bmax3gcsfve3yrzu6npguhe:
- resolution: {integrity: sha512-TknEcP+EdTqLvJ2zMY1KnWqcx8ZHl1C2Tjjbq3qmtWcHRU5oxe1PAsz3vrKG3NOzonSaPcB2SpCSfYqcgj6nfA==}
+ /eslint-config-next/13.4.0_ze6bmax3gcsfve3yrzu6npguhe:
+ resolution: {integrity: sha512-FkO3QRyUEKAHM4ie0xAcxo7fQ8gWevuLqgf6/g1Y6zWybqSa4FNeJr4hqqTbP25xIRgUUIPILBlx9RSH4C6+gQ==}
peerDependencies:
eslint: ^7.23.0 || ^8.0.0
typescript: '>=3.3.1'
@@ -3428,7 +3428,7 @@ packages:
typescript:
optional: true
dependencies:
- '@next/eslint-plugin-next': 13.3.4
+ '@next/eslint-plugin-next': 13.4.0
'@rushstack/eslint-patch': 1.2.0
'@typescript-eslint/parser': 5.59.2_ze6bmax3gcsfve3yrzu6npguhe
eslint: 8.38.0
@@ -5201,7 +5201,7 @@ packages:
engines: {node: '>= 0.6'}
dev: false
- /next-intl/2.13.1_next@13.3.4+react@18.2.0:
+ /next-intl/2.13.1_next@13.4.0+react@18.2.0:
resolution: {integrity: sha512-3XUZ7c123QHgQGcz5UUkTtakJdLETBlcHcdHop43iVToOpsezxvMZW6jxWwuHTRvkElfNPy1fhHwzBo/mhVVvQ==}
engines: {node: '>=10'}
peerDependencies:
@@ -5210,12 +5210,12 @@ packages:
dependencies:
'@formatjs/intl-localematcher': 0.2.32
negotiator: 0.6.3
- next: 13.3.4_5lnmxaau2bs7vcvowl2iwadrxa
+ next: 13.4.0_5lnmxaau2bs7vcvowl2iwadrxa
react: 18.2.0
use-intl: 2.13.1_react@18.2.0
dev: false
- /next-sanity/4.2.0_ng6tx5vtrrzblbayibx5wevyra:
+ /next-sanity/4.2.0_aehsfoaj4shzjn3qi6ffpl7sie:
resolution: {integrity: sha512-4GNEgXXDWPlvXqdJaAfKBR8BNvwQqUCynJ9GCgL6tVGcfZvcAImyZkzLTXj75PTZDPDcc7OfKHXg+XbmbUp7hA==}
engines: {node: '>=16'}
peerDependencies:
@@ -5236,7 +5236,7 @@ packages:
'@sanity/webhook': 2.0.0
'@types/styled-components': 5.1.26
groq: 3.9.1
- next: 13.3.4_5lnmxaau2bs7vcvowl2iwadrxa
+ next: 13.4.0_5lnmxaau2bs7vcvowl2iwadrxa
react: 18.2.0
sanity: 3.9.1_inskn5v7aqlrr54h6fubgcms5y
styled-components: 5.3.10_7i5myeigehqah43i5u7wbekgba
@@ -5244,8 +5244,8 @@ packages:
- supports-color
dev: false
- /next/13.3.4_5lnmxaau2bs7vcvowl2iwadrxa:
- resolution: {integrity: sha512-sod7HeokBSvH5QV0KB+pXeLfcXUlLrGnVUXxHpmhilQ+nQYT3Im2O8DswD5e4uqbR8Pvdu9pcWgb1CbXZQZlmQ==}
+ /next/13.4.0_5lnmxaau2bs7vcvowl2iwadrxa:
+ resolution: {integrity: sha512-y3E+2ZjiVrphkz7zcJvd2rEG6miOekI8krPfWV4AZZ9TaF0LDuFdP/f+RQ5M9wRvsz6GWw8k8+7jsO860GxSqg==}
engines: {node: '>=16.8.0'}
hasBin: true
peerDependencies:
@@ -5265,7 +5265,7 @@ packages:
sass:
optional: true
dependencies:
- '@next/env': 13.3.4
+ '@next/env': 13.4.0
'@swc/helpers': 0.5.1
busboy: 1.6.0
caniuse-lite: 1.0.30001482
@@ -5273,16 +5273,17 @@ packages:
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
styled-jsx: 5.1.1_yxvpwo57iqrkjg2xxfiwjdgilu
+ zod: 3.21.4
optionalDependencies:
- '@next/swc-darwin-arm64': 13.3.4
- '@next/swc-darwin-x64': 13.3.4
- '@next/swc-linux-arm64-gnu': 13.3.4
- '@next/swc-linux-arm64-musl': 13.3.4
- '@next/swc-linux-x64-gnu': 13.3.4
- '@next/swc-linux-x64-musl': 13.3.4
- '@next/swc-win32-arm64-msvc': 13.3.4
- '@next/swc-win32-ia32-msvc': 13.3.4
- '@next/swc-win32-x64-msvc': 13.3.4
+ '@next/swc-darwin-arm64': 13.4.0
+ '@next/swc-darwin-x64': 13.4.0
+ '@next/swc-linux-arm64-gnu': 13.4.0
+ '@next/swc-linux-arm64-musl': 13.4.0
+ '@next/swc-linux-x64-gnu': 13.4.0
+ '@next/swc-linux-x64-musl': 13.4.0
+ '@next/swc-win32-arm64-msvc': 13.4.0
+ '@next/swc-win32-ia32-msvc': 13.4.0
+ '@next/swc-win32-x64-msvc': 13.4.0
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
@@ -7538,3 +7539,7 @@ packages:
compress-commons: 4.1.1
readable-stream: 3.6.2
dev: false
+
+ /zod/3.21.4:
+ resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
+ dev: false
diff --git a/tailwind.config.js b/tailwind.config.js
index abdadb7d8..31c915bd1 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -11,6 +11,18 @@ module.exports = {
],
safelist: ['outline-none'],
theme: {
+ fontSize: {
+ xs: '0.75rem',
+ sm: '0.875rem',
+ base: '1rem',
+ lg: '1.125rem',
+ xl: '1.25rem',
+ '2xl': '1.5rem',
+ '3xl': '1.75rem',
+ '4xl': '2rem',
+ '5xl': '3rem',
+ '6xl': '4rem',
+ },
extend: {
colors: {
app: '#ffffff',