Next and next sanity fetching and preview updates

This commit is contained in:
Henrik Larsson 2023-08-23 22:44:06 +02:00
parent 9cab4ac2c6
commit ae873b5d3f
20 changed files with 428 additions and 265 deletions

View File

@ -5,7 +5,6 @@ import ProductPagePreview from '@/components/pages/product-page-preview';
import SearchPage from '@/components/pages/search-page'; import SearchPage from '@/components/pages/search-page';
import SearchPagePreview from '@/components/pages/search-page-preview'; import SearchPagePreview from '@/components/pages/search-page-preview';
import SinglePage from '@/components/pages/single-page'; import SinglePage from '@/components/pages/single-page';
// import PreviewProvider from '@/components/preview-provider';
import SinglePagePreview from '@/components/pages/single-page-preview'; import SinglePagePreview from '@/components/pages/single-page-preview';
import getQueryFromSlug from '@/helpers/get-query-from-slug'; import getQueryFromSlug from '@/helpers/get-query-from-slug';
import { categoryQuery, pageQuery, productQuery, searchPageQuery } from '@/lib/sanity/queries'; import { categoryQuery, pageQuery, productQuery, searchPageQuery } from '@/lib/sanity/queries';

View File

@ -7,6 +7,8 @@ import { LiveQuery } from 'next-sanity/preview/live-query';
import { draftMode } from 'next/headers'; import { draftMode } from 'next/headers';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
export const runtime = 'edge';
export async function generateMetadata({ export async function generateMetadata({
params params
}: { }: {

View File

@ -1,5 +1,10 @@
import { previewSecretId } from '@/lib/sanity/sanity.api'
import { client } from '@/lib/sanity/sanity.client'
import { token } from '@/lib/sanity/sanity.fetch' import { token } from '@/lib/sanity/sanity.fetch'
import { draftMode } from 'next/headers' import { draftMode } from 'next/headers'
import { isValidSecret } from 'sanity-plugin-iframe-pane/is-valid-secret'
export const runtime = 'edge'
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url) const { searchParams } = new URL(request.url)
@ -14,8 +19,20 @@ export async function GET(request: Request) {
) )
} }
if (secret !== process.env.SANITY_API_READ_TOKEN) { if (!secret) {
return new Response('Invalid token', { status: 401 }) return new Response('Invalid secret', { status: 401 })
}
const authenticatedClient = client.withConfig({ token })
const validSecret = await isValidSecret(
authenticatedClient,
previewSecretId,
secret,
)
if (!validSecret) {
return new Response('Invalid secret', { status: 401 })
} }
draftMode().enable() draftMode().enable()

View File

@ -36,39 +36,12 @@
:root { :root {
--background: 0 0% 100%; --background: 0 0% 100%;
--foreground: 0 0% 3.9%; --foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%; --border: 0 0% 89.8%;
--input: 0 0% 89.8%; --input: 0 0% 89.8%;
--ring: 0 0% 3.9%; --ring: 0 0% 3.9%;
--radius: 0.5rem; --radius: 0.5rem;
} }
* {
@apply border-border;
}
::-moz-selection { ::-moz-selection {
/* Code for Firefox */ /* Code for Firefox */
color: #ffffff; color: #ffffff;
@ -82,7 +55,7 @@
html, html,
body { body {
@apply h-full bg-white font-sans text-high-contrast; @apply h-full bg-background text-foreground;
box-sizing: border-box; box-sizing: border-box;
touch-action: manipulation; touch-action: manipulation;
@ -91,9 +64,6 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
overscroll-behavior-x: none; overscroll-behavior-x: none;
} }
body {
@apply bg-background text-foreground;
}
} }
@layer components { @layer components {

View File

@ -1,5 +1,5 @@
// import { footerMenusQuery } from '@/lib/sanity/queries'; import Text from '@/components/ui/text/text';
// import { getCachedClient } from '@/lib/sanity/sanity.client'; import { getFooterMenus } from '@/lib/sanity/sanity.fetch';
import LocaleSwitcher from 'components/ui/locale-switcher/locale-switcher'; import LocaleSwitcher from 'components/ui/locale-switcher/locale-switcher';
import Logo from 'components/ui/logo/logo'; import Logo from 'components/ui/logo/logo';
import Link from 'next/link'; import Link from 'next/link';
@ -14,7 +14,7 @@ export default async function Footer({ locale }: FooterProps) {
locale: locale locale: locale
}; };
// const footerMenus = await getCachedClient()(footerMenusQuery, params); const footerMenus = await getFooterMenus(params.locale);
return ( return (
<footer className="border-t border-ui-border bg-app"> <footer className="border-t border-ui-border bg-app">
@ -26,12 +26,14 @@ export default async function Footer({ locale }: FooterProps) {
<LocaleSwitcher /> <LocaleSwitcher />
</div> </div>
{/* {footerMenus.length > 0 && ( {footerMenus && (
<div className="grid w-full grid-cols-2 gap-4 p-4 lg:grid-cols-4 lg:gap-8 lg:px-8 lg:py-6 2xl:px-16 2xl:py-8"> <div className="grid w-full grid-cols-2 gap-4 p-4 lg:grid-cols-4 lg:gap-8 lg:px-8 lg:py-6 2xl:px-16 2xl:py-8">
{/* @ts-ignore */}
{footerMenus.map((menu: object | any, index: number) => { {footerMenus.map((menu: object | any, index: number) => {
return ( return (
<div key={index}> <div key={index}>
<Text variant="label">{menu.title}</Text> <Text variant="label">{menu.title}</Text>
<ul className="mt-4 flex flex-col space-y-2" aria-label={menu.title}> <ul className="mt-4 flex flex-col space-y-2" aria-label={menu.title}>
{menu.menu.links.map((link: object | any, index: number) => { {menu.menu.links.map((link: object | any, index: number) => {
return ( return (
@ -60,7 +62,7 @@ export default async function Footer({ locale }: FooterProps) {
); );
})} })}
</div> </div>
)} */} )}
<div className="flex items-center justify-center border-t border-ui-border bg-black px-4 py-3 lg:px-8 2xl:px-16"> <div className="flex items-center justify-center border-t border-ui-border bg-black px-4 py-3 lg:px-8 2xl:px-16">
<CopyRight /> <CopyRight />

View File

@ -22,7 +22,7 @@ export default function ProductPage({ data }: ProductPageParams) {
__html: JSON.stringify(productJsonLd) __html: JSON.stringify(productJsonLd)
}} }}
/> />
<ProductView product={product} relatedProducts={[]} />; <ProductView product={product} relatedProducts={[]} />
</> </>
); );
} }

View File

@ -24,7 +24,7 @@ const SheetOverlay = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay <SheetPrimitive.Overlay
className={cn( className={cn(
'fixed inset-0 z-50 bg-foreground/70 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', 'bg-foreground/70 fixed inset-0 z-50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className className
)} )}
{...props} {...props}
@ -34,7 +34,7 @@ const SheetOverlay = React.forwardRef<
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
const sheetVariants = cva( const sheetVariants = cva(
'fixed z-50 gap-4 bg-background p-4 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 lg:p-6', 'fixed z-50 gap-4 bg-white p-4 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 lg:p-6',
{ {
variants: { variants: {
side: { side: {
@ -64,7 +64,7 @@ const SheetContent = React.forwardRef<
<SheetOverlay /> <SheetOverlay />
<SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}> <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
{children} {children}
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary md:right-6 md:top-6"> <SheetPrimitive.Close className="ring-offset-background focus:ring-blue-500 data-[state=open]:bg-secondary absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none md:right-6 md:top-6">
<XMarkIcon className="h-6 w-6" /> <XMarkIcon className="h-6 w-6" />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</SheetPrimitive.Close> </SheetPrimitive.Close>
@ -92,7 +92,7 @@ const SheetTitle = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Title <SheetPrimitive.Title
ref={ref} ref={ref}
className={cn('text-lg font-semibold text-foreground', className)} className={cn('text-foreground text-lg font-semibold', className)}
{...props} {...props}
/> />
)); ));
@ -104,7 +104,7 @@ const SheetDescription = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Description <SheetPrimitive.Description
ref={ref} ref={ref}
className={cn('text-sm text-muted-foreground', className)} className={cn('text-muted-foreground text-sm', className)}
{...props} {...props}
/> />
)); ));

