Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
492 changes: 11 additions & 481 deletions apps/docs/app/api/registry/[component]/route.ts

Large diffs are not rendered by default.

497 changes: 497 additions & 0 deletions apps/docs/app/api/registry/_lib/create-registry.ts

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions apps/docs/app/api/registry/base/[component]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createRegistryGET, createRegistryHandler } from "../../_lib/create-registry";

const registryPromise = createRegistryHandler({
elementsPackage: "elements-base",
uiPackageName: "@repo/base-ui",
registryStyle: "base",
uiImportPrefix: "@/registry/base/ui/",
utilsImportPrefix: "@/lib/",
apiBasePath: "/api/registry/base",
examplesPackage: "examples-base",
});

export const GET = createRegistryGET(registryPromise);
1 change: 1 addition & 0 deletions apps/docs/app/global.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import "tailwindcss";
@import "shadcn/tailwind.css";
@import "./styles/geistdocs.css";

@source "../**/*.{ts,tsx,mdx}";
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/components.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"style": "radix-vega",
"rsc": true,
"tsx": true,
"tailwind": {
Expand Down
68 changes: 68 additions & 0 deletions apps/docs/components/custom/elements-installer-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"use client";

import { CodeBlock } from "@/components/geistdocs/code-block";
import {
CodeBlockTab,
CodeBlockTabs,
CodeBlockTabsList,
CodeBlockTabsTrigger,
} from "@/components/geistdocs/code-block-tabs";
import { useUILibrary } from "@/hooks/geistdocs/use-ui-library";

interface VariantData {
elementsCommand: string;
shadcnCommand: string;
highlightedCode: string;
hasSource: boolean;
}

interface ElementsInstallerTabsProps {
radix: VariantData;
base: VariantData;
}

const HighlightedCodePreview = ({
highlightedCode,
}: {
highlightedCode: string;
}) => (
// oxlint-disable-next-line eslint-plugin-react(no-danger)
<pre dangerouslySetInnerHTML={{ __html: highlightedCode }} />
);

export const ElementsInstallerTabs = ({
radix,
base,
}: ElementsInstallerTabsProps) => {
const { library } = useUILibrary();
const data = library === "base" ? base : radix;

return (
<div className="not-prose">
<CodeBlockTabs defaultValue="ai-elements">
<CodeBlockTabsList>
<CodeBlockTabsTrigger value="ai-elements">
AI Elements
</CodeBlockTabsTrigger>
<CodeBlockTabsTrigger value="shadcn">shadcn CLI</CodeBlockTabsTrigger>
{data.hasSource && (
<CodeBlockTabsTrigger value="manual">Manual</CodeBlockTabsTrigger>
)}
</CodeBlockTabsList>
<CodeBlockTab className="not-prose" value="ai-elements">
<CodeBlock className="px-4">{data.elementsCommand}</CodeBlock>
</CodeBlockTab>
<CodeBlockTab className="not-prose" value="shadcn">
<CodeBlock className="px-4">{data.shadcnCommand}</CodeBlock>
</CodeBlockTab>
{data.hasSource && (
<CodeBlockTab className="not-prose" value="manual">
<CodeBlock className="max-h-[600px] overflow-y-auto">
<HighlightedCodePreview highlightedCode={data.highlightedCode} />
</CodeBlock>
</CodeBlockTab>
)}
</CodeBlockTabs>
</div>
);
};
103 changes: 47 additions & 56 deletions apps/docs/components/custom/elements-installer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,30 @@
import { readFile } from "node:fs/promises";
// oxlint-disable-next-line eslint-plugin-import(no-nodejs-modules)
import { join } from "node:path";

import { codeToHtml } from "shiki";

import { CodeBlock } from "@/components/geistdocs/code-block";
import {
CodeBlockTab,
CodeBlockTabs,
CodeBlockTabsList,
CodeBlockTabsTrigger,
} from "@/components/geistdocs/code-block-tabs";
import { ElementsInstallerTabs } from "./elements-installer-tabs";

interface ElementsInstallerProps {
path?: string;
}

const loadSourceCode = async (componentPath: string): Promise<string> => {
const loadSourceCode = async (
packageName: string,
componentPath: string
): Promise<string> => {
try {
const code = await readFile(
join(
process.cwd(),
"..",
"..",
"packages",
"elements",
packageName,
"src",
`${componentPath}.tsx`
),
"utf8"
"utf-8"
);
return code
.replaceAll("@ai-studio/shadcn-ui/", "@/")
Expand All @@ -44,61 +40,56 @@ const loadSourceCode = async (componentPath: string): Promise<string> => {
}
};

const getCommands = (path?: string) => {
const getCommands = (path?: string, variant?: "radix" | "base") => {
const registryPrefix =
variant === "base" ? "@ai-elements/base/" : "@ai-elements/";
const elementsCommand = path
? `npx ai-elements@latest add ${path}`
: "npx ai-elements@latest";
const shadcnCommand = path
? `npx shadcn@latest add @ai-elements/${path}`
: "npx shadcn@latest add @ai-elements/all";
? `npx shadcn@latest add ${registryPrefix}${path}`
: `npx shadcn@latest add ${registryPrefix}all`;
return { elementsCommand, shadcnCommand };
};

interface HighlightedCodePreviewProps {
highlightedCode: string;
}
export const ElementsInstaller = async ({ path }: ElementsInstallerProps) => {
const [radixSource, baseSource] = await Promise.all([
path ? loadSourceCode("elements", path) : Promise.resolve(""),
path ? loadSourceCode("elements-base", path) : Promise.resolve(""),
]);

const HighlightedCodePreview = ({
highlightedCode,
}: HighlightedCodePreviewProps) => (
// oxlint-disable-next-line eslint-plugin-react(no-danger)
<pre dangerouslySetInnerHTML={{ __html: highlightedCode }} />
);
const radixCommands = getCommands(path, "radix");
const baseCommands = getCommands(path, "base");

export const ElementsInstaller = async ({ path }: ElementsInstallerProps) => {
const sourceCode = path ? await loadSourceCode(path) : "";
const { elementsCommand, shadcnCommand } = getCommands(path);
const highlightedCode = await codeToHtml(sourceCode, {
lang: "tsx",
themes: { dark: "github-dark", light: "github-light" },
});
const [radixHighlighted, baseHighlighted] = await Promise.all([
radixSource
? codeToHtml(radixSource, {
lang: "tsx",
themes: { dark: "github-dark", light: "github-light" },
})
: Promise.resolve(""),
baseSource
? codeToHtml(baseSource, {
lang: "tsx",
themes: { dark: "github-dark", light: "github-light" },
})
: Promise.resolve(""),
]);

return (
<div className="not-prose">
<CodeBlockTabs defaultValue="ai-elements">
<CodeBlockTabsList>
<CodeBlockTabsTrigger value="ai-elements">
AI Elements
</CodeBlockTabsTrigger>
<CodeBlockTabsTrigger value="shadcn">shadcn CLI</CodeBlockTabsTrigger>
{sourceCode && (
<CodeBlockTabsTrigger value="manual">Manual</CodeBlockTabsTrigger>
)}
</CodeBlockTabsList>
<CodeBlockTab className="not-prose" value="ai-elements">
<CodeBlock className="px-4">{elementsCommand}</CodeBlock>
</CodeBlockTab>
<CodeBlockTab className="not-prose" value="shadcn">
<CodeBlock className="px-4">{shadcnCommand}</CodeBlock>
</CodeBlockTab>
{sourceCode && (
<CodeBlockTab className="not-prose" value="manual">
<CodeBlock className="max-h-[600px] overflow-y-auto">
<HighlightedCodePreview highlightedCode={highlightedCode} />
</CodeBlock>
</CodeBlockTab>
)}
</CodeBlockTabs>
</div>
<ElementsInstallerTabs
radix={{
elementsCommand: radixCommands.elementsCommand,
shadcnCommand: radixCommands.shadcnCommand,
highlightedCode: radixHighlighted,
hasSource: Boolean(radixSource),
}}
base={{
elementsCommand: baseCommands.elementsCommand,
shadcnCommand: baseCommands.shadcnCommand,
highlightedCode: baseHighlighted,
hasSource: Boolean(baseSource),
}}
/>
);
};
18 changes: 18 additions & 0 deletions apps/docs/components/custom/preview-library-switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use client";

import type { ReactNode } from "react";

import { useUILibrary } from "@/hooks/geistdocs/use-ui-library";

interface PreviewLibrarySwitchProps {
radix: ReactNode;
base: ReactNode;
}

export const PreviewLibrarySwitch = ({
radix,
base,
}: PreviewLibrarySwitchProps) => {
const { library } = useUILibrary();
return <>{library === "base" ? base : radix}</>;
};
Loading
Loading