Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 114 additions & 5 deletions components/docs/component-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
import React, { useState, useEffect } from "react";
import { CodeBlock } from "@/components/ui/code-block";
import { InstallationTabs } from "@/components/docs/installation-tabs";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

export interface ComponentExample {
title: string;
Expand Down Expand Up @@ -102,6 +109,48 @@ export function ComponentPreview({
dependencies: false,
});

// Fonctions helper pour LLM et navigation
const copyPageContent = async () => {
const content = `# ${name}\n\n${description}\n\n## Installation\n\n\`\`\`bash\nnpx @nativeui/cli add ${registryName}\n\`\`\`\n\n## Code\n\n\`\`\`tsx\n${componentCode}\n\`\`\`\n\n## Usage\n\n\`\`\`tsx\n${previewCode}\n\`\`\``;
await navigator.clipboard.writeText(content);
};

const openInLLM = (llm: string) => {
const prompt = `I'm looking at this NativeUI documentation: https://nativeui.io/docs/components/${registryName}.md
Help me understand how to use it. Be ready to explain concepts, give examples, or help debug based on it.`;

const urls = {
chatgpt: `https://chat.openai.com/?q=${encodeURIComponent(prompt)}`,
claude: `https://claude.ai/new?q=${encodeURIComponent(prompt)}`
};

window.open(urls[llm as keyof typeof urls], '_blank');
};

const viewAsMarkdown = () => {
window.open(`/docs/components/${registryName}.md`, '_blank');
};

const navigateToComponent = (direction: 'next' | 'prev') => {
// Liste des composants (à adapter selon votre structure)
const components = ['accordion', 'alert', 'alert-dialog', 'avatar', 'badge', 'breadcrumb', 'button', 'calendar', 'card', 'carousel', 'checkbox', 'collapsible', 'combobox', 'date-time-picker', 'dialog', 'drawer', 'dropdown', 'input', 'input-otp', 'label', 'pagination', 'popover', 'progress', 'radio-group', 'select', 'separator', 'sheet', 'skeleton', 'slider', 'switch', 'table', 'tabs', 'textarea', 'toggle', 'toggle-group', 'tooltip'];

const currentIndex = components.indexOf(registryName);
if (currentIndex === -1) return;

let targetIndex;
if (direction === 'next') {
targetIndex = currentIndex + 1;
if (targetIndex >= components.length) targetIndex = 0;
} else {
targetIndex = currentIndex - 1;
if (targetIndex < 0) targetIndex = components.length - 1;
}

const targetComponent = components[targetIndex];
window.location.href = `/docs/components/${targetComponent}`;
};

useEffect(() => {
const loadAllResources = async () => {
setIsLoading(true);
Expand Down Expand Up @@ -162,7 +211,67 @@ export function ComponentPreview({
return (
<div className="container max-w-3xl py-10">
<div className="space-y-4">
<h1 className="text-3xl font-bold tracking-tight">{name}</h1>
<div className="flex items-center justify-between">
<h1 className="text-3xl font-bold tracking-tight">{name}</h1>
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="sm"
onClick={() => navigateToComponent('prev')}
className="text-muted-foreground hover:text-foreground"
>
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => navigateToComponent('next')}
className="text-muted-foreground hover:text-foreground"
>
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="sm" className="gap-2">
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
Copy Page
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuItem onClick={copyPageContent}>
<svg className="h-4 w-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
Copy as Markdown
</DropdownMenuItem>
<DropdownMenuItem onClick={viewAsMarkdown}>
<svg className="h-4 w-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
View as Markdown
</DropdownMenuItem>
<DropdownMenuItem onClick={() => openInLLM('chatgpt')}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M22.282 9.821a5.985 5.985 0 0 0-.516-4.91 6.046 6.046 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a5.985 5.985 0 0 0-3.998 2.9 6.046 6.046 0 0 0 .743 7.097 5.98 5.98 0 0 0 .51 4.911 6.051 6.051 0 0 0 6.515 2.9A5.985 5.985 0 0 0 13.26 24a6.056 6.056 0 0 0 5.772-4.206 5.99 5.99 0 0 0 3.997-2.9 6.056 6.056 0 0 0-.747-7.073zM13.26 22.43a4.476 4.476 0 0 1-2.876-1.04l.141-.081 4.779-2.758a.795.795 0 0 0 .392-.681v-6.737l2.02 1.168a.071.071 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494zM3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085 4.783 2.759a.771.771 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646zM2.34 7.896a4.485 4.485 0 0 1 2.366-1.973V11.6a.766.766 0 0 0 .388.676l5.815 3.355-2.02 1.168a.076.076 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855-5.833-3.387L15.119 7.2a.076.076 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667zm2.01-3.023-.141-.085-4.774-2.782a.776.776 0 0 0-.785 0L9.409 9.23V6.897a.066.066 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08-4.778 2.758a.795.795 0 0 0-.393.681zm1.097-2.365 2.602-1.5 2.607 1.5v2.999l-2.597 1.5-2.607-1.5Z" fill="currentColor"></path></svg>
Open in ChatGPT
</DropdownMenuItem>
<DropdownMenuItem onClick={() => openInLLM('claude')}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m4.714 15.956 4.718-2.648.079-.23-.08-.128h-.23l-.79-.048-2.695-.073-2.337-.097-2.265-.122-.57-.121-.535-.704.055-.353.48-.321.685.06 1.518.104 2.277.157 1.651.098 2.447.255h.389l.054-.158-.133-.097-.103-.098-2.356-1.596-2.55-1.688-1.336-.972-.722-.491L2 6.223l-.158-1.008.655-.722.88.06.225.061.893.686 1.906 1.476 2.49 1.833.364.304.146-.104.018-.072-.164-.274-1.354-2.446-1.445-2.49-.644-1.032-.17-.619a2.972 2.972 0 0 1-.103-.729L6.287.133 6.7 0l.995.134.42.364.619 1.415L9.735 4.14l1.555 3.03.455.898.243.832.09.255h.159V9.01l.127-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.583.28.48.685-.067.444-.286 1.851-.558 2.903-.365 1.942h.213l.243-.242.983-1.306 1.652-2.064.728-.82.85-.904.547-.431h1.032l.759 1.129-.34 1.166-1.063 1.347-.88 1.142-1.263 1.7-.79 1.36.074.11.188-.02 2.853-.606 1.542-.28 1.84-.315.832.388.09.395-.327.807-1.967.486-2.307.462-3.436.813-.043.03.049.061 1.548.146.662.036h1.62l3.018.225.79.522.473.638-.08.485-1.213.62-1.64-.389-3.825-.91-1.31-.329h-.183v.11l1.093 1.068 2.003 1.81 2.508 2.33.127.578-.321.455-.34-.049-2.204-1.657-.85-.747-1.925-1.62h-.127v.17l.443.649 2.343 3.521.122 1.08-.17.353-.607.213-.668-.122-1.372-1.924-1.415-2.168-1.141-1.943-.14.08-.674 7.254-.316.37-.728.28-.607-.461-.322-.747.322-1.476.388-1.924.316-1.53.285-1.9.17-.632-.012-.042-.14.018-1.432 1.967-2.18 2.945-1.724 1.845-.413.164-.716-.37.066-.662.401-.589 2.386-3.036 1.439-1.882.929-1.086-.006-.158h-.055L4.138 18.56l-1.13.146-.485-.456.06-.746.231-.243 1.907-1.312Z" fill="currentColor"></path></svg>
Open in Claude
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
<p className="text-muted-foreground text-lg">{description}</p>
</div>

Expand Down Expand Up @@ -279,17 +388,17 @@ export function ComponentPreview({
<button
onClick={() => setActiveInstallTab("cli")}
className={`px-4 py-2 text-sm font-medium ${activeInstallTab === "cli"
? "border-b-2 border-primary text-primary"
: "text-muted-foreground hover:text-foreground"
? "border-b-2 border-primary text-primary"
: "text-muted-foreground hover:text-foreground"
}`}
>
CLI
</button>
<button
onClick={() => setActiveInstallTab("manual")}
className={`px-4 py-2 text-sm font-medium ${activeInstallTab === "manual"
? "border-b-2 border-primary text-primary"
: "text-muted-foreground hover:text-foreground"
? "border-b-2 border-primary text-primary"
: "text-muted-foreground hover:text-foreground"
}`}
>
Manual
Expand Down
Loading