View File

@ -19,7 +19,6 @@ export const PAGE_REFERENCES = [
{type: 'home'}, {type: 'home'},
{type: 'page'}, {type: 'page'},
{type: 'product'}, {type: 'product'},
{type: 'productVariant'},
] ]
// Objects to include in page building arrays. // Objects to include in page building arrays.
@ -36,11 +35,6 @@ export const COMPONENT_REFERENCES = [
// https://www.sanity.io/help/studio-client-specify-api-version // https://www.sanity.io/help/studio-client-specify-api-version
export const SANITY_API_VERSION = '2022-10-25' export const SANITY_API_VERSION = '2022-10-25'
// Your Shopify store ID.
// This is your unique store URL (e.g. 'my-store-name.myshopify.com').
// Set this to enable helper links in document status banners and shortcut links on products and collections.
export const STORM_STORE_ID = ''
// Project preview URLs // Project preview URLs
export const localStorefrontUrl = 'http://localhost:3000'; export const localStorefrontUrl = 'http://localhost:3000';
export const localStorefrontPreviewUrl = 'http://localhost:3000/api/preview'; export const localStorefrontPreviewUrl = 'http://localhost:3000/api/preview';

View File

@ -59,16 +59,16 @@ export const structure: StructureResolver = (S, context) =>
home(S, context), home(S, context),
pages(S, context), pages(S, context),
S.divider(), S.divider(),
products(S, context),
categories(S, context), categories(S, context),
products(S, context),
S.divider(), S.divider(),
blurbs(S, context), blurbs(S, context),
usps(S, context),
sections(S, context), sections(S, context),
usps(S, context),
S.divider(), S.divider(),
settings(S, context),
search(S, context),
navigation(S, context), navigation(S, context),
search(S, context),
settings(S, context),
S.divider(), S.divider(),
...S.documentTypeListItems().filter(hiddenDocTypes), ...S.documentTypeListItems().filter(hiddenDocTypes),
S.divider(), S.divider(),

View File

@ -7,9 +7,9 @@ import { draftMode } from 'next/headers'
import { revalidateSecret } from './sanity.api' import { revalidateSecret } from './sanity.api'
import { categoryQuery, homePageQuery, mainMenuQuery, pageQuery, productQuery, searchPageQuery } from './queries' import { categoryQuery, footerMenusQuery, homePageQuery, mainMenuQuery, pageQuery, productQuery, searchPageQuery } from './queries'
import { CategoryPayload, HomePagePayload, MainMenuPayload, PagePayload, ProductPayload, SearchPayload } from './sanity.types' import { CategoryPayload, FooterMenusPayload, HomePagePayload, MainMenuPayload, PagePayload, ProductPayload, SearchPayload } from './sanity.types'
export const token = process.env.SANITY_API_READ_TOKEN export const token = process.env.SANITY_API_READ_TOKEN
@ -99,3 +99,11 @@ export function getMainMenu(locale: string) {
tags: ['menu'], tags: ['menu'],
}) })
} }
export function getFooterMenus(locale: string) {
return sanityFetch<FooterMenusPayload | null>({
query: footerMenusQuery,
params: { locale },
tags: ['menu'],
})
}

View File

@ -71,3 +71,9 @@ export interface MainMenuPayload {
_type?: string _type?: string
items?: MenuItem[] items?: MenuItem[]
} }
export interface FooterMenusPayload {
title?: string
_type?: string
menu?: MenuItem[]
}

View File

@ -1,7 +1,7 @@
import {CommentIcon} from '@sanity/icons' import { CommentIcon } from '@sanity/icons';
import {defineField} from 'sanity' import { defineField } from 'sanity';
import {languages} from '../../languages' import { languages } from '../../languages';
import {validateImage} from '../../utils/validation' import { validateImage } from '../../utils/validation';
export default defineField({ export default defineField({
name: 'blurb', name: 'blurb',
@ -13,7 +13,7 @@ export default defineField({
name: 'language', name: 'language',
type: 'string', type: 'string',
readOnly: true, readOnly: true,
description: 'Language of this document.', description: 'Language of this document.'
// hidden: true, // hidden: true,
}), }),
// Title // Title
@ -22,14 +22,14 @@ export default defineField({
title: 'Title', title: 'Title',
type: 'string', type: 'string',
description: 'What do you want to convey?', description: 'What do you want to convey?',
validation: (Rule) => Rule.required(), validation: (Rule) => Rule.required()
}), }),
// Image // Image
defineField({ defineField({
name: 'image', name: 'image',
title: 'Image', title: 'Image',
type: 'mainImage', type: 'mainImage',
validation: (Rule) => validateImage(Rule, true), validation: (Rule) => validateImage(Rule, true)
}), }),
// Text // Text
defineField({ defineField({
@ -37,7 +37,7 @@ export default defineField({
title: 'Text', title: 'Text',
type: 'text', type: 'text',
description: 'Small text displayed below title.', description: 'Small text displayed below title.',
rows: 5, rows: 5
}), }),
// Link // Link
{ {
@ -54,8 +54,8 @@ export default defineField({
validation: (Rule) => Rule.required(), validation: (Rule) => Rule.required(),
options: { options: {
list: ['internal', 'external'], list: ['internal', 'external'],
layout: 'radio', layout: 'radio'
}, }
}, },
{ {
name: 'internalLink', name: 'internalLink',
@ -63,18 +63,18 @@ export default defineField({
title: 'Internal link', title: 'Internal link',
hidden: ({ parent }) => parent?.linkType !== 'internal', hidden: ({ parent }) => parent?.linkType !== 'internal',
options: { options: {
collapsible: false, collapsible: false
}, },
validation: (Rule) => validation: (Rule) =>
Rule.custom((value: any, context: any) => { Rule.custom((value: any, context: any) => {
if (context.parent.linkType == 'internal') { if (context.parent.linkType == 'internal') {
const currentLink = value && value.reference const currentLink = value && value.reference;
if (!currentLink) { if (!currentLink) {
return 'Reference is required' return 'Reference is required';
} }
} }
return true return true;
}), })
}, },
{ {
name: 'externalLink', name: 'externalLink',
@ -82,41 +82,41 @@ export default defineField({
title: 'External link', title: 'External link',
hidden: ({ parent }) => parent?.linkType !== 'external', hidden: ({ parent }) => parent?.linkType !== 'external',
options: { options: {
collapsible: false, collapsible: false
}, },
validation: (Rule) => validation: (Rule) =>
Rule.custom((value: any, context: any) => { Rule.custom((value: any, context: any) => {
if (context.parent.linkType == 'external') { if (context.parent.linkType == 'external') {
const currentTitle = value?.title const currentTitle = value?.title;
const currentUrl = value?.url const currentUrl = value?.url;
if (!currentTitle) { if (!currentTitle) {
return 'Title is required' return 'Title is required';
} else if (!currentUrl) { } else if (!currentUrl) {
return 'URL is required' return 'URL is required';
} }
} }
return true return true;
}), })
}, }
], ]
}, }
], ],
preview: { preview: {
select: { select: {
title: 'title', title: 'title',
image: 'image', image: 'image',
language: 'language', language: 'language'
}, },
prepare(selection) { prepare(selection) {
const {image, title, language} = selection const { image, title, language } = selection;
const currentLang = languages.find((lang) => lang.id === language) const currentLang = languages.find((lang) => lang.id === language);
return { return {
media: image, media: image,
title, title,
subtitle: `${currentLang ? currentLang.title : ''}`, subtitle: `${currentLang ? currentLang.title : ''}`
};
} }
}, }
}, });
})

