Openstatus www.openstatus.dev

๐Ÿ’… prettier (#195)

authored by

Thibault Le Ouay and committed by
GitHub
70cba955 f34d297d

+466 -460
+1 -1
.github/workflows/lint.yml
··· 66 66 run: pnpm install 67 67 68 68 - name: ๐Ÿ’… Prettier check 69 - run: pnpm format 69 + run: pnpm format:check
+2 -1
apps/docs/theme.config.tsx
··· 8 8 chat: { 9 9 link: "https://discord.com/invite/dHD4JtSfsn", 10 10 }, 11 - docsRepositoryBase: "https://github.com/openstatusHQ/openstatus/tree/main/apps/docs", 11 + docsRepositoryBase: 12 + "https://github.com/openstatusHQ/openstatus/tree/main/apps/docs", 12 13 footer: { 13 14 text: "OpenStatus Documentation", 14 15 },
+16 -13
apps/web/README.md
··· 3 3 First, run the development server: 4 4 5 5 ```bash 6 - yarn dev 6 + pnpm dev 7 7 ``` 8 8 9 - Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 10 - 11 - You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 12 - 13 - [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. 14 - 15 - The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 9 + Open [http://localhost:3000](http://localhost:3000) with your browser to see the 10 + result. 16 11 17 12 ## Learn More 18 13 19 14 To learn more about Next.js, take a look at the following resources: 20 15 21 - - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 22 - - [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. 16 + - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js 17 + features and API. 18 + - [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an 19 + interactive Next.js tutorial. 23 20 24 - You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 21 + You can check out 22 + [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your 23 + feedback and contributions are welcome! 25 24 26 25 ## Deploy on Vercel 27 26 28 - The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. 27 + The easiest way to deploy your Next.js app is to use the 28 + [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) 29 + from the creators of Next.js. 29 30 30 - Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 31 + Check out our 32 + [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more 33 + details.
+17 -17
apps/web/contentlayer.config.ts
··· 1 - import { makeSource } from "contentlayer/source-files"; 2 - import rehypeSlug from "rehype-slug"; 3 - import remarkGfm from "remark-gfm"; 4 - 5 - import { LegalPost } from "./src/contentlayer/documents/legal"; 6 - import { Post } from "./src/contentlayer/documents/post"; 7 - import autolinkHeadings from "./src/contentlayer/plugins/autolink-headings"; 8 - import prettyCode from "./src/contentlayer/plugins/pretty-code"; 9 - 10 - export default makeSource({ 11 - contentDirPath: "src/content/", 12 - documentTypes: [Post, LegalPost], 13 - mdx: { 14 - remarkPlugins: [remarkGfm], 15 - rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], 16 - }, 17 - }); 1 + import { makeSource } from "contentlayer/source-files"; 2 + import rehypeSlug from "rehype-slug"; 3 + import remarkGfm from "remark-gfm"; 4 + 5 + import { LegalPost } from "./src/contentlayer/documents/legal"; 6 + import { Post } from "./src/contentlayer/documents/post"; 7 + import autolinkHeadings from "./src/contentlayer/plugins/autolink-headings"; 8 + import prettyCode from "./src/contentlayer/plugins/pretty-code"; 9 + 10 + export default makeSource({ 11 + contentDirPath: "src/content/", 12 + documentTypes: [Post, LegalPost], 13 + mdx: { 14 + remarkPlugins: [remarkGfm], 15 + rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], 16 + }, 17 + });
+2 -2
apps/web/src/app/_components/background.tsx
··· 13 13 useMouseMove(); 14 14 return ( 15 15 <> 16 - <div className="fixed top-0 left-0 -z-50"> 17 - <div className="sticky top-0 left-0 h-screen w-screen overflow-hidden"> 16 + <div className="fixed left-0 top-0 -z-50"> 17 + <div className="sticky left-0 top-0 h-screen w-screen overflow-hidden"> 18 18 <div className="bg-muted-foreground/20 absolute inset-0 z-[-1]" /> 19 19 <div className="bg-gradient-radial from-muted-foreground/80 absolute left-[--x] top-[--y] z-[-1] h-56 w-56 -translate-x-1/2 -translate-y-1/2 rounded-full from-0% to-transparent to-90% blur-md" /> 20 20 <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
+99 -99
apps/web/src/app/blog/[slug]/page.tsx
··· 1 - import type { Metadata } from "next"; 2 - import { notFound } from "next/navigation"; 3 - import { allPosts } from "contentlayer/generated"; 4 - 5 - import { Mdx } from "@/components/content/mdx"; 6 - import { Shell } from "@/components/dashboard/shell"; 7 - import { BackButton } from "@/components/layout/back-button"; 8 - import { formatDate } from "@/lib/utils"; 9 - 10 - export const dynamic = "force-static"; 11 - 12 - export async function generateStaticParams() { 13 - return allPosts.map((post) => ({ 14 - slug: post.slug, 15 - })); 16 - } 17 - 18 - export async function generateMetadata({ 19 - params, 20 - }: { 21 - params: { slug: string }; 22 - }): Promise<Metadata | void> { 23 - const post = allPosts.find((post) => post.slug === params.slug); 24 - if (!post) { 25 - return; 26 - } 27 - const { title, publishedAt: publishedTime, description, slug, image } = post; 28 - 29 - return { 30 - title, 31 - description, 32 - openGraph: { 33 - title, 34 - description, 35 - type: "article", 36 - publishedTime, 37 - url: `https://www.openstatus.dev/blog/${slug}`, 38 - images: [ 39 - { 40 - url: `https://openstatus.dev/api/og/post?title=${title}&description=${description}&image=${image}`, 41 - }, 42 - ], 43 - }, 44 - twitter: { 45 - card: "summary_large_image", 46 - title, 47 - description, 48 - images: [ 49 - `https://openstatus.dev/api/og/post?title=${title}&description=${description}&image=${image}`, 50 - ], 51 - }, 52 - }; 53 - } 54 - 55 - export default function PostPage({ params }: { params: { slug: string } }) { 56 - const post = allPosts.find((post) => post.slug === params.slug); 57 - 58 - if (!post) { 59 - notFound(); 60 - } 61 - 62 - // TODO: add author.avatar and author.url 63 - return ( 64 - <> 65 - <BackButton href="/blog" /> 66 - <Shell className="sm:py-8 md:py-12"> 67 - <article className="grid gap-8"> 68 - <div className="mx-auto grid w-full max-w-prose gap-3"> 69 - <h1 className="font-cal mb-5 text-3xl">{post.title}</h1> 70 - <div className="border-border relative h-64 w-full overflow-hidden rounded-lg border"> 71 - {/* <Image 72 - src={post.image} 73 - fill={true} 74 - alt={post.title} 75 - className="object-cover" 76 - /> */} 77 - {/* HOTFIX: plain `img` */} 78 - <img 79 - src={post.image} 80 - alt={post.title} 81 - className="h-full w-full object-cover" 82 - /> 83 - </div> 84 - <p className="text-muted-foreground text-sm font-light"> 85 - {post.author.name} 86 - <span className="text-muted-foreground/70 mx-1">&bull;</span> 87 - {formatDate(new Date(post.publishedAt))} 88 - <span className="text-muted-foreground/70 mx-1">&bull;</span> 89 - {post.readingTime} 90 - </p> 91 - </div> 92 - <div className="mx-auto max-w-prose"> 93 - <Mdx code={post.body.code} /> 94 - </div> 95 - </article> 96 - </Shell> 97 - </> 98 - ); 99 - } 1 + import type { Metadata } from "next"; 2 + import { notFound } from "next/navigation"; 3 + import { allPosts } from "contentlayer/generated"; 4 + 5 + import { Mdx } from "@/components/content/mdx"; 6 + import { Shell } from "@/components/dashboard/shell"; 7 + import { BackButton } from "@/components/layout/back-button"; 8 + import { formatDate } from "@/lib/utils"; 9 + 10 + export const dynamic = "force-static"; 11 + 12 + export async function generateStaticParams() { 13 + return allPosts.map((post) => ({ 14 + slug: post.slug, 15 + })); 16 + } 17 + 18 + export async function generateMetadata({ 19 + params, 20 + }: { 21 + params: { slug: string }; 22 + }): Promise<Metadata | void> { 23 + const post = allPosts.find((post) => post.slug === params.slug); 24 + if (!post) { 25 + return; 26 + } 27 + const { title, publishedAt: publishedTime, description, slug, image } = post; 28 + 29 + return { 30 + title, 31 + description, 32 + openGraph: { 33 + title, 34 + description, 35 + type: "article", 36 + publishedTime, 37 + url: `https://www.openstatus.dev/blog/${slug}`, 38 + images: [ 39 + { 40 + url: `https://openstatus.dev/api/og/post?title=${title}&description=${description}&image=${image}`, 41 + }, 42 + ], 43 + }, 44 + twitter: { 45 + card: "summary_large_image", 46 + title, 47 + description, 48 + images: [ 49 + `https://openstatus.dev/api/og/post?title=${title}&description=${description}&image=${image}`, 50 + ], 51 + }, 52 + }; 53 + } 54 + 55 + export default function PostPage({ params }: { params: { slug: string } }) { 56 + const post = allPosts.find((post) => post.slug === params.slug); 57 + 58 + if (!post) { 59 + notFound(); 60 + } 61 + 62 + // TODO: add author.avatar and author.url 63 + return ( 64 + <> 65 + <BackButton href="/blog" /> 66 + <Shell className="sm:py-8 md:py-12"> 67 + <article className="grid gap-8"> 68 + <div className="mx-auto grid w-full max-w-prose gap-3"> 69 + <h1 className="font-cal mb-5 text-3xl">{post.title}</h1> 70 + <div className="border-border relative h-64 w-full overflow-hidden rounded-lg border"> 71 + {/* <Image 72 + src={post.image} 73 + fill={true} 74 + alt={post.title} 75 + className="object-cover" 76 + /> */} 77 + {/* HOTFIX: plain `img` */} 78 + <img 79 + src={post.image} 80 + alt={post.title} 81 + className="h-full w-full object-cover" 82 + /> 83 + </div> 84 + <p className="text-muted-foreground text-sm font-light"> 85 + {post.author.name} 86 + <span className="text-muted-foreground/70 mx-1">&bull;</span> 87 + {formatDate(new Date(post.publishedAt))} 88 + <span className="text-muted-foreground/70 mx-1">&bull;</span> 89 + {post.readingTime} 90 + </p> 91 + </div> 92 + <div className="mx-auto max-w-prose"> 93 + <Mdx code={post.body.code} /> 94 + </div> 95 + </article> 96 + </Shell> 97 + </> 98 + ); 99 + }
+39 -39
apps/web/src/app/blog/page.tsx
··· 1 - import Link from "next/link"; 2 - import { allPosts } from "contentlayer/generated"; 3 - 4 - import { Shell } from "@/components/dashboard/shell"; 5 - import { formatDate } from "@/lib/utils"; 6 - 7 - export default async function Post() { 8 - const posts = allPosts.sort( 9 - (a, b) => 10 - new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime(), 11 - ); 12 - 13 - return ( 14 - <Shell> 15 - <div className="grid gap-8"> 16 - <h1 className="text-foreground font-cal text-4xl">Blog</h1> 17 - <div> 18 - {posts.map((post) => ( 19 - <Link href={`/blog/${post.slug}`} key={post.slug}> 20 - <section> 21 - <p className="text-foreground font-cal text-2xl"> 22 - {post.title} 23 - </p> 24 - <p className="text-muted-foreground">{post.description}</p> 25 - <p className="text-muted-foreground mt-1 text-xs"> 26 - {post.author.name} 27 - <span className="text-muted-foreground/70 mx-1">&bull;</span> 28 - {formatDate(new Date(post.publishedAt))} 29 - <span className="text-muted-foreground/70 mx-1">&bull;</span> 30 - {post.readingTime} 31 - </p> 32 - </section> 33 - </Link> 34 - ))} 35 - </div> 36 - </div> 37 - </Shell> 38 - ); 39 - } 1 + import Link from "next/link"; 2 + import { allPosts } from "contentlayer/generated"; 3 + 4 + import { Shell } from "@/components/dashboard/shell"; 5 + import { formatDate } from "@/lib/utils"; 6 + 7 + export default async function Post() { 8 + const posts = allPosts.sort( 9 + (a, b) => 10 + new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime(), 11 + ); 12 + 13 + return ( 14 + <Shell> 15 + <div className="grid gap-8"> 16 + <h1 className="text-foreground font-cal text-4xl">Blog</h1> 17 + <div> 18 + {posts.map((post) => ( 19 + <Link href={`/blog/${post.slug}`} key={post.slug}> 20 + <section> 21 + <p className="text-foreground font-cal text-2xl"> 22 + {post.title} 23 + </p> 24 + <p className="text-muted-foreground">{post.description}</p> 25 + <p className="text-muted-foreground mt-1 text-xs"> 26 + {post.author.name} 27 + <span className="text-muted-foreground/70 mx-1">&bull;</span> 28 + {formatDate(new Date(post.publishedAt))} 29 + <span className="text-muted-foreground/70 mx-1">&bull;</span> 30 + {post.readingTime} 31 + </p> 32 + </section> 33 + </Link> 34 + ))} 35 + </div> 36 + </div> 37 + </Shell> 38 + ); 39 + }
+2 -2
apps/web/src/app/play/@modal/(..)monitor/[id]/page.tsx
··· 29 29 }) { 30 30 const search = searchParamsSchema.safeParse(searchParams); 31 31 const data = search.success 32 - // TODO: lets hard-code our `monitorId` here 33 - ? await getResponseListData({ monitorId: params.id, ...search.data }) 32 + ? // TODO: lets hard-code our `monitorId` here 33 + await getResponseListData({ monitorId: params.id, ...search.data }) 34 34 : await getResponseListData({ monitorId: params.id }); 35 35 36 36 if (!data) return <div>Something went wrong</div>;
+38 -38
apps/web/src/components/content/mdx-components.tsx
··· 1 - import * as React from "react"; 2 - import Link from "next/link"; 3 - import type { TweetProps } from "react-tweet"; 4 - import { Tweet } from "react-tweet"; 5 - 6 - export const components = { 7 - a: ({ 8 - href = "", 9 - ...props 10 - }: React.AnchorHTMLAttributes<HTMLAnchorElement>) => { 11 - if (href.startsWith("http")) { 12 - return ( 13 - <a 14 - className="text-foreground underline underline-offset-4 hover:no-underline" 15 - href={href} 16 - target="_blank" 17 - rel="noopener noreferrer" 18 - {...props} 19 - /> 20 - ); 21 - } 22 - 23 - return ( 24 - <Link 25 - href={href} 26 - className="text-foreground underline underline-offset-4 hover:no-underline" 27 - {...props} 28 - /> 29 - ); 30 - }, 31 - Tweet: (props: TweetProps) => { 32 - return ( 33 - <div data-theme="light" className="not-prose [&>div]:mx-auto"> 34 - <Tweet {...props} /> 35 - </div> 36 - ); 37 - }, 38 - }; 1 + import * as React from "react"; 2 + import Link from "next/link"; 3 + import type { TweetProps } from "react-tweet"; 4 + import { Tweet } from "react-tweet"; 5 + 6 + export const components = { 7 + a: ({ 8 + href = "", 9 + ...props 10 + }: React.AnchorHTMLAttributes<HTMLAnchorElement>) => { 11 + if (href.startsWith("http")) { 12 + return ( 13 + <a 14 + className="text-foreground underline underline-offset-4 hover:no-underline" 15 + href={href} 16 + target="_blank" 17 + rel="noopener noreferrer" 18 + {...props} 19 + /> 20 + ); 21 + } 22 + 23 + return ( 24 + <Link 25 + href={href} 26 + className="text-foreground underline underline-offset-4 hover:no-underline" 27 + {...props} 28 + /> 29 + ); 30 + }, 31 + Tweet: (props: TweetProps) => { 32 + return ( 33 + <div data-theme="light" className="not-prose [&>div]:mx-auto"> 34 + <Tweet {...props} /> 35 + </div> 36 + ); 37 + }, 38 + };
+18 -18
apps/web/src/components/content/mdx.tsx
··· 1 - import { getMDXComponent } from "next-contentlayer/hooks"; 2 - 3 - import { components } from "./mdx-components"; 4 - 5 - interface MdxProps { 6 - code: string; 7 - } 8 - 9 - export function Mdx({ code }: MdxProps) { 10 - const MDXComponent = getMDXComponent(code); 11 - 12 - return ( 13 - // FIXME: weird behaviour when `prose-headings:font-cal` and on mouse movement font gets bigger 14 - <div className="prose prose-neutral dark:prose-invert prose-pre:border prose-pre:border-border prose-pre:rounded-lg prose-img:rounded-lg prose-img:border prose-img:border-border"> 15 - <MDXComponent components={{ ...components }} /> 16 - </div> 17 - ); 18 - } 1 + import { getMDXComponent } from "next-contentlayer/hooks"; 2 + 3 + import { components } from "./mdx-components"; 4 + 5 + interface MdxProps { 6 + code: string; 7 + } 8 + 9 + export function Mdx({ code }: MdxProps) { 10 + const MDXComponent = getMDXComponent(code); 11 + 12 + return ( 13 + // FIXME: weird behaviour when `prose-headings:font-cal` and on mouse movement font gets bigger 14 + <div className="prose prose-neutral dark:prose-invert prose-pre:border prose-pre:border-border prose-pre:rounded-lg prose-img:rounded-lg prose-img:border prose-img:border-border"> 15 + <MDXComponent components={{ ...components }} /> 16 + </div> 17 + ); 18 + }
+5 -3
apps/web/src/components/tracker.tsx
··· 70 70 { 71 71 count: 0, 72 72 ok: 0, 73 - } 73 + }, 74 74 ); 75 75 76 76 const uptime = ··· 83 83 <div className="mb-1 flex justify-between text-sm sm:mb-2"> 84 84 <div className="flex items-center gap-2"> 85 85 <p className="text-foreground font-semibold">{name}</p> 86 - { description ? <MoreInfo {...{ url, id, context, description }} /> : null } 86 + {description ? ( 87 + <MoreInfo {...{ url, id, context, description }} /> 88 + ) : null} 87 89 </div> 88 90 <p className="text-muted-foreground font-light">{uptime}</p> 89 91 </div> ··· 208 210 209 211 // FIXME this is a temporary solution 210 212 const getStatus = ( 211 - ratio: number 213 + ratio: number, 212 214 ): { label: string; variant: "up" | "degraded" | "down" } => { 213 215 if (ratio >= 0.98) return { label: "Operational", variant: "up" }; 214 216 if (ratio >= 0.5) return { label: "Degraded", variant: "degraded" };
+16 -16
apps/web/src/components/ui/accordion.tsx
··· 1 - "use client" 1 + "use client"; 2 2 3 - import * as React from "react" 4 - import * as AccordionPrimitive from "@radix-ui/react-accordion" 5 - import { ChevronDown } from "lucide-react" 3 + import * as React from "react"; 4 + import * as AccordionPrimitive from "@radix-ui/react-accordion"; 5 + import { ChevronDown } from "lucide-react"; 6 6 7 - import { cn } from "@/lib/utils" 7 + import { cn } from "@/lib/utils"; 8 8 9 - const Accordion = AccordionPrimitive.Root 9 + const Accordion = AccordionPrimitive.Root; 10 10 11 11 const AccordionItem = React.forwardRef< 12 12 React.ElementRef<typeof AccordionPrimitive.Item>, ··· 17 17 className={cn("border-b", className)} 18 18 {...props} 19 19 /> 20 - )) 21 - AccordionItem.displayName = "AccordionItem" 20 + )); 21 + AccordionItem.displayName = "AccordionItem"; 22 22 23 23 const AccordionTrigger = React.forwardRef< 24 24 React.ElementRef<typeof AccordionPrimitive.Trigger>, ··· 29 29 ref={ref} 30 30 className={cn( 31 31 "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180", 32 - className 32 + className, 33 33 )} 34 34 {...props} 35 35 > ··· 37 37 <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" /> 38 38 </AccordionPrimitive.Trigger> 39 39 </AccordionPrimitive.Header> 40 - )) 41 - AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName 40 + )); 41 + AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; 42 42 43 43 const AccordionContent = React.forwardRef< 44 44 React.ElementRef<typeof AccordionPrimitive.Content>, ··· 47 47 <AccordionPrimitive.Content 48 48 ref={ref} 49 49 className={cn( 50 - "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down", 51 - className 50 + "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all", 51 + className, 52 52 )} 53 53 {...props} 54 54 > 55 55 <div className="pb-4 pt-0">{children}</div> 56 56 </AccordionPrimitive.Content> 57 - )) 58 - AccordionContent.displayName = AccordionPrimitive.Content.displayName 57 + )); 58 + AccordionContent.displayName = AccordionPrimitive.Content.displayName; 59 59 60 - export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } 60 + export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
+34 -34
apps/web/src/components/ui/alert-dialog.tsx
··· 1 - "use client" 1 + "use client"; 2 2 3 - import * as React from "react" 4 - import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" 3 + import * as React from "react"; 4 + import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; 5 5 6 - import { cn } from "@/lib/utils" 7 - import { buttonVariants } from "@/components/ui/button" 6 + import { buttonVariants } from "@/components/ui/button"; 7 + import { cn } from "@/lib/utils"; 8 8 9 - const AlertDialog = AlertDialogPrimitive.Root 9 + const AlertDialog = AlertDialogPrimitive.Root; 10 10 11 - const AlertDialogTrigger = AlertDialogPrimitive.Trigger 11 + const AlertDialogTrigger = AlertDialogPrimitive.Trigger; 12 12 13 13 const AlertDialogPortal = ({ 14 14 className, 15 15 ...props 16 16 }: AlertDialogPrimitive.AlertDialogPortalProps) => ( 17 17 <AlertDialogPrimitive.Portal className={cn(className)} {...props} /> 18 - ) 19 - AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName 18 + ); 19 + AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName; 20 20 21 21 const AlertDialogOverlay = React.forwardRef< 22 22 React.ElementRef<typeof AlertDialogPrimitive.Overlay>, ··· 24 24 >(({ className, children, ...props }, ref) => ( 25 25 <AlertDialogPrimitive.Overlay 26 26 className={cn( 27 - "fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", 28 - className 27 + "bg-background/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 backdrop-blur-sm", 28 + className, 29 29 )} 30 30 {...props} 31 31 ref={ref} 32 32 /> 33 - )) 34 - AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName 33 + )); 34 + AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; 35 35 36 36 const AlertDialogContent = React.forwardRef< 37 37 React.ElementRef<typeof AlertDialogPrimitive.Content>, ··· 42 42 <AlertDialogPrimitive.Content 43 43 ref={ref} 44 44 className={cn( 45 - "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full", 46 - className 45 + "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg md:w-full", 46 + className, 47 47 )} 48 48 {...props} 49 49 /> 50 50 </AlertDialogPortal> 51 - )) 52 - AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName 51 + )); 52 + AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; 53 53 54 54 const AlertDialogHeader = ({ 55 55 className, ··· 58 58 <div 59 59 className={cn( 60 60 "flex flex-col space-y-2 text-center sm:text-left", 61 - className 61 + className, 62 62 )} 63 63 {...props} 64 64 /> 65 - ) 66 - AlertDialogHeader.displayName = "AlertDialogHeader" 65 + ); 66 + AlertDialogHeader.displayName = "AlertDialogHeader"; 67 67 68 68 const AlertDialogFooter = ({ 69 69 className, ··· 72 72 <div 73 73 className={cn( 74 74 "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", 75 - className 75 + className, 76 76 )} 77 77 {...props} 78 78 /> 79 - ) 80 - AlertDialogFooter.displayName = "AlertDialogFooter" 79 + ); 80 + AlertDialogFooter.displayName = "AlertDialogFooter"; 81 81 82 82 const AlertDialogTitle = React.forwardRef< 83 83 React.ElementRef<typeof AlertDialogPrimitive.Title>, ··· 88 88 className={cn("text-lg font-semibold", className)} 89 89 {...props} 90 90 /> 91 - )) 92 - AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName 91 + )); 92 + AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; 93 93 94 94 const AlertDialogDescription = React.forwardRef< 95 95 React.ElementRef<typeof AlertDialogPrimitive.Description>, ··· 97 97 >(({ className, ...props }, ref) => ( 98 98 <AlertDialogPrimitive.Description 99 99 ref={ref} 100 - className={cn("text-sm text-muted-foreground", className)} 100 + className={cn("text-muted-foreground text-sm", className)} 101 101 {...props} 102 102 /> 103 - )) 103 + )); 104 104 AlertDialogDescription.displayName = 105 - AlertDialogPrimitive.Description.displayName 105 + AlertDialogPrimitive.Description.displayName; 106 106 107 107 const AlertDialogAction = React.forwardRef< 108 108 React.ElementRef<typeof AlertDialogPrimitive.Action>, ··· 113 113 className={cn(buttonVariants(), className)} 114 114 {...props} 115 115 /> 116 - )) 117 - AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName 116 + )); 117 + AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; 118 118 119 119 const AlertDialogCancel = React.forwardRef< 120 120 React.ElementRef<typeof AlertDialogPrimitive.Cancel>, ··· 125 125 className={cn( 126 126 buttonVariants({ variant: "outline" }), 127 127 "mt-2 sm:mt-0", 128 - className 128 + className, 129 129 )} 130 130 {...props} 131 131 /> 132 - )) 133 - AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName 132 + )); 133 + AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; 134 134 135 135 export { 136 136 AlertDialog, ··· 142 142 AlertDialogDescription, 143 143 AlertDialogAction, 144 144 AlertDialogCancel, 145 - } 145 + };
+48 -48
apps/web/src/components/ui/dropdown-menu.tsx
··· 1 - "use client" 1 + "use client"; 2 2 3 - import * as React from "react" 4 - import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" 5 - import { Check, ChevronRight, Circle } from "lucide-react" 3 + import * as React from "react"; 4 + import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; 5 + import { Check, ChevronRight, Circle } from "lucide-react"; 6 6 7 - import { cn } from "@/lib/utils" 7 + import { cn } from "@/lib/utils"; 8 8 9 - const DropdownMenu = DropdownMenuPrimitive.Root 9 + const DropdownMenu = DropdownMenuPrimitive.Root; 10 10 11 - const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger 11 + const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; 12 12 13 - const DropdownMenuGroup = DropdownMenuPrimitive.Group 13 + const DropdownMenuGroup = DropdownMenuPrimitive.Group; 14 14 15 - const DropdownMenuPortal = DropdownMenuPrimitive.Portal 15 + const DropdownMenuPortal = DropdownMenuPrimitive.Portal; 16 16 17 - const DropdownMenuSub = DropdownMenuPrimitive.Sub 17 + const DropdownMenuSub = DropdownMenuPrimitive.Sub; 18 18 19 - const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup 19 + const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; 20 20 21 21 const DropdownMenuSubTrigger = React.forwardRef< 22 22 React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>, 23 23 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & { 24 - inset?: boolean 24 + inset?: boolean; 25 25 } 26 26 >(({ className, inset, children, ...props }, ref) => ( 27 27 <DropdownMenuPrimitive.SubTrigger 28 28 ref={ref} 29 29 className={cn( 30 - "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent", 30 + "focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none", 31 31 inset && "pl-8", 32 - className 32 + className, 33 33 )} 34 34 {...props} 35 35 > 36 36 {children} 37 37 <ChevronRight className="ml-auto h-4 w-4" /> 38 38 </DropdownMenuPrimitive.SubTrigger> 39 - )) 39 + )); 40 40 DropdownMenuSubTrigger.displayName = 41 - DropdownMenuPrimitive.SubTrigger.displayName 41 + DropdownMenuPrimitive.SubTrigger.displayName; 42 42 43 43 const DropdownMenuSubContent = React.forwardRef< 44 44 React.ElementRef<typeof DropdownMenuPrimitive.SubContent>, ··· 47 47 <DropdownMenuPrimitive.SubContent 48 48 ref={ref} 49 49 className={cn( 50 - "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 51 - className 50 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg", 51 + className, 52 52 )} 53 53 {...props} 54 54 /> 55 - )) 55 + )); 56 56 DropdownMenuSubContent.displayName = 57 - DropdownMenuPrimitive.SubContent.displayName 57 + DropdownMenuPrimitive.SubContent.displayName; 58 58 59 59 const DropdownMenuContent = React.forwardRef< 60 60 React.ElementRef<typeof DropdownMenuPrimitive.Content>, ··· 65 65 ref={ref} 66 66 sideOffset={sideOffset} 67 67 className={cn( 68 - "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 69 - className 68 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md", 69 + className, 70 70 )} 71 71 {...props} 72 72 /> 73 73 </DropdownMenuPrimitive.Portal> 74 - )) 75 - DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName 74 + )); 75 + DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; 76 76 77 77 const DropdownMenuItem = React.forwardRef< 78 78 React.ElementRef<typeof DropdownMenuPrimitive.Item>, 79 79 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & { 80 - inset?: boolean 80 + inset?: boolean; 81 81 } 82 82 >(({ className, inset, ...props }, ref) => ( 83 83 <DropdownMenuPrimitive.Item 84 84 ref={ref} 85 85 className={cn( 86 - "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 86 + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 87 87 inset && "pl-8", 88 - className 88 + className, 89 89 )} 90 90 {...props} 91 91 /> 92 - )) 93 - DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName 92 + )); 93 + DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; 94 94 95 95 const DropdownMenuCheckboxItem = React.forwardRef< 96 96 React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>, ··· 99 99 <DropdownMenuPrimitive.CheckboxItem 100 100 ref={ref} 101 101 className={cn( 102 - "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 103 - className 102 + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 103 + className, 104 104 )} 105 105 checked={checked} 106 106 {...props} ··· 112 112 </span> 113 113 {children} 114 114 </DropdownMenuPrimitive.CheckboxItem> 115 - )) 115 + )); 116 116 DropdownMenuCheckboxItem.displayName = 117 - DropdownMenuPrimitive.CheckboxItem.displayName 117 + DropdownMenuPrimitive.CheckboxItem.displayName; 118 118 119 119 const DropdownMenuRadioItem = React.forwardRef< 120 120 React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>, ··· 123 123 <DropdownMenuPrimitive.RadioItem 124 124 ref={ref} 125 125 className={cn( 126 - "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 127 - className 126 + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 127 + className, 128 128 )} 129 129 {...props} 130 130 > ··· 135 135 </span> 136 136 {children} 137 137 </DropdownMenuPrimitive.RadioItem> 138 - )) 139 - DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName 138 + )); 139 + DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; 140 140 141 141 const DropdownMenuLabel = React.forwardRef< 142 142 React.ElementRef<typeof DropdownMenuPrimitive.Label>, 143 143 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { 144 - inset?: boolean 144 + inset?: boolean; 145 145 } 146 146 >(({ className, inset, ...props }, ref) => ( 147 147 <DropdownMenuPrimitive.Label ··· 149 149 className={cn( 150 150 "px-2 py-1.5 text-sm font-semibold", 151 151 inset && "pl-8", 152 - className 152 + className, 153 153 )} 154 154 {...props} 155 155 /> 156 - )) 157 - DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName 156 + )); 157 + DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; 158 158 159 159 const DropdownMenuSeparator = React.forwardRef< 160 160 React.ElementRef<typeof DropdownMenuPrimitive.Separator>, ··· 162 162 >(({ className, ...props }, ref) => ( 163 163 <DropdownMenuPrimitive.Separator 164 164 ref={ref} 165 - className={cn("-mx-1 my-1 h-px bg-muted", className)} 165 + className={cn("bg-muted -mx-1 my-1 h-px", className)} 166 166 {...props} 167 167 /> 168 - )) 169 - DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName 168 + )); 169 + DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; 170 170 171 171 const DropdownMenuShortcut = ({ 172 172 className, ··· 177 177 className={cn("ml-auto text-xs tracking-widest opacity-60", className)} 178 178 {...props} 179 179 /> 180 - ) 181 - } 182 - DropdownMenuShortcut.displayName = "DropdownMenuShortcut" 180 + ); 181 + }; 182 + DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; 183 183 184 184 export { 185 185 DropdownMenu, ··· 197 197 DropdownMenuSubContent, 198 198 DropdownMenuSubTrigger, 199 199 DropdownMenuRadioGroup, 200 - } 200 + };
+11 -11
apps/web/src/components/ui/hover-card.tsx
··· 1 - "use client" 1 + "use client"; 2 2 3 - import * as React from "react" 4 - import * as HoverCardPrimitive from "@radix-ui/react-hover-card" 3 + import * as React from "react"; 4 + import * as HoverCardPrimitive from "@radix-ui/react-hover-card"; 5 5 6 - import { cn } from "@/lib/utils" 6 + import { cn } from "@/lib/utils"; 7 7 8 - const HoverCard = HoverCardPrimitive.Root 8 + const HoverCard = HoverCardPrimitive.Root; 9 9 10 - const HoverCardTrigger = HoverCardPrimitive.Trigger 10 + const HoverCardTrigger = HoverCardPrimitive.Trigger; 11 11 12 12 const HoverCardContent = React.forwardRef< 13 13 React.ElementRef<typeof HoverCardPrimitive.Content>, ··· 18 18 align={align} 19 19 sideOffset={sideOffset} 20 20 className={cn( 21 - "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 22 - className 21 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 rounded-md border p-4 shadow-md outline-none", 22 + className, 23 23 )} 24 24 {...props} 25 25 /> 26 - )) 27 - HoverCardContent.displayName = HoverCardPrimitive.Content.displayName 26 + )); 27 + HoverCardContent.displayName = HoverCardPrimitive.Content.displayName; 28 28 29 - export { HoverCard, HoverCardTrigger, HoverCardContent } 29 + export { HoverCard, HoverCardTrigger, HoverCardContent };
+27 -27
apps/web/src/components/ui/select.tsx
··· 1 - "use client" 1 + "use client"; 2 2 3 - import * as React from "react" 4 - import * as SelectPrimitive from "@radix-ui/react-select" 5 - import { Check, ChevronDown } from "lucide-react" 3 + import * as React from "react"; 4 + import * as SelectPrimitive from "@radix-ui/react-select"; 5 + import { Check, ChevronDown } from "lucide-react"; 6 6 7 - import { cn } from "@/lib/utils" 7 + import { cn } from "@/lib/utils"; 8 8 9 - const Select = SelectPrimitive.Root 9 + const Select = SelectPrimitive.Root; 10 10 11 - const SelectGroup = SelectPrimitive.Group 11 + const SelectGroup = SelectPrimitive.Group; 12 12 13 - const SelectValue = SelectPrimitive.Value 13 + const SelectValue = SelectPrimitive.Value; 14 14 15 15 const SelectTrigger = React.forwardRef< 16 16 React.ElementRef<typeof SelectPrimitive.Trigger>, ··· 19 19 <SelectPrimitive.Trigger 20 20 ref={ref} 21 21 className={cn( 22 - "flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", 23 - className 22 + "border-input ring-offset-background placeholder:text-muted-foreground focus:ring-ring flex h-10 w-full items-center justify-between rounded-md border bg-transparent px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", 23 + className, 24 24 )} 25 25 {...props} 26 26 > ··· 29 29 <ChevronDown className="h-4 w-4 opacity-50" /> 30 30 </SelectPrimitive.Icon> 31 31 </SelectPrimitive.Trigger> 32 - )) 33 - SelectTrigger.displayName = SelectPrimitive.Trigger.displayName 32 + )); 33 + SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; 34 34 35 35 const SelectContent = React.forwardRef< 36 36 React.ElementRef<typeof SelectPrimitive.Content>, ··· 40 40 <SelectPrimitive.Content 41 41 ref={ref} 42 42 className={cn( 43 - "relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 43 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 min-w-[8rem] overflow-hidden rounded-md border shadow-md", 44 44 position === "popper" && 45 45 "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", 46 - className 46 + className, 47 47 )} 48 48 position={position} 49 49 {...props} ··· 52 52 className={cn( 53 53 "p-1", 54 54 position === "popper" && 55 - "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]" 55 + "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]", 56 56 )} 57 57 > 58 58 {children} 59 59 </SelectPrimitive.Viewport> 60 60 </SelectPrimitive.Content> 61 61 </SelectPrimitive.Portal> 62 - )) 63 - SelectContent.displayName = SelectPrimitive.Content.displayName 62 + )); 63 + SelectContent.displayName = SelectPrimitive.Content.displayName; 64 64 65 65 const SelectLabel = React.forwardRef< 66 66 React.ElementRef<typeof SelectPrimitive.Label>, ··· 71 71 className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} 72 72 {...props} 73 73 /> 74 - )) 75 - SelectLabel.displayName = SelectPrimitive.Label.displayName 74 + )); 75 + SelectLabel.displayName = SelectPrimitive.Label.displayName; 76 76 77 77 const SelectItem = React.forwardRef< 78 78 React.ElementRef<typeof SelectPrimitive.Item>, ··· 81 81 <SelectPrimitive.Item 82 82 ref={ref} 83 83 className={cn( 84 - "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 85 - className 84 + "focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 85 + className, 86 86 )} 87 87 {...props} 88 88 > ··· 94 94 95 95 <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText> 96 96 </SelectPrimitive.Item> 97 - )) 98 - SelectItem.displayName = SelectPrimitive.Item.displayName 97 + )); 98 + SelectItem.displayName = SelectPrimitive.Item.displayName; 99 99 100 100 const SelectSeparator = React.forwardRef< 101 101 React.ElementRef<typeof SelectPrimitive.Separator>, ··· 103 103 >(({ className, ...props }, ref) => ( 104 104 <SelectPrimitive.Separator 105 105 ref={ref} 106 - className={cn("-mx-1 my-1 h-px bg-muted", className)} 106 + className={cn("bg-muted -mx-1 my-1 h-px", className)} 107 107 {...props} 108 108 /> 109 - )) 110 - SelectSeparator.displayName = SelectPrimitive.Separator.displayName 109 + )); 110 + SelectSeparator.displayName = SelectPrimitive.Separator.displayName; 111 111 112 112 export { 113 113 Select, ··· 118 118 SelectLabel, 119 119 SelectItem, 120 120 SelectSeparator, 121 - } 121 + };
+12 -12
apps/web/src/components/ui/tooltip.tsx
··· 1 - "use client" 1 + "use client"; 2 2 3 - import * as React from "react" 4 - import * as TooltipPrimitive from "@radix-ui/react-tooltip" 3 + import * as React from "react"; 4 + import * as TooltipPrimitive from "@radix-ui/react-tooltip"; 5 5 6 - import { cn } from "@/lib/utils" 6 + import { cn } from "@/lib/utils"; 7 7 8 - const TooltipProvider = TooltipPrimitive.Provider 8 + const TooltipProvider = TooltipPrimitive.Provider; 9 9 10 - const Tooltip = TooltipPrimitive.Root 10 + const Tooltip = TooltipPrimitive.Root; 11 11 12 - const TooltipTrigger = TooltipPrimitive.Trigger 12 + const TooltipTrigger = TooltipPrimitive.Trigger; 13 13 14 14 const TooltipContent = React.forwardRef< 15 15 React.ElementRef<typeof TooltipPrimitive.Content>, ··· 19 19 ref={ref} 20 20 sideOffset={sideOffset} 21 21 className={cn( 22 - "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 23 - className 22 + "bg-popover text-popover-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md border px-3 py-1.5 text-sm shadow-md", 23 + className, 24 24 )} 25 25 {...props} 26 26 /> 27 - )) 28 - TooltipContent.displayName = TooltipPrimitive.Content.displayName 27 + )); 28 + TooltipContent.displayName = TooltipPrimitive.Content.displayName; 29 29 30 - export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } 30 + export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
+50 -50
apps/web/src/contentlayer/documents/post.ts
··· 1 - import { 2 - defineDocumentType, 3 - defineNestedType, 4 - } from "contentlayer/source-files"; 5 - import readingTime from "reading-time"; 6 - 7 - const Author = defineNestedType(() => ({ 8 - name: "Author", 9 - fields: { 10 - name: { type: "string", required: true }, 11 - url: { type: "string" }, 12 - avatar: { type: "string" }, 13 - }, 14 - })); 15 - 16 - export const Post = defineDocumentType(() => ({ 17 - name: "Post", 18 - contentType: "mdx", 19 - filePathPattern: "posts/*.mdx", 20 - fields: { 21 - title: { 22 - type: "string", 23 - required: true, 24 - }, 25 - description: { 26 - type: "string", 27 - required: true, 28 - }, 29 - image: { 30 - type: "string", 31 - required: true, 32 - }, 33 - publishedAt: { type: "date", required: true }, 34 - author: { 35 - type: "nested", // TODO: allow list of authors 36 - of: Author, 37 - required: true, 38 - }, 39 - }, 40 - computedFields: { 41 - slug: { 42 - type: "string", 43 - resolve: (post) => post._raw.sourceFileName.replace(/\.mdx$/, ""), 44 - }, 45 - readingTime: { 46 - type: "string", 47 - resolve: (post) => readingTime(post.body.raw).text, 48 - }, 49 - }, 50 - })); 1 + import { 2 + defineDocumentType, 3 + defineNestedType, 4 + } from "contentlayer/source-files"; 5 + import readingTime from "reading-time"; 6 + 7 + const Author = defineNestedType(() => ({ 8 + name: "Author", 9 + fields: { 10 + name: { type: "string", required: true }, 11 + url: { type: "string" }, 12 + avatar: { type: "string" }, 13 + }, 14 + })); 15 + 16 + export const Post = defineDocumentType(() => ({ 17 + name: "Post", 18 + contentType: "mdx", 19 + filePathPattern: "posts/*.mdx", 20 + fields: { 21 + title: { 22 + type: "string", 23 + required: true, 24 + }, 25 + description: { 26 + type: "string", 27 + required: true, 28 + }, 29 + image: { 30 + type: "string", 31 + required: true, 32 + }, 33 + publishedAt: { type: "date", required: true }, 34 + author: { 35 + type: "nested", // TODO: allow list of authors 36 + of: Author, 37 + required: true, 38 + }, 39 + }, 40 + computedFields: { 41 + slug: { 42 + type: "string", 43 + resolve: (post) => post._raw.sourceFileName.replace(/\.mdx$/, ""), 44 + }, 45 + readingTime: { 46 + type: "string", 47 + resolve: (post) => readingTime(post.body.raw).text, 48 + }, 49 + }, 50 + }));
+29 -29
apps/web/src/contentlayer/plugins/pretty-code.ts
··· 1 - import rehypePrettyCode from "rehype-pretty-code"; 2 - import type * as unified from "unified"; 3 - 4 - const prettyCode: unified.Pluggable<any[]> = [ 5 - rehypePrettyCode, 6 - { 7 - // prepacked themes 8 - // https://github.com/shikijs/shiki/blob/main/docs/themes.md 9 - theme: "github-light", 10 - 11 - // https://stackoverflow.com/questions/76549262/onvisithighlightedline-cannot-push-classname-using-rehype-pretty-code 12 - // FIXME: maybe properly type this 13 - onVisitLine(node: any) { 14 - // Prevent lines from collapsing in `display: grid` mode, and 15 - // allow empty lines to be copy/pasted 16 - if (node.children.length === 0) { 17 - node.children = [{ type: "text", value: " " }]; 18 - } 19 - node.properties.className = ["line"]; // add 'line' class to each line in the code block 20 - }, 21 - 22 - // FIXME: maybe properly type this 23 - onVisitHighlightedLine(node: any) { 24 - node.properties.className?.push("line--highlighted"); 25 - }, 26 - }, 27 - ]; 28 - 29 - export default prettyCode; 1 + import rehypePrettyCode from "rehype-pretty-code"; 2 + import type * as unified from "unified"; 3 + 4 + const prettyCode: unified.Pluggable<any[]> = [ 5 + rehypePrettyCode, 6 + { 7 + // prepacked themes 8 + // https://github.com/shikijs/shiki/blob/main/docs/themes.md 9 + theme: "github-light", 10 + 11 + // https://stackoverflow.com/questions/76549262/onvisithighlightedline-cannot-push-classname-using-rehype-pretty-code 12 + // FIXME: maybe properly type this 13 + onVisitLine(node: any) { 14 + // Prevent lines from collapsing in `display: grid` mode, and 15 + // allow empty lines to be copy/pasted 16 + if (node.children.length === 0) { 17 + node.children = [{ type: "text", value: " " }]; 18 + } 19 + node.properties.className = ["line"]; // add 'line' class to each line in the code block 20 + }, 21 + 22 + // FIXME: maybe properly type this 23 + onVisitHighlightedLine(node: any) { 24 + node.properties.className?.push("line--highlighted"); 25 + }, 26 + }, 27 + ]; 28 + 29 + export default prettyCode;