UNPKG

fumadocs-ui

Version:

The Radix UI version of Fumadocs UI

126 lines (123 loc) 4.94 kB
'use client'; import { buttonVariants } from "./ui/button.js"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs.js"; import { cn } from "@fumadocs/ui/cn"; import { jsx, jsxs } from "react/jsx-runtime"; import { Check, Clipboard } from "lucide-react"; import { createContext, use, useMemo, useRef } from "react"; import { useCopyButton } from "@fumadocs/ui/hooks/use-copy-button"; import { mergeRefs } from "@fumadocs/ui/merge-refs"; //#region src/components/codeblock.tsx const TabsContext = createContext(null); function Pre(props) { return /* @__PURE__ */ jsx("pre", { ...props, className: cn("min-w-full w-max *:flex *:flex-col", props.className), children: props.children }); } function CodeBlock({ ref, title, allowCopy = true, keepBackground = false, icon, viewportProps = {}, children, Actions = (props$1) => /* @__PURE__ */ jsx("div", { ...props$1, className: cn("empty:hidden", props$1.className) }), ...props }) { const inTab = use(TabsContext) !== null; const areaRef = useRef(null); return /* @__PURE__ */ jsxs("figure", { ref, dir: "ltr", ...props, tabIndex: -1, className: cn(inTab ? "bg-fd-secondary -mx-px -mb-px last:rounded-b-xl" : "my-4 bg-fd-card rounded-xl", keepBackground && "bg-(--shiki-light-bg) dark:bg-(--shiki-dark-bg)", "shiki relative border shadow-sm not-prose overflow-hidden text-sm", props.className), children: [title ? /* @__PURE__ */ jsxs("div", { className: "flex text-fd-muted-foreground items-center gap-2 h-9.5 border-b px-4", children: [ typeof icon === "string" ? /* @__PURE__ */ jsx("div", { className: "[&_svg]:size-3.5", dangerouslySetInnerHTML: { __html: icon } }) : icon, /* @__PURE__ */ jsx("figcaption", { className: "flex-1 truncate", children: title }), Actions({ className: "-me-2", children: allowCopy && /* @__PURE__ */ jsx(CopyButton, { containerRef: areaRef }) }) ] }) : Actions({ className: "absolute top-3 right-2 z-2 backdrop-blur-lg rounded-lg text-fd-muted-foreground", children: allowCopy && /* @__PURE__ */ jsx(CopyButton, { containerRef: areaRef }) }), /* @__PURE__ */ jsx("div", { ref: areaRef, ...viewportProps, role: "region", tabIndex: 0, className: cn("text-[0.8125rem] py-3.5 overflow-auto max-h-[600px] fd-scroll-container focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-fd-ring", viewportProps.className), style: { "--padding-right": !title ? "calc(var(--spacing) * 8)" : void 0, counterSet: props["data-line-numbers"] ? `line ${Number(props["data-line-numbers-start"] ?? 1) - 1}` : void 0, ...viewportProps.style }, children })] }); } function CopyButton({ className, containerRef, ...props }) { const [checked, onClick] = useCopyButton(() => { const pre = containerRef.current?.getElementsByTagName("pre").item(0); if (!pre) return; const clone = pre.cloneNode(true); clone.querySelectorAll(".nd-copy-ignore").forEach((node) => { node.replaceWith("\n"); }); navigator.clipboard.writeText(clone.textContent ?? ""); }); return /* @__PURE__ */ jsx("button", { type: "button", "data-checked": checked || void 0, className: cn(buttonVariants({ className: "hover:text-fd-accent-foreground data-checked:text-fd-accent-foreground", size: "icon-xs" }), className), "aria-label": checked ? "Copied Text" : "Copy Text", onClick, ...props, children: checked ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(Clipboard, {}) }); } function CodeBlockTabs({ ref, ...props }) { const containerRef = useRef(null); const nested = use(TabsContext) !== null; return /* @__PURE__ */ jsx(Tabs, { ref: mergeRefs(containerRef, ref), ...props, className: cn("bg-fd-card rounded-xl border", !nested && "my-4", props.className), children: /* @__PURE__ */ jsx(TabsContext, { value: useMemo(() => ({ containerRef, nested }), [nested]), children: props.children }) }); } function CodeBlockTabsList(props) { return /* @__PURE__ */ jsx(TabsList, { ...props, className: cn("flex flex-row px-2 overflow-x-auto text-fd-muted-foreground", props.className), children: props.children }); } function CodeBlockTabsTrigger({ children, ...props }) { return /* @__PURE__ */ jsxs(TabsTrigger, { ...props, className: cn("relative group inline-flex text-sm font-medium text-nowrap items-center transition-colors gap-2 px-2 py-1.5 hover:text-fd-accent-foreground data-[state=active]:text-fd-primary [&_svg]:size-3.5", props.className), children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-x-2 bottom-0 h-px group-data-[state=active]:bg-fd-primary" }), children] }); } function CodeBlockTab(props) { return /* @__PURE__ */ jsx(TabsContent, { ...props }); } //#endregion export { CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, Pre }; //# sourceMappingURL=codeblock.js.map