View File

@ -1,30 +0,0 @@
import {CopyIcon} from '@sanity/icons'
import {defineField, defineType} from 'sanity'
export default defineType({
name: 'productVariant',
title: 'Product variant',
type: 'document',
icon: CopyIcon,
fields: [
// Title
defineField({
title: 'Title',
name: 'title',
type: 'string',
description: 'Product variant title/name.'
}),
],
preview: {
select: {
title: 'title',
},
prepare(selection) {
const {title} = selection
return {
title,
}
},
},
})

View File

@ -17,7 +17,6 @@ import category from './documents/category'
import footerMenu from './documents/footerMenu' import footerMenu from './documents/footerMenu'
import page from './documents/page' import page from './documents/page'
import product from './documents/product' import product from './documents/product'
import productVariant from './documents/productVariant'
import section from './documents/section' import section from './documents/section'
import usp from './documents/usp' import usp from './documents/usp'
@ -25,7 +24,6 @@ const documents = [
category, category,
page, page,
product, product,
productVariant,
blurb, blurb,
section, section,
usp, usp,

View File

@ -2,7 +2,7 @@
import { isDev, SanityDocument } from 'sanity' import { isDev, SanityDocument } from 'sanity'
import { localStorefrontPreviewUrl, publicStorefrontPreviewUrl } from '../constants' import { localStorefrontPreviewUrl, publicStorefrontPreviewUrl } from '../constants'
const SANITY_STUDIO_API_READ_TOKEN = "skYG2HXNga8uxSL7rFIreJEnP0SdVjCZ2nzB8rUHD4wRWxXPGceXTuR5vCVBP99mWZ9ULhghmpUyX7EtzDmJusSk6Gwvdr3nLAsdWI9ZktIWvSWUNpHbu0Xfrrt0UUaktrLglk7ToABvjXlaPHLpOIR3dnjl4MGByutPmyra0b5t20kgDrmF" const SANITY_STUDIO_API_READ_TOKEN = "preview.skYG2HXNga8uxSL7rFIreJEnP0SdVjCZ2nzB8rUHD4wRWxXPGceXTuR5vCVBP99mWZ9ULhghmpUyX7EtzDmJusSk6Gwvdr3nLAsdWI9ZktIWvSWUNpHbu0Xfrrt0UUaktrLglk7ToABvjXlaPHLpOIR3dnjl4MGByutPmyra0b5t20kgDrmF"
// Customise this function to show the correct URL based on the current document // Customise this function to show the correct URL based on the current document
export default async function getPreviewUrl(doc: SanityDocument) { export default async function getPreviewUrl(doc: SanityDocument) {

View File

@ -23,47 +23,47 @@
"@portabletext/react": "^3.0.4", "@portabletext/react": "^3.0.4",
"@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.4", "@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-navigation-menu": "^1.1.2", "@radix-ui/react-navigation-menu": "^1.1.3",
"@sanity/client": "^6.4.4", "@sanity/client": "^6.4.4",
"@sanity/document-internationalization": "^2.0.1", "@sanity/document-internationalization": "^2.0.1",
"@sanity/icons": "^2.4.1", "@sanity/icons": "^2.4.1",
"@sanity/image-url": "^1.0.2", "@sanity/image-url": "^1.0.2",
"@sanity/preview-kit": "^2.4.9", "@sanity/preview-kit": "^2.4.9",
"@sanity/types": "^3.11.1", "@sanity/types": "^3.15.0",
"@sanity/ui": "^1.3.3", "@sanity/ui": "^1.7.4",
"@sanity/vision": "^3.0.0", "@sanity/vision": "^3.0.0",
"@sanity/webhook": "^2.0.0", "@sanity/webhook": "^2.0.0",
"@types/styled-components": "^5.1.26", "@types/styled-components": "^5.1.26",
"@vercel/analytics": "^1.0.2", "@vercel/analytics": "^1.0.2",
"@vercel/og": "^0.1.0", "@vercel/og": "^0.1.0",
"algoliasearch": "^4.19.1", "algoliasearch": "^4.19.1",
"class-variance-authority": "^0.6.0", "class-variance-authority": "^0.6.1",
"clsx": "^1.2.1", "clsx": "^1.2.1",
"framer-motion": "^8.5.5", "framer-motion": "^8.5.5",
"is-empty-iterable": "^3.0.0", "is-empty-iterable": "^3.0.0",
"next": "13.4.19", "next": "13.4.19",
"next-intl": "2.19.1", "next-intl": "2.19.1",
"next-sanity": "^5.4.2", "next-sanity": "^5.4.6",
"react": "18.2.0", "react": "18.2.0",
"react-cookie": "^4.1.1", "react-cookie": "^4.1.1",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-glider": "^4.0.2", "react-glider": "^4.0.2",
"react-instantsearch": "^7.0.1", "react-instantsearch": "^7.0.1",
"sanity": "^3.11.1", "sanity": "^3.15.0",
"sanity-plugin-iframe-pane": "^2.3.0", "sanity-plugin-iframe-pane": "^2.5.5",
"sanity-plugin-media": "^2.0.4", "sanity-plugin-media": "^2.0.4",
"sharp": "^0.32.1", "sharp": "^0.32.4",
"slug": "^8.2.2", "slug": "^8.2.2",
"slugify": "^1.6.5", "slugify": "^1.6.5",
"styled-components": "^5.3.10", "styled-components": "^5.3.11",
"suspend-react": "^0.1.3", "suspend-react": "^0.1.3",
"tailwind-merge": "^1.12.0", "tailwind-merge": "^1.14.0",
"tailwindcss-animate": "^1.0.5" "tailwindcss-animate": "^1.0.6"
}, },
"devDependencies": { "devDependencies": {
"@next/bundle-analyzer": "^13.4.13", "@next/bundle-analyzer": "^13.4.13",
"@playwright/test": "^1.34.1", "@playwright/test": "^1.36.2",
"@tailwindcss/typography": "^0.5.9", "@tailwindcss/typography": "^0.5.9",
"@types/negotiator": "^0.6.1", "@types/negotiator": "^0.6.1",
"@types/node": "18.13.0", "@types/node": "18.13.0",
@ -73,15 +73,15 @@
"@vercel/git-hooks": "^1.0.0", "@vercel/git-hooks": "^1.0.0",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^8.41.0", "eslint": "^8.46.0",
"eslint-config-next": "^13.4.3", "eslint-config-next": "^13.4.13",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.10.0",
"eslint-plugin-unicorn": "^45.0.2", "eslint-plugin-unicorn": "^45.0.2",
"lint-staged": "^13.2.2", "lint-staged": "^13.2.3",
"postcss": "^8.4.23", "postcss": "^8.4.27",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.2.8", "prettier-plugin-tailwindcss": "^0.2.8",
"tailwindcss": "^3.3.2", "tailwindcss": "^3.3.3",
"typescript": "^5.1.3" "typescript": "^5.1.6"
} }
} }

