finalize site 🎉

This commit is contained in:
Jack Merrill 2023-06-14 22:44:22 -05:00
parent 6b0efea07c
commit f4318dcda8
No known key found for this signature in database
GPG Key ID: B8E3CDF57DD80CA5
15 changed files with 307 additions and 112 deletions

1
.vercelignore Normal file
View File

@ -0,0 +1 @@
/src/app/internal

View File

@ -10,6 +10,7 @@
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^2.0.18", "@heroicons/react": "^2.0.18",
"@next/bundle-analyzer": "^13.4.5",
"@radix-ui/react-context-menu": "^2.1.3", "@radix-ui/react-context-menu": "^2.1.3",
"@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.4",

View File

@ -62,7 +62,7 @@ export default function ProjectModal({
<Dialog.Root open onOpenChange={handleOpenChange}> <Dialog.Root open onOpenChange={handleOpenChange}>
<Dialog.Portal> <Dialog.Portal>
<Dialog.Overlay className="bg-zinc-900 opacity-75 data-[state=open]:animate-overlayShow fixed inset-0" /> <Dialog.Overlay className="bg-zinc-900 opacity-75 data-[state=open]:animate-overlayShow fixed inset-0" />
<Dialog.Content className="data-[state=open]:animate-contentShow overflow-y-scroll fixed top-[50%] left-[50%] w-[90vw] max-h-[85vh] max-w-[50vw] translate-x-[-50%] translate-y-[-50%] rounded-[6px] bg-white dark:bg-zinc-800 px-8 py-12 shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none"> <Dialog.Content className="data-[state=open]:animate-contentShow overflow-y-scroll fixed top-[50%] left-[50%] w-[90vw] max-h-[85vh] md:max-w-[50vw] max-w-[90vw] translate-x-[-50%] translate-y-[-50%] rounded-[6px] bg-white dark:bg-zinc-800 px-8 py-12 shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none">
<Dialog.Title <Dialog.Title
className={cn( className={cn(
"dark:text-white text-indigo-600 m-0 text-6xl font-bold", "dark:text-white text-indigo-600 m-0 text-6xl font-bold",

View File

@ -6,19 +6,21 @@ import Link from "next/link";
export default async function Page() { export default async function Page() {
return ( return (
<div className="grid grid-cols-5 gap-4 mx-auto max-w-7xl"> <div className="grid grid-cols-5 gap-4 px-4 mx-auto text-black max-w-7xl dark:text-white">
<div className="col-span-4 space-y-3"> <div className="col-span-4 space-y-3">
<h1 className="font-black text-8xl">Hey! I&apos;m Jack Merrill.</h1> <h1 className="text-4xl font-black md:text-8xl">
Hey! I&apos;m Jack Merrill.
</h1>
<p className="text-2xl"> <p className="text-xl md:text-2xl">
I&apos;m a software engineer, designer, and student from the United I&apos;m a software engineer, designer, and student from the United
States. I&apos;m working to bring accessible designs to the masses. States. I&apos;m working to bring accessible designs to the masses.
</p> </p>
</div> </div>
<div className="w-full h-full col-span-1 row-span-3 px-8 py-4 space-y-12 rounded-md bg-violet-500"> <div className="grid order-last w-full h-full grid-cols-2 px-8 py-4 rounded-md lg:order-none lg:space-y-12 gap-x-2 lg:row-span-3 lg:grid-cols-1 lg:col-span-1 col-span-full bg-violet-500">
<div className="flex justify-center w-full"> <div className="flex justify-center lg:w-full">
<div className="h-auto p-12 border-2 border-white rounded-md"> <div className="h-auto p-8 border-4 border-white aspect-square w-fit max-h-48 lg:p-12 md:p-10 sm:p-6 rounded-xl">
<Logo /> <Logo />
</div> </div>
</div> </div>
@ -27,9 +29,9 @@ export default async function Page() {
</div> </div>
<div className="col-span-4 space-y-3"> <div className="col-span-4 space-y-3">
<h2 className="text-6xl font-black">About Me</h2> <h2 className="text-3xl font-black md:text-6xl">About Me</h2>
<p className="text-2xl"> <p className="text-xl md:text-2xl">
I&apos;m a Division II (sophomore) student at Hampshire College, I&apos;m a Division II (sophomore) student at Hampshire College,
studying interaction design. I&apos;m also a full-stack web developer studying interaction design. I&apos;m also a full-stack web developer
at{" "} at{" "}
@ -43,8 +45,6 @@ export default async function Page() {
</Link> </Link>
. .
</p> </p>
<p className="text-2xl"></p>
</div> </div>
</div> </div>
); );

View File

@ -55,7 +55,7 @@ export default async function Page({
</div> </div>
{/* the content */} {/* the content */}
<article className="prose dark:prose-invert prose-zinc max-w-none lg:prose-xl"> <article className="mx-auto prose dark:prose-invert prose-zinc max-w-7xl lg:prose-xl">
<ReactMarkdown <ReactMarkdown
remarkPlugins={[remarkGfm]} remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw]} rehypePlugins={[rehypeRaw]}
@ -84,3 +84,13 @@ export default async function Page({
</div> </div>
); );
} }
export async function generateStaticParams() {
const { query, schema } = q("*")
.filterByType("post")
.grabOne$("slug.current", q.string());
const slugs = schema.parse(await client.fetch(query));
return slugs.map((slug) => ({ params: { id: slug } }));
}

View File

@ -12,7 +12,11 @@
import { NextStudio } from "next-sanity/studio"; import { NextStudio } from "next-sanity/studio";
import config from "../../../../../sanity.config"; import config from "../../../../../sanity.config";
const isDev = process.env.NODE_ENV === "development" || !process.env.NODE_ENV; const isDev =
process.env.NODE_ENV === "development" ||
!process.env.NODE_ENV ||
process.env.NEXT_PUBLIC_ENV === "development" ||
!process.env.NEXT_PUBLIC_ENV;
export default function StudioPage() { export default function StudioPage() {
return isDev ? <NextStudio config={config} /> : null; return isDev ? <NextStudio config={config} /> : null;

View File

@ -32,15 +32,15 @@ export default async function RootLayout({
}) { }) {
const { query: projectQuery, schema: projectSchema } = q("*") const { query: projectQuery, schema: projectSchema } = q("*")
.filterByType("project") .filterByType("project")
.slice(0, 3)
.order("publishedAt desc") .order("publishedAt desc")
.grab$({ .grab$({
title: q.string(), title: q.string(),
subtitle: q.string(), subtitle: q.string(),
slug: q.slug("slug"), slug: q.slug("slug"),
publishedAt: q.date(), publishedAt: q.date(),
mainImage: q("mainImage").grabOne$("asset->url", q.string()), mainImage: q("mainImage").grabOne$("asset->url", q.string().optional()),
}); })
.slice(0, 2);
const { query: blogQuery, schema: blogSchema } = q("*") const { query: blogQuery, schema: blogSchema } = q("*")
.filterByType("post") .filterByType("post")
@ -53,7 +53,8 @@ export default async function RootLayout({
categories: q("categories") categories: q("categories")
.filter() .filter()
.deref() .deref()
.grabOne$("title", q.string()), .grabOne$("title", q.string())
.nullable(),
}); });
const latestThreeProjects = projectSchema.parse( const latestThreeProjects = projectSchema.parse(
@ -74,13 +75,13 @@ export default async function RootLayout({
<main className="w-full min-h-full space-y-6">{children}</main> <main className="w-full min-h-full space-y-6">{children}</main>
<footer className="flex justify-center w-full py-8 bg-zinc-900"> <footer className="flex justify-center w-full py-8 dark:bg-zinc-900 bg-zinc-300">
<div className="flex items-center justify-between w-full max-w-7xl"> <div className="flex flex-col items-center w-full px-4 space-y-2 md:flex-row md:justify-between max-w-7xl">
<p className="flex items-center space-x-1 text-lg text-center text-zinc-100"> <p className="flex items-center space-x-1 text-lg text-center text-black dark:text-zinc-100">
Made with Made with
<Twemoji <Twemoji
emoji="❤️" emoji="❤️"
className="w-5 h-5 mx-1 text-red-500 transition-all duration-150 hover:scale-110" className="w-5 h-5 mx-1 text-red-500 hover:animate-heartbeat"
ext="svg" ext="svg"
/> />
by Jack Merrill by Jack Merrill
@ -93,20 +94,20 @@ export default async function RootLayout({
: "dev"} : "dev"}
</p> </p>
<div className="flex space-x-4"> <div className="flex space-x-4 text-black dark:text-zinc-100">
<Link <Link
href="https://www.linkedin.com/in/jack-merrill-39aa7520b/" href="https://www.linkedin.com/in/jack-merrill-39aa7520b/"
target="_blank" target="_blank"
> >
<LinkedInLogoIcon className="w-6 h-6 transition-colors duration-150 cursor-pointer text-zinc-100 hover:text-[#0a66c2]" /> <LinkedInLogoIcon className="w-6 h-6 transition-colors duration-150 cursor-pointer hover:text-[#0a66c2]" />
</Link> </Link>
<Link href="https://github.com/jackmerrill" target="_blank"> <Link href="https://github.com/jackmerrill" target="_blank">
<GitHubLogoIcon className="w-6 h-6 transition-colors duration-150 cursor-pointer text-zinc-100 hover:text-pink-500" /> <GitHubLogoIcon className="w-6 h-6 transition-colors duration-150 cursor-pointer hover:text-pink-500" />
</Link> </Link>
<Link href="https://twitter.com/jack__merrill" target="_blank"> <Link href="https://twitter.com/jack__merrill" target="_blank">
<TwitterLogoIcon className="w-6 h-6 transition-colors duration-150 cursor-pointer text-zinc-100 hover:text-[#1d9bf0]" /> <TwitterLogoIcon className="w-6 h-6 transition-colors duration-150 cursor-pointer hover:text-[#1d9bf0]" />
</Link> </Link>
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@ import Image from "next/image";
export default function Home() { export default function Home() {
return ( return (
<> <>
<section className="flex items-center px-6 py-48 mx-auto h-2/3 max-w-7xl"> <section className="flex items-center px-6 py-48 mx-auto text-black dark:text-white h-2/3 max-w-7xl">
<div className="space-y-4"> <div className="space-y-4">
<h1 className="flex items-center text-6xl font-bold gap-x-4"> <h1 className="flex items-center text-6xl font-bold gap-x-4">
<Twemoji <Twemoji
@ -38,15 +38,15 @@ export default function Home() {
</div> </div>
</section> </section>
<section className="px-6 py-28 bg-zinc-900"> <section className="px-6 py-28 dark:bg-zinc-900 bg-slate-100">
<div className="flex flex-col items-center mx-auto space-y-4 max-w-7xl"> <div className="flex flex-col items-center mx-auto space-y-4 max-w-7xl">
<h2 className="text-4xl font-bold">What I do</h2> <h2 className="text-4xl font-bold">What I do</h2>
<div className="grid grid-cols-4 gap-x-4"> <div className="grid gap-4 text-black md:grid-cols-2 lg:grid-cols-4 dark:text-zinc-100">
<div className="grid items-center grid-rows-2 p-4 group gap-y-2 bg-zinc-800"> <div className="grid items-center grid-rows-2 p-4 group gap-y-2 dark:bg-zinc-800 bg-slate-300">
<div></div> <div></div>
<div className="space-y-2"> <div className="space-y-2">
<FrameIcon className="w-12 h-12 transition-colors duration-150 text-zinc-100 group-hover:text-pink-500" /> <FrameIcon className="w-12 h-12 transition-colors duration-150 group-hover:text-pink-500" />
<h3 className="text-2xl font-semibold">UI Design</h3> <h3 className="text-2xl font-semibold">UI Design</h3>
<p className="text-lg"> <p className="text-lg">
Designing interfaces and websites that are accessible, usable, Designing interfaces and websites that are accessible, usable,
@ -55,10 +55,10 @@ export default function Home() {
</div> </div>
</div> </div>
<div className="grid items-center grid-rows-2 p-4 group gap-y-2 bg-zinc-800"> <div className="grid items-center grid-rows-2 p-4 group gap-y-2 dark:bg-zinc-800 bg-slate-300">
<div></div> <div></div>
<div className="space-y-2"> <div className="space-y-2">
<CodeIcon className="w-12 h-12 transition-colors duration-150 text-zinc-100 group-hover:text-teal-500" />{" "} <CodeIcon className="w-12 h-12 transition-colors duration-150 group-hover:text-teal-500" />{" "}
<h3 className="text-2xl font-semibold">Development</h3> <h3 className="text-2xl font-semibold">Development</h3>
<p className="text-lg"> <p className="text-lg">
Building websites and software that are fast, responsive, and Building websites and software that are fast, responsive, and
@ -67,10 +67,10 @@ export default function Home() {
</div> </div>
</div> </div>
<div className="grid items-center grid-rows-2 p-4 group gap-y-2 bg-zinc-800"> <div className="grid items-center grid-rows-2 p-4 group gap-y-2 dark:bg-zinc-800 bg-slate-300">
<div></div> <div></div>
<div className="space-y-2"> <div className="space-y-2">
<MagicWandIcon className="w-12 h-12 transition-colors duration-150 text-zinc-100 group-hover:text-indigo-500" />{" "} <MagicWandIcon className="w-12 h-12 transition-colors duration-150 group-hover:text-indigo-500" />{" "}
<h3 className="text-2xl font-semibold">Creative</h3> <h3 className="text-2xl font-semibold">Creative</h3>
<p className="text-lg"> <p className="text-lg">
Creating stunning designs and illustrations that are unique Creating stunning designs and illustrations that are unique
@ -79,10 +79,10 @@ export default function Home() {
</div> </div>
</div> </div>
<div className="grid items-center grid-rows-2 p-4 group gap-y-2 bg-zinc-800"> <div className="grid items-center grid-rows-2 p-4 group gap-y-2 dark:bg-zinc-800 bg-slate-300">
<div></div> <div></div>
<div className="space-y-2"> <div className="space-y-2">
<ScissorsIcon className="w-12 h-12 transition-colors duration-150 text-zinc-100 group-hover:text-green-500" />{" "} <ScissorsIcon className="w-12 h-12 transition-colors duration-150 group-hover:text-green-500" />{" "}
<h3 className="text-2xl font-semibold">Other</h3> <h3 className="text-2xl font-semibold">Other</h3>
<p className="text-lg"> <p className="text-lg">
I&apos;m always looking to learn new things and expand my I&apos;m always looking to learn new things and expand my
@ -95,8 +95,8 @@ export default function Home() {
</section> </section>
<section className="px-6 py-28"> <section className="px-6 py-28">
<div className="flex flex-col items-center mx-auto space-y-4 max-w-7xl"> <div className="flex flex-col items-center mx-auto space-y-4 text-center max-w-7xl">
<h2 className="text-4xl font-bold"> <h2 className="text-4xl font-bold text-black dark:text-zinc-100">
Tell me about your next project Tell me about your next project
</h2> </h2>

View File

@ -7,26 +7,25 @@ import remarkGfm from "remark-gfm";
import rehypeRaw from "rehype-raw"; import rehypeRaw from "rehype-raw";
export default async function Page({ export default async function Page({
params: { id: slug }, params: { id },
}: { }: {
params: { id: string }; params: { id: string };
}) { }) {
const { query: projectQuery, schema: projectSchema } = q("*") const { query: projectQuery, schema: projectSchema } = q("*")
.filterByType("project") .filterByType("project")
.filter(`slug.current == "${slug}"`) .filter(`slug.current == "${id}"`)
.grab$({ .grab$({
title: q.string(), title: q.string(),
subtitle: q.string(), subtitle: q.string(),
slug: q.slug("slug"), slug: q.slug("slug"),
publishedAt: q.date(), publishedAt: q.date(),
content: q.string(), content: q.string(),
mainImage: q("mainImage").grabOne$("asset->url", q.string()), mainImage: q("mainImage").grabOne$("asset->url", q.string().optional()),
}) });
.slice(0, 1);
const project = projectSchema.parse(await client.fetch(projectQuery))[0]; const project = projectSchema.parse(await client.fetch(projectQuery))[0];
const r = project.mainImage.match(/(?<width>\d+)x(?<height>\d+)/); const r = project.mainImage?.match(/(?<width>\d+)x(?<height>\d+)/);
return ( return (
<div className="flex flex-col items-center justify-center min-h-screen py-2"> <div className="flex flex-col items-center justify-center min-h-screen py-2">
@ -44,18 +43,20 @@ export default async function Page({
</h2> </h2>
</div> </div>
</div> </div>
<Image {project.mainImage && (
className="object-cover w-full h-full" <Image
src={project.mainImage} className="object-cover w-full h-full"
alt={project.title} src={project.mainImage}
width={parseInt(r?.groups?.width ?? "400")} alt={project.title}
height={parseInt(r?.groups?.height ?? "400")} width={parseInt(r?.groups?.width ?? "400")}
/> height={parseInt(r?.groups?.height ?? "400")}
/>
)}
</div> </div>
</div> </div>
{/* the content */} {/* the content */}
<article className="prose dark:prose-invert prose-zinc max-w-none lg:prose-xl"> <article className="px-4 pb-12 mx-auto prose dark:prose-invert prose-zinc max-w-7xl lg:prose-xl">
<ReactMarkdown <ReactMarkdown
remarkPlugins={[remarkGfm]} remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw]} rehypePlugins={[rehypeRaw]}
@ -84,3 +85,17 @@ export default async function Page({
</div> </div>
); );
} }
export async function generateStaticParams() {
const { query: projectQuery, schema: projectSchema } = q("*")
.filterByType("project")
.grabOne$("slug.current", q.string());
const projects = projectSchema.parse(await client.fetch(projectQuery));
return projects.map((project) => ({
params: {
slug: project,
},
}));
}

View File

@ -13,7 +13,7 @@ export default async function Page() {
subtitle: q.string(), subtitle: q.string(),
slug: q.slug("slug"), slug: q.slug("slug"),
publishedAt: q.date(), publishedAt: q.date(),
mainImage: q("mainImage").grabOne$("asset->url", q.string()), mainImage: q("mainImage").grabOne$("asset->url", q.string().optional()),
categories: q("categories") categories: q("categories")
.filter() .filter()
.deref() .deref()
@ -24,7 +24,7 @@ export default async function Page() {
return ( return (
<div> <div>
<section className="flex items-center px-6 py-48 mx-auto h-2/3 max-w-7xl"> <section className="flex items-center px-6 py-48 mx-auto text-black dark:text-white h-2/3 max-w-7xl">
<div className="space-y-4"> <div className="space-y-4">
<h1 className="flex items-center text-6xl font-bold gap-x-4"> <h1 className="flex items-center text-6xl font-bold gap-x-4">
<Twemoji emoji="🛠" ext="svg" /> Projects <Twemoji emoji="🛠" ext="svg" /> Projects
@ -35,39 +35,45 @@ export default async function Page() {
</div> </div>
</section> </section>
<div className="dark:bg-zinc-900"> <div className="dark:bg-zinc-900 bg-slate-200">
<section className="grid grid-cols-4 gap-4 py-8 mx-auto max-w-7xl"> <section className="grid gap-4 px-4 py-8 mx-auto md:grid-cols-4 max-w-7xl">
{projects.map((project) => { {projects.map((project) => {
const r = project.mainImage.match(/(?<width>\d+)x(?<height>\d+)/); const r = project.mainImage?.match(/(?<width>\d+)x(?<height>\d+)/);
return ( return (
<Link <Link
key={project.slug} key={project.slug}
className="flex flex-col items-center justify-center p-6 space-y-4 transition-all duration-150 rounded-md dark:bg-zinc-800 hover:scale-105" className="flex flex-col items-center justify-center h-full p-6 space-y-4 text-black transition-all duration-150 rounded-md dark:text-white dark:bg-zinc-800 bg-slate-300 hover:scale-105"
href={`/projects/${project.slug}`} href={`/projects/${project.slug}`}
> >
<Image <div>
src={project.mainImage} {project.mainImage && (
alt={project.title} <Image
width={parseInt(r?.groups?.width ?? "400")} src={project.mainImage}
height={parseInt(r?.groups?.height ?? "400")} alt={project.title}
/> width={parseInt(r?.groups?.width ?? "400")}
<h3 className="text-xl font-semibold">{project.title}</h3> height={parseInt(r?.groups?.height ?? "400")}
<p className="text-lg">{project.subtitle}</p> />
)}
<h3 className="text-xl font-semibold">{project.title}</h3>
<p className="text-lg">{project.subtitle}</p>
</div>
<p className="text-md text-zinc-400"> <p className="flex-grow">
Categories: <div className="flex flex-wrap flex-grow gap-1 text-md dark:text-zinc-400 text-slate-600">
{project.categories.map((category) => ( <span className="w-full">Categories:</span>
<span {project.categories.map((category) => (
key={category} <span
className="px-2 py-1 ml-2 text-sm font-semibold text-white bg-indigo-500 rounded-md" key={category}
> className="px-2 py-1 text-sm font-semibold text-white bg-indigo-500 rounded-md"
{category} >
</span> {category}
))} </span>
))}
</div>
</p> </p>
<div className="flex items-center space-x-2"> <div className="flex items-center mt-auto space-x-2">
<time <time
className="text-sm text-gray-500" className="text-sm text-gray-500"
dateTime={project.publishedAt.toISOString()} dateTime={project.publishedAt.toISOString()}

View File

@ -2,8 +2,8 @@
import { CopyIcon } from "@radix-ui/react-icons"; import { CopyIcon } from "@radix-ui/react-icons";
import { CopyCheckIcon } from "lucide-react"; import { CopyCheckIcon } from "lucide-react";
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { PrismAsync as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
const CodeBlock = ({ const CodeBlock = ({
@ -32,6 +32,7 @@ const CodeBlock = ({
}; };
const match = /language-(\w+)/.exec(className || ""); const match = /language-(\w+)/.exec(className || "");
return !inline && match ? ( return !inline && match ? (
<div className="relative"> <div className="relative">
<SyntaxHighlighter <SyntaxHighlighter

View File

@ -13,7 +13,12 @@ import {
} from "./ui/context-menu"; } from "./ui/context-menu";
import * as NavigationMenu from "@radix-ui/react-navigation-menu"; import * as NavigationMenu from "@radix-ui/react-navigation-menu";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { BackpackIcon, Pencil2Icon } from "@radix-ui/react-icons"; import {
ArrowRightIcon,
BackpackIcon,
Pencil2Icon,
} from "@radix-ui/react-icons";
import { ContextMenuSeparator } from "@radix-ui/react-context-menu";
export default function Navbar({ export default function Navbar({
projects, projects,
@ -24,40 +29,73 @@ export default function Navbar({
title: string; title: string;
subtitle: string; subtitle: string;
slug: string; slug: string;
mainImage: string; mainImage?: string;
}[]; }[];
blogPosts: { blogPosts: {
publishedAt: Date; publishedAt: Date;
title: string; title: string;
slug: string; slug: string;
categories: string[]; categories?: string[] | null;
}[]; }[];
}) { }) {
return ( return (
<div className="flex items-center w-full p-6 mx-auto max-w-7xl"> <div className="flex items-center justify-between w-full p-6 mx-auto md:justify-normal max-w-7xl">
<ContextMenu> <ContextMenu>
<ContextMenuTrigger> <ContextMenuTrigger>
<div className="p-4 bg-gray-800 rounded-md w-14 h-14 animate-rainbow-outline"> <Link href="/">
<Logo /> <div className="p-4 bg-gray-800 rounded-md w-14 h-14 animate-rainbow-outline">
</div> <Logo />
</div>
</Link>
</ContextMenuTrigger> </ContextMenuTrigger>
<ContextMenuContent> <ContextMenuContent>
<ContextMenuItem> <ContextMenuItem asChild>
<Link href="/">Home</Link> <Link href="/" className="cursor-pointer">
Home
</Link>
</ContextMenuItem>
<ContextMenuItem asChild>
<Link href="/projects" className="cursor-pointer">
Projects
</Link>
</ContextMenuItem>
<ContextMenuItem asChild>
<Link href="/blog" className="cursor-pointer">
Blog
</Link>
</ContextMenuItem>
<ContextMenuItem asChild>
<Link href="/about" className="cursor-pointer">
About
</Link>
</ContextMenuItem>
<ContextMenuSeparator className="h-[1px] dark:bg-gray-600 m-[5px]" />
<ContextMenuItem asChild>
<Link
href="mailto:contact@jackmerrill.com"
className="cursor-pointer"
>
Contact
</Link>
</ContextMenuItem> </ContextMenuItem>
</ContextMenuContent> </ContextMenuContent>
</ContextMenu> </ContextMenu>
<div className="flex items-center flex-grow min-h-full px-4"> <div className="flex items-center min-h-full md:px-4 md:flex-grow">
<NavigationMenu.Root className="relative z-[1] mx-auto w-full flex h-full justify-center font-bold "> <NavigationMenu.Root className="relative z-[1] mx-auto w-full flex h-full justify-center font-bold ">
<NavigationMenu.List className="flex m-0 list-none transition-all duration-150 rounded-full center text-slate-900 dark:text-white bg-slate-300 dark:bg-gray-800 hover:px-2"> <NavigationMenu.List className="flex m-0 list-none transition-all duration-150 rounded-full center text-slate-900 dark:text-white bg-slate-300 dark:bg-gray-800 md:hover:px-2">
<NavigationMenu.Item> <NavigationMenu.Item>
<NavigationMenu.Trigger className="hover:bg-gray-700 group flex select-none items-center justify-between gap-[2px] rounded-full h-full px-3 text-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]"> <NavigationMenu.Trigger className="dark:hover:bg-gray-700 hover:bg-slate-400 group flex select-none items-center justify-between gap-[2px] rounded-full h-full px-3 text-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]">
Projects Projects
</NavigationMenu.Trigger> </NavigationMenu.Trigger>
<NavigationMenu.Content className="data-[motion=from-start]:animate-enterFromLeft data-[motion=from-end]:animate-enterFromRight data-[motion=to-start]:animate-exitToLeft data-[motion=to-end]:animate-exitToRight absolute top-0 left-0 w-full sm:w-auto"> <NavigationMenu.Content className="data-[motion=from-start]:animate-enterFromLeft data-[motion=from-end]:animate-enterFromRight data-[motion=to-start]:animate-exitToLeft data-[motion=to-end]:animate-exitToRight absolute top-0 left-0 w-full sm:w-auto">
<ul className="m-0 grid list-none gap-x-[10px] p-[22px] sm:w-[500px] sm:grid-cols-5"> <ul className="m-0 grid list-none gap-[10px] p-[22px] sm:w-[500px] sm:grid-cols-5">
<li className="grid col-span-2 row-span-3"> <li className="hidden col-span-2 row-span-3 md:grid">
<NavigationMenu.Link asChild> <NavigationMenu.Link asChild>
<Link <Link
className="focus:shadow-purple-500 from-purple-500 to-indigo-500 flex className="focus:shadow-purple-500 from-purple-500 to-indigo-500 flex
@ -79,13 +117,13 @@ export default function Navbar({
{projects.map((project) => ( {projects.map((project) => (
<li <li
key={project.slug} key={project.slug}
className="col-span-3 transition duration-150 rounded-md hover:bg-gray-900" className="col-span-3 text-black transition duration-150 rounded-md dark:hover:bg-gray-900 hover:bg-slate-400 dark:text-white"
> >
<NavigationMenu.Link asChild> <NavigationMenu.Link asChild>
<Link <Link
href={`/projects/${project.slug}`} href={`/projects/${project.slug}`}
className={ className={
"focus:shadow-[0_0_0_2px] grid grid-cols-4 items-center focus:shadow-violet7 hover:bg-mauve3 select-none rounded-[6px] p-3 text-[15px] leading-none no-underline outline-none transition-colors" "focus:shadow-[0_0_0_2px] grid md:grid-cols-4 items-center focus:shadow-violet7 hover:bg-mauve3 select-none rounded-[6px] p-3 text-[15px] leading-none no-underline outline-none transition-colors"
} }
> >
<div className="col-span-3"> <div className="col-span-3">
@ -99,7 +137,7 @@ export default function Navbar({
{/* project image */} {/* project image */}
{project.mainImage && ( {project.mainImage && (
<div className="relative w-full h-full overflow-hidden rounded-md"> <div className="relative hidden w-full h-full overflow-hidden rounded-md md:block">
<Image <Image
src={project.mainImage} src={project.mainImage}
alt="" alt=""
@ -113,17 +151,34 @@ export default function Navbar({
</NavigationMenu.Link> </NavigationMenu.Link>
</li> </li>
))} ))}
<li className="col-span-3 text-black transition duration-150 rounded-md md:hidden dark:hover:bg-gray-900 hover:bg-slate-400 dark:text-white">
<NavigationMenu.Link asChild>
<Link
href="/projects"
className={
"focus:shadow-[0_0_0_2px] flex items-center justify-between focus:shadow-violet7 hover:bg-mauve3 select-none rounded-[6px] p-3 text-[15px] leading-none no-underline outline-none transition-colors"
}
>
<p className="font-bold leading-[1.2]">
See all projects
</p>
<ArrowRightIcon className="w-5 h-5" />
</Link>
</NavigationMenu.Link>
</li>
</ul> </ul>
</NavigationMenu.Content> </NavigationMenu.Content>
</NavigationMenu.Item> </NavigationMenu.Item>
<NavigationMenu.Item> <NavigationMenu.Item>
<NavigationMenu.Trigger className="hover:bg-gray-700 h-full group flex select-none items-center justify-between gap-[2px] rounded-full px-3 py-2 text-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]"> <NavigationMenu.Trigger className="dark:hover:bg-gray-700 hover:bg-slate-400 h-full group flex select-none items-center justify-between gap-[2px] rounded-full px-3 py-2 text-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]">
Blog Blog
</NavigationMenu.Trigger> </NavigationMenu.Trigger>
<NavigationMenu.Content className="data-[motion=from-start]:animate-enterFromLeft data-[motion=from-end]:animate-enterFromRight data-[motion=to-start]:animate-exitToLeft data-[motion=to-end]:animate-exitToRight absolute top-0 left-0 w-full sm:w-auto"> <NavigationMenu.Content className="data-[motion=from-start]:animate-enterFromLeft data-[motion=from-end]:animate-enterFromRight data-[motion=to-start]:animate-exitToLeft data-[motion=to-end]:animate-exitToRight absolute top-0 left-0 w-full sm:w-auto">
<ul className="m-0 grid list-none gap-x-[10px] p-[22px] sm:w-[500px] sm:grid-cols-5"> <ul className="m-0 grid list-none gap-[10px] p-[22px] sm:w-[500px] sm:grid-cols-5">
<li className="grid col-span-2 row-span-3"> <li className="hidden col-span-2 row-span-3 md:grid">
<NavigationMenu.Link asChild> <NavigationMenu.Link asChild>
<Link <Link
className="focus:shadow-green-500 from-green-500 to-cyan-500 flex className="focus:shadow-green-500 from-green-500 to-cyan-500 flex
@ -144,7 +199,7 @@ export default function Navbar({
{blogPosts.map((post) => ( {blogPosts.map((post) => (
<li <li
key={post.slug} key={post.slug}
className="col-span-3 transition duration-150 rounded-md hover:bg-gray-900" className="col-span-3 text-black transition duration-150 rounded-md dark:hover:bg-gray-900 hover:bg-slate-400 dark:text-white"
> >
<NavigationMenu.Link asChild> <NavigationMenu.Link asChild>
<Link <Link
@ -156,20 +211,39 @@ export default function Navbar({
<div className="mb-[5px] font-bold leading-[1.2]"> <div className="mb-[5px] font-bold leading-[1.2]">
{post.title} {post.title}
</div> </div>
<p className="font-medium leading-[1.4]"> {post.categories && post.categories.length > 0 && (
Categories: {post.categories.join(", ")} <p className="font-medium leading-[1.4]">
</p> Categories: {post.categories.join(", ")}
</p>
)}
</Link> </Link>
</NavigationMenu.Link> </NavigationMenu.Link>
</li> </li>
))} ))}
<li className="col-span-3 text-black transition duration-150 rounded-md md:hidden dark:hover:bg-gray-900 hover:bg-slate-400 dark:text-white">
<NavigationMenu.Link asChild>
<Link
href="/blog"
className={
"focus:shadow-[0_0_0_2px] flex items-center justify-between focus:shadow-violet7 hover:bg-mauve3 select-none rounded-[6px] p-3 text-[15px] leading-none no-underline outline-none transition-colors"
}
>
<p className="font-bold leading-[1.2]">
See all blog posts
</p>
<ArrowRightIcon className="w-5 h-5" />
</Link>
</NavigationMenu.Link>
</li>
</ul> </ul>
</NavigationMenu.Content> </NavigationMenu.Content>
</NavigationMenu.Item> </NavigationMenu.Item>
<NavigationMenu.Item> <NavigationMenu.Item>
<NavigationMenu.Link <NavigationMenu.Link
className="hover:bg-gray-700 h-full items-center flex select-none rounded-full px-3 py-2 text-[15px] font-medium leading-none no-underline outline-none focus:shadow-[0_0_0_2px]" className="dark:hover:bg-gray-700 hover:bg-slate-400 h-full items-center flex select-none rounded-full px-3 py-2 text-[15px] font-medium leading-none no-underline outline-none focus:shadow-[0_0_0_2px]"
asChild asChild
> >
<Link href="/about">About</Link> <Link href="/about">About</Link>
@ -191,7 +265,7 @@ export default function Navbar({
</NavigationMenu.Root> </NavigationMenu.Root>
</div> </div>
<div className="flex items-center"> <div className="items-center hidden md:flex">
<Button link rainbow href="mailto:contact@jackmerrill.com"> <Button link rainbow href="mailto:contact@jackmerrill.com">
Contact Contact
</Button> </Button>

View File

@ -6,14 +6,17 @@ import * as Tooltip from "@radix-ui/react-tooltip";
export default function SidecardList() { export default function SidecardList() {
return ( return (
<Tooltip.Provider> <Tooltip.Provider>
<ul className="flex flex-col gap-4 mt-4"> <ul className="flex flex-col justify-center gap-4 lg:mt-4">
<Tooltip.Root> <Tooltip.Root>
<Tooltip.Trigger asChild> <Tooltip.Trigger asChild>
<li className="flex items-center gap-2 w-min"> <li className="flex items-center gap-2 w-min">
<PersonIcon className="w-6 h-6" /> <PersonIcon className="w-6 h-6" />
<span className="ml-2 font-semibold text-md"> <span className="ml-2 font-semibold text-md">
<span className="sr-only">Age</span> <span className="sr-only">Age</span>
{new Date().getFullYear() - 2004} {Math.floor(
(new Date().getTime() - new Date(2004, 7, 13).getTime()) /
31557600000
)}
</span> </span>
</li> </li>
</Tooltip.Trigger> </Tooltip.Trigger>
@ -43,11 +46,11 @@ export default function SidecardList() {
<Tooltip.Root> <Tooltip.Root>
<Tooltip.Trigger asChild> <Tooltip.Trigger asChild>
<li className="flex items-center w-full gap-2"> <li className="flex items-center gap-2 w-min min-w-fit">
<Crosshair2Icon className="w-6 h-6" /> <Crosshair2Icon className="w-6 h-6" />
<span className="ml-2 font-semibold text-md"> <span className="ml-2 font-semibold text-md">
<span className="sr-only">Location</span> <span className="sr-only">Location</span>
Chicago, IL / Amherst, MA Chicago, IL
</span> </span>
</li> </li>
</Tooltip.Trigger> </Tooltip.Trigger>

View File

@ -128,6 +128,11 @@ module.exports = {
from: { opacity: 0, transform: "translateX(-2px)" }, from: { opacity: 0, transform: "translateX(-2px)" },
to: { opacity: 1, transform: "translateX(0)" }, to: { opacity: 1, transform: "translateX(0)" },
}, },
heartbeat: {
"0%": { transform: "scale(1)" },
"50%": { transform: "scale(1.05)" },
"100%": { transform: "scale(1)" },
},
}, },
animation: { animation: {
"accordion-down": "accordion-down 0.2s ease-out", "accordion-down": "accordion-down 0.2s ease-out",
@ -148,6 +153,7 @@ module.exports = {
slideUpAndFade: "slideUpAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)", slideUpAndFade: "slideUpAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)",
slideRightAndFade: slideRightAndFade:
"slideRightAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)", "slideRightAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)",
heartbeat: "heartbeat 1s ease-in-out infinite",
}, },
}, },
}, },

View File

@ -812,6 +812,13 @@
dependencies: dependencies:
"@lezer/common" "^1.0.0" "@lezer/common" "^1.0.0"
"@next/bundle-analyzer@^13.4.5":
version "13.4.5"
resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-13.4.5.tgz#19877dea00c829b0a23a189d821591bd49e0bbfb"
integrity sha512-jrjJ/m7YHqYDuLSXaAWv6eUEgH0gTSFaNCLRxnO6wSJODNV6BMbfYZsa5RJFVGzApPHj4DTPrz0rxn/9flIAXA==
dependencies:
webpack-bundle-analyzer "4.7.0"
"@next/env@13.4.3": "@next/env@13.4.3":
version "13.4.3" version "13.4.3"
resolved "https://registry.npmjs.org/@next/env/-/env-13.4.3.tgz" resolved "https://registry.npmjs.org/@next/env/-/env-13.4.3.tgz"
@ -902,6 +909,11 @@
picocolors "^1.0.0" picocolors "^1.0.0"
tslib "^2.5.0" tslib "^2.5.0"
"@polka/url@^1.0.0-next.20":
version "1.0.0-next.21"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
"@portabletext/react@^1.0.6": "@portabletext/react@^1.0.6":
version "1.0.6" version "1.0.6"
resolved "https://registry.npmjs.org/@portabletext/react/-/react-1.0.6.tgz" resolved "https://registry.npmjs.org/@portabletext/react/-/react-1.0.6.tgz"
@ -2144,7 +2156,7 @@ acorn-walk@^7.0.0:
resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
acorn-walk@^8.0.2: acorn-walk@^8.0.0, acorn-walk@^8.0.2:
version "8.2.0" version "8.2.0"
resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz"
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
@ -2154,7 +2166,7 @@ acorn@^7.0.0:
resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.1.0, acorn@^8.8.0, acorn@^8.8.1: acorn@^8.0.4, acorn@^8.1.0, acorn@^8.8.0, acorn@^8.8.1:
version "8.8.2" version "8.8.2"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz" resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz"
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
@ -2565,7 +2577,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2:
escape-string-regexp "^1.0.5" escape-string-regexp "^1.0.5"
supports-color "^5.3.0" supports-color "^5.3.0"
"chalk@^3.0.0 || ^4.0.0", chalk@^4.0.0, chalk@^4.1.2: "chalk@^3.0.0 || ^4.0.0", chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -2741,6 +2753,11 @@ commander@^5.0.0:
resolved "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" resolved "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
commander@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
compress-commons@^4.1.0: compress-commons@^4.1.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz" resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz"
@ -3157,6 +3174,11 @@ dot-prop@^5.2.0:
dependencies: dependencies:
is-obj "^2.0.0" is-obj "^2.0.0"
duplexer@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
duplexify@^3.5.0, duplexify@^3.6.0: duplexify@^3.5.0, duplexify@^3.6.0:
version "3.7.1" version "3.7.1"
resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz" resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz"
@ -4161,6 +4183,13 @@ gunzip-maybe@^1.4.1:
pumpify "^1.3.3" pumpify "^1.3.3"
through2 "^2.0.3" through2 "^2.0.3"
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
dependencies:
duplexer "^0.1.2"
has-bigints@^1.0.1, has-bigints@^1.0.2: has-bigints@^1.0.1, has-bigints@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz"
@ -5597,6 +5626,11 @@ mri@^1.1.0:
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
mrmime@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27"
integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==
ms@2.0.0: ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
@ -5867,6 +5901,11 @@ open@^9.1.0:
is-inside-container "^1.0.0" is-inside-container "^1.0.0"
is-wsl "^2.2.0" is-wsl "^2.2.0"
opener@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
optionator@^0.8.1: optionator@^0.8.1:
version "0.8.3" version "0.8.3"
resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz"
@ -7021,6 +7060,15 @@ simple-wcswidth@^1.0.1:
resolved "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz" resolved "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz"
integrity sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg== integrity sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==
sirv@^1.0.7:
version "1.0.19"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49"
integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==
dependencies:
"@polka/url" "^1.0.0-next.20"
mrmime "^1.0.0"
totalist "^1.0.0"
slash@^3.0.0: slash@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
@ -7504,6 +7552,11 @@ toggle-selection@^1.0.6:
resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz" resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz"
integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==
totalist@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
tough-cookie@^4.1.2: tough-cookie@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz" resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz"
@ -7898,6 +7951,21 @@ webidl-conversions@^7.0.0:
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz"
integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
webpack-bundle-analyzer@4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66"
integrity sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg==
dependencies:
acorn "^8.0.4"
acorn-walk "^8.0.0"
chalk "^4.1.0"
commander "^7.2.0"
gzip-size "^6.0.0"
lodash "^4.17.20"
opener "^1.5.2"
sirv "^1.0.7"
ws "^7.3.1"
whatwg-encoding@^2.0.0: whatwg-encoding@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz" resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz"
@ -7987,6 +8055,11 @@ write-file-atomic@^3.0.0:
signal-exit "^3.0.2" signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5" typedarray-to-buffer "^3.1.5"
ws@^7.3.1:
version "7.5.9"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
ws@^8.11.0: ws@^8.11.0:
version "8.13.0" version "8.13.0"
resolved "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz" resolved "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz"