@frontlit/text-editor 0.1.0-alpha.3 → 0.1.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/text-renderer.tsx","../../src/extract-text-from-node.ts","../../src/empty-doc.ts","../../src/extensions.ts","../../src/create-id.ts","../../src/components/custom-code-mirror.tsx","../../src/lib/cn.ts","../../src/components/rendered-code-block.tsx","../../src/docs/headings.ts"],"sourcesContent":["import React from \"react\";\nimport { renderToReactElement } from \"@tiptap/static-renderer\";\nimport { getSchema } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { extractTextFromNode } from \"./extract-text-from-node\";\nimport emptyDoc from \"./empty-doc\";\nimport { createExtensions } from \"./extensions\";\nimport { createId } from \"./create-id\";\nimport type { TextEditorContent } from \"./text-editor-content\";\nimport type { TextRendererTheme } from \"./renderer-theme\";\nimport { cn } from \"./lib/cn\";\nimport { RenderedCodeBlock } from \"./components/rendered-code-block\";\nimport { extractDocsHeadings } from \"./docs/headings\";\n\ninterface TextRendererProps {\n profile?: \"default\" | \"documentation\";\n json: TextEditorContent;\n className?: string;\n theme?: TextRendererTheme;\n}\n\nconst typographyClasses = (typography?: {\n fontFamily?: string;\n fontSize?: string;\n fontWeight?: string;\n lineHeight?: string;\n letterSpacing?: string;\n textTransform?: string;\n textDecoration?: string;\n textOverflow?: string;\n}) => [\n typography?.fontFamily,\n typography?.fontSize,\n typography?.fontWeight,\n typography?.lineHeight,\n typography?.letterSpacing,\n typography?.textTransform,\n typography?.textDecoration,\n typography?.textOverflow,\n];\n\nfunction removeEmptyTextNodes(node: any): any {\n if (!node || typeof node !== \"object\") {\n return node;\n }\n\n if (node.type === \"text\" && node.text === \"\") {\n return undefined;\n }\n\n if (!Array.isArray(node.content)) {\n return node;\n }\n\n const content = node.content\n .map(removeEmptyTextNodes)\n .filter((child: any) => child !== undefined);\n\n return {\n ...node,\n content,\n };\n}\n\n/**\n * Renders TipTap `TextEditorContent` JSON as static React elements — used to\n * display rich text saved by the `Editor` (e.g. inside a block's body). When\n * a `theme` is provided, headings/paragraphs/links pick up its typography;\n * otherwise plain semantic HTML tags are used.\n */\nexport function TextRenderer({\n json,\n className,\n theme,\n profile = \"default\",\n}: TextRendererProps) {\n const extensions = createExtensions();\n const content = removeEmptyTextNodes(\n (json as any) ?? (emptyDoc as any),\n ) as TextEditorContent;\n const docsHeadings = profile === \"documentation\" ? extractDocsHeadings(content) : [];\n // React can replay each mapped node (StrictMode, hydration, or a retry).\n // Bind IDs before rendering instead of consuming an iterator in a component.\n const renderContent =\n profile === \"documentation\" ? getSchema(extensions).nodeFromJSON(content) : content;\n const headingIds = new WeakMap<ProseMirrorNode, string>();\n if (profile === \"documentation\") {\n let headingIndex = 0;\n (renderContent as ProseMirrorNode).descendants((node) => {\n if (node.type.name === \"heading\") {\n headingIds.set(node, docsHeadings[headingIndex++].id);\n }\n });\n }\n\n const rendered = renderToReactElement({\n extensions,\n content: renderContent,\n options: {\n nodeMapping: {\n paragraph: ({ children }) => {\n const classes = cn(\n \"text-base\",\n ...typographyClasses(theme?.typography?.text1),\n );\n return <p className={classes}>{children}</p>;\n },\n hardBreak: () => <br />,\n heading: ({ node, children }) => {\n const level = node?.attrs?.level ?? 1;\n // Extract text from the node structure (same as extractHeadings does)\n const textContent = extractTextFromNode(node);\n const id =\n profile === \"documentation\" ? headingIds.get(node) : createId(textContent);\n\n if (!theme) {\n const Tag = `h${level}` as React.ElementType;\n return <Tag id={id}>{children}</Tag>;\n }\n\n if (level === 1) {\n const classes = cn(\n \"scroll-m-20 text-4xl font-bold tracking-tight\",\n ...typographyClasses(theme?.typography?.header1),\n );\n return (\n <h1 id={id} className={classes}>\n {children}\n </h1>\n );\n }\n if (level === 2) {\n const classes = cn(\n \"scroll-m-20 text-3xl font-bold tracking-tight\",\n ...typographyClasses(theme?.typography?.header2),\n );\n return (\n <h2 id={id} className={classes}>\n {children}\n </h2>\n );\n }\n const classes = cn(\n \"scroll-m-20 text-2xl font-semibold tracking-normal\",\n ...typographyClasses(\n profile === \"documentation\" && level >= 4\n ? (theme?.typography?.header4 ?? theme?.typography?.header3)\n : theme?.typography?.header3,\n ),\n );\n const Tag = (\n profile === \"documentation\" ? `h${level}` : \"h3\"\n ) as React.ElementType;\n return (\n <Tag id={id} className={classes}>\n {children}\n </Tag>\n );\n },\n codeBlock: ({ node, children }) => (\n <RenderedCodeBlock node={node} language={node?.attrs?.language}>\n {children}\n </RenderedCodeBlock>\n ),\n codeMirror: ({ node, children }) => (\n <RenderedCodeBlock node={node}>{children}</RenderedCodeBlock>\n ),\n },\n markMapping: {\n link: ({ mark, children }) => {\n const href = mark?.attrs?.href;\n const linkStyle = theme?.interactives?.link;\n const classes = cn(\n \"font-medium cursor-pointer\",\n ...typographyClasses(theme?.typography?.link),\n linkStyle?.padding?.x,\n linkStyle?.padding?.y,\n linkStyle?.border?.width,\n linkStyle?.border?.radius,\n linkStyle?.border?.style,\n linkStyle?.custom,\n );\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={classes}\n style={{\n textShadow: linkStyle?.textShadow || undefined,\n }}\n >\n {children}\n </a>\n );\n },\n highlight: ({ children }) => (\n <mark className=\"bg-accent text-accent-foreground\">{children}</mark>\n ),\n },\n },\n });\n\n const combinedClassName = [\"tiptap-renderer\", className].filter(Boolean).join(\" \");\n\n return (\n <div className=\"text-editor flex flex-col gap-4\">\n <div className={combinedClassName}>{rendered}</div>\n </div>\n );\n}\n\nexport default TextRenderer;\n","export function extractTextFromNode(node): string {\n if (!node) {\n return \"\";\n }\n\n // ProseMirror nodes have a textContent property that contains all text\n if (typeof node.textContent === \"string\") {\n return node.textContent;\n }\n\n // Fallback: if content is a Fragment, access its content array\n if (node.content && node.content.content && Array.isArray(node.content.content)) {\n return node.content.content\n .map((child: any) => {\n // Text nodes have a text property\n if (child.text) {\n return child.text;\n }\n // Recursively extract from child nodes\n return extractTextFromNode(child);\n })\n .join(\"\");\n }\n\n // Fallback: if content is directly an array\n if (Array.isArray(node.content)) {\n return node.content\n .map((child: any) => {\n if (child.text) {\n return child.text;\n }\n return extractTextFromNode(child);\n })\n .join(\"\");\n }\n\n return \"\";\n}\n","import type { TextEditorContent } from \"./text-editor-content\";\n\nconst emptyDoc: TextEditorContent = {\n type: \"doc\",\n content: [],\n};\n\nexport default emptyDoc;\n","import StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport Link from \"@tiptap/extension-link\";\nimport { Table, TableCell, TableHeader, TableRow } from \"@tiptap/extension-table\";\nimport Image from \"@tiptap/extension-image\";\nimport Dropcursor from \"@tiptap/extension-dropcursor\";\nimport Gapcursor from \"@tiptap/extension-gapcursor\";\nimport CodeBlockLowlight from \"@tiptap/extension-code-block-lowlight\";\nimport Heading from \"@tiptap/extension-heading\";\nimport Highlight from \"@tiptap/extension-highlight\";\nimport { lowlight } from \"lowlight\";\nimport javascript from \"highlight.js/lib/languages/javascript\";\nimport typescript from \"highlight.js/lib/languages/typescript\";\nimport json from \"highlight.js/lib/languages/json\";\nimport css from \"highlight.js/lib/languages/css\";\nimport xml from \"highlight.js/lib/languages/xml\";\nimport type { Extensions } from \"@tiptap/core\";\nimport { createId } from \"./create-id\";\nimport { CodeMirrorNode } from \"./components/custom-code-mirror\";\n\nlowlight.registerLanguage(\"javascript\", javascript);\nlowlight.registerLanguage(\"typescript\", typescript);\nlowlight.registerLanguage(\"json\", json);\nlowlight.registerLanguage(\"css\", css);\nlowlight.registerLanguage(\"html\", xml);\n\ninterface ExtensionOptions {\n placeholder?: string;\n}\n\nexport const createExtensions = ({\n placeholder,\n}: ExtensionOptions = {}): Extensions => [\n StarterKit.configure({\n codeBlock: false,\n // Configured/replaced explicitly below (custom options or a\n // `.extend()`) — disabled here to avoid tiptap's duplicate-extension\n // warning and constructing throwaway instances of each.\n link: false,\n dropcursor: false,\n gapcursor: false,\n heading: false,\n }),\n Placeholder.configure({\n placeholder: placeholder || \"Write something…\",\n }),\n Link.configure({\n openOnClick: false,\n autolink: true,\n linkOnPaste: true,\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableHeader,\n TableCell,\n Image.configure({\n // We embed uploaded images as data URLs (no backend/media library in\n // this package), so base64 sources must be allowed.\n allowBase64: true,\n HTMLAttributes: {\n class: \"max-w-full h-auto rounded-md\",\n },\n resize: {\n enabled: true,\n directions: [\"top\", \"bottom\", \"left\", \"right\"],\n alwaysPreserveAspectRatio: true,\n },\n }),\n Dropcursor.configure({\n color: \"hsl(var(--foreground))\",\n width: 2,\n }),\n Gapcursor,\n CodeBlockLowlight.configure({\n lowlight,\n }),\n Heading.extend({\n renderHTML({ node, HTMLAttributes }) {\n const level = this.options.levels.includes(node.attrs.level)\n ? node.attrs.level\n : this.options.levels[0];\n const id =\n typeof node.textContent === \"string\" ? createId(node.textContent) : undefined;\n\n return [\n `h${level}`,\n {\n ...HTMLAttributes,\n id,\n },\n 0,\n ];\n },\n }),\n Highlight,\n CodeMirrorNode,\n];\n","export function createId(textContent: string) {\n return textContent.replace(/\\s/g, \"-\").toLowerCase();\n}\n","// This is only to maintain backward compatibility for codeMirror node type\n\nimport { Node } from \"@tiptap/core\";\n\nexport const CodeMirrorNode = Node.create({\n name: \"codeMirror\",\n content: \"block+\",\n code: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"pre\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"pre\", HTMLAttributes, 0];\n },\n});\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from \"react\";\nimport { extractTextFromNode } from \"../extract-text-from-node\";\nimport { CopyCodeButton } from \"./copy-code-button\";\n\nfunction textFromChildren(node: React.ReactNode): string {\n if (node == null || typeof node === \"boolean\") return \"\";\n if (typeof node === \"string\" || typeof node === \"number\") {\n return String(node);\n }\n if (Array.isArray(node)) return node.map(textFromChildren).join(\"\");\n if (React.isValidElement<{ children?: React.ReactNode }>(node)) {\n return textFromChildren(node.props.children);\n }\n return \"\";\n}\n\nexport function RenderedCodeBlock({\n node,\n children,\n language,\n}: {\n node?: { textContent?: string; content?: unknown };\n children?: React.ReactNode;\n language?: string;\n}): React.JSX.Element {\n const source = extractTextFromNode(node) || textFromChildren(children);\n\n return (\n <div className=\"te-code-block\">\n <pre>\n <code className={language ? `language-${language}` : undefined}>\n {children}\n </code>\n </pre>\n <CopyCodeButton source={source} />\n </div>\n );\n}\n","export const DOCS_HEADING_POLICY_VERSION = 1;\n\nexport interface HeadingNode {\n type?: string;\n text?: string;\n attrs?: Record<string, unknown>;\n content?: HeadingNode[];\n}\n\nexport function docsNodeText(node: HeadingNode): string {\n if (typeof node.text === \"string\") return node.text;\n if (node.type === \"hardBreak\") return \"\\n\";\n return (node.content ?? []).map(docsNodeText).join(\"\");\n}\n\n/** DM-CONVERT: deterministic Unicode anchors, including duplicate-base collisions. */\nexport function createHeadingIdGenerator(): (text: string) => string {\n const used = new Set<string>();\n return (text) => {\n const base =\n text\n .normalize(\"NFKC\")\n .toLowerCase()\n .trim()\n .replace(/[^\\p{L}\\p{N}\\s_-]/gu, \"\")\n .replace(/\\s+/g, \"-\") || \"section\";\n let id = base;\n let suffix = 2;\n while (used.has(id)) id = `${base}-${suffix++}`;\n used.add(id);\n return id;\n };\n}\n\nexport function extractDocsHeadings(json: HeadingNode | null | undefined) {\n const nextId = createHeadingIdGenerator();\n const headings: { level: number; text: string; id: string }[] = [];\n function walk(node: HeadingNode) {\n if (node.type === \"heading\") {\n const text = docsNodeText(node);\n headings.push({ level: Number(node.attrs?.level ?? 1), text, id: nextId(text) });\n }\n for (const child of node.content ?? []) walk(child);\n }\n if (json) walk(json);\n return headings;\n}\n"],"mappings":"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","names":["json","jsx","json","Tag","classes"]}
1
+ {"version":3,"sources":["../../src/text-renderer.tsx","../../src/extract-text-from-node.ts","../../src/empty-doc.ts","../../src/extensions.ts","../../src/create-id.ts","../../src/components/custom-code-mirror.tsx","../../src/docs/blocks.ts","../../src/lib/cn.ts","../../src/components/rendered-code-block.tsx","../../src/docs/headings.ts","../../src/components/docs-blocks.tsx"],"sourcesContent":["import React from \"react\";\nimport { renderToReactElement } from \"@tiptap/static-renderer\";\nimport { getSchema } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { extractTextFromNode } from \"./extract-text-from-node\";\nimport emptyDoc from \"./empty-doc\";\nimport { createExtensions } from \"./extensions\";\nimport { createId } from \"./create-id\";\nimport type { TextEditorContent } from \"./text-editor-content\";\nimport type { TextRendererTheme } from \"./renderer-theme\";\nimport { cn } from \"./lib/cn\";\nimport { RenderedCodeBlock } from \"./components/rendered-code-block\";\nimport { extractDocsHeadings } from \"./docs/headings\";\nimport { docsBlockMapping } from \"./components/docs-blocks\";\n\ninterface TextRendererProps {\n profile?: \"default\" | \"documentation\";\n json: TextEditorContent;\n className?: string;\n theme?: TextRendererTheme;\n}\n\nconst typographyClasses = (typography?: {\n fontFamily?: string;\n fontSize?: string;\n fontWeight?: string;\n lineHeight?: string;\n letterSpacing?: string;\n textTransform?: string;\n textDecoration?: string;\n textOverflow?: string;\n}) => [\n typography?.fontFamily,\n typography?.fontSize,\n typography?.fontWeight,\n typography?.lineHeight,\n typography?.letterSpacing,\n typography?.textTransform,\n typography?.textDecoration,\n typography?.textOverflow,\n];\n\nfunction removeEmptyTextNodes(node: any): any {\n if (!node || typeof node !== \"object\") {\n return node;\n }\n\n if (node.type === \"text\" && node.text === \"\") {\n return undefined;\n }\n\n if (!Array.isArray(node.content)) {\n return node;\n }\n\n const content = node.content\n .map(removeEmptyTextNodes)\n .filter((child: any) => child !== undefined);\n\n return {\n ...node,\n content,\n };\n}\n\n/**\n * Renders TipTap `TextEditorContent` JSON as static React elements — used to\n * display rich text saved by the `Editor` (e.g. inside a block's body). When\n * a `theme` is provided, headings/paragraphs/links pick up its typography;\n * otherwise plain semantic HTML tags are used.\n */\nexport function TextRenderer({\n json,\n className,\n theme,\n profile = \"default\",\n}: TextRendererProps) {\n const extensions = createExtensions();\n const content = removeEmptyTextNodes(\n (json as any) ?? (emptyDoc as any),\n ) as TextEditorContent;\n const docsHeadings = profile === \"documentation\" ? extractDocsHeadings(content) : [];\n // React can replay each mapped node (StrictMode, hydration, or a retry).\n // Bind IDs before rendering instead of consuming an iterator in a component.\n const renderContent =\n profile === \"documentation\" ? getSchema(extensions).nodeFromJSON(content) : content;\n const headingIds = new WeakMap<ProseMirrorNode, string>();\n if (profile === \"documentation\") {\n let headingIndex = 0;\n (renderContent as ProseMirrorNode).descendants((node) => {\n if (node.type.name === \"heading\") {\n headingIds.set(node, docsHeadings[headingIndex++].id);\n }\n });\n }\n\n const rendered = renderToReactElement({\n extensions,\n content: renderContent,\n options: {\n nodeMapping: {\n paragraph: ({ children }) => {\n const classes = cn(\n \"text-base\",\n ...typographyClasses(theme?.typography?.text1),\n );\n return <p className={classes}>{children}</p>;\n },\n hardBreak: () => <br />,\n heading: ({ node, children }) => {\n const level = node?.attrs?.level ?? 1;\n // Extract text from the node structure (same as extractHeadings does)\n const textContent = extractTextFromNode(node);\n const id =\n profile === \"documentation\" ? headingIds.get(node) : createId(textContent);\n\n if (!theme) {\n const Tag = `h${level}` as React.ElementType;\n return <Tag id={id}>{children}</Tag>;\n }\n\n if (level === 1) {\n const classes = cn(\n \"scroll-m-20 text-4xl font-bold tracking-tight\",\n ...typographyClasses(theme?.typography?.header1),\n );\n return (\n <h1 id={id} className={classes}>\n {children}\n </h1>\n );\n }\n if (level === 2) {\n const classes = cn(\n \"scroll-m-20 text-3xl font-bold tracking-tight\",\n ...typographyClasses(theme?.typography?.header2),\n );\n return (\n <h2 id={id} className={classes}>\n {children}\n </h2>\n );\n }\n const classes = cn(\n \"scroll-m-20 text-2xl font-semibold tracking-normal\",\n ...typographyClasses(\n profile === \"documentation\" && level >= 4\n ? (theme?.typography?.header4 ?? theme?.typography?.header3)\n : theme?.typography?.header3,\n ),\n );\n const Tag = (\n profile === \"documentation\" ? `h${level}` : \"h3\"\n ) as React.ElementType;\n return (\n <Tag id={id} className={classes}>\n {children}\n </Tag>\n );\n },\n ...docsBlockMapping,\n codeBlock: ({ node, children }) => (\n <RenderedCodeBlock\n node={node}\n language={node?.attrs?.language}\n title={node?.attrs?.title}\n >\n {children}\n </RenderedCodeBlock>\n ),\n codeMirror: ({ node, children }) => (\n <RenderedCodeBlock node={node}>{children}</RenderedCodeBlock>\n ),\n },\n markMapping: {\n link: ({ mark, children }) => {\n const href = mark?.attrs?.href;\n const linkStyle = theme?.interactives?.link;\n const classes = cn(\n \"font-medium cursor-pointer\",\n ...typographyClasses(theme?.typography?.link),\n linkStyle?.padding?.x,\n linkStyle?.padding?.y,\n linkStyle?.border?.width,\n linkStyle?.border?.radius,\n linkStyle?.border?.style,\n linkStyle?.custom,\n );\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={classes}\n style={{\n textShadow: linkStyle?.textShadow || undefined,\n }}\n >\n {children}\n </a>\n );\n },\n highlight: ({ children }) => (\n <mark className=\"bg-accent text-accent-foreground\">{children}</mark>\n ),\n },\n },\n });\n\n const combinedClassName = [\"tiptap-renderer\", className].filter(Boolean).join(\" \");\n\n return (\n <div className=\"text-editor flex flex-col gap-4\">\n <div className={combinedClassName}>{rendered}</div>\n </div>\n );\n}\n\nexport default TextRenderer;\n","export function extractTextFromNode(node): string {\n if (!node) {\n return \"\";\n }\n\n // ProseMirror nodes have a textContent property that contains all text\n if (typeof node.textContent === \"string\") {\n return node.textContent;\n }\n\n // Fallback: if content is a Fragment, access its content array\n if (node.content && node.content.content && Array.isArray(node.content.content)) {\n return node.content.content\n .map((child: any) => {\n // Text nodes have a text property\n if (child.text) {\n return child.text;\n }\n // Recursively extract from child nodes\n return extractTextFromNode(child);\n })\n .join(\"\");\n }\n\n // Fallback: if content is directly an array\n if (Array.isArray(node.content)) {\n return node.content\n .map((child: any) => {\n if (child.text) {\n return child.text;\n }\n return extractTextFromNode(child);\n })\n .join(\"\");\n }\n\n return \"\";\n}\n","import type { TextEditorContent } from \"./text-editor-content\";\n\nconst emptyDoc: TextEditorContent = {\n type: \"doc\",\n content: [],\n};\n\nexport default emptyDoc;\n","import StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport Link from \"@tiptap/extension-link\";\nimport { Table, TableCell, TableHeader, TableRow } from \"@tiptap/extension-table\";\nimport Image from \"@tiptap/extension-image\";\nimport Dropcursor from \"@tiptap/extension-dropcursor\";\nimport Gapcursor from \"@tiptap/extension-gapcursor\";\nimport CodeBlockLowlight from \"@tiptap/extension-code-block-lowlight\";\nimport Heading from \"@tiptap/extension-heading\";\nimport Highlight from \"@tiptap/extension-highlight\";\nimport { lowlight } from \"lowlight\";\nimport javascript from \"highlight.js/lib/languages/javascript\";\nimport typescript from \"highlight.js/lib/languages/typescript\";\nimport json from \"highlight.js/lib/languages/json\";\nimport css from \"highlight.js/lib/languages/css\";\nimport xml from \"highlight.js/lib/languages/xml\";\nimport type { Extensions } from \"@tiptap/core\";\nimport { createId } from \"./create-id\";\nimport { CodeMirrorNode } from \"./components/custom-code-mirror\";\nimport { CodeBlockTitle, createDocsBlockExtensions } from \"./docs/blocks\";\n\nlowlight.registerLanguage(\"javascript\", javascript);\nlowlight.registerLanguage(\"typescript\", typescript);\nlowlight.registerLanguage(\"json\", json);\nlowlight.registerLanguage(\"css\", css);\nlowlight.registerLanguage(\"html\", xml);\n\ninterface ExtensionOptions {\n placeholder?: string;\n}\n\nexport const createExtensions = ({\n placeholder,\n}: ExtensionOptions = {}): Extensions => [\n StarterKit.configure({\n code: false,\n codeBlock: false,\n // Configured/replaced explicitly below (custom options or a\n // `.extend()`) — disabled here to avoid tiptap's duplicate-extension\n // warning and constructing throwaway instances of each.\n link: false,\n dropcursor: false,\n gapcursor: false,\n heading: false,\n }),\n Placeholder.configure({\n placeholder: placeholder || \"Write something…\",\n }),\n Link.configure({\n openOnClick: false,\n autolink: true,\n linkOnPaste: true,\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableHeader,\n TableCell,\n Image.configure({\n // We embed uploaded images as data URLs (no backend/media library in\n // this package), so base64 sources must be allowed.\n allowBase64: true,\n HTMLAttributes: {\n class: \"max-w-full h-auto rounded-md\",\n },\n resize: {\n enabled: true,\n directions: [\"top\", \"bottom\", \"left\", \"right\"],\n alwaysPreserveAspectRatio: true,\n },\n }),\n Dropcursor.configure({\n color: \"hsl(var(--foreground))\",\n width: 2,\n }),\n Gapcursor,\n CodeBlockLowlight.configure({\n lowlight,\n }),\n Heading.extend({\n renderHTML({ node, HTMLAttributes }) {\n const level = this.options.levels.includes(node.attrs.level)\n ? node.attrs.level\n : this.options.levels[0];\n const id =\n typeof node.textContent === \"string\" ? createId(node.textContent) : undefined;\n\n return [\n `h${level}`,\n {\n ...HTMLAttributes,\n id,\n },\n 0,\n ];\n },\n }),\n Highlight,\n CodeMirrorNode,\n CodeBlockTitle,\n ...createDocsBlockExtensions(),\n];\n","export function createId(textContent: string) {\n return textContent.replace(/\\s/g, \"-\").toLowerCase();\n}\n","// This is only to maintain backward compatibility for codeMirror node type\n\nimport { Node } from \"@tiptap/core\";\n\nexport const CodeMirrorNode = Node.create({\n name: \"codeMirror\",\n content: \"block+\",\n code: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"pre\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"pre\", HTMLAttributes, 0];\n },\n});\n","import { Extension, Node, type Extensions } from \"@tiptap/core\";\nimport Code from \"@tiptap/extension-code\";\n\n/**\n * Rich documentation blocks (Callout, Tabs, Steps, Cards, Accordion, Code\n * group, Type table). Schema-only: no React, so the server-side docs profile\n * and the browser editor share them. Markdown form is MDX-style JSX with\n * literal props; see `markdown.ts`.\n */\nexport const CALLOUT_TYPES = [\"note\", \"tip\", \"info\", \"warning\", \"danger\"] as const;\nexport type CalloutType = (typeof CALLOUT_TYPES)[number];\n\nexport interface TypeTableRow {\n name: string;\n type: string;\n default: string | null;\n description: string | null;\n required: boolean;\n}\n\nfunction attr(name: string, fallback: unknown = null) {\n return {\n [name]: {\n default: fallback,\n parseHTML: (element: HTMLElement) => {\n const value = element.getAttribute(`data-${name}`);\n if (value === null) return fallback;\n try {\n return JSON.parse(value);\n } catch {\n return fallback;\n }\n },\n renderHTML: (attributes: Record<string, unknown>) =>\n attributes[name] === null || attributes[name] === undefined\n ? {}\n : { [`data-${name}`]: JSON.stringify(attributes[name]) },\n },\n };\n}\n\nfunction block(\n name: string,\n spec: {\n content?: string;\n group?: string;\n attrs?: Record<string, unknown>;\n atom?: boolean;\n },\n) {\n const tag = `div[data-docs-block=\"${name}\"]`;\n return Node.create({\n name,\n group: spec.group,\n content: spec.content,\n atom: spec.atom,\n defining: true,\n isolating: true,\n addAttributes() {\n return Object.assign(\n {},\n ...Object.entries(spec.attrs ?? {}).map(([key, value]) => attr(key, value)),\n );\n },\n parseHTML() {\n return [{ tag }];\n },\n renderHTML({ HTMLAttributes }) {\n return spec.atom\n ? [\"div\", { ...HTMLAttributes, \"data-docs-block\": name }]\n : [\"div\", { ...HTMLAttributes, \"data-docs-block\": name }, 0];\n },\n });\n}\n\n/** Inline code may sit inside links, bold, italic and strike (e.g. a linked `useUpload`). */\nexport const DocsCode = Code.extend({ excludes: \"\" });\n\nexport function createDocsBlockExtensions(): Extensions {\n return [\n DocsCode,\n block(\"callout\", {\n group: \"block\",\n content: \"block+\",\n attrs: { type: null, title: null },\n }),\n block(\"tabs\", { group: \"block\", content: \"tab+\" }),\n block(\"tab\", { content: \"block+\", attrs: { label: \"\" } }),\n block(\"steps\", { group: \"block\", content: \"step+\" }),\n block(\"step\", { content: \"block+\" }),\n block(\"cards\", { group: \"block\", content: \"card+\" }),\n block(\"card\", {\n content: \"block*\",\n attrs: { title: \"\", href: null, icon: null },\n }),\n block(\"accordions\", {\n group: \"block\",\n content: \"accordion+\",\n attrs: { type: null },\n }),\n block(\"accordion\", { content: \"block+\", attrs: { title: \"\" } }),\n block(\"codeGroup\", { group: \"block\", content: \"codeBlock+\" }),\n block(\"typeTable\", { group: \"block\", atom: true, attrs: { rows: [] } }),\n ];\n}\n\n/** Node names owned by this module, in Markdown component order. */\nexport const DOCS_BLOCK_COMPONENTS = {\n Callout: \"callout\",\n Tabs: \"tabs\",\n Tab: \"tab\",\n Steps: \"steps\",\n Step: \"step\",\n Cards: \"cards\",\n Card: \"card\",\n Accordions: \"accordions\",\n Accordion: \"accordion\",\n CodeGroup: \"codeGroup\",\n TypeTable: \"typeTable\",\n} as const;\n\n/** Code fence `title=\"…\"` metadata, shown as the block's file name or tab label. */\nexport const CodeBlockTitle = Extension.create({\n name: \"codeBlockTitle\",\n addGlobalAttributes() {\n return [\n {\n types: [\"codeBlock\"],\n attributes: {\n title: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-title\"),\n renderHTML: (attributes) =>\n attributes.title ? { \"data-title\": attributes.title } : {},\n },\n },\n },\n ];\n },\n});\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from \"react\";\nimport { extractTextFromNode } from \"../extract-text-from-node\";\nimport { CopyCodeButton } from \"./copy-code-button\";\n\nfunction textFromChildren(node: React.ReactNode): string {\n if (node == null || typeof node === \"boolean\") return \"\";\n if (typeof node === \"string\" || typeof node === \"number\") {\n return String(node);\n }\n if (Array.isArray(node)) return node.map(textFromChildren).join(\"\");\n if (React.isValidElement<{ children?: React.ReactNode }>(node)) {\n return textFromChildren(node.props.children);\n }\n return \"\";\n}\n\nexport function RenderedCodeBlock({\n node,\n children,\n language,\n title,\n}: {\n node?: { textContent?: string; content?: unknown };\n children?: React.ReactNode;\n language?: string;\n title?: string | null;\n}): React.JSX.Element {\n const source = extractTextFromNode(node) || textFromChildren(children);\n\n return (\n <div className=\"te-code-block\">\n {title && <div className=\"te-code-block__title\">{title}</div>}\n <pre>\n <code className={language ? `language-${language}` : undefined}>\n {children}\n </code>\n </pre>\n <CopyCodeButton source={source} />\n </div>\n );\n}\n","export const DOCS_HEADING_POLICY_VERSION = 1;\n\nexport interface HeadingNode {\n type?: string;\n text?: string;\n attrs?: Record<string, unknown>;\n content?: HeadingNode[];\n}\n\nexport function docsNodeText(node: HeadingNode): string {\n if (typeof node.text === \"string\") return node.text;\n if (node.type === \"hardBreak\") return \"\\n\";\n return (node.content ?? []).map(docsNodeText).join(\"\");\n}\n\n/** DM-CONVERT: deterministic Unicode anchors, including duplicate-base collisions. */\nexport function createHeadingIdGenerator(): (text: string) => string {\n const used = new Set<string>();\n return (text) => {\n const base =\n text\n .normalize(\"NFKC\")\n .toLowerCase()\n .trim()\n .replace(/[^\\p{L}\\p{N}\\s_-]/gu, \"\")\n .replace(/\\s+/g, \"-\") || \"section\";\n let id = base;\n let suffix = 2;\n while (used.has(id)) id = `${base}-${suffix++}`;\n used.add(id);\n return id;\n };\n}\n\nexport function extractDocsHeadings(json: HeadingNode | null | undefined) {\n const nextId = createHeadingIdGenerator();\n const headings: { level: number; text: string; id: string }[] = [];\n function walk(node: HeadingNode) {\n if (node.type === \"heading\") {\n const text = docsNodeText(node);\n headings.push({ level: Number(node.attrs?.level ?? 1), text, id: nextId(text) });\n }\n for (const child of node.content ?? []) walk(child);\n }\n if (json) walk(json);\n return headings;\n}\n","import React from \"react\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { CircleAlert, Info, Lightbulb, OctagonAlert, StickyNote } from \"lucide-react\";\nimport { DynamicIcon, type IconName } from \"lucide-react/dynamic\";\nimport type { NodeProps } from \"@tiptap/static-renderer\";\nimport type { TypeTableRow } from \"../docs/blocks\";\nimport { DocsTabs } from \"./docs-tabs\";\n\ntype BlockProps = NodeProps<ProseMirrorNode, React.ReactNode>;\n\nconst childAttrs = (node: ProseMirrorNode) => {\n const attrs: Record<string, any>[] = [];\n node.forEach((child) => {\n attrs.push(child.attrs);\n });\n return attrs;\n};\n\nconst CALLOUT_ICONS = {\n note: StickyNote,\n tip: Lightbulb,\n info: Info,\n warning: CircleAlert,\n danger: OctagonAlert,\n};\n\nexport function Callout({ node, children }: BlockProps) {\n const type = (node.attrs.type ?? \"info\") as keyof typeof CALLOUT_ICONS;\n const Icon = CALLOUT_ICONS[type] ?? Info;\n return (\n <div className=\"te-callout\" data-type={type} role=\"note\">\n <Icon className=\"te-callout__icon\" aria-hidden />\n <div className=\"te-callout__body\">\n {node.attrs.title && <p className=\"te-callout__title\">{node.attrs.title}</p>}\n {children}\n </div>\n </div>\n );\n}\n\nexport function Tabs({ node, children }: BlockProps) {\n return (\n <DocsTabs className=\"te-tabs\" labels={childAttrs(node).map((attrs) => attrs.label)}>\n {children}\n </DocsTabs>\n );\n}\n\nexport function CodeGroup({ node, children }: BlockProps) {\n const labels = childAttrs(node).map(\n (attrs, index) => attrs.title ?? attrs.language ?? `Code ${index + 1}`,\n );\n return (\n <DocsTabs className=\"te-tabs te-code-group\" labels={labels}>\n {children}\n </DocsTabs>\n );\n}\n\nexport function Steps({ children }: BlockProps) {\n return <ol className=\"te-steps\">{children}</ol>;\n}\n\nexport function Step({ children }: BlockProps) {\n return <li className=\"te-step\">{children}</li>;\n}\n\nexport function Cards({ children }: BlockProps) {\n return <div className=\"te-cards\">{children}</div>;\n}\n\n/** Card icons are lucide names, written in Fumadocs as `<BookOpen />`. */\nconst iconName = (name: string) =>\n name\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Za-z])([0-9])/g, \"$1-$2\")\n .toLowerCase() as IconName;\n\nexport function Card({ node, children }: BlockProps) {\n const { title, href, icon } = node.attrs;\n const body = (\n <>\n {icon && (\n <DynamicIcon name={iconName(icon)} className=\"te-card__icon\" aria-hidden />\n )}\n <span className=\"te-card__title\">{title}</span>\n {node.childCount > 0 && <div className=\"te-card__body\">{children}</div>}\n </>\n );\n return href ? (\n <a className=\"te-card\" href={href}>\n {body}\n </a>\n ) : (\n <div className=\"te-card\">{body}</div>\n );\n}\n\nexport function Accordions({ children }: BlockProps) {\n return <div className=\"te-accordions\">{children}</div>;\n}\n\nexport function Accordion({ node, children }: BlockProps) {\n return (\n <details className=\"te-accordion\">\n <summary className=\"te-accordion__title\">{node.attrs.title}</summary>\n <div className=\"te-accordion__body\">{children}</div>\n </details>\n );\n}\n\nexport function TypeTable({ node }: BlockProps) {\n const rows = (node.attrs.rows ?? []) as TypeTableRow[];\n return (\n <div className=\"te-type-table\">\n <table>\n <thead>\n <tr>\n <th>Prop</th>\n <th>Type</th>\n <th>Default</th>\n <th>Description</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.name}>\n <td>\n <code>{row.name}</code>\n {row.required && (\n <span className=\"te-type-table__required\"> (required)</span>\n )}\n </td>\n <td>\n <code>{row.type}</code>\n </td>\n <td>{row.default === null ? \"—\" : <code>{row.default}</code>}</td>\n <td>{row.description ?? \"\"}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nexport const docsBlockMapping = {\n callout: Callout,\n tabs: Tabs,\n tab: ({ children }: BlockProps) => <>{children}</>,\n codeGroup: CodeGroup,\n steps: Steps,\n step: Step,\n cards: Cards,\n card: Card,\n accordions: Accordions,\n accordion: Accordion,\n typeTable: TypeTable,\n};\n"],"mappings":"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","names":["Node","Node","json","jsx","jsxs","jsx","json","Tag","classes"]}
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ "use client";
3
+
4
+ // src/components/docs-tabs.tsx
5
+ import React, { useId, useState } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ function DocsTabs({
8
+ labels,
9
+ children,
10
+ className
11
+ }) {
12
+ const id = useId();
13
+ const [active, setActive] = useState(0);
14
+ const panels = React.Children.toArray(children);
15
+ function onKeyDown(event, index) {
16
+ const step = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0;
17
+ if (!step) return;
18
+ event.preventDefault();
19
+ const next = (index + step + labels.length) % labels.length;
20
+ setActive(next);
21
+ document.getElementById(`${id}-tab-${next}`)?.focus();
22
+ }
23
+ return /* @__PURE__ */ jsxs("div", { className, children: [
24
+ /* @__PURE__ */ jsx("div", { role: "tablist", className: "te-tabs__list", children: labels.map((label, index) => /* @__PURE__ */ jsx(
25
+ "button",
26
+ {
27
+ id: `${id}-tab-${index}`,
28
+ type: "button",
29
+ role: "tab",
30
+ "aria-selected": index === active,
31
+ "aria-controls": `${id}-panel-${index}`,
32
+ tabIndex: index === active ? 0 : -1,
33
+ className: "te-tabs__tab",
34
+ onClick: () => setActive(index),
35
+ onKeyDown: (event) => onKeyDown(event, index),
36
+ children: label
37
+ },
38
+ index
39
+ )) }),
40
+ panels.map((panel, index) => /* @__PURE__ */ jsx(
41
+ "div",
42
+ {
43
+ id: `${id}-panel-${index}`,
44
+ role: "tabpanel",
45
+ "aria-labelledby": `${id}-tab-${index}`,
46
+ hidden: index !== active,
47
+ className: "te-tabs__panel",
48
+ children: panel
49
+ },
50
+ index
51
+ ))
52
+ ] });
53
+ }
54
+ export {
55
+ DocsTabs
56
+ };
57
+ //# sourceMappingURL=docs-tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/docs-tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useId, useState } from \"react\";\n\n/**\n * Tab switching for docs Tabs and Code groups; the only client part of them.\n * Every panel is server-rendered, so hidden tabs stay in the page for search.\n */\nexport function DocsTabs({\n labels,\n children,\n className,\n}: {\n labels: string[];\n children: React.ReactNode;\n className?: string;\n}) {\n const id = useId();\n const [active, setActive] = useState(0);\n const panels = React.Children.toArray(children);\n\n function onKeyDown(event: React.KeyboardEvent<HTMLButtonElement>, index: number) {\n const step = event.key === \"ArrowRight\" ? 1 : event.key === \"ArrowLeft\" ? -1 : 0;\n if (!step) return;\n event.preventDefault();\n const next = (index + step + labels.length) % labels.length;\n setActive(next);\n document.getElementById(`${id}-tab-${next}`)?.focus();\n }\n\n return (\n <div className={className}>\n <div role=\"tablist\" className=\"te-tabs__list\">\n {labels.map((label, index) => (\n <button\n // biome-ignore lint/suspicious/noArrayIndexKey: labels may repeat or be empty.\n key={index}\n id={`${id}-tab-${index}`}\n type=\"button\"\n role=\"tab\"\n aria-selected={index === active}\n aria-controls={`${id}-panel-${index}`}\n tabIndex={index === active ? 0 : -1}\n className=\"te-tabs__tab\"\n onClick={() => setActive(index)}\n onKeyDown={(event) => onKeyDown(event, index)}\n >\n {label}\n </button>\n ))}\n </div>\n {panels.map((panel, index) => (\n <div\n // biome-ignore lint/suspicious/noArrayIndexKey: panels follow their tab's position.\n key={index}\n id={`${id}-panel-${index}`}\n role=\"tabpanel\"\n aria-labelledby={`${id}-tab-${index}`}\n hidden={index !== active}\n className=\"te-tabs__panel\"\n >\n {panel}\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":";;;;AAEA,OAAO,SAAS,OAAO,gBAAgB;AA6BnC,SAGM,KAHN;AAvBG,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,KAAK,MAAM;AACjB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,CAAC;AACtC,QAAM,SAAS,MAAM,SAAS,QAAQ,QAAQ;AAE9C,WAAS,UAAU,OAA+C,OAAe;AAC/E,UAAM,OAAO,MAAM,QAAQ,eAAe,IAAI,MAAM,QAAQ,cAAc,KAAK;AAC/E,QAAI,CAAC,KAAM;AACX,UAAM,eAAe;AACrB,UAAM,QAAQ,QAAQ,OAAO,OAAO,UAAU,OAAO;AACrD,cAAU,IAAI;AACd,aAAS,eAAe,GAAG,EAAE,QAAQ,IAAI,EAAE,GAAG,MAAM;AAAA,EACtD;AAEA,SACE,qBAAC,SAAI,WACH;AAAA,wBAAC,SAAI,MAAK,WAAU,WAAU,iBAC3B,iBAAO,IAAI,CAAC,OAAO,UAClB;AAAA,MAAC;AAAA;AAAA,QAGC,IAAI,GAAG,EAAE,QAAQ,KAAK;AAAA,QACtB,MAAK;AAAA,QACL,MAAK;AAAA,QACL,iBAAe,UAAU;AAAA,QACzB,iBAAe,GAAG,EAAE,UAAU,KAAK;AAAA,QACnC,UAAU,UAAU,SAAS,IAAI;AAAA,QACjC,WAAU;AAAA,QACV,SAAS,MAAM,UAAU,KAAK;AAAA,QAC9B,WAAW,CAAC,UAAU,UAAU,OAAO,KAAK;AAAA,QAE3C;AAAA;AAAA,MAXI;AAAA,IAYP,CACD,GACH;AAAA,IACC,OAAO,IAAI,CAAC,OAAO,UAClB;AAAA,MAAC;AAAA;AAAA,QAGC,IAAI,GAAG,EAAE,UAAU,KAAK;AAAA,QACxB,MAAK;AAAA,QACL,mBAAiB,GAAG,EAAE,QAAQ,KAAK;AAAA,QACnC,QAAQ,UAAU;AAAA,QAClB,WAAU;AAAA,QAET;AAAA;AAAA,MAPI;AAAA,IAQP,CACD;AAAA,KACH;AAEJ;","names":[]}
package/dist/styles.css CHANGED
@@ -219,6 +219,24 @@
219
219
  .z-30 {
220
220
  z-index: 30;
221
221
  }