99
plugins/settings.tsx Normal file
View File

@ -0,0 +1,99 @@
// @ts-nocheck
/**
* This plugin contains all the logic for setting up the singletons
*/
import { type DocumentDefinition } from 'sanity';
import { Iframe } from 'sanity-plugin-iframe-pane';
import { ListItemBuilder, type StructureResolver } from 'sanity/desk';
import { iframeOptions, PREVIEWABLE_DOCUMENT_TYPES } from '../sanity.config';
const hiddenDocTypes = (listItem: ListItemBuilder) => {
const id = listItem.getId();
if (!id) {
return false;
}
return ![
// 'category',
// 'home',
'media.tag',
// 'page',
// 'product',
// 'settings',
// 'blurb',
// 'section',
// 'usp',
'navigation',
'footerMenu',
'utilityMenu'
].includes(id);
};
export const singletonPlugin = (types: string[]) => {
return {
name: 'singletonPlugin',
document: {
// Hide 'Singletons (such as Home)' from new document options
// https://user-images.githubusercontent.com/81981/195728798-e0c6cf7e-d442-4e58-af3a-8cd99d7fcc28.png
newDocumentOptions: (prev, { creationContext }) => {
if (creationContext.type === 'global') {
return prev.filter((templateItem) => !types.includes(templateItem.templateId));
}
return prev;
},
// Removes the "duplicate" action on the Singletons (such as Home)
actions: (prev, { schemaType }) => {
if (types.includes(schemaType)) {
return prev.filter(({ action }) => action !== 'duplicate');
}
return prev;
}
}
};
};
// The StructureResolver is how we're changing the DeskTool structure to linking to document (named Singleton)
// like how "Home" is handled.
export const pageStructure = (typeDefArray: DocumentDefinition[]): StructureResolver => {
return (S) => {
// Goes through all of the singletons that were provided and translates them into something the
// Desktool can understand
const singletonItems = typeDefArray.map((typeDef) => {
return S.listItem()
.title(typeDef.title!)
.icon(typeDef.icon)
.child(
S.documentList()
.title(`${typeDef.name.charAt(0).toUpperCase() + typeDef.name.slice(1)} pages`)
.filter(`_type == "${typeDef.name}"`)
.child((id) =>
S.document()
.schemaType(typeDef.name)
.id(id)
.views([
S.view.form().icon('f'),
// Preview
...(PREVIEWABLE_DOCUMENT_TYPES.includes(typeDef.name as any)
? [S.view.component(Iframe).options(iframeOptions).title('Preview')]
: [])
])
)
);
});
// The default root list items (except custom ones)
const defaultListItems = S.documentTypeListItems()
.filter((listItem) => !typeDefArray.find((singleton) => singleton.name === listItem.getId()))
.filter(hiddenDocTypes);
return S.list()
.title('Content')
.items([...singletonItems, S.divider(), ...defaultListItems]);
};
};

164
pnpm-lock.yaml generated
View File

