TypeScript 97.5%
SQL 1.4%
Python 0.8%
1import * as React from "react";2import Link from "next/link";3import { cn } from "@/lib/utils";4import { InlineCode } from "@/components/ui/code-block";56/**7 * Prose primitives for the documentation. Implemented with plain Tailwind classes8 * (no typography plugin) so the docs share the exact tokens used by the product.9 */1011function textOf(node: React.ReactNode): string {12 if (node == null || typeof node === "boolean") return "";13 if (typeof node === "string" || typeof node === "number") return String(node);14 if (Array.isArray(node)) return node.map(textOf).join("");15 if (React.isValidElement<{ children?: React.ReactNode }>(node)) return textOf(node.props.children);16 return "";17}1819export function headingId(children: React.ReactNode, explicit?: string): string {20 if (explicit) return explicit;21 return (22 textOf(children)23 .normalize("NFD")24 .replace(/[̀-ͯ]/g, "")25 .toLowerCase()26 .trim()27 .replace(/[^a-z0-9]+/g, "-")28 .replace(/^-+|-+$/g, "")29 .slice(0, 80) || "section"30 );31}3233function AnchorLink({ id }: { id: string }) {34 return (35 <a36 href={`#${id}`}37 aria-label="Link to this section"38 className="ml-2 inline-block select-none text-fg-subtle/0 transition-colors group-hover:text-fg-subtle focus-visible:text-fg-subtle"39 >40 #41 </a>42 );43}4445export function H2({ id, children, className }: { id?: string; children: React.ReactNode; className?: string }) {46 const hid = headingId(children, id);47 return (48 <h2 id={hid} data-toc data-toc-level="2" className={cn("group mt-12 mb-4 scroll-mt-24 text-[20px] font-semibold tracking-tight text-fg first:mt-0", className)}>49 {children}50 <AnchorLink id={hid} />51 </h2>52 );53}5455export function H3({ id, children, className }: { id?: string; children: React.ReactNode; className?: string }) {56 const hid = headingId(children, id);57 return (58 <h3 id={hid} data-toc data-toc-level="3" className={cn("group mt-8 mb-3 scroll-mt-24 text-[15.5px] font-semibold tracking-tight text-fg", className)}>59 {children}60 <AnchorLink id={hid} />61 </h3>62 );63}6465export function H4({ children, className }: { children: React.ReactNode; className?: string }) {66 return <h4 className={cn("mt-6 mb-2 text-[13.5px] font-semibold text-fg", className)}>{children}</h4>;67}6869export function P({ children, className }: { children: React.ReactNode; className?: string }) {70 return <p className={cn("my-4 text-[14.5px] leading-[1.7] text-fg-muted", className)}>{children}</p>;71}7273export function Lead({ children, className }: { children: React.ReactNode; className?: string }) {74 return <p className={cn("my-4 text-[16px] leading-[1.65] text-fg-muted", className)}>{children}</p>;75}7677export function Strong({ children }: { children: React.ReactNode }) {78 return <strong className="font-medium text-fg">{children}</strong>;79}8081export function Ul({ children, className }: { children: React.ReactNode; className?: string }) {82 return <ul className={cn("my-4 list-disc space-y-1.5 pl-5 text-[14.5px] leading-[1.7] text-fg-muted marker:text-fg-subtle", className)}>{children}</ul>;83}8485export function Ol({ children, className }: { children: React.ReactNode; className?: string }) {86 return <ol className={cn("my-4 list-decimal space-y-1.5 pl-5 text-[14.5px] leading-[1.7] text-fg-muted marker:text-fg-subtle marker:tabular", className)}>{children}</ol>;87}8889export function Li({ children, className }: { children: React.ReactNode; className?: string }) {90 return <li className={cn("pl-0.5", className)}>{children}</li>;91}9293export function Code({ children }: { children: React.ReactNode }) {94 return <InlineCode>{children}</InlineCode>;95}9697export function A({ href, children, className }: { href: string; children: React.ReactNode; className?: string }) {98 const external = /^https?:\/\//.test(href) || href.startsWith("mailto:");99 const cls = cn("font-medium text-accent underline decoration-accent/30 underline-offset-[3px] transition-colors hover:decoration-accent", className);100 if (external) {101 return (102 <a href={href} className={cls} target={href.startsWith("mailto:") ? undefined : "_blank"} rel="noreferrer">103 {children}104 </a>105 );106 }107 return (108 <Link href={href} className={cls}>109 {children}110 </Link>111 );112}113114export function Kbd({ children }: { children: React.ReactNode }) {115 return <kbd className="rounded-[4px] border border-border bg-bg-muted px-1.5 py-0.5 font-mono text-[0.8em] text-fg">{children}</kbd>;116}117118export function Hr() {119 return <hr className="my-10 border-border" />;120}121122/* ---------------------------------------------------------------------------------------------- */123/* Tables */124/* ---------------------------------------------------------------------------------------------- */125126export function Table({ children, className, dense }: { children: React.ReactNode; className?: string; dense?: boolean }) {127 return (128 <div className={cn("my-5 overflow-x-auto rounded-lg border border-border scrollbar-thin", className)}>129 <table className={cn("w-full border-collapse text-left text-[13.5px] leading-relaxed", dense && "text-[13px]")}>{children}</table>130 </div>131 );132}133134export function THead({ children }: { children: React.ReactNode }) {135 return <thead className="bg-bg-subtle text-[12px] font-medium uppercase tracking-wide text-fg-subtle">{children}</thead>;136}137138export function TBody({ children }: { children: React.ReactNode }) {139 return <tbody className="divide-y divide-border">{children}</tbody>;140}141142export function Tr({ children, className }: { children: React.ReactNode; className?: string }) {143 return <tr className={cn("align-top", className)}>{children}</tr>;144}145146export function Th({ children, className }: { children?: React.ReactNode; className?: string }) {147 return <th className={cn("px-3.5 py-2 font-medium", className)}>{children}</th>;148}149150export function Td({ children, className, mono }: { children?: React.ReactNode; className?: string; mono?: boolean }) {151 return <td className={cn("px-3.5 py-2.5 text-fg-muted", mono && "font-mono text-[12.5px] text-fg", className)}>{children}</td>;152}153154/* ---------------------------------------------------------------------------------------------- */155/* Small layout helpers */156/* ---------------------------------------------------------------------------------------------- */157158export function Steps({ children }: { children: React.ReactNode }) {159 return <ol className="my-6 space-y-0 border-l border-border pl-0 [counter-reset:step]">{children}</ol>;160}161162export function Step({ title, children }: { title: React.ReactNode; children?: React.ReactNode }) {163 return (164 <li className="relative pb-8 pl-8 last:pb-0 [counter-increment:step]">165 <span166 aria-hidden167 className="absolute -left-[13px] top-0 flex size-[26px] items-center justify-center rounded-full border border-border bg-bg font-mono text-[11.5px] font-medium text-fg-muted tabular before:content-[counter(step)]"168 />169 <div className="text-[15px] font-semibold text-fg">{title}</div>170 {children ? <div className="mt-1 [&>p]:my-2 [&>ul]:my-2">{children}</div> : null}171 </li>172 );173}174175export function CardGrid({ children, className }: { children: React.ReactNode; className?: string }) {176 return <div className={cn("my-6 grid gap-3 sm:grid-cols-2", className)}>{children}</div>;177}178179export function LinkCard({ href, title, description }: { href: string; title: string; description: string }) {180 return (181 <Link href={href} className="group rounded-lg border border-border bg-bg p-4 transition-colors hover:border-border-strong hover:bg-bg-subtle">182 <div className="flex items-center justify-between gap-2 text-[14px] font-medium text-fg">183 {title}184 <span aria-hidden className="text-fg-subtle transition-transform group-hover:translate-x-0.5">185 →186 </span>187 </div>188 <p className="mt-1 text-[13px] leading-relaxed text-fg-muted">{description}</p>189 </Link>190 );191}192