222
+ .container {
223
+ width: 100%;
224
+ @media (width >= 40rem) {
225
+ max-width: 40rem;
226
+ }
227
+ @media (width >= 48rem) {
228
+ max-width: 48rem;
229
+ }
230
+ @media (width >= 64rem) {
231
+ max-width: 64rem;
232
+ }
233
+ @media (width >= 80rem) {
234
+ max-width: 80rem;
235
+ }
236
+ @media (width >= 96rem) {
237
+ max-width: 96rem;
238
+ }
239
+ }
222
240
  .mx-1 {
223
241
  margin-inline: var(--spacing);
224
242
  }
@@ -255,6 +273,10 @@
255
273
  .table {
256
274
  display: table;
257
275
  }
276
+ .size-3\.5 {
277
+ width: calc(var(--spacing) * 3.5);
278
+ height: calc(var(--spacing) * 3.5);
279
+ }
258
280
  .size-4 {
259
281
  width: calc(var(--spacing) * 4);
260
282
  height: calc(var(--spacing) * 4);
@@ -265,6 +287,9 @@
265
287
  .h-6 {
266
288
  height: calc(var(--spacing) * 6);
267
289
  }
290
+ .h-7 {
291
+ height: calc(var(--spacing) * 7);
292
+ }
268
293
  .h-8 {
269
294
  height: calc(var(--spacing) * 8);
270
295
  }
@@ -286,6 +311,12 @@
286
311
  .w-8 {
287
312
  width: calc(var(--spacing) * 8);
288
313
  }
314
+ .w-24 {
315
+ width: calc(var(--spacing) * 24);
316
+ }
317
+ .w-32 {
318
+ width: calc(var(--spacing) * 32);
319
+ }
289
320
  .w-40 {
290
321
  width: calc(var(--spacing) * 40);
291
322
  }
@@ -310,6 +341,9 @@
310
341
  .max-w-sm {
311
342
  max-width: var(--container-sm);
312
343
  }
344
+ .min-w-0 {
345
+ min-width: 0px;
346
+ }
313
347
  .min-w-28 {
314
348
  min-width: calc(var(--spacing) * 28);
315
349
  }
@@ -539,6 +573,9 @@
539
573
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
540
574
  transition-duration: var(--tw-duration, var(--default-transition-duration));
541
575
  }