@ -18,10 +18,10 @@ dependencies:
specifier: ^1.0.4 specifier: ^1.0.4
version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0) version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-dropdown-menu': '@radix-ui/react-dropdown-menu':
specifier: ^2.0.4 specifier: ^2.0.5
version: 2.0.5(@types/react-dom@18.2.7)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0) version: 2.0.5(@types/react-dom@18.2.7)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-navigation-menu': '@radix-ui/react-navigation-menu':
specifier: ^1.1.2 specifier: ^1.1.3
version: 1.1.3(@types/react-dom@18.2.7)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0) version: 1.1.3(@types/react-dom@18.2.7)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0)
'@sanity/client': '@sanity/client':
specifier: ^6.4.4 specifier: ^6.4.4
@ -39,14 +39,14 @@ dependencies:
specifier: ^2.4.9 specifier: ^2.4.9
version: 2.4.9(@sanity/client@6.4.4)(react@18.2.0) version: 2.4.9(@sanity/client@6.4.4)(react@18.2.0)
'@sanity/types': '@sanity/types':
specifier: ^3.11.1 specifier: ^3.15.0
version: 3.15.0 version: 3.15.0
'@sanity/ui': '@sanity/ui':
specifier: ^1.3.3 specifier: ^1.7.4
version: 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11) version: 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11)
'@sanity/vision': '@sanity/vision':
specifier: ^3.0.0 specifier: ^3.0.0
version: 3.0.0(@babel/runtime@7.22.10)(@codemirror/lint@6.4.0)(@codemirror/state@6.2.1)(@codemirror/theme-one-dark@6.1.2)(@lezer/common@1.0.3)(@sanity/client@6.4.4)(codemirror@6.0.1)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(rxjs@7.8.1)(styled-components@5.3.11) version: 3.0.0(@babel/runtime@7.22.10)(@codemirror/lint@6.4.0)(@codemirror/state@6.2.1)(@codemirror/theme-one-dark@6.1.2)(@lezer/common@1.0.4)(@sanity/client@6.4.4)(codemirror@6.0.1)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(rxjs@7.8.1)(styled-components@5.3.11)
'@sanity/webhook': '@sanity/webhook':
specifier: ^2.0.0 specifier: ^2.0.0
version: 2.0.0 version: 2.0.0
@ -63,7 +63,7 @@ dependencies:
specifier: ^4.19.1 specifier: ^4.19.1
version: 4.19.1 version: 4.19.1
class-variance-authority: class-variance-authority:
specifier: ^0.6.0 specifier: ^0.6.1
version: 0.6.1 version: 0.6.1
clsx: clsx:
specifier: ^1.2.1 specifier: ^1.2.1
@ -81,8 +81,8 @@ dependencies:
specifier: 2.19.1 specifier: 2.19.1
version: 2.19.1(next@13.4.19)(react@18.2.0) version: 2.19.1(next@13.4.19)(react@18.2.0)
next-sanity: next-sanity:
specifier: ^5.4.2 specifier: ^5.4.6
version: 5.4.2(@sanity/client@6.4.4)(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(@types/styled-components@5.1.26)(next@13.4.19)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11) version: 5.4.6(@sanity/client@6.4.4)(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(next@13.4.19)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11)
react: react:
specifier: 18.2.0 specifier: 18.2.0
version: 18.2.0 version: 18.2.0
@ -99,16 +99,16 @@ dependencies:
specifier: ^7.0.1 specifier: ^7.0.1
version: 7.0.1(algoliasearch@4.19.1)(react-dom@18.2.0)(react@18.2.0) version: 7.0.1(algoliasearch@4.19.1)(react-dom@18.2.0)(react@18.2.0)
sanity: sanity:
specifier: ^3.11.1 specifier: ^3.15.0
version: 3.15.0(@types/node@18.13.0)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0)(styled-components@5.3.11) version: 3.15.0(@types/node@18.13.0)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0)(styled-components@5.3.11)
sanity-plugin-iframe-pane: sanity-plugin-iframe-pane:
specifier: ^2.3.0 specifier: ^2.5.5
version: 2.3.0(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11) version: 2.5.5(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11)
sanity-plugin-media: sanity-plugin-media:
specifier: ^2.0.4 specifier: ^2.0.4
version: 2.0.4(@sanity/color@2.2.5)(@sanity/icons@2.4.1)(@types/react@18.2.19)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11) version: 2.0.4(@sanity/color@2.2.5)(@sanity/icons@2.4.1)(@types/react@18.2.19)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11)
sharp: sharp:
specifier: ^0.32.1 specifier: ^0.32.4
version: 0.32.4 version: 0.32.4
slug: slug:
specifier: ^8.2.2 specifier: ^8.2.2
@ -117,16 +117,16 @@ dependencies:
specifier: ^1.6.5 specifier: ^1.6.5
version: 1.6.5 version: 1.6.5
styled-components: styled-components:
specifier: ^5.3.10 specifier: ^5.3.11
version: 5.3.11(@babel/core@7.22.10)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0) version: 5.3.11(@babel/core@7.22.10)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)
suspend-react: suspend-react:
specifier: ^0.1.3 specifier: ^0.1.3
version: 0.1.3(react@18.2.0) version: 0.1.3(react@18.2.0)
tailwind-merge: tailwind-merge:
specifier: ^1.12.0 specifier: ^1.14.0
version: 1.14.0 version: 1.14.0
tailwindcss-animate: tailwindcss-animate:
specifier: ^1.0.5 specifier: ^1.0.6
version: 1.0.6(tailwindcss@3.3.3) version: 1.0.6(tailwindcss@3.3.3)
devDependencies: devDependencies:
@ -134,7 +134,7 @@ devDependencies:
specifier: ^13.4.13 specifier: ^13.4.13
version: 13.4.13 version: 13.4.13
'@playwright/test': '@playwright/test':
specifier: ^1.34.1 specifier: ^1.36.2
version: 1.36.2 version: 1.36.2
'@tailwindcss/typography': '@tailwindcss/typography':
specifier: ^0.5.9 specifier: ^0.5.9
@ -164,22 +164,22 @@ devDependencies:
specifier: ^7.0.3 specifier: ^7.0.3
version: 7.0.3 version: 7.0.3
eslint: eslint:
specifier: ^8.41.0 specifier: ^8.46.0
version: 8.46.0 version: 8.46.0
eslint-config-next: eslint-config-next:
specifier: ^13.4.3 specifier: ^13.4.13
version: 13.4.13(eslint@8.46.0)(typescript@5.1.6) version: 13.4.13(eslint@8.46.0)(typescript@5.1.6)
eslint-config-prettier: eslint-config-prettier:
specifier: ^8.8.0 specifier: ^8.10.0
version: 8.10.0(eslint@8.46.0) version: 8.10.0(eslint@8.46.0)
eslint-plugin-unicorn: eslint-plugin-unicorn:
specifier: ^45.0.2 specifier: ^45.0.2
version: 45.0.2(eslint@8.46.0) version: 45.0.2(eslint@8.46.0)
lint-staged: lint-staged:
specifier: ^13.2.2 specifier: ^13.2.3
version: 13.2.3 version: 13.2.3
postcss: postcss:
specifier: ^8.4.23 specifier: ^8.4.27
version: 8.4.27 version: 8.4.27
prettier: prettier:
specifier: ^2.8.8 specifier: ^2.8.8
@ -188,10 +188,10 @@ devDependencies:
specifier: ^0.2.8 specifier: ^0.2.8
version: 0.2.8(prettier@2.8.8) version: 0.2.8(prettier@2.8.8)
tailwindcss: tailwindcss:
specifier: ^3.3.2 specifier: ^3.3.3
version: 3.3.3 version: 3.3.3
typescript: typescript:
specifier: ^5.1.3 specifier: ^5.1.6
version: 5.1.6 version: 5.1.6
packages: packages:
@ -568,6 +568,20 @@ packages:
'@lezer/common': 1.0.3 '@lezer/common': 1.0.3
dev: false dev: false
/@codemirror/autocomplete@6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4):
resolution: {integrity: sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==}
peerDependencies:
'@codemirror/language': ^6.0.0
'@codemirror/state': ^6.0.0
'@codemirror/view': ^6.0.0
'@lezer/common': ^1.0.0
dependencies:
'@codemirror/language': 6.9.0
'@codemirror/state': 6.2.1
'@codemirror/view': 6.16.0
'@lezer/common': 1.0.4
dev: false
/@codemirror/commands@6.2.4: /@codemirror/commands@6.2.4:
resolution: {integrity: sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==} resolution: {integrity: sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==}
dependencies: dependencies:
@ -600,6 +614,17 @@ packages:
style-mod: 4.0.3 style-mod: 4.0.3
dev: false dev: false
/@codemirror/language@6.9.0:
resolution: {integrity: sha512-nFu311/0ne/qGuGCL3oKuktBgzVOaxCHZPZv1tLSZkNjPYxxvkjSbzno3MlErG2tgw1Yw1yF8BxMCegeMXqpiw==}
dependencies:
'@codemirror/state': 6.2.1
'@codemirror/view': 6.16.0
'@lezer/common': 1.0.4
'@lezer/highlight': 1.1.6
'@lezer/lr': 1.3.10
style-mod: 4.1.0
dev: false
/@codemirror/lint@6.4.0: /@codemirror/lint@6.4.0:
resolution: {integrity: sha512-6VZ44Ysh/Zn07xrGkdtNfmHCbGSHZzFBdzWi0pbd7chAQ/iUcpLGX99NYRZTa7Ugqg4kEHCqiHhcZnH0gLIgSg==} resolution: {integrity: sha512-6VZ44Ysh/Zn07xrGkdtNfmHCbGSHZzFBdzWi0pbd7chAQ/iUcpLGX99NYRZTa7Ugqg4kEHCqiHhcZnH0gLIgSg==}
dependencies: dependencies:
@ -623,7 +648,7 @@ packages:
/@codemirror/theme-one-dark@6.1.2: /@codemirror/theme-one-dark@6.1.2:
resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==} resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
dependencies: dependencies:
'@codemirror/language': 6.8.0 '@codemirror/language': 6.9.0
'@codemirror/state': 6.2.1 '@codemirror/state': 6.2.1
'@codemirror/view': 6.16.0 '@codemirror/view': 6.16.0
'@lezer/highlight': 1.1.6 '@lezer/highlight': 1.1.6
@ -1209,6 +1234,10 @@ packages:
resolution: {integrity: sha512-JH4wAXCgUOcCGNekQPLhVeUtIqjH0yPBs7vvUdSjyQama9618IOKFJwkv2kcqdhF0my8hQEgCTEJU0GIgnahvA==} resolution: {integrity: sha512-JH4wAXCgUOcCGNekQPLhVeUtIqjH0yPBs7vvUdSjyQama9618IOKFJwkv2kcqdhF0my8hQEgCTEJU0GIgnahvA==}
dev: false dev: false
/@lezer/common@1.0.4:
resolution: {integrity: sha512-lZHlk8p67x4aIDtJl6UQrXSOP6oi7dQR3W/geFVrENdA1JDaAJWldnVqVjPMJupbTKbzDfFcePfKttqVidS/dg==}
dev: false
/@lezer/highlight@1.1.6: /@lezer/highlight@1.1.6:
resolution: {integrity: sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==} resolution: {integrity: sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==}
dependencies: dependencies:
@ -1222,6 +1251,12 @@ packages:
'@lezer/lr': 1.3.9 '@lezer/lr': 1.3.9
dev: false dev: false
/@lezer/lr@1.3.10:
resolution: {integrity: sha512-BZfVvf7Re5BIwJHlZXbJn9L8lus5EonxQghyn+ih8Wl36XMFBPTXC0KM0IdUtj9w/diPHsKlXVgL+AlX2jYJ0Q==}
dependencies:
'@lezer/common': 1.0.4
dev: false
/@lezer/lr@1.3.9: /@lezer/lr@1.3.9:
resolution: {integrity: sha512-XPz6dzuTHlnsbA5M2DZgjflNQ+9Hi5Swhic0RULdp3oOs3rh6bqGZolosVqN/fQIT8uNiepzINJDnS39oweTHQ==} resolution: {integrity: sha512-XPz6dzuTHlnsbA5M2DZgjflNQ+9Hi5Swhic0RULdp3oOs3rh6bqGZolosVqN/fQIT8uNiepzINJDnS39oweTHQ==}
dependencies: dependencies:
@ -2241,15 +2276,15 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@sanity/groq-store@4.0.4: /@sanity/groq-store@4.1.1:
resolution: {integrity: sha512-Bk1ZsS6PGeCtmP8a4FJfvHws1WlnQUPdcr9MbO38Fbbtp55ZdLjTbxozxo//mK7jsbmNxf2HjpQ1mm5jDI49RQ==} resolution: {integrity: sha512-SZg6i5Vb/fncUk5le42ijwkPeOm8WRkPoofM5d+BBqcAAuHctD1qZV0TMyZkw+HFNXbjzhW76rrytTgzsP+ZaQ==}
engines: {node: '>=14.18'} engines: {node: '>=14.18'}
dependencies: dependencies:
'@sanity/eventsource': 5.0.0 '@sanity/eventsource': 5.0.0
'@sanity/types': 3.15.0 '@sanity/types': 3.15.0
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
groq: 3.15.0 groq: 3.15.0
groq-js: 1.1.12 groq-js: 1.2.0
mendoza: 3.0.3 mendoza: 3.0.3
simple-get: 4.0.1 simple-get: 4.0.1
split2: 4.2.0 split2: 4.2.0
@ -2412,11 +2447,11 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@sanity/preview-kit@3.1.3(@sanity/client@6.4.4)(react@18.2.0): /@sanity/preview-kit@3.1.6(@sanity/client@6.4.4)(react@18.2.0):
resolution: {integrity: sha512-v8zqm4uxE42RXmYySrULfscvdIFPjLwIrBbhRb+qumZNdGkTZph3y0Zo9rdW9MnOEYwew0pz6BUq+n7y/NoRwA==} resolution: {integrity: sha512-V8gZlIcyqqMr1WDAzrNXntrgYVeR56EKEZHbXOoHIr3qjgCRXPogVJ5w09DJ6cMhv2NKClOpAqmA9MWzt81wXw==}
engines: {node: '>=14'} engines: {node: '>=14'}
peerDependencies: peerDependencies:
'@sanity/client': ^6.4.8 '@sanity/client': ^6.4.9
react: ^18.0.0 react: ^18.0.0
peerDependenciesMeta: peerDependenciesMeta:
react: react:
@ -2424,7 +2459,7 @@ packages:
dependencies: dependencies:
'@sanity/client': 6.4.4 '@sanity/client': 6.4.4
'@sanity/eventsource': 5.0.0 '@sanity/eventsource': 5.0.0
'@sanity/groq-store': 4.0.4 '@sanity/groq-store': 4.1.1
'@vercel/stega': 0.1.0 '@vercel/stega': 0.1.0
lodash.get: 4.4.2 lodash.get: 4.4.2
lodash.isplainobject: 4.0.6 lodash.isplainobject: 4.0.6
@ -2519,7 +2554,7 @@ packages:
uuid: 8.3.2 uuid: 8.3.2
dev: false dev: false
/@sanity/vision@3.0.0(@babel/runtime@7.22.10)(@codemirror/lint@6.4.0)(@codemirror/state@6.2.1)(@codemirror/theme-one-dark@6.1.2)(@lezer/common@1.0.3)(@sanity/client@6.4.4)(codemirror@6.0.1)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(rxjs@7.8.1)(styled-components@5.3.11): /@sanity/vision@3.0.0(@babel/runtime@7.22.10)(@codemirror/lint@6.4.0)(@codemirror/state@6.2.1)(@codemirror/theme-one-dark@6.1.2)(@lezer/common@1.0.4)(@sanity/client@6.4.4)(codemirror@6.0.1)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(rxjs@7.8.1)(styled-components@5.3.11):
resolution: {integrity: sha512-Dr18Iugz2xHEavag4asOzYBIjwnj+5SEB7DlbyNow0mQ5fQWYh8eRES2OBDvrOLbBJ5rVuZMIzrcokQ+nzmrBw==} resolution: {integrity: sha512-Dr18Iugz2xHEavag4asOzYBIjwnj+5SEB7DlbyNow0mQ5fQWYh8eRES2OBDvrOLbBJ5rVuZMIzrcokQ+nzmrBw==}
peerDependencies: peerDependencies:
'@sanity/client': ^3.4.1 '@sanity/client': ^3.4.1
@ -2527,7 +2562,7 @@ packages:
rxjs: ^6.5.3 rxjs: ^6.5.3
styled-components: ^5.2 styled-components: ^5.2
dependencies: dependencies:
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.8.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.3) '@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
'@codemirror/commands': 6.2.4 '@codemirror/commands': 6.2.4
'@codemirror/lang-javascript': 6.1.9 '@codemirror/lang-javascript': 6.1.9
'@codemirror/language': 6.8.0 '@codemirror/language': 6.8.0
@ -2568,6 +2603,13 @@ packages:
tslib: 2.6.1 tslib: 2.6.1
dev: false dev: false
/@sanity/webhook@3.0.1:
resolution: {integrity: sha512-2eTDg/+TR8lSX2OH6wH7M8UUwZUsD/i8Raw9mFH9myt2mkPY3ns77cU6K1QL2ZhwIIDJT5tttTELURF7RjlzVg==}
engines: {node: '>=12.0.0'}
dependencies:
base64url: 3.0.1
dev: false
/@shuding/opentype.js@1.4.0-beta.0: /@shuding/opentype.js@1.4.0-beta.0:
resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==} resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==}
engines: {node: '>= 8.0.0'} engines: {node: '>= 8.0.0'}
@ -2858,7 +2900,7 @@ packages:
'@codemirror/state': '>=6.0.0' '@codemirror/state': '>=6.0.0'
'@codemirror/view': '>=6.0.0' '@codemirror/view': '>=6.0.0'
dependencies: dependencies:
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.8.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.3) '@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
'@codemirror/commands': 6.2.4 '@codemirror/commands': 6.2.4
'@codemirror/language': 6.8.0 '@codemirror/language': 6.8.0
'@codemirror/lint': 6.4.0 '@codemirror/lint': 6.4.0
@ -2884,7 +2926,7 @@ packages:
'@codemirror/theme-one-dark': 6.1.2 '@codemirror/theme-one-dark': 6.1.2
'@codemirror/view': 6.16.0 '@codemirror/view': 6.16.0
'@uiw/codemirror-extensions-basic-setup': 4.21.9(@codemirror/autocomplete@6.9.0)(@codemirror/commands@6.2.4)(@codemirror/language@6.8.0)(@codemirror/lint@6.4.0)(@codemirror/search@6.5.1)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0) '@uiw/codemirror-extensions-basic-setup': 4.21.9(@codemirror/autocomplete@6.9.0)(@codemirror/commands@6.2.4)(@codemirror/language@6.8.0)(@codemirror/lint@6.4.0)(@codemirror/search@6.5.1)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)
codemirror: 6.0.1(@lezer/common@1.0.3) codemirror: 6.0.1(@lezer/common@1.0.4)
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
@ -3491,7 +3533,7 @@ packages:
normalize-path: 3.0.0 normalize-path: 3.0.0
readdirp: 3.6.0 readdirp: 3.6.0
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.3
/chownr@1.1.4: /chownr@1.1.4:
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
@ -3565,12 +3607,12 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: false dev: false
/codemirror@6.0.1(@lezer/common@1.0.3): /codemirror@6.0.1(@lezer/common@1.0.4):
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
dependencies: dependencies:
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.8.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.3) '@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
'@codemirror/commands': 6.2.4 '@codemirror/commands': 6.2.4
'@codemirror/language': 6.8.0 '@codemirror/language': 6.9.0
'@codemirror/lint': 6.4.0 '@codemirror/lint': 6.4.0
'@codemirror/search': 6.5.1 '@codemirror/search': 6.5.1
'@codemirror/state': 6.2.1 '@codemirror/state': 6.2.1
@ -4811,6 +4853,14 @@ packages:
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: true
optional: true
/fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
requiresBuild: true
optional: true optional: true
/ftp@0.3.10: /ftp@0.3.10:
@ -5083,8 +5133,8 @@ packages:
engines: {node: '>= 14'} engines: {node: '>= 14'}
dev: false dev: false
/groq-js@1.1.12: /groq-js@1.2.0:
resolution: {integrity: sha512-02KhsoLuTwr/MOf6bBzt+rQOj+QuLoZ5IDDkzXM2NWY73CF1d29KTRBffzCAjsjBvY7kn+oQcwPdQVb3vBkl9w==} resolution: {integrity: sha512-XW4PXKqf4LMsRGGz2MmBRcxDg8NJD0qTJxvd7YOdb6/IH1RQcqL/QK2o76Uxd0A3CiwMlJLUoPrL9KGUDWT39A==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
dev: false dev: false
@ -6104,27 +6154,25 @@ packages:
use-intl: 2.19.1(react@18.2.0) use-intl: 2.19.1(react@18.2.0)
dev: false dev: false
/next-sanity@5.4.2(@sanity/client@6.4.4)(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(@types/styled-components@5.1.26)(next@13.4.19)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11): /next-sanity@5.4.6(@sanity/client@6.4.4)(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(next@13.4.19)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11):
resolution: {integrity: sha512-gLpS0GlapXtDjRUaPcZ9DUeiNSznhtqh0kyxygQS9MDtecCiphVAhXYwvJMQcxfY1u5KVWAxZMyy+Bs6h8G+jA==} resolution: {integrity: sha512-VgbLxYfgzLETNXKuvShhtaYKlz7DDb5QlFvvjf0eF82lIevI1c0jGHgPRhOTRuv0csvy9FVFCyMlxoc+BkAVmQ==}
engines: {node: '>=16.14'} engines: {node: '>=16.14'}
peerDependencies: peerDependencies:
'@sanity/client': ^6.4.8 '@sanity/client': ^6.4.9
'@sanity/icons': ^2.0.0 '@sanity/icons': ^2.0.0
'@sanity/types': ^3.0.0 '@sanity/types': ^3.0.0
'@sanity/ui': ^1.0.0 '@sanity/ui': ^1.0.0
'@types/styled-components': ^5.1.0
next: ^13.0.0 next: ^13.0.0
react: ^18.0.0 react: ^18.0.0
sanity: ^3.0.0 sanity: ^3.0.0
styled-components: ^5.2.0 styled-components: ^5.2.0 || ^6.0.0
dependencies: dependencies:
'@sanity/client': 6.4.4 '@sanity/client': 6.4.4
'@sanity/icons': 2.4.1(react@18.2.0) '@sanity/icons': 2.4.1(react@18.2.0)
'@sanity/preview-kit': 3.1.3(@sanity/client@6.4.4)(react@18.2.0) '@sanity/preview-kit': 3.1.6(@sanity/client@6.4.4)(react@18.2.0)
'@sanity/types': 3.15.0 '@sanity/types': 3.15.0
'@sanity/ui': 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11) '@sanity/ui': 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11)
'@sanity/webhook': 2.0.0 '@sanity/webhook': 3.0.1
'@types/styled-components': 5.1.26
groq: 3.15.0 groq: 3.15.0
next: 13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) next: 13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0 react: 18.2.0
@ -7363,7 +7411,7 @@ packages:
engines: {node: '>=14.18.0', npm: '>=8.0.0'} engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.3
dev: false dev: false
/run-applescript@5.0.0: /run-applescript@5.0.0:
@ -7443,23 +7491,25 @@ packages:
diff-match-patch: 1.0.5 diff-match-patch: 1.0.5
dev: false dev: false
/sanity-plugin-iframe-pane@2.3.0(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11): /sanity-plugin-iframe-pane@2.5.5(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11):
resolution: {integrity: sha512-bTq1Fnj1AQv5FXOE/88z41tSlJkfd7Ra/+19CvFOkOdopr7nnCWtztaG+phlqm8cndIs+CMnSxaBByLf/RGcPQ==} resolution: {integrity: sha512-GoOjYXw7KKmPwA5+dy3ebR27cN/v6DGPtBxx2eaiBvJdVBHQ74JiCs97Kx9y0cAPFBtmTQ+bg0JkKPtxJLl9cw==}
engines: {node: '>=14'} engines: {node: '>=14'}
peerDependencies: peerDependencies:
react: ^18 react: ^18
sanity: ^3.0.0 sanity: ^3
styled-components: ^5.2
dependencies: dependencies:
'@sanity/icons': 2.4.1(react@18.2.0) '@sanity/icons': 2.4.1(react@18.2.0)
'@sanity/incompatible-plugin': 1.0.4(react-dom@18.2.0)(react@18.2.0) '@sanity/incompatible-plugin': 1.0.4(react-dom@18.2.0)(react@18.2.0)
'@sanity/ui': 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11) '@sanity/ui': 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11)
framer-motion: 10.15.1(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0 react: 18.2.0
sanity: 3.15.0(@types/node@18.13.0)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0)(styled-components@5.3.11) sanity: 3.15.0(@types/node@18.13.0)(@types/react@18.2.19)(react-dom@18.2.0)(react@18.2.0)(styled-components@5.3.11)
styled-components: 5.3.11(@babel/core@7.22.10)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)
usehooks-ts: 2.9.1(react-dom@18.2.0)(react@18.2.0) usehooks-ts: 2.9.1(react-dom@18.2.0)(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- react-dom - react-dom
- react-is - react-is
- styled-components
dev: false dev: false
/sanity-plugin-internationalized-array@1.10.1(@sanity/ui@1.7.4)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11): /sanity-plugin-internationalized-array@1.10.1(@sanity/ui@1.7.4)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11):
@ -8088,6 +8138,10 @@ packages:
resolution: {integrity: sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==} resolution: {integrity: sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==}
dev: false dev: false
/style-mod@4.1.0:
resolution: {integrity: sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==}
dev: false
/styled-components@5.3.11(@babel/core@7.22.10)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0): /styled-components@5.3.11(@babel/core@7.22.10)(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -8689,7 +8743,7 @@ packages:
postcss: 8.4.27 postcss: 8.4.27
rollup: 3.28.0 rollup: 3.28.0
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.3
dev: false dev: false
/w3c-keyname@2.2.8: /w3c-keyname@2.2.8:

View File

@ -1,13 +1,60 @@
import Kodamera from '@/lib/sanity/components/icons/kodamera' import Kodamera from '@/lib/sanity/components/icons/kodamera'
import { structure } from '@/lib/sanity/desk'
import { schemaTypes } from '@/lib/sanity/schemas' import { schemaTypes } from '@/lib/sanity/schemas'
import { documentInternationalization } from '@sanity/document-internationalization' import { documentInternationalization } from '@sanity/document-internationalization'
import { visionTool } from '@sanity/vision' import { visionTool } from '@sanity/vision'
import { defineConfig, isDev } from 'sanity' import { defineConfig } from 'sanity'
import { Iframe, IframeOptions } from 'sanity-plugin-iframe-pane'
import { previewUrl } from 'sanity-plugin-iframe-pane/preview-url'
import { media } from 'sanity-plugin-media' import { media } from 'sanity-plugin-media'
import { deskTool } from 'sanity/desk' import { deskTool } from 'sanity/desk'
import { apiVersion, dataset, previewSecretId, projectId } from './lib/sanity/sanity.api'
import category from './lib/sanity/schemas/documents/category'
import page from './lib/sanity/schemas/documents/page'
import product from './lib/sanity/schemas/documents/product'
import home from './lib/sanity/schemas/singletons/home'
import search from './lib/sanity/schemas/singletons/search'
import { pageStructure, singletonPlugin } from './plugins/settings'
const devOnlyPlugins = [visionTool()] const devOnlyPlugins = [visionTool({ defaultApiVersion: apiVersion})]
export const PREVIEWABLE_DOCUMENT_TYPES = [
home.name,
page.name,
category.name,
product.name,
search.name
] satisfies string[]
// Used to generate URLs for drafts and live previews
export const PREVIEW_BASE_URL = '/api/preview'
// export const urlResolver = defineUrlResolver({
// base: PREVIEW_BASE_URL,
// })
// import {MissingSlug, type UrlResolver} from 'sanity-plugin-iframe-pane'
export const urlResolver = (document: any, urlSecret: any) => {
const url = new URL(PREVIEW_BASE_URL, location.origin)
url.searchParams.set('type', document._type)
const lang = document?.language
url.searchParams.set('locale', lang)
const slug = (document?.slug as any)?.current
if (slug) {
url.searchParams.set('slug', slug)
}
if (urlSecret) {
url.searchParams.set('secret', urlSecret)
}
return url.toString()
}
export const iframeOptions = {
url: urlResolver,
urlSecretId: previewSecretId,
} satisfies IframeOptions
// Define the actions that should be available for singleton documents // Define the actions that should be available for singleton documents
const singletonActions = new Set(["publish", "discardChanges", "restore"]) const singletonActions = new Set(["publish", "discardChanges", "restore"])
@ -20,13 +67,42 @@ const singletonTypes = new Set(["settings", "home", "utilityMenu", "media.tag",
export default defineConfig({ export default defineConfig({
name: 'default', name: 'default',
title: 'KM Storefront CMS', title: 'KM Storefront CMS',
projectId: 'opfmivlh', projectId: projectId,
basePath: '/studio', basePath: '/studio',
dataset: 'production', dataset: dataset,
plugins: [ plugins: [
deskTool({structure}), // deskTool({structure}),
deskTool({
structure: pageStructure([home, search]),
// `defaultDocumentNode` is responsible for adding a “Preview” tab to the document pane
// You can add any React component to `S.view.component` and it will be rendered in the pane
// and have access to content in the form in real-time.
// It's part of the Studio's “Structure Builder API” and is documented here:
// https://www.sanity.io/docs/structure-builder-reference
defaultDocumentNode: (S, { schemaType }) => {
if ((PREVIEWABLE_DOCUMENT_TYPES as string[]).includes(schemaType)) {
return S.document().views([
// Default form view
S.view.form(),
// Preview
S.view.component(Iframe).options(iframeOptions).title('Preview'),
])
}
return null
},
}),
// Configures the global "new document" button, and document actions, to suit the Settings document singleton
singletonPlugin([home.name]),
// Add the "Open preview" action
previewUrl({
base: PREVIEW_BASE_URL,
urlSecretId: previewSecretId,
matchTypes: PREVIEWABLE_DOCUMENT_TYPES,
}),
media(), media(),
...(isDev ? devOnlyPlugins : []), // ...(isDev ? devOnlyPlugins : []),
documentInternationalization({ documentInternationalization({
// Required, either: // Required, either:
// An array of supported languages // An array of supported languages
@ -48,10 +124,6 @@ export default defineConfig({
'utilityMenu', 'utilityMenu',
'search' 'search'
], ],
// Optional
// languageField: `language`, // defauts to "language"
// Optional, requires access to the Publishing API
// bulkPublish: true // defaults to false
}), }),
], ],
schema: { schema: {

View File

@ -1,5 +1,5 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
const { fontFamily } = require('tailwindcss/defaultTheme') const { fontFamily } = require('tailwindcss/defaultTheme');
const plugin = require('tailwindcss/plugin'); const plugin = require('tailwindcss/plugin');
module.exports = { module.exports = {
@ -21,7 +21,7 @@ module.exports = {
'3xl': '1.75rem', '3xl': '1.75rem',
'4xl': '2rem', '4xl': '2rem',
'5xl': '3rem', '5xl': '3rem',
'6xl': '4rem', '6xl': '4rem'
}, },
extend: { extend: {
colors: { colors: {
@ -42,62 +42,34 @@ module.exports = {
red: '#ec5d40', red: '#ec5d40',
yellow: '#ffcb47', yellow: '#ffcb47',
// UI.SHADCN.COM // UI.SHADCN.COM
border: "hsl(var(--border))", border: 'hsl(var(--border))',
input: "hsl(var(--input))", input: 'hsl(var(--input))',
ring: "hsl(var(--ring))", ring: 'hsl(var(--ring))',
background: "hsl(var(--background))", background: 'hsl(var(--background))',
foreground: "hsl(var(--foreground))", foreground: 'hsl(var(--foreground))'
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
}, },
textColor: { textColor: {
base: '#333333', base: '#333333',
'low-contrast': '#585858', 'low-contrast': '#585858',
'high-contrast': '#333333', 'high-contrast': '#333333'
}, },
fontFamily: { fontFamily: {
sans: ['var(--font-inter)', ...fontFamily.sans], sans: ['var(--font-inter)', ...fontFamily.sans],
display: ['var(--font-inter-tight)', ...fontFamily.sans], display: ['var(--font-inter-tight)', ...fontFamily.sans]
}, },
keyframes: { keyframes: {
"accordion-down": { 'accordion-down': {
from: { height: 0 }, from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" }, to: { height: 'var(--radix-accordion-content-height)' }
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
}, },
'accordion-up': {
from: { height: 'var(--radix-accordion-content-height)' },
to: { height: 0 }
}
}, },
animation: { animation: {
"accordion-down": "accordion-down 0.2s ease-out", 'accordion-down': 'accordion-down 0.2s ease-out',
"accordion-up": "accordion-up 0.2s ease-out", 'accordion-up': 'accordion-up 0.2s ease-out'
}, },
typography: { typography: {
DEFAULT: { DEFAULT: {
@ -107,13 +79,13 @@ module.exports = {
textDecoration: 'underline', textDecoration: 'underline',
color: '#3182ce', color: '#3182ce',
'&:hover': { '&:hover': {
color: '#2c5282', color: '#2c5282'
}, }
}, }
}, }
}, }
}, }
}, }
}, },
plugins: [ plugins: [
require('tailwindcss-animate'), require('tailwindcss-animate'),
@ -135,5 +107,5 @@ module.exports = {
], ],
future: { future: {
hoverOnlyWhenSupported: true hoverOnlyWhenSupported: true
},
} }
};