diff --git a/cloud/app/components/blocks/copy-markdown-button.tsx b/cloud/app/components/blocks/copy-markdown-button.tsx new file mode 100644 index 000000000..e9bf4a501 --- /dev/null +++ b/cloud/app/components/blocks/copy-markdown-button.tsx @@ -0,0 +1,61 @@ +import { useState } from "react"; +import { Button } from "@/app/components/ui/button"; +import { Clipboard, Check } from "lucide-react"; +// import analyticsManager from "@/app/lib/services/analytics"; + +interface CopyMarkdownButtonProps { + content: string; + itemId: string; + contentType: "blog_markdown" | "document_markdown"; + className?: string; +} + +export function CopyMarkdownButton({ + content, + className = "", +}: CopyMarkdownButtonProps) { + const [isCopied, setIsCopied] = useState(false); + + const handleCopy = () => { + if (!content) return; + + navigator.clipboard + .writeText(content) + .then(() => { + setIsCopied(true); + setTimeout(() => { + setIsCopied(false); + }, 2000); + + // analyticsManager.trackCopyEvent({ + // contentType, + // itemId, + // }); + }) + .catch((err) => { + console.error("Failed to copy content: ", err); + }); + }; + + return ( + + ); +} diff --git a/cloud/app/components/blocks/docs/api-signature.tsx b/cloud/app/components/blocks/docs/api-signature.tsx new file mode 100644 index 000000000..79d79aac9 --- /dev/null +++ b/cloud/app/components/blocks/docs/api-signature.tsx @@ -0,0 +1,16 @@ +import React from "react"; + +/** + * Component to display an API function/method signature + */ +export default function ApiSignature({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
| Name | +Type | +Description | +
|---|---|---|
| {attr.name} | +
+ |
+ + {attr.description || "-"} + | +
| Name | +Type | +Description | +
|---|---|---|
| + {param.name} + {param.default && ( + + = {param.default} + + )} + | +
+ |
+ + {param.description || "-"} + | +
| Name | + )} +Type | +Description | +
|---|---|---|
| + {returnType.name} + | + )} +
+ |
+ + {returnType.description || "-"} + | +
;
+// }
+
+// return (
+//
+// );
+// },
+
+// // Code blocks - use our custom CodeBlock component with provider substitution
+// pre: (props: React.ComponentPropsWithoutRef<"pre">) => {
+// // Get meta information from our data attribute or initialize to empty
+// let meta = (props as any)["data-meta"] || "";
+
+// // Initialize variables for code content and language
+// let codeContent = "";
+// let language = "txt";
+
+// // Process children to find code content and language
+// if (props.children) {
+// const children = React.Children.toArray(props.children);
+
+// // Loop through children to find code content (typically there's only one child)
+// for (const child of children) {
+// if (!React.isValidElement(child)) continue;
+
+// // Check if this is a code element or has code-like properties
+// const childProps = child.props as {
+// className?: string;
+// children?: React.ReactNode | string;
+// };
+
+// // Extract language from className
+// if (childProps.className?.includes("language-")) {
+// language =
+// (childProps.className.match(/language-(\w+)/) || [])[1] || "txt";
+
+// // Also check for meta in className (legacy approach)
+// // This looks for patterns like {1-3} or {1,3} after the language
+// if (!meta) {
+// const metaMatch = childProps.className.match(/\{([^}]+)\}/);
+// meta = metaMatch ? `{${metaMatch[1]}}` : "";
+// }
+// }
+
+// // Get code content
+// if (typeof childProps.children === "string") {
+// codeContent = childProps.children;
+// break;
+// }
+// }
+// }
+
+// // Handle mermaid diagrams
+// if (language === "mermaid" && codeContent) {
+// return Diagram Error
+{error}
++ No headings found +
+ ); + } + + return ( +