Merge branch 'main' into feat/stats

# Conflicts:
#	pnpm-lock.yaml
This commit is contained in:
shadcn 2022-12-06 10:33:24 +04:00
commit 4567261e7f
29 changed files with 507 additions and 286 deletions

View file

@ -1,3 +1,6 @@
# -----------------------------------------------------------------------------
# App
# -----------------------------------------------------------------------------
NEXT_PUBLIC_APP_URL=http://localhost:3000
# -----------------------------------------------------------------------------
@ -19,12 +22,10 @@ PLANETSCALE_SERVERLESS_DATABASE_URL=
# -----------------------------------------------------------------------------
# Email (Postmark)
# -----------------------------------------------------------------------------
SMTP_FROM=
POSTMARK_API_TOKEN=
SMTP_HOST=smtp.postmarkapp.com
SMTP_PORT=25
SMTP_USER=
SMTP_PASSWORD=
SMTP_FROM=Taxonomy <taxonomy@example.com>
POSTMARK_SIGN_IN_TEMPLATE=
POSTMARK_ACTIVATION_TEMPLATE=
# -----------------------------------------------------------------------------
# Subscriptions (Stripe)

View file

@ -50,7 +50,8 @@ A few people have asked me to turn this into a starter. I think we could do that
- [x] ~Build marketing pages~
- [x] ~Subscriptions using Stripe~
- [x] ~Responsive styles~
- [ ] Add OG image for blog using @vercel/og
- [x] ~Add OG image for blog using @vercel/og~
- [ ] Add tests
- [ ] Dark mode
## Known Issues
@ -77,6 +78,10 @@ pnpm install
2. Copy `.env.example` to `.env.local` and update the variables.
```sh
cp .env.example .env.local
```
3. Start the development server:
```sh

View file

@ -1,4 +1,5 @@
import { redirect } from "next/navigation"
import { cache } from "react"
import { db } from "@/lib/db"
import { getCurrentUser } from "@/lib/session"
@ -10,7 +11,7 @@ import { DashboardShell } from "@/components/dashboard/shell"
import { PostItem } from "@/components/dashboard/post-item"
import { EmptyPlaceholder } from "@/components/dashboard/empty-placeholder"
async function getPostsForUser(userId: User["id"]) {
const getPostsForUser = cache(async (userId: User["id"]) => {
return await db.post.findMany({
where: {
authorId: userId,
@ -25,7 +26,7 @@ async function getPostsForUser(userId: User["id"]) {
updatedAt: "desc",
},
})
}
})
export default async function DashboardPage() {
const user = await getCurrentUser()

View file

@ -1,5 +1,14 @@
import { allDocs } from "contentlayer/generated"
import MdxHead from "@/components/docs/mdx-head"
export default function Head({ params }) {
return <MdxHead params={params} />
const slug = params?.slug?.join("/") || ""
const doc = allDocs.find((doc) => doc.slugAsParams === slug)
return (
<MdxHead
params={params}
og={{ heading: doc.description, type: "Documentation", mode: "light" }}
/>
)
}

View file

@ -1,5 +1,5 @@
import MdxHead from "@/components/docs/mdx-head"
export default function Head({ params }) {
return <MdxHead params={params} />
return <MdxHead params={params} og={{ type: "Guide" }} />
}

View file

@ -1,5 +1,12 @@
import MdxHead from "@/components/docs/mdx-head"
export default function Head({ params }) {
return <MdxHead params={params} />
return (
<MdxHead
params={params}
og={{
type: "Blog Post",
}}
/>
)
}

View file

@ -8,12 +8,15 @@ export default function Head() {
name="description"
content="An open source application built using the new router, server components and everything new in Next.js 13."
/>
<meta property="og:title" content="Taxonomy" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://tx.shadcn.com" />
<meta property="og:image" content="https://tx.shadcn.com/og.jpg" />
<meta property="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Taxonomy" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://tx.shadcn.com" />
<meta property="twitter:image" content="https://tx.shadcn.com/og.jpg" />
<meta name="twitter:image" content="https://tx.shadcn.com/og.jpg" />
</>
)
}

BIN
assets/fonts/Inter-Bold.ttf Normal file

Binary file not shown.

Binary file not shown.

View file

@ -28,7 +28,7 @@ export function DashboardNav({ items }: DashboardNavProps) {
className={cn(
"group flex items-center rounded-md px-3 py-2 text-sm font-medium text-slate-800 hover:bg-slate-100",
path === item.href ? "bg-slate-200" : "transparent",
item.disabled && "cursor-not-allowed opacity-50"
item.disabled && "cursor-not-allowed opacity-80"
)}
>
<Icon className="mr-2 h-4 w-4" />

View file

@ -40,6 +40,7 @@ export function PostOperations({ post }: PostOperationsProps) {
<DropdownMenu>
<DropdownMenu.Trigger className="flex h-8 w-8 items-center justify-center rounded-md border transition-colors hover:bg-slate-50">
<Icons.ellipsis className="h-4 w-4" />
<span className="sr-only">Open</span>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content>

View file

@ -41,7 +41,7 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
if (!signInResult?.ok) {
return toast({
title: "Something went wrong.",
message: "Your post was not saved. Please try again.",
message: "Your sign in request failed. Please try again.",
type: "error",
})
}

View file

@ -1,12 +1,17 @@
import * as z from "zod"
import { allDocuments } from "contentlayer/generated"
import { ogImageSchema } from "@/lib/validations/og"
import { absoluteUrl } from "@/lib/utils"
interface MdxHeadProps {
params: {
slug?: string[]
}
og?: z.infer<typeof ogImageSchema>
}
export default function MdxHead({ params }: MdxHeadProps) {
export default function MdxHead({ params, og }: MdxHeadProps) {
const slug = params?.slug?.join("/") || ""
const mdxDoc = allDocuments.find((doc) => doc.slugAsParams === slug)
@ -15,19 +20,36 @@ export default function MdxHead({ params }: MdxHeadProps) {
}
const title = `${mdxDoc.title} - Taxonomy`
const url = process.env.NEXT_PUBLIC_APP_URL
let ogUrl = new URL(`${url}/og.jpg`)
const ogTitle = og?.heading || mdxDoc.title
const ogDescription = mdxDoc.description
if (og?.type) {
ogUrl = new URL(`${url}/api/og`)
ogUrl.searchParams.set("heading", ogTitle)
ogUrl.searchParams.set("type", og.type)
ogUrl.searchParams.set("mode", og.mode || "dark")
}
return (
<>
<title>{title}</title>
<meta name="description" content={mdxDoc.description} />
<link rel="canonical" href={absoluteUrl(mdxDoc.slug)} />
<meta name="description" content={ogDescription} />
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://tx.shadcn.com" />
<meta property="og:image" content="https://tx.shadcn.com/og.jpg" />
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://tx.shadcn.com" />
<meta property="twitter:image" content="https://tx.shadcn.com/og.jpg" />
<meta property="og:title" content={ogTitle} />
<meta property="og:description" content={ogDescription} />
<meta property="og:url" content={url} />
<meta property="og:image" content={ogUrl.toString()} />
<meta name="twitter:title" content={ogTitle} />
<meta name="twitter:description" content={ogDescription} />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={url} />
<meta name="twitter:image" content={ogUrl.toString()} />
</>
)
}

View file

@ -144,7 +144,7 @@ const components = {
pre: ({ className, ...props }) => (
<pre
className={cn(
"mt-6 mb-4 overflow-x-auto rounded-lg bg-slate-50 py-4",
"mt-6 mb-4 overflow-x-auto rounded-lg bg-slate-900 py-4",
className
)}
{...props}

View file

@ -68,7 +68,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
![](/images/blog/blog-post-4.jpg)
<Image
src="/images/blog/blog-post-4.jpg"
width="718"
height="404"
alt="Image"
/>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.

View file

@ -68,7 +68,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
![](/images/blog/blog-post-4.jpg)
<Image
src="/images/blog/blog-post-4.jpg"
width="718"
height="404"
alt="Image"
/>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.

View file

@ -68,7 +68,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
![](/images/blog/blog-post-4.jpg)
<Image
src="/images/blog/blog-post-4.jpg"
width="718"
height="404"
alt="Image"
/>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.

View file

@ -68,7 +68,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
![](/images/blog/blog-post-4.jpg)
<Image
src="/images/blog/blog-post-4.jpg"
width="718"
height="404"
alt="Image"
/>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.

View file

@ -65,7 +65,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
![](/images/blog/blog-post-4.jpg)
<Image
src="/images/blog/blog-post-4.jpg"
width="718"
height="404"
alt="Image"
/>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.

View file

@ -71,7 +71,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
![](/images/blog/blog-post-4.jpg)
<Image
src="/images/blog/blog-post-4.jpg"
width="718"
height="404"
alt="Image"
/>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.

View file

@ -71,7 +71,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
![](/images/blog/blog-post-4.jpg)
<Image
src="/images/blog/blog-post-4.jpg"
width="718"
height="404"
alt="Image"
/>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.

View file

@ -151,7 +151,7 @@ export default makeSource({
[
rehypePrettyCode,
{
theme: "css-variables",
theme: "github-dark",
onVisitLine(node) {
// Prevent lines from collapsing in `display: grid` mode, and allow empty
// lines to be copy/pasted

View file

@ -5,12 +5,10 @@ import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { Client } from "postmark"
import { db } from "@/lib/db"
import { siteConfig } from "@/config/site"
const postmarkClient = new Client(process.env.POSTMARK_API_TOKEN)
const POSTMARK_SIGN_IN_TEMPLATE = 29559329
const POSTMARK_ACTIVATION_TEMPLATE = 29559329
export const authOptions: NextAuthOptions = {
// huh any! I know.
// This is a temporary fix for prisma client.
@ -28,14 +26,6 @@ export const authOptions: NextAuthOptions = {
clientSecret: process.env.GITHUB_CLIENT_SECRET,
}),
EmailProvider({
server: {
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
},
},
from: process.env.SMTP_FROM,
sendVerificationRequest: async ({ identifier, url, provider }) => {
const user = await db.user.findUnique({
@ -47,15 +37,16 @@ export const authOptions: NextAuthOptions = {
},
})
const templateId = user?.emailVerified
? process.env.POSTMARK_SIGN_IN_TEMPLATE
: process.env.POSTMARK_ACTIVATION_TEMPLATE
const result = await postmarkClient.sendEmailWithTemplate({
TemplateId: user?.emailVerified
? POSTMARK_SIGN_IN_TEMPLATE
: POSTMARK_ACTIVATION_TEMPLATE,
TemplateId: parseInt(templateId),
To: identifier,
From: provider.from,
TemplateModel: {
action_url: url,
product_name: "Taxonomy",
product_name: siteConfig.name,
},
Headers: [
{

7
lib/validations/og.ts Normal file
View file

@ -0,0 +1,7 @@
import * as z from "zod"
export const ogImageSchema = z.object({
heading: z.string(),
type: z.string(),
mode: z.enum(["light", "dark"]).default("dark"),
})

View file

@ -13,7 +13,7 @@
"start": "next start",
"lint": "next lint",
"preview": "next build && next start",
"vercel-build": "prisma generate && next build"
"postinstall": "prisma generate"
},
"dependencies": {
"@editorjs/code": "^2.7.0",
@ -36,6 +36,7 @@
"@radix-ui/react-popover": "^1.0.2",
"@radix-ui/react-toggle": "^1.0.0",
"@vercel/analytics": "^0.1.3",
"@vercel/og": "^0.0.21",
"clsx": "^1.2.1",
"contentlayer": "^0.2.9",
"date-fns": "^2.29.3",

150
pages/api/og.tsx Normal file
View file

@ -0,0 +1,150 @@
import { ogImageSchema } from "@/lib/validations/og"
import { ImageResponse } from "@vercel/og"
import { NextRequest } from "next/server"
export const config = {
runtime: "experimental-edge",
}
const interRegular = fetch(
new URL("../../assets/fonts/Inter-Regular.ttf", import.meta.url)
).then((res) => res.arrayBuffer())
const interBold = fetch(
new URL("../../assets/fonts/Inter-Bold.ttf", import.meta.url)
).then((res) => res.arrayBuffer())
export default async function handler(req: NextRequest) {
try {
const fontRegular = await interRegular
const fontBold = await interBold
const url = new URL(req.url)
const values = ogImageSchema.parse(Object.fromEntries(url.searchParams))
const heading =
values.heading.length > 140
? `${values.heading.substring(0, 140)}...`
: values.heading
const { mode } = values
const paint = mode === "dark" ? "#fff" : "#000"
const fontSize = heading.length > 100 ? "70px" : "100px"
return new ImageResponse(
(
<div
tw="flex relative flex-col p-12 w-full h-full items-start"
style={{
color: paint,
background:
mode === "dark"
? "linear-gradient(90deg, #000 0%, #121 100%)"
: "white",
}}
>
<svg width="212" height="50" viewBox="0 0 212 50" fill="none">
<g clip-path="url(#a)" fill={paint}>
<path d="M99.715 9.784h26.128v4.823h-10.365v25.37h-5.182v-25.37h-10.58V9.784ZM56.746 9.784v4.823H35.803v7.757h16.842v4.823H35.803v7.967h20.943v4.823H30.62v-25.37h-.002V9.784h26.128ZM69.792 9.797H63.01l24.292 30.192h6.801L81.956 24.903 94.084 9.82l-6.782.01-8.742 10.856-8.768-10.89ZM76.751 31.363l-3.396-4.222L62.99 40.012h6.802l6.96-8.649Z" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M30.802 39.977 6.478 9.77H0v30.193h5.182V16.225l19.11 23.752h6.51Z"
/>
<path d="M127.008 39.792c-.38 0-.703-.131-.973-.394a1.267 1.267 0 0 1-.4-.959c-.004-.366.13-.681.4-.944.27-.263.593-.395.973-.395.365 0 .684.132.955.395.274.263.41.578.414.944-.004.25-.067.478-.193.682-.13.208-.295.37-.502.488a1.298 1.298 0 0 1-.674.183ZM135.853 27.073h2.296v8.847c-.003.814-.179 1.51-.523 2.094a3.477 3.477 0 0 1-1.447 1.346c-.614.311-1.334.47-2.152.47-.748 0-1.419-.135-2.016-.398a3.239 3.239 0 0 1-1.418-1.176c-.352-.519-.524-1.166-.524-1.941h2.301c.003.339.08.633.228.879.147.245.351.432.611.564.263.131.565.197.905.197.369 0 .685-.076.942-.232.256-.152.453-.38.59-.685.133-.301.203-.675.207-1.118v-8.847ZM147.598 30.533a1.67 1.67 0 0 0-.73-1.252c-.432-.301-.99-.45-1.675-.45-.481 0-.895.073-1.239.214-.345.146-.611.34-.794.585a1.423 1.423 0 0 0-.281.84c0 .264.063.492.186.683.123.193.288.356.502.487.211.135.446.246.703.336.259.09.519.166.779.228l1.197.294c.481.111.949.26 1.394.45.446.187.85.426 1.205.713.354.287.635.633.842 1.038.208.405.313.879.313 1.426 0 .737-.19 1.384-.573 1.944-.382.557-.933.993-1.657 1.308-.72.312-1.59.47-2.616.47-.99 0-1.854-.151-2.581-.456-.73-.301-1.299-.744-1.71-1.325-.41-.582-.632-1.29-.663-2.125h2.275c.032.436.172.8.411 1.094.242.29.558.505.945.65.389.142.825.215 1.306.215.502 0 .944-.076 1.327-.225.379-.149.678-.357.892-.626.218-.267.327-.582.33-.942-.003-.328-.102-.602-.292-.816-.193-.215-.459-.395-.8-.54a8.25 8.25 0 0 0-1.201-.39l-1.454-.368c-1.05-.266-1.882-.671-2.489-1.214-.611-.543-.913-1.263-.913-2.166 0-.74.203-1.391.615-1.948.407-.557.965-.99 1.671-1.298.709-.311 1.51-.463 2.401-.463.906 0 1.7.152 2.385.463.684.308 1.222.737 1.611 1.284a3.25 3.25 0 0 1 .605 1.882h-2.227Z" />
</g>
<path
d="M181.335 14.636V35h-5.528V19.727h-.119l-4.455 2.665v-4.693l5.011-3.063h5.091Zm12.136 20.642c-1.604 0-3.029-.275-4.276-.825-1.239-.557-2.214-1.322-2.923-2.297-.709-.974-1.067-2.094-1.074-3.36h5.568c.007.39.126.742.358 1.053.239.305.564.544.975.716.411.173.881.259 1.412.259.51 0 .961-.09 1.352-.269.391-.185.696-.44.915-.765.218-.325.325-.696.318-1.114a1.637 1.637 0 0 0-.378-1.094c-.252-.318-.606-.566-1.064-.745-.457-.18-.984-.269-1.581-.269h-2.068V22.75h2.068c.55 0 1.034-.09 1.452-.268.424-.18.752-.428.984-.746.239-.318.355-.683.348-1.094a1.824 1.824 0 0 0-.288-1.054 2.012 2.012 0 0 0-.835-.716c-.352-.172-.759-.258-1.223-.258-.504 0-.955.09-1.353.268a2.25 2.25 0 0 0-.924.746 1.891 1.891 0 0 0-.348 1.094h-5.29c.007-1.247.348-2.347 1.024-3.302.683-.954 1.617-1.703 2.804-2.247 1.187-.543 2.549-.815 4.087-.815 1.504 0 2.833.255 3.987.766 1.16.51 2.065 1.213 2.714 2.107.657.889.981 1.906.975 3.053.013 1.14-.378 2.075-1.174 2.804-.788.73-1.789 1.16-3.002 1.293v.159c1.644.179 2.88.683 3.708 1.511.829.822 1.237 1.856 1.223 3.102.007 1.194-.351 2.25-1.073 3.172-.716.922-1.714 1.644-2.993 2.168-1.273.524-2.741.785-4.405.785Z"
fill={paint}
/>
<rect
x="163"
y="1"
width="48"
height="48"
rx="9"
stroke={paint}
stroke-width="2"
/>
<defs>
<clipPath id="a">
<path fill={paint} d="M0 9.771h150v30.457H0z" />
</clipPath>
</defs>
</svg>
<div tw="flex flex-col flex-1 py-10">
<div
tw="flex text-xl uppercase font-bold tracking-tight"
style={{ fontFamily: "Inter", fontWeight: "normal" }}
>
{values.type}
</div>
<div
tw="flex leading-[1.1] text-[80px] font-bold tracking-tighter"
style={{
fontFamily: "Inter",
fontWeight: "bolder",
marginLeft: "-3px",
fontSize,
}}
>
{heading}
</div>
</div>
<div tw="flex items-center w-full justify-between">
<div
tw="flex text-xl"
style={{ fontFamily: "Inter", fontWeight: "normal" }}
>
tx.shadcn.com
</div>
<div
tw="flex items-center text-xl"
style={{ fontFamily: "Inter", fontWeight: "normal" }}
>
<svg width="32" height="32" viewBox="0 0 48 48" fill="none">
<path
d="M30 44v-8a9.6 9.6 0 0 0-2-7c6 0 12-4 12-11 .16-2.5-.54-4.96-2-7 .56-2.3.56-4.7 0-7 0 0-2 0-6 3-5.28-1-10.72-1-16 0-4-3-6-3-6-3-.6 2.3-.6 4.7 0 7a10.806 10.806 0 0 0-2 7c0 7 6 11 12 11a9.43 9.43 0 0 0-1.7 3.3c-.34 1.2-.44 2.46-.3 3.7v8"
stroke={paint}
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M18 36c-9.02 4-10-4-14-4"
stroke={paint}
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
<div tw="flex ml-2">github.com/shadcn/taxonomy</div>
</div>
</div>
</div>
),
{
width: 1200,
height: 630,
fonts: [
{
name: "Inter",
data: fontRegular,
weight: 400,
style: "normal",
},
{
name: "Inter",
data: fontBold,
weight: 700,
style: "normal",
},
],
}
)
} catch (error) {
return new Response(`Failed to generate image`, {
status: 500,
})
}
}

View file

@ -15,7 +15,6 @@ specifiers:
"@hookform/resolvers": ^2.9.10
"@next-auth/prisma-adapter": ^1.0.4
"@next/font": ^13.0.3
"@planetscale/database": ^1.4.0
"@prisma/client": ^4.5.0
"@radix-ui/react-alert-dialog": ^1.0.2
"@radix-ui/react-avatar": ^1.0.1
@ -27,17 +26,17 @@ specifiers:
"@types/react": 18.0.15
"@types/react-dom": 18.0.6
"@vercel/analytics": ^0.1.3
"@vercel/og": ^0.0.21
autoprefixer: ^10.4.8
clsx: ^1.2.1
contentlayer: ^0.2.9
date-fns: ^2.29.3
eslint: 8.21.0
eslint-config-next: ^13.0.0
framer-motion: ^7.6.12
husky: ^8.0.2
lucide-react: ^0.92.0
mdast-util-toc: ^6.1.0
next: 13.0.6-canary.1
next: ^13.0.4-canary.5
next-auth: ^4.16.4
next-contentlayer: ^0.2.9
nodemailer: ^6.8.0
@ -84,7 +83,6 @@ dependencies:
"@hookform/resolvers": 2.9.10_react-hook-form@7.39.5
"@next-auth/prisma-adapter": 1.0.5_o53gfpk3vz2btjrokqfjjwwn3m
"@next/font": 13.0.4
"@planetscale/database": 1.4.0
"@prisma/client": 4.6.1_prisma@4.6.1
"@radix-ui/react-alert-dialog": 1.0.2_bb2bxwco6ptpubzwpazr52qf6i
"@radix-ui/react-avatar": 1.0.1_biqbaboplfbrettd7655fr4n2y
@ -92,14 +90,14 @@ dependencies:
"@radix-ui/react-popover": 1.0.2_bb2bxwco6ptpubzwpazr52qf6i
"@radix-ui/react-toggle": 1.0.1_biqbaboplfbrettd7655fr4n2y
"@vercel/analytics": 0.1.5_react@18.2.0
"@vercel/og": 0.0.21
clsx: 1.2.1
contentlayer: 0.2.9
date-fns: 2.29.3
framer-motion: 7.6.12_biqbaboplfbrettd7655fr4n2y
lucide-react: 0.92.0_sh5qlbywuemxd2y3xkrw2y2kr4
next: 13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y
next-auth: 4.17.0_thl2nqbeqzylnsbfarzmi6laiy
next-contentlayer: 0.2.9_cejjzyjft5qpe7pbv5t5jzassa
next: 13.0.4_biqbaboplfbrettd7655fr4n2y
next-auth: 4.17.0_icxl3uciip5l2ulzmmrvkhve3i
next-contentlayer: 0.2.9_dcors23iqtgxrhrwosgnnc4xji
nodemailer: 6.8.0
postmark: 3.0.14
prop-types: 15.8.1
@ -684,25 +682,6 @@ packages:
}
dev: false
/@emotion/is-prop-valid/0.8.8:
resolution:
{
integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==,
}
requiresBuild: true
dependencies:
"@emotion/memoize": 0.7.4
dev: false
optional: true
/@emotion/memoize/0.7.4:
resolution:
{
integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==,
}
dev: false
optional: true
/@esbuild-plugins/node-resolve/0.1.4_esbuild@0.15.15:
resolution:
{
@ -963,71 +942,6 @@ packages:
- supports-color
dev: false
/@motionone/animation/10.14.0:
resolution:
{
integrity: sha512-h+1sdyBP8vbxEBW5gPFDnj+m2DCqdlAuf2g6Iafb1lcMnqjsRXWlPw1AXgvUMXmreyhqmPbJqoNfIKdytampRQ==,
}
dependencies:
"@motionone/easing": 10.14.0
"@motionone/types": 10.14.0
"@motionone/utils": 10.14.0
tslib: 2.4.1
dev: false
/@motionone/dom/10.13.1:
resolution:
{
integrity: sha512-zjfX+AGMIt/fIqd/SL1Lj93S6AiJsEA3oc5M9VkUr+Gz+juRmYN1vfvZd6MvEkSqEjwPQgcjN7rGZHrDB9APfQ==,
}
dependencies:
"@motionone/animation": 10.14.0
"@motionone/generators": 10.14.0
"@motionone/types": 10.14.0
"@motionone/utils": 10.14.0
hey-listen: 1.0.8
tslib: 2.4.1
dev: false
/@motionone/easing/10.14.0:
resolution:
{
integrity: sha512-2vUBdH9uWTlRbuErhcsMmt1jvMTTqvGmn9fHq8FleFDXBlHFs5jZzHJT9iw+4kR1h6a4SZQuCf72b9ji92qNYA==,
}
dependencies:
"@motionone/utils": 10.14.0
tslib: 2.4.1
dev: false
/@motionone/generators/10.14.0:
resolution:
{
integrity: sha512-6kRHezoFfIjFN7pPpaxmkdZXD36tQNcyJe3nwVqwJ+ZfC0e3rFmszR8kp9DEVFs9QL/akWjuGPSLBI1tvz+Vjg==,
}
dependencies:
"@motionone/types": 10.14.0
"@motionone/utils": 10.14.0
tslib: 2.4.1
dev: false
/@motionone/types/10.14.0:
resolution:
{
integrity: sha512-3bNWyYBHtVd27KncnJLhksMFQ5o2MSdk1cA/IZqsHtA9DnRM1SYgN01CTcJ8Iw8pCXF5Ocp34tyAjY7WRpOJJQ==,
}
dev: false
/@motionone/utils/10.14.0:
resolution:
{
integrity: sha512-sLWBLPzRqkxmOTRzSaD3LFQXCPHvDzyHJ1a3VP9PRzBxyVd2pv51/gMOsdAcxQ9n+MIeGJnxzXBYplUHKj4jkw==,
}
dependencies:
"@motionone/types": 10.14.0
hey-listen: 1.0.8
tslib: 2.4.1
dev: false
/@next-auth/prisma-adapter/1.0.5_o53gfpk3vz2btjrokqfjjwwn3m:
resolution:
{
@ -1038,13 +952,13 @@ packages:
next-auth: ^4
dependencies:
"@prisma/client": 4.6.1_prisma@4.6.1
next-auth: 4.17.0_thl2nqbeqzylnsbfarzmi6laiy
next-auth: 4.17.0_icxl3uciip5l2ulzmmrvkhve3i
dev: false
/@next/env/13.0.6-canary.1:
/@next/env/13.0.4:
resolution:
{
integrity: sha512-L88vP2GvU2NvF5YSIDjqYzzJQRNDg3F08qE/pTLClsYXLusRWAJ1lgI9sZFqLrMbZuj2xd0hWYyYjCrrg/LLLw==,
integrity: sha512-N5Z3bdxBzoxrC5bwykDFITzdWuwDteOdZ+7nxixY+I1XpRX8/iQYbw2wuXMdqdfBGm2NNUpAqg8YF2e4oAC2UQ==,
}
dev: false
@ -1064,10 +978,10 @@ packages:
}
dev: false
/@next/swc-android-arm-eabi/13.0.6-canary.1:
/@next/swc-android-arm-eabi/13.0.4:
resolution:
{
integrity: sha512-3/ZSIsm2yYZXUyqupAri4+6J97wVdHIP2yrcTLoKdYQKm1lp1z5hIZLtxQCV4vLyYNlNIafvIqeasfYWuYzCgw==,
integrity: sha512-SD9H+/zuV3L0oHIhsDdFkDqFtg6pIHtqRUPlsrNdOsmWXgMlSzxBmwt2ta4kyrazS62BQu7XRUG++ZyODS7AWg==,
}
engines: { node: ">= 10" }
cpu: [arm]
@ -1076,10 +990,10 @@ packages:
dev: false
optional: true
/@next/swc-android-arm64/13.0.6-canary.1:
/@next/swc-android-arm64/13.0.4:
resolution:
{
integrity: sha512-/J2EXT8L82HgV8sf2SzSdpTuT5gtpPGgekPRCF1ttYyN8FAR/VHPKOLYTbKz3NQ95ogttrW28RFPsMSekQpLaQ==,
integrity: sha512-F8W5WcBbdn/zBoy32/mQiefs9DNsT12CTSSVCsO8GvQR7GjJU+uduQ4drKcSDoDLuAFULc2jDN06Circq4vuQg==,
}
engines: { node: ">= 10" }
cpu: [arm64]
@ -1088,10 +1002,10 @@ packages:
dev: false
optional: true
/@next/swc-darwin-arm64/13.0.6-canary.1:
/@next/swc-darwin-arm64/13.0.4:
resolution:
{
integrity: sha512-n+IxXIJSEm3HdumauULSZCehyKyQ0EfWU/qf5oMjyGOQ/sHQfgT5sGYtfnnNvvhSlVgFhyz7MalPRwJQWAIIZQ==,
integrity: sha512-/lajev+9GSie+rRTl5z8skW9RJwZ+TwMKLzzM24TbDk8lUjqPTyJZ/cU0NDj8J7VQAZ6EehACSh9rcJeBRtLuA==,
}
engines: { node: ">= 10" }
cpu: [arm64]
@ -1100,10 +1014,10 @@ packages:
dev: false
optional: true
/@next/swc-darwin-x64/13.0.6-canary.1:
/@next/swc-darwin-x64/13.0.4:
resolution:
{
integrity: sha512-0gQ2zLBFJT8rO080APvY/fHxjSIRVD7VpF0C12BXroFJ3XMnCoa6scniVgKwV4pjhTtlJoLSk3y4wNITyouLDQ==,
integrity: sha512-HK4b2rFiju8d40GTL/jH9U6OQ7BYA2MeEHs7Dm7Rp7kwQtLzP3z6osdQS8er20tIFHDE4b+oVBy03ZUQkHf0Pg==,
}
engines: { node: ">= 10" }
cpu: [x64]
@ -1112,10 +1026,10 @@ packages:
dev: false
optional: true
/@next/swc-freebsd-x64/13.0.6-canary.1:
/@next/swc-freebsd-x64/13.0.4:
resolution:
{
integrity: sha512-zAnm1JtxgrNkjiBef7U8lO9JOqNhy13mKA0Z27XCeAunhaar0hNZNHnKUlISVhAZovpHs96fp0mm7Skw0WCkpA==,
integrity: sha512-xBvIGLaGzZtgJfRRJ2DBN82DQCJ/O7jkXyBp8X/vHefPWyVXVqF6C68Rv8ADp11thPpf8WpjkvDDLb9AuWHQUA==,
}
engines: { node: ">= 10" }
cpu: [x64]
@ -1124,10 +1038,10 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm-gnueabihf/13.0.6-canary.1:
/@next/swc-linux-arm-gnueabihf/13.0.4:
resolution:
{
integrity: sha512-JJCdGBEeNzGXm0AQUfVY9x3C3WvxCcawZ1tCYYkOqLD21Dj5gDTNSZT2cAGFDovfyn5hN/Vltf20Zs8ilUPr1w==,
integrity: sha512-s13pxNp9deKmmxEGTp1MoL1e4nf4wbEymEaHgFxUlhoR1OD9tK8oTNrQphQePJgVjzcWmRGH/dX7O9mVkHbU/g==,
}
engines: { node: ">= 10" }
cpu: [arm]
@ -1136,10 +1050,10 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm64-gnu/13.0.6-canary.1:
/@next/swc-linux-arm64-gnu/13.0.4:
resolution:
{
integrity: sha512-oE9D+Mm240fRpZWZBhFiztmJ/D7uwQ3jfOZcQVf1aN3P+9De+5jyv2TKoHrjrRh5xjloTEDIpt2wNKimlwZvkg==,
integrity: sha512-Lklo65usNzoYwjX51CpDKOepWVZBdwO49/Jz3djxiYUr2lRtpDVnlfwCvzN+47j3BMVMWtC2ndIi8Q4s3J0v4g==,
}
engines: { node: ">= 10" }
cpu: [arm64]
@ -1148,10 +1062,10 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm64-musl/13.0.6-canary.1:
/@next/swc-linux-arm64-musl/13.0.4:
resolution:
{
integrity: sha512-+DukK2LdoZo4Ds0o2XGAC9324O9auxvHMF4MwDzrXrherBFEeSZUDIxcz4zu5/pd8dyQ8JY9nwILJEevla23pA==,
integrity: sha512-+3BXtXBwjVhd5lahDe5nKZ7EwD6hE/oLFQkITCvgxymU5qYHGlLFyF52/lyw8qhyxoCr7mMVsUFhlCzVwCfNjg==,
}
engines: { node: ">= 10" }
cpu: [arm64]
@ -1160,10 +1074,10 @@ packages:
dev: false
optional: true
/@next/swc-linux-x64-gnu/13.0.6-canary.1:
/@next/swc-linux-x64-gnu/13.0.4:
resolution:
{
integrity: sha512-1bULat6aif5E48s23lAh4vmuVogxz3arXMawlqHwHqwJWpzxF2vyAl3Ilh4mXJnD1xvwiGRH7Aov7HMQJhF2+g==,
integrity: sha512-QB8qoZrvHhZsz62nUrTKlp5IiZ8I7KZsaa6437H/W/NOZHLGJjCxROnhUjLvKVe/T5P86pjya2SUOUqWAjz4Pg==,
}
engines: { node: ">= 10" }
cpu: [x64]
@ -1172,10 +1086,10 @@ packages:
dev: false
optional: true
/@next/swc-linux-x64-musl/13.0.6-canary.1:
/@next/swc-linux-x64-musl/13.0.4:
resolution:
{
integrity: sha512-LN9qXV3Rh1jMcaSXg5DGZYbN6nVCn6A/aQBTw4K5DWu7bHTiEkq4d7/OZN+gfJcqW8BuRtG4zLeraae/1RO9pw==,
integrity: sha512-WaahF6DYUQRg1QqIMcuOu2ZsFhS3aC5iWeQyeptMHklP9wb4FfTNmBArKHknX/GXD8P9gI38WTAHJ25cc0zVwg==,
}
engines: { node: ">= 10" }
cpu: [x64]
@ -1184,10 +1098,10 @@ packages:
dev: false
optional: true
/@next/swc-win32-arm64-msvc/13.0.6-canary.1:
/@next/swc-win32-arm64-msvc/13.0.4:
resolution:
{
integrity: sha512-792QCYO+lF4N1c2bwYVwhLwMJMhnmvQRVOnCmRlGhbaZJ0f6ZuIYCxjqAqV8Por+u0ErenRMv5BGleK8wHfQJA==,
integrity: sha512-FD+k1j2jeY0aKcqcpzFKfTsv55PPmIZ5GKDyPjjV5AO6XvQ4nALwWl4JwizjH2426TfLXObb+C3MH0bl9Ok1Kw==,
}
engines: { node: ">= 10" }
cpu: [arm64]
@ -1196,10 +1110,10 @@ packages:
dev: false
optional: true
/@next/swc-win32-ia32-msvc/13.0.6-canary.1:
/@next/swc-win32-ia32-msvc/13.0.4:
resolution:
{
integrity: sha512-hwL9JjT7C1ZP+Wj7F4QIoewEErqc70Ax0aeKqQZdKU57djmIWvvvnyh9p/uUQFHLc3M4Um+XvtqpyFZB6RcYbg==,
integrity: sha512-+Q/Q8Ydvz3X3U84CyZdNv1HC7fE43k+xB8C6b3IFmWGa5Tu2tfskQ2FsUNBrYreZjhFC/894J3rVQ6Vj6Auugg==,
}
engines: { node: ">= 10" }
cpu: [ia32]
@ -1208,10 +1122,10 @@ packages:
dev: false
optional: true
/@next/swc-win32-x64-msvc/13.0.6-canary.1:
/@next/swc-win32-x64-msvc/13.0.4:
resolution:
{
integrity: sha512-KA6/9W7ZEfkN/ecH8f/fg+WyQaJnRG/UE2IKOdQHbL4uVtHJk5PQmYT+nBZFVnbNHJB2ouNmL4pFJM/7JjNBww==,
integrity: sha512-vXtbo9N1FdtZZRcv4BliU28tTYrkb1EnVpUiiFFe88I6kS9aZVTMY9Z/OtDR52rl1JF1hgs9sL/59D/TQqSATQ==,
}
engines: { node: ">= 10" }
cpu: [x64]
@ -1476,14 +1390,6 @@ packages:
tslib: 2.4.1
dev: true
/@planetscale/database/1.4.0:
resolution:
{
integrity: sha512-lva57Z/Nz57ocB3dwaWPDGMbb+dj5HtooVB9c0DPcAF9SHbQyfovDyGK5bDgcmCMVoonfblcYv7fr+WBLc3xNw==,
}
engines: { node: ">=16" }
dev: false
/@prisma/client/4.6.1_prisma@4.6.1:
resolution:
{
@ -2139,6 +2045,14 @@ packages:
react: 18.2.0
dev: false
/@resvg/resvg-wasm/2.0.0-alpha.4:
resolution:
{
integrity: sha512-pWIG9a/x1ky8gXKRhPH1OPKpHFoMN1ISLbJ+O+gPXQHIAKhNd5I28RlWf7q576hAOQA9JZTlo3p/M2uyLzJmmw==,
}
engines: { node: ">= 10" }
dev: false
/@rushstack/eslint-patch/1.2.0:
resolution:
{
@ -2146,10 +2060,22 @@ packages:
}
dev: true
/@swc/helpers/0.4.14:
/@shuding/opentype.js/1.4.0-beta.0:
resolution:
{
integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==,
integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==,
}
engines: { node: ">= 8.0.0" }
hasBin: true
dependencies:
fflate: 0.7.4
string.prototype.codepointat: 0.2.1
dev: false
/@swc/helpers/0.4.11:
resolution:
{
integrity: sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==,
}
dependencies:
tslib: 2.4.1
@ -2380,6 +2306,13 @@ packages:
integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==,
}
/@types/yoga-layout/1.9.2:
resolution:
{
integrity: sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==,
}
dev: false
/@typescript-eslint/parser/5.44.0_qugx7qdu5zevzvxaiqyxfiwquq:
resolution:
{
@ -2468,6 +2401,18 @@ packages:
react: 18.2.0
dev: false
/@vercel/og/0.0.21:
resolution:
{
integrity: sha512-WgMahG5c8UM7xtn/mT+ljUpDMSDnSlu8AXL52JtTwxb1odrd0GWqZg2N1X38wulPj+sCccNpDdFmmAuw0GLc+Q==,
}
engines: { node: ">=16" }
dependencies:
"@resvg/resvg-wasm": 2.0.0-alpha.4
satori: 0.0.44
yoga-wasm-web: 0.1.2
dev: false
/JSONStream/1.3.5:
resolution:
{
@ -2956,6 +2901,13 @@ packages:
engines: { node: ">=6" }
dev: true
/camelize/1.0.1:
resolution:
{
integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==,
}
dev: false
/caniuse-lite/1.0.30001434:
resolution:
{
@ -3334,6 +3286,39 @@ packages:
which: 2.0.2
dev: true
/css-background-parser/0.1.0:
resolution:
{
integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==,
}
dev: false
/css-box-shadow/1.0.0-3:
resolution:
{
integrity: sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==,
}
dev: false
/css-color-keywords/1.0.0:
resolution:
{
integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==,
}
engines: { node: ">=4" }
dev: false
/css-to-react-native/3.0.0:
resolution:
{
integrity: sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==,
}
dependencies:
camelize: 1.0.1
css-color-keywords: 1.0.0
postcss-value-parser: 4.2.0
dev: false
/cssesc/3.0.0:
resolution:
{
@ -3614,6 +3599,13 @@ packages:
}
dev: true
/emoji-regex/10.2.1:
resolution:
{
integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==,
}
dev: false
/emoji-regex/8.0.0:
resolution:
{
@ -4548,6 +4540,13 @@ packages:
web-streams-polyfill: 3.2.1
dev: false
/fflate/0.7.4:
resolution:
{
integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==,
}
dev: false
/file-entry-cache/6.0.1:
resolution:
{
@ -4645,36 +4644,6 @@ packages:
}
dev: true
/framer-motion/7.6.12_biqbaboplfbrettd7655fr4n2y:
resolution:
{
integrity: sha512-Xm1jPB91v6vIr9b+V3q6c96sPzU1jWdvN+Mv4CvIAY23ZIezGNIWxWNGIWj1We0CZ8SSOQkttz8921M10TQjXg==,
}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
dependencies:
"@motionone/dom": 10.13.1
framesync: 6.1.2
hey-listen: 1.0.8
popmotion: 11.0.5
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
style-value-types: 5.1.2
tslib: 2.4.0
optionalDependencies:
"@emotion/is-prop-valid": 0.8.8
dev: false
/framesync/6.1.2:
resolution:
{
integrity: sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==,
}
dependencies:
tslib: 2.4.0
dev: false
/fs-constants/1.0.0:
resolution:
{
@ -5187,13 +5156,6 @@ packages:
space-separated-tokens: 2.0.2
dev: true
/hey-listen/1.0.8:
resolution:
{
integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==,
}
dev: false
/hosted-git-info/2.8.9:
resolution:
{
@ -6893,7 +6855,7 @@ packages:
}
dev: true
/next-auth/4.17.0_thl2nqbeqzylnsbfarzmi6laiy:
/next-auth/4.17.0_icxl3uciip5l2ulzmmrvkhve3i:
resolution:
{
integrity: sha512-aN2tdnjS0MDeUpB2tBDOaWnegkgeMWrsccujbXRGMJ607b+EwRcy63MFGSr0OAboDJEe0902piXQkt94GqF8Qw==,
@ -6912,7 +6874,7 @@ packages:
"@panva/hkdf": 1.0.2
cookie: 0.5.0
jose: 4.11.1
next: 13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y
next: 13.0.4_biqbaboplfbrettd7655fr4n2y
nodemailer: 6.8.0
oauth: 0.9.15
openid-client: 5.3.0
@ -6923,7 +6885,7 @@ packages:
uuid: 8.3.2
dev: false
/next-contentlayer/0.2.9_cejjzyjft5qpe7pbv5t5jzassa:
/next-contentlayer/0.2.9_dcors23iqtgxrhrwosgnnc4xji:
resolution:
{
integrity: sha512-W3sDr86zqfjOc6WaKnIbYtR4mTbwQ/Kql/8FGpbk6cAAn42sHW9tuRpQi0mpdHOIIn1mg/ms/L/r7aM4rdk4gA==,
@ -6935,7 +6897,7 @@ packages:
dependencies:
"@contentlayer/core": 0.2.9
"@contentlayer/utils": 0.2.9
next: 13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y
next: 13.0.4_biqbaboplfbrettd7655fr4n2y
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
transitivePeerDependencies:
@ -6944,10 +6906,10 @@ packages:
- supports-color
dev: false
/next/13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y:
/next/13.0.4_biqbaboplfbrettd7655fr4n2y:
resolution:
{
integrity: sha512-aLHWxU8tMcsVKyStTQvfATZ8TzX/X/VbfV1erVn+pF4uI5+ETvAGWO1geo1FrLzrW+xB/h+9UPAUiqh21oVZEA==,
integrity: sha512-4P0MvbjPCI1E/UPL1GrTXtYlgFnbBbY3JQ+AMY8jYE2SwyvCWctEJySoRjveznAHjrl6TIjuAJeB8u1c2StYUQ==,
}
engines: { node: ">=14.6.0" }
hasBin: true
@ -6965,27 +6927,28 @@ packages:
sass:
optional: true
dependencies:
"@next/env": 13.0.6-canary.1
"@swc/helpers": 0.4.14
"@next/env": 13.0.4
"@swc/helpers": 0.4.11
caniuse-lite: 1.0.30001434
postcss: 8.4.14
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
styled-jsx: 5.1.0_react@18.2.0
use-sync-external-store: 1.2.0_react@18.2.0
optionalDependencies:
"@next/swc-android-arm-eabi": 13.0.6-canary.1
"@next/swc-android-arm64": 13.0.6-canary.1
"@next/swc-darwin-arm64": 13.0.6-canary.1
"@next/swc-darwin-x64": 13.0.6-canary.1
"@next/swc-freebsd-x64": 13.0.6-canary.1
"@next/swc-linux-arm-gnueabihf": 13.0.6-canary.1
"@next/swc-linux-arm64-gnu": 13.0.6-canary.1
"@next/swc-linux-arm64-musl": 13.0.6-canary.1
"@next/swc-linux-x64-gnu": 13.0.6-canary.1
"@next/swc-linux-x64-musl": 13.0.6-canary.1
"@next/swc-win32-arm64-msvc": 13.0.6-canary.1
"@next/swc-win32-ia32-msvc": 13.0.6-canary.1
"@next/swc-win32-x64-msvc": 13.0.6-canary.1
"@next/swc-android-arm-eabi": 13.0.4
"@next/swc-android-arm64": 13.0.4
"@next/swc-darwin-arm64": 13.0.4
"@next/swc-darwin-x64": 13.0.4
"@next/swc-freebsd-x64": 13.0.4
"@next/swc-linux-arm-gnueabihf": 13.0.4
"@next/swc-linux-arm64-gnu": 13.0.4
"@next/swc-linux-arm64-musl": 13.0.4
"@next/swc-linux-x64-gnu": 13.0.4
"@next/swc-linux-x64-musl": 13.0.4
"@next/swc-win32-arm64-msvc": 13.0.4
"@next/swc-win32-ia32-msvc": 13.0.4
"@next/swc-win32-x64-msvc": 13.0.4
transitivePeerDependencies:
- "@babel/core"
- babel-plugin-macros
@ -7457,18 +7420,6 @@ packages:
}
engines: { node: ">=0.10.0" }
/popmotion/11.0.5:
resolution:
{
integrity: sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==,
}
dependencies:
framesync: 6.1.2
hey-listen: 1.0.8
style-value-types: 5.1.2
tslib: 2.4.0
dev: false
/postcss-import/14.1.0_postcss@8.4.19:
resolution:
{
@ -8385,6 +8336,22 @@ packages:
}
dev: false
/satori/0.0.44:
resolution:
{
integrity: sha512-WKUxXC2qeyno6J3ucwwLozPL6j1HXOZiN5wIUf7iqAhlx1RUC/6ePIKHi7iPc3Cy6DYuZcJriZXxXkSdo2FQHg==,
}
engines: { node: ">=16" }
dependencies:
"@shuding/opentype.js": 1.4.0-beta.0
css-background-parser: 0.1.0
css-box-shadow: 1.0.0-3
css-to-react-native: 3.0.0
emoji-regex: 10.2.1
postcss-value-parser: 4.2.0
yoga-layout-prebuilt: 1.10.0
dev: false
/scheduler/0.23.0:
resolution:
{
@ -8663,6 +8630,13 @@ packages:
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
/string.prototype.codepointat/0.2.1:
resolution:
{
integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==,
}
dev: false
/string.prototype.matchall/4.0.8:
resolution:
{
@ -8797,16 +8771,6 @@ packages:
inline-style-parser: 0.1.1
dev: false
/style-value-types/5.1.2:
resolution:
{
integrity: sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==,
}
dependencies:
hey-listen: 1.0.8
tslib: 2.4.0
dev: false
/styled-jsx/5.1.0_react@18.2.0:
resolution:
{
@ -9099,13 +9063,6 @@ packages:
}
dev: true
/tslib/2.4.0:
resolution:
{
integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==,
}
dev: false
/tslib/2.4.1:
resolution:
{
@ -9444,6 +9401,17 @@ packages:
tslib: 2.4.1
dev: false
/use-sync-external-store/1.2.0_react@18.2.0:
resolution:
{
integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==,
}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
react: 18.2.0
dev: false
/util-deprecate/1.0.2:
resolution:
{
@ -9690,6 +9658,23 @@ packages:
engines: { node: ">=10" }
dev: true
/yoga-layout-prebuilt/1.10.0:
resolution:
{
integrity: sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==,
}
engines: { node: ">=8" }
dependencies:
"@types/yoga-layout": 1.9.2
dev: false
/yoga-wasm-web/0.1.2:
resolution:
{
integrity: sha512-8SkgawHcA0RUbMrnhxbaQkZDBi8rMed8pQHixkFF9w32zGhAwZ9/cOHWlpYfr6RCx42Yp3siV45/jPEkJxsk6w==,
}
dev: false
/zod/3.19.1:
resolution:
{

View file

@ -1,19 +1,3 @@
:root {
--shiki-color-text: #414141;
--shiki-color-background: transparent;
--shiki-token-constant: #114b84;
--shiki-token-string: #0e7226;
--shiki-token-comment: #aaa;
--shiki-token-keyword: #d32f2f;
--shiki-token-parameter: #ff9800;
--shiki-token-function: #6f42c1;
--shiki-token-string-expression: #0e7226;
--shiki-token-punctuation: #212121;
--shiki-token-link: #0e7226;
--nextra-shiki-deleted: #f00;
--nextra-shiki-inserted: #0e7226;
}
[data-rehype-pretty-code-fragment] code {
@apply grid min-w-full break-words rounded-none border-0 bg-transparent p-0 text-sm text-black;
counter-reset: line;
@ -32,13 +16,13 @@
color: gray;
}
[data-rehype-pretty-code-fragment] .line--highlighted {
@apply bg-slate-500 bg-opacity-10;
@apply bg-slate-300 bg-opacity-10;
}
[data-rehype-pretty-code-fragment] .line-highlighted span {
@apply relative;
}
[data-rehype-pretty-code-fragment] .word--highlighted {
@apply rounded-md bg-slate-500 bg-opacity-10 p-1;
@apply rounded-md bg-slate-300 bg-opacity-10 p-1;
}
[data-rehype-pretty-code-title] {
@apply mt-4 py-2 px-4 text-sm font-medium;

View file

@ -1,6 +1,7 @@
import * as AvatarPrimitive from "@radix-ui/react-avatar"
import { cn } from "@/lib/utils"
import Image, { ImageProps } from "next/image"
type AvatarProps = AvatarPrimitive.AvatarProps
@ -16,10 +17,28 @@ export function Avatar({ className, ...props }: AvatarProps) {
)
}
type AvatarImageProps = AvatarPrimitive.AvatarImageProps
Avatar.Image = function AvatarImage({
src,
className,
alt,
width = 32,
height = 32,
...props
}: ImageProps) {
if (!src) {
return <Avatar.Fallback />
}
Avatar.Image = function AvatarImage({ className, ...props }: AvatarImageProps) {
return <AvatarPrimitive.Image className={cn("", className)} {...props} />
return (
<Image
src={src}
className={cn("", className)}
alt={alt}
width={width}
height={height}
{...props}
/>
)
}
Avatar.Fallback = function AvatarFallback({