import { useT } from "@agent-native/core/client/i18n"; import type { Editor } from "@tiptap/react"; import { useEffect, useState, useRef } from "react"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; const LANGUAGES = [ { value: "", label: "" }, { value: "javascript", label: "JavaScript" }, { value: "typescript", label: "TypeScript" }, { value: "python", label: "Python" }, { value: "html", label: "HTML" }, { value: "css", label: "CSS" }, { value: "json", label: "JSON" }, { value: "sql", label: "SQL" }, { value: "bash", label: "Bash" }, { value: "go", label: "Go" }, { value: "rust", label: "Rust" }, { value: "java", label: "Java" }, { value: "ruby", label: "Ruby" }, { value: "php", label: "PHP" }, { value: "yaml", label: "YAML" }, { value: "markdown", label: "Markdown" }, { value: "xml", label: "XML" }, { value: "graphql", label: "GraphQL" }, ]; interface CodeBlockLangPickerProps { editor: Editor; } export function CodeBlockLangPicker({ editor }: CodeBlockLangPickerProps) { const t = useT(); const [position, setPosition] = useState<{ top: number; right: number; } | null>(null); const [currentLang, setCurrentLang] = useState(""); const wrapperRef = useRef(null); useEffect(() => { const update = () => { if (!editor.isActive("codeBlock")) { setPosition(null); return; } const lang = editor.getAttributes("codeBlock").language || ""; setCurrentLang(lang); // Find the code block DOM node const { $from } = editor.state.selection; let depth = $from.depth; while (depth > 0 && $from.node(depth).type.name !== "codeBlock") { depth--; } if (depth === 0 && $from.node(0).type.name !== "codeBlock") { setPosition(null); return; } const start = $from.start(depth); try { const domNode = editor.view.nodeDOM(start - 1); if (!domNode || !(domNode instanceof HTMLElement)) { setPosition(null); return; } const wrapper = domNode.closest(".compose-editor-wrapper"); if (!wrapper) { setPosition(null); return; } const blockRect = domNode.getBoundingClientRect(); const wrapperRect = wrapper.getBoundingClientRect(); setPosition({ top: blockRect.top - wrapperRect.top + 4, right: wrapperRect.right - blockRect.right + 4, }); } catch { setPosition(null); } }; editor.on("selectionUpdate", update); editor.on("transaction", update); return () => { editor.off("selectionUpdate", update); editor.off("transaction", update); }; }, [editor]); if (!position) return null; return (
); }