{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tutorial-mdx",
  "type": "registry:component",
  "title": "Tutorial MDX",
  "description": "MDX renderer tailored for tutorial content with custom components.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/tutorial-mdx/tutorial-mdx.tsx",
      "content": "\"use client\";\n\nimport { lazy, memo, Suspense, use, useMemo } from \"react\";\n\nimport { evaluate } from \"@mdx-js/mdx\";\nimport * as runtime from \"react/jsx-runtime\";\nimport ReactMarkdown, { type Components } from \"react-markdown\";\n\nimport { cn } from \"@vllnt/ui\";\nimport {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n} from \"@vllnt/ui\";\nimport { Callout } from \"@vllnt/ui\";\nimport { Checklist } from \"@vllnt/ui\";\nimport { CodePlayground, FileTree } from \"@vllnt/ui\";\nimport { BeforeAfter, Comparison } from \"@vllnt/ui\";\nimport { Exercise } from \"@vllnt/ui\";\nimport { FAQ, FAQItem } from \"@vllnt/ui\";\nimport { Glossary, KeyConcept } from \"@vllnt/ui\";\nimport {\n  LearningObjectives,\n  Prerequisites,\n  Summary,\n} from \"@vllnt/ui\";\nimport { CommonMistake, ProTip } from \"@vllnt/ui\";\nimport { Quiz } from \"@vllnt/ui\";\nimport { Step, StepByStep } from \"@vllnt/ui\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@vllnt/ui\";\nimport { SimpleTerminal, Terminal } from \"@vllnt/ui\";\nimport { VideoEmbed } from \"@vllnt/ui\";\n\n// Lazy load FlowDiagram to avoid loading @xyflow/react (~185KB) on every page\nconst LazyFlowDiagram = lazy(() =>\n  import(\"../flow-diagram\").then((module_) => ({\n    default: module_.FlowDiagram,\n  })),\n);\n\n// Wrapper component with Suspense fallback for FlowDiagram\nfunction FlowDiagramWithSuspense(\n  props: React.ComponentProps<typeof LazyFlowDiagram>,\n) {\n  return (\n    <Suspense\n      fallback={\n        <div\n          aria-label=\"Loading diagram...\"\n          className=\"h-96 bg-muted animate-pulse rounded-lg\"\n        />\n      }\n    >\n      <LazyFlowDiagram {...props} />\n    </Suspense>\n  );\n}\n\n// MDX component map - all available components for tutorials\nconst mdxComponents = {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n  BeforeAfter,\n  Callout,\n  Checklist,\n  CodePlayground,\n  CommonMistake,\n  Comparison,\n  Exercise,\n  FAQ,\n  FAQItem,\n  FileTree,\n  FlowDiagram: FlowDiagramWithSuspense,\n  Glossary,\n  KeyConcept,\n  LearningObjectives,\n  Prerequisites,\n  ProTip,\n  Quiz,\n  SimpleTerminal,\n  Step,\n  StepByStep,\n  Summary,\n  Tabs,\n  TabsContent,\n  TabsList,\n  TabsTrigger,\n  Terminal,\n  VideoEmbed,\n};\n\n// Base markdown components for styling\nconst markdownComponents: Components = {\n  a: ({ children, href, ...props }) => (\n    <a\n      className=\"text-primary underline underline-offset-4 hover:text-primary/80 font-medium\"\n      href={href}\n      {...props}\n    >\n      {children}\n    </a>\n  ),\n  blockquote: ({ children, ...props }) => (\n    <blockquote\n      className=\"border-l-4 border-primary pl-4 italic text-muted-foreground my-6 py-2 text-sm\"\n      {...props}\n    >\n      {children}\n    </blockquote>\n  ),\n  code: ({ children, className, ...props }) => {\n    const isBlock = className?.includes(\"language-\");\n    if (isBlock) {\n      return (\n        <code className={cn(\"font-mono text-sm\", className)} {...props}>\n          {children}\n        </code>\n      );\n    }\n    return (\n      <code\n        className=\"bg-muted px-1.5 py-0.5 rounded text-sm font-mono\"\n        {...props}\n      >\n        {children}\n      </code>\n    );\n  },\n  h1: ({ children, ...props }) => (\n    <h1 className=\"text-2xl font-semibold mt-8 mb-4\" {...props}>\n      {children}\n    </h1>\n  ),\n  h2: ({ children, ...props }) => (\n    <h2 className=\"text-xl font-semibold mt-6 mb-3\" {...props}>\n      {children}\n    </h2>\n  ),\n  h3: ({ children, ...props }) => (\n    <h3 className=\"text-lg font-semibold mt-4 mb-2\" {...props}>\n      {children}\n    </h3>\n  ),\n  h4: ({ children, ...props }) => (\n    <h4 className=\"text-base font-semibold mt-3 mb-2\" {...props}>\n      {children}\n    </h4>\n  ),\n  hr: ({ ...props }) => <hr className=\"my-8 border-border\" {...props} />,\n  li: ({ children, ...props }) => (\n    <li\n      className=\"mb-2 leading-relaxed text-muted-foreground text-sm pl-2\"\n      {...props}\n    >\n      {children}\n    </li>\n  ),\n  ol: ({ children, ...props }) => (\n    <ol\n      className=\"list-decimal list-outside mb-6 space-y-2 ml-6 text-muted-foreground text-sm\"\n      {...props}\n    >\n      {children}\n    </ol>\n  ),\n  p: ({ children, ...props }) => (\n    <p\n      className=\"mb-4 leading-relaxed text-muted-foreground text-sm\"\n      {...props}\n    >\n      {children}\n    </p>\n  ),\n  pre: ({ children, ...props }) => (\n    <pre\n      className=\"bg-zinc-950 dark:bg-zinc-900 text-zinc-100 p-4 rounded-lg overflow-x-auto my-6 border border-zinc-800 shadow-lg font-mono text-sm\"\n      {...props}\n    >\n      {children}\n    </pre>\n  ),\n  strong: ({ children, ...props }) => (\n    <strong className=\"font-semibold text-foreground\" {...props}>\n      {children}\n    </strong>\n  ),\n  table: ({ children, ...props }) => (\n    <div className=\"my-6 overflow-x-auto\">\n      <table className=\"w-full border-collapse border border-border\" {...props}>\n        {children}\n      </table>\n    </div>\n  ),\n  td: ({ children, ...props }) => (\n    <td className=\"border border-border p-2 text-sm\" {...props}>\n      {children}\n    </td>\n  ),\n  th: ({ children, ...props }) => (\n    <th\n      className=\"border border-border bg-muted p-2 text-left font-medium text-sm\"\n      {...props}\n    >\n      {children}\n    </th>\n  ),\n  ul: ({ children, ...props }) => (\n    <ul\n      className=\"list-disc list-outside mb-6 space-y-2 ml-6 text-muted-foreground text-sm\"\n      {...props}\n    >\n      {children}\n    </ul>\n  ),\n};\n\n// Combine all components\nconst allComponents = {\n  ...markdownComponents,\n  ...mdxComponents,\n};\n\nexport type TutorialMDXProps = {\n  className?: string;\n  content: string;\n};\n\n// Check if content contains JSX components (excluding code blocks)\nfunction hasJSXComponents(content: string): boolean {\n  const contentWithoutCodeBlocks = content.replaceAll(/```[\\S\\s]*?```/g, \"\");\n  return /<[A-Z][A-Za-z]*[\\s/>]/.test(contentWithoutCodeBlocks);\n}\n\n// Component that renders MDX with Suspense\nfunction MDXWithSuspense({ className, content }: TutorialMDXProps) {\n  const mdxPromise = useMemo(\n    () =>\n      evaluate(content, {\n        ...runtime,\n        baseUrl: import.meta.url,\n      }),\n    [content],\n  );\n\n  return (\n    <div className={className}>\n      <Suspense fallback={<MDXLoadingFallback />}>\n        <MDXContent mdxPromise={mdxPromise} />\n      </Suspense>\n    </div>\n  );\n}\n\n// Component that renders plain markdown\nfunction MarkdownOnly({ className, content }: TutorialMDXProps) {\n  return (\n    <div className={className}>\n      <ReactMarkdown components={markdownComponents}>{content}</ReactMarkdown>\n    </div>\n  );\n}\n\n// Component that uses the promise\nfunction MDXContent({\n  mdxPromise,\n}: {\n  mdxPromise: Promise<{\n    default: React.ComponentType<{ components: typeof allComponents }>;\n  }>;\n}) {\n  const { default: Component } = use(mdxPromise);\n  return <Component components={allComponents} />;\n}\n\nfunction MDXLoadingFallback() {\n  return <div aria-hidden=\"true\" className=\"min-h-[100px]\" />;\n}\n\n// Main component that decides which renderer to use\nfunction TutorialMDXImpl({\n  className,\n  content,\n}: TutorialMDXProps): React.ReactNode {\n  const hasJSX = hasJSXComponents(content);\n\n  if (hasJSX) {\n    return <MDXWithSuspense className={className} content={content} />;\n  }\n\n  return <MarkdownOnly className={className} content={content} />;\n}\n\nexport const TutorialMDX = memo(TutorialMDXImpl);\nTutorialMDX.displayName = \"TutorialMDX\";\n\nexport { mdxComponents };\n",
      "type": "registry:component"
    }
  ],
  "version": "0.2.1",
  "stability": "stable"
}
