"use client"; import { useEffect, useRef, useState } from "react"; import { EditorView } from "@codemirror/view"; import { EditorState } from "@codemirror/state"; import { javascript } from "@codemirror/lang-javascript"; import { oneDark } from "@codemirror/theme-one-dark"; import { Button } from "./ui/Button"; import { Terminal, Copy, Check } from "lucide-react"; interface BashEditorProps { value: string; onChange: (value: string) => void; placeholder?: string; className?: string; label?: string; } export function BashEditor({ value, onChange, placeholder = "#!/bin/bash\n# Your bash script here\necho 'Hello World'", className = "", label = "Bash Script", }: BashEditorProps) { const [copied, setCopied] = useState(false); const editorRef = useRef(null); const editorViewRef = useRef(null); useEffect(() => { if (!editorRef.current) return; const bashLanguage = javascript({ typescript: false, jsx: false, }); const state = EditorState.create({ doc: value || placeholder, extensions: [ bashLanguage, oneDark, EditorView.updateListener.of((update: any) => { if (update.docChanged) { onChange(update.state.doc.toString()); } }), EditorView.theme({ "&": { fontSize: "14px", fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace', height: "100%", maxHeight: "100%", }, ".cm-content": { padding: "12px", minHeight: "200px", }, ".cm-line": { lineHeight: "1.4", }, ".cm-scroller": { fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace', height: "100%", maxHeight: "100%", }, }), ], }); const view = new EditorView({ state, parent: editorRef.current, }); editorViewRef.current = view; return () => { view.destroy(); }; }, []); useEffect(() => { if (editorViewRef.current) { const currentValue = editorViewRef.current.state.doc.toString(); if (currentValue !== value) { editorViewRef.current.dispatch({ changes: { from: 0, to: editorViewRef.current.state.doc.length, insert: value, }, }); } } }, [value]); const handleCopy = async () => { if (editorViewRef.current) { const text = editorViewRef.current.state.doc.toString(); await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); } }; return (
{label && (
{label}
)}
); }