feat(www): code blocks package manager (#6075)

* feat(www): code blocks

* fix: code style
This commit is contained in:
shadcn
2024-12-14 19:13:06 +04:00
committed by GitHub
parent 102b0b0c62
commit 2f869a2590
7 changed files with 159 additions and 26 deletions

View File

@@ -0,0 +1,108 @@
"use client"
import * as React from "react"
import { CheckIcon, ClipboardIcon } from "lucide-react"
import { NpmCommands } from "@/types/unist"
import { useConfig } from "@/hooks/use-config"
import { copyToClipboardWithMeta } from "@/components/copy-button"
import { Tabs } from "@/registry/default/ui/tabs"
import { Button } from "@/registry/new-york/ui/button"
import { TabsContent, TabsList, TabsTrigger } from "@/registry/new-york/ui/tabs"
export function CodeBlockCommand({
__npmCommand__,
__yarnCommand__,
__pnpmCommand__,
__bunCommand__,
}: React.ComponentProps<"pre"> & NpmCommands) {
const [config, setConfig] = useConfig()
const [hasCopied, setHasCopied] = React.useState(false)
React.useEffect(() => {
if (hasCopied) {
const timer = setTimeout(() => setHasCopied(false), 2000)
return () => clearTimeout(timer)
}
}, [hasCopied])
const packageManager = config.packageManager || "pnpm"
const tabs = React.useMemo(() => {
return {
pnpm: __pnpmCommand__,
npm: __npmCommand__,
yarn: __yarnCommand__,
bun: __bunCommand__,
}
}, [__npmCommand__, __pnpmCommand__, __yarnCommand__, __bunCommand__])
const copyCommand = React.useCallback(() => {
const command = tabs[packageManager]
if (!command) {
return
}
copyToClipboardWithMeta(command, {
name: "copy_npm_command",
properties: {
command,
pm: packageManager,
},
})
setHasCopied(true)
}, [packageManager, tabs])
return (
<div className="relative mt-6 max-h-[650px] overflow-x-auto rounded-xl bg-zinc-950 dark:bg-zinc-900">
<Tabs
defaultValue={packageManager}
onValueChange={(value) => {
setConfig({
...config,
packageManager: value as "pnpm" | "npm" | "yarn" | "bun",
})
}}
>
<div className="flex items-center justify-between border-b border-zinc-800 bg-zinc-900 px-3 pt-2.5">
<TabsList className="h-7 translate-y-[2px] gap-3 bg-transparent p-0 pl-1">
{Object.entries(tabs).map(([key, value]) => {
return (
<TabsTrigger
key={key}
value={key}
className="rounded-none border-b border-transparent bg-transparent p-0 pb-1.5 font-mono text-zinc-400 data-[state=active]:border-b-zinc-50 data-[state=active]:bg-transparent data-[state=active]:text-zinc-50"
>
{key}
</TabsTrigger>
)
})}
</TabsList>
</div>
{Object.entries(tabs).map(([key, value]) => {
return (
<TabsContent key={key} value={key} className="mt-0">
<pre className="px-4 py-5">
<code
className="relative font-mono text-sm leading-none"
data-language="bash"
>
{value}
</code>
</pre>
</TabsContent>
)
})}
</Tabs>
<Button
size="icon"
variant="ghost"
className="absolute right-2.5 top-2 z-10 h-6 w-6 text-zinc-50 hover:bg-zinc-700 hover:text-zinc-50 [&_svg]:h-3 [&_svg]:w-3"
onClick={copyCommand}
>
<span className="sr-only">Copy</span>
{hasCopied ? <CheckIcon /> : <ClipboardIcon />}
</Button>
</div>
)
}

View File

@@ -11,6 +11,7 @@ import { Event } from "@/lib/events"
import { cn } from "@/lib/utils"
import { useConfig } from "@/hooks/use-config"
import { Callout } from "@/components/callout"
import { CodeBlockCommand } from "@/components/code-block-command"
import { CodeBlockWrapper } from "@/components/code-block-wrapper"
import { ComponentExample } from "@/components/component-example"
import { ComponentPreview } from "@/components/component-preview"
@@ -192,16 +193,30 @@ const components = {
__src__?: string
__event__?: Event["name"]
} & NpmCommands) => {
const isNpmCommand =
__npmCommand__ && __yarnCommand__ && __pnpmCommand__ && __bunCommand__
if (isNpmCommand) {
return (
<CodeBlockCommand
__npmCommand__={__npmCommand__}
__yarnCommand__={__yarnCommand__}
__pnpmCommand__={__pnpmCommand__}
__bunCommand__={__bunCommand__}
/>
)
}
return (
<StyleWrapper styleName={__style__}>
<pre
className={cn(
"mb-4 mt-6 max-h-[650px] overflow-x-auto rounded-lg border bg-zinc-950 py-4 dark:bg-zinc-900",
"mb-4 mt-6 max-h-[650px] overflow-x-auto rounded-xl bg-zinc-950 py-4 dark:bg-zinc-900",
className
)}
{...props}
/>
{__rawString__ && !__npmCommand__ && (
{__rawString__ && (
<CopyButton
value={__rawString__}
src={__src__}
@@ -209,20 +224,6 @@ const components = {
className={cn("absolute right-4 top-4", __withMeta__ && "top-16")}
/>
)}
{__npmCommand__ &&
__yarnCommand__ &&
__pnpmCommand__ &&
__bunCommand__ && (
<CopyNpmCommandButton
commands={{
__npmCommand__,
__yarnCommand__,
__pnpmCommand__,
__bunCommand__,
}}
className={cn("absolute right-4 top-4", __withMeta__ && "top-16")}
/>
)}
</StyleWrapper>
)
},