feat: Script Generator Phase 1 — backend models, engine, API, and AD templates #105
48
frontend/src/components/script-editor/ScriptBodyEditor.tsx
Normal file
48
frontend/src/components/script-editor/ScriptBodyEditor.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { useRef, useCallback } from 'react'
|
||||
import { PowerShellHighlighter } from '@/components/scripts/PowerShellHighlighter'
|
||||
|
||||
interface Props {
|
||||
value: string
|
||||
onChange: (value: string) => void
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export function ScriptBodyEditor({ value, onChange, disabled }: Props) {
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
||||
|
||||
const handleTab = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Tab') {
|
||||
e.preventDefault()
|
||||
const ta = e.currentTarget
|
||||
const start = ta.selectionStart
|
||||
const end = ta.selectionEnd
|
||||
const newValue = value.substring(0, start) + ' ' + value.substring(end)
|
||||
onChange(newValue)
|
||||
// Restore cursor position after React re-render
|
||||
requestAnimationFrame(() => {
|
||||
ta.selectionStart = ta.selectionEnd = start + 4
|
||||
})
|
||||
}
|
||||
}, [value, onChange])
|
||||
|
||||
return (
|
||||
<div className="relative rounded-xl border border-border overflow-hidden">
|
||||
{/* Highlighted overlay (read-only visual layer) */}
|
||||
<div className="absolute inset-0 pointer-events-none overflow-auto p-4">
|
||||
<PowerShellHighlighter script={value || ' '} />
|
||||
</div>
|
||||
|
||||
{/* Editable textarea (transparent text, visible caret) */}
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
value={value}
|
||||
onChange={e => onChange(e.target.value)}
|
||||
onKeyDown={handleTab}
|
||||
disabled={disabled}
|
||||
spellCheck={false}
|
||||
className="relative z-10 w-full min-h-[300px] resize-y font-label text-sm bg-transparent text-transparent caret-foreground p-4 focus:outline-none focus:ring-1 focus:ring-[rgba(6,182,212,0.2)] disabled:cursor-not-allowed disabled:opacity-50"
|
||||
placeholder="# Enter your PowerShell script here… # Use {{ param_name }} for parameter placeholders"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user