576
+ .placeholder\:text-muted-foreground::placeholder {
577
+ color: var(--muted-foreground);
578
+ }
542
579
  @media (hover: hover) {
543
580
  .hover\:bg-\[var\(--primary-soft\)\]:hover {
544
581
  background-color: var(--primary-soft);
@@ -562,6 +599,9 @@
562
599
  background-color: color-mix(in oklab, var(--primary) 90%, transparent);
563
600
  }
564
601
  }
602
+ .hover\:text-foreground:hover {
603
+ color: var(--foreground);
604
+ }
565
605
  }
566
606
  .focus-visible\:outline:focus-visible {
567
607
  outline-style: var(--tw-outline-style);
@@ -580,6 +620,9 @@
580
620
  .disabled\:cursor-not-allowed:disabled {
581
621
  cursor: not-allowed;
582
622
  }
623
+ .disabled\:opacity-40:disabled {
624
+ opacity: 40%;
625
+ }
583
626
  .disabled\:opacity-50:disabled {
584
627
  opacity: 50%;
585
628
  }
@@ -909,6 +952,262 @@
909
952
  border-radius: 0.5rem;
910
953
  margin: 1rem auto;
911
954
  }
955
+ .tiptap-renderer .te-code-block__title {
956
+ border: 1px solid var(--border, hsl(214.3 31.8% 91.4%));
957
+ border-bottom: none;
958
+ border-radius: 0.5rem 0.5rem 0 0;
959
+ color: var(--muted-foreground, hsl(215.4 16.3% 46.9%));
960
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
961
+ font-size: 0.8125rem;
962
+ padding: 0.5rem 1rem;
963
+ padding-right: 2.75rem;
964
+ }
965
+ .tiptap-renderer .te-code-block__title + pre {
966
+ border-top-left-radius: 0;
967
+ border-top-right-radius: 0;
968
+ }
969
+ .tiptap-renderer .te-callout {
970
+ --te-callout-accent: var(--primary, hsl(222.2 47.4% 11.2%));
971
+ display: flex;
972
+ gap: 0.75rem;
973
+ margin: 1rem 0;
974
+ padding: 0.75rem 1rem;
975
+ border: 1px solid var(--te-callout-accent);
976
+ @supports (color: color-mix(in lab, red, red)) {
977
+ border: 1px solid color-mix(in srgb, var(--te-callout-accent) 35%, transparent);
978
+ }
979
+ border-radius: 0.5rem;
980
+ background: var(--te-callout-accent);
981
+ @supports (color: color-mix(in lab, red, red)) {
982
+ background: color-mix(in srgb, var(--te-callout-accent) 7%, transparent);
983
+ }
984
+ }
985
+ .tiptap-renderer .te-callout[data-type="tip"] {
986
+ --te-callout-accent: hsl(142 71% 36%);
987
+ }
988
+ .tiptap-renderer .te-callout[data-type="warning"] {
989
+ --te-callout-accent: hsl(38 92% 45%);
990
+ }
991
+ .tiptap-renderer .te-callout[data-type="danger"] {
992
+ --te-callout-accent: hsl(0 72% 51%);
993
+ }
994
+ .tiptap-renderer .te-callout[data-type="note"] {
995
+ --te-callout-accent: var(--muted-foreground, hsl(215.4 16.3% 46.9%));
996
+ }
997
+ .tiptap-renderer .te-callout__icon {
998
+ flex-shrink: 0;
999
+ width: 1.125rem;
1000
+ height: 1.125rem;
1001
+ margin-top: 0.2rem;
1002
+ color: var(--te-callout-accent);
1003
+ }
1004
+ .tiptap-renderer .te-callout__body {
1005
+ min-width: 0;
1006
+ flex: 1;
1007
+ }
1008
+ .tiptap-renderer .te-callout__body > :first-child {
1009
+ margin-top: 0;
1010
+ }
1011
+ .tiptap-renderer .te-callout__body > :last-child {
1012
+ margin-bottom: 0;
1013
+ }
1014
+ .tiptap-renderer .te-callout__title {
1015
+ font-weight: 600;
1016
+ }
1017
+ .tiptap-renderer .te-tabs {
1018
+ margin: 1rem 0;
1019
+ }
1020
+ .tiptap-renderer .te-tabs__list {
1021
+ display: flex;
1022
+ gap: 0.25rem;
1023
+ overflow-x: auto;
1024
+ border-bottom: 1px solid var(--border, hsl(214.3 31.8% 91.4%));
1025
+ }
1026
+ .tiptap-renderer .te-tabs__tab {
1027
+ appearance: none;
1028
+ background: none;
1029
+ border: none;
1030
+ border-bottom: 2px solid transparent;
1031
+ margin-bottom: -1px;
1032
+ padding: 0.5rem 0.75rem;
1033
+ color: var(--muted-foreground, hsl(215.4 16.3% 46.9%));
1034
+ font: inherit;
1035
+ font-size: 0.875rem;
1036
+ font-weight: 500;
1037
+ white-space: nowrap;
1038
+ cursor: pointer;
1039
+ }
1040
+ .tiptap-renderer .te-tabs__tab[aria-selected="true"] {
1041
+ border-bottom-color: var(--primary, hsl(222.2 47.4% 11.2%));
1042
+ color: var(--foreground, hsl(222.2 84% 4.9%));
1043
+ }
1044
+ .tiptap-renderer .te-tabs__panel > :first-child {
1045
+ margin-top: 0.75rem;
1046
+ }
1047
+ .tiptap-renderer .te-code-group .te-code-block__title {
1048
+ display: none;
1049
+ }
1050
+ .tiptap-renderer .te-steps {
1051
+ counter-reset: te-step;
1052
+ margin: 1rem 0;
1053
+ padding-left: 0;
1054
+ }
1055
+ .tiptap-renderer .te-steps > .te-step {
1056
+ counter-increment: te-step;
1057
+ list-style: none;
1058
+ position: relative;
1059
+ padding-left: 2.75rem;
1060
+ padding-bottom: 0.5rem;
1061
+ }
1062
+ .tiptap-renderer .te-steps > .te-step::before {
1063
+ content: counter(te-step);
1064
+ position: absolute;
1065
+ left: 0;
1066
+ top: 0;
1067
+ display: flex;
1068
+ align-items: center;
1069
+ justify-content: center;
1070
+ width: 1.75rem;
1071
+ height: 1.75rem;
1072
+ border: 1px solid var(--border, hsl(214.3 31.8% 91.4%));
1073
+ border-radius: 9999px;
1074
+ background: var(--muted, hsl(210 40% 96.1%));
1075
+ font-size: 0.875rem;
1076
+ font-weight: 600;
1077
+ }
1078
+ .tiptap-renderer .te-steps > .te-step::after {
1079
+ content: "";
1080
+ position: absolute;
1081
+ left: 0.875rem;
1082
+ top: 2.25rem;
1083
+ bottom: 0.25rem;
1084
+ border-left: 1px solid var(--border, hsl(214.3 31.8% 91.4%));
1085
+ }
1086
+ .tiptap-renderer .te-steps > .te-step > :first-child {
1087
+ margin-top: 0;
1088
+ }
1089
+ .tiptap-renderer .te-cards {
1090
+ display: grid;
1091
+ grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
1092
+ gap: 0.75rem;
1093
+ margin: 1rem 0;
1094
+ }
1095
+ .tiptap-renderer .te-card {
1096
+ display: flex;
1097
+ flex-direction: column;
1098
+ gap: 0.25rem;
1099
+ padding: 1rem;
1100
+ border: 1px solid var(--border, hsl(214.3 31.8% 91.4%));
1101
+ border-radius: 0.5rem;
1102
+ background: var(--card, transparent);
1103
+ color: inherit;
1104
+ text-decoration: none;
1105
+ }
1106
+ .tiptap-renderer a.te-card:hover {
1107
+ background: var(--muted, hsl(210 40% 96.1%));
1108
+ }
1109
+ .tiptap-renderer .te-card__icon {
1110
+ width: 1.25rem;
1111
+ height: 1.25rem;
1112
+ margin-bottom: 0.25rem;
1113
+ color: var(--muted-foreground, hsl(215.4 16.3% 46.9%));
1114
+ }
1115
+ .tiptap-renderer .te-card__title {
1116
+ font-weight: 600;
1117
+ }
1118
+ .tiptap-renderer .te-card__body {
1119
+ color: var(--muted-foreground, hsl(215.4 16.3% 46.9%));
1120
+ font-size: 0.875rem;
1121
+ }
1122
+ .tiptap-renderer .te-card__body > * {
1123
+ margin: 0;
1124
+ }
1125
+ .tiptap-renderer .te-accordions {
1126
+ margin: 1rem 0;
1127
+ border: 1px solid var(--border, hsl(214.3 31.8% 91.4%));
1128
+ border-radius: 0.5rem;
1129
+ }
1130
+ .tiptap-renderer .te-accordion + .te-accordion {
1131
+ border-top: 1px solid var(--border, hsl(214.3 31.8% 91.4%));
1132
+ }
1133
+ .tiptap-renderer .te-accordion__title {
1134
+ padding: 0.75rem 1rem;
1135
+ font-weight: 600;
1136
+ cursor: pointer;
1137
+ }
1138
+ .tiptap-renderer .te-accordion__body {
1139
+ padding: 0 1rem;
1140
+ }
1141
+ .tiptap-renderer .te-type-table {
1142
+ overflow-x: auto;
1143
+ }
1144
+ .tiptap-renderer .te-type-table table {
1145
+ table-layout: auto;
1146
+ }
1147
+ .tiptap-renderer .te-type-table__required {
1148
+ color: var(--muted-foreground, hsl(215.4 16.3% 46.9%));
1149
+ font-size: 0.75rem;
1150
+ }
1151
+ .tiptap-editor .ProseMirror .te-block {
1152
+ margin: 0.75rem 0;
1153
+ border: 1px solid var(--border);
1154
+ border-radius: 0.5rem;
1155
+ }
1156
+ .tiptap-editor .ProseMirror .te-block__bar {
1157
+ display: flex;
1158
+ flex-wrap: wrap;
1159
+ align-items: center;
1160
+ gap: 0.375rem;
1161
+ padding: 0.25rem 0.5rem;
1162
+ border-bottom: 1px solid var(--border);
1163
+ background: var(--muted);
1164
+ border-radius: 0.5rem 0.5rem 0 0;
1165
+ font-size: 0.75rem;
1166
+ }
1167
+ .tiptap-editor .ProseMirror .te-block__label {
1168
+ font-weight: 600;
1169
+ color: var(--muted-foreground);
1170
+ text-transform: uppercase;
1171
+ letter-spacing: 0.04em;
1172
+ }
1173
+ .tiptap-editor .ProseMirror .te-block__content {
1174
+ padding: 0.25rem 0.75rem;
1175
+ }
1176
+ .tiptap-editor .ProseMirror .te-block-item {
1177
+ margin: 0.5rem 0;
1178
+ border: 1px dashed var(--border);
1179
+ border-radius: 0.375rem;
1180
+ }
1181
+ .tiptap-editor .ProseMirror .te-block-item > .te-block__bar {
1182
+ background: transparent;
1183
+ }
1184
+ .tiptap-editor .ProseMirror .te-block[data-block="steps"] > .te-block__content {
1185
+ counter-reset: te-step;
1186
+ }
1187
+ .tiptap-editor .ProseMirror .te-block-item[data-block="step"]::before {
1188
+ counter-increment: te-step;
1189
+ content: "Step " counter(te-step);
1190
+ display: block;
1191
+ padding: 0.25rem 0.75rem 0;
1192
+ font-size: 0.75rem;
1193
+ font-weight: 600;
1194
+ color: var(--muted-foreground);
1195
+ }
1196
+ .tiptap-editor .ProseMirror .te-block-code {
1197
+ margin: 0.75rem 0;
1198
+ }
1199
+ .tiptap-editor .ProseMirror .te-block-code pre {
1200
+ margin-top: 0;
1201
+ border-top-left-radius: 0;
1202
+ border-top-right-radius: 0;
1203
+ }
1204
+ .tiptap-editor .ProseMirror .te-block-table {
1205
+ table-layout: auto;
1206
+ margin: 0.5rem 0;
1207
+ }
1208
+ .tiptap-editor .ProseMirror .te-block-table th, .tiptap-editor .ProseMirror .te-block-table td {
1209
+ padding: 0.25rem;
1210
+ }
912
1211
  @property --tw-border-style {
913
1212
  syntax: "*";
914
1213
  inherits: false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontlit/text-editor",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.5",
4
4
  "description": "A TipTap-based rich text editor and static renderer for React",
5
5
  "author": "FrontLit",
6
6
  "license": "MIT",
@@ -63,7 +63,6 @@
63
63
  ],
64
64
  "scripts": {
65
65
  "build": "tsup && tsup --config tsup.renderer.config.ts && node scripts/add-use-client.mjs && tailwindcss -i src/styles.css -o dist/styles.css && cp src/prose.css dist/prose.css && cp src/tokens.css dist/tokens.css",
66
- "prepublishOnly": "bun run build",
67
66
  "dev": "tsup --watch",
68
67
  "clean": "rimraf dist",
69
68
  "check-types": "tsc --noEmit",
@@ -75,25 +74,31 @@
75
74
  },
76
75
  "dependencies": {
77
76
  "@floating-ui/dom": "^1.6.0",
78
- "@tiptap/core": "^3.0.0",
79
- "@tiptap/extension-bubble-menu": "^3.10.4",
80
- "@tiptap/extension-code-block-lowlight": "^3.0.0",
81
- "@tiptap/extension-dropcursor": "^3.0.0",
82
- "@tiptap/extension-gapcursor": "^3.0.0",
83
- "@tiptap/extension-heading": "^3.0.0",
84
- "@tiptap/extension-highlight": "^3.11.0",
85
- "@tiptap/extension-image": "^3.0.0",
86
- "@tiptap/extension-link": "^3.0.0",
87
- "@tiptap/extension-placeholder": "^3.0.0",
88
- "@tiptap/extension-table": "^3.10.7",
89
- "@tiptap/pm": "^3.0.0",
90
- "@tiptap/react": "^3.0.0",
91
- "@tiptap/starter-kit": "^3.0.0",
92
- "@tiptap/static-renderer": "^3.10.7",
77
+ "@tiptap/core": "^3.31.3",
78
+ "@tiptap/extension-bubble-menu": "^3.31.3",
79
+ "@tiptap/extension-code": "^3.31.3",
80
+ "@tiptap/extension-code-block": "^3.31.3",
81
+ "@tiptap/extension-code-block-lowlight": "^3.31.3",
82
+ "@tiptap/extension-dropcursor": "^3.31.3",
83
+ "@tiptap/extension-gapcursor": "^3.31.3",
84
+ "@tiptap/extension-heading": "^3.31.3",
85
+ "@tiptap/extension-highlight": "^3.31.3",
86
+ "@tiptap/extension-image": "^3.31.3",
87
+ "@tiptap/extension-link": "^3.31.3",
88
+ "@tiptap/extension-placeholder": "^3.31.3",
89
+ "@tiptap/extension-table": "^3.31.3",
90
+ "@tiptap/extensions": "^3.31.3",
91
+ "@tiptap/pm": "^3.31.3",
92
+ "@tiptap/react": "^3.31.3",
93
+ "@tiptap/starter-kit": "^3.31.3",
94
+ "@tiptap/static-renderer": "^3.31.3",
95
+ "acorn": "^8.19.0",
93
96
  "clsx": "^2.1.1",
94
97
  "highlight.js": "^11.10.0",
95
98
  "lowlight": "^2.9.0",
96
99
  "lucide-react": "^0.553.0",
100
+ "mdast-util-mdx-jsx": "^3.2.0",
101
+ "micromark-extension-mdx-jsx": "^3.0.2",
97
102
  "remark-gfm": "^4.0.1",
98
103
  "remark-parse": "^11.0.0",
99
104
  "remark-stringify": "^11.0.0",