Custom Editor
Live.Editor accepts renderEditor to fully replace the built-in CodeMirror
editing surface — the example below uses a plain <textarea>. It still syncs
to the shared preview code automatically, exactly like the default editor.
import { useState } from 'react';
import Live from '@jbpark/live-editor';
export default function CustomEditor() {
const [value, setValue] = useState('// your code');
return (
<Live>
<Live.Preview
showError
dynamicTailwind
frame={{ mode: 'shadow', syncStyle: true }}
/>
<Live.Editor
value={value}
onChange={setValue}
renderEditor={({ value: text, onChange }) => (
<textarea
value={text}
onChange={e => onChange(e.target.value)}
spellCheck={false}
style={{ width: '100%', height: '100%', fontFamily: 'monospace' }}
/>
)}
/>
</Live>
);
}
The renderEditor render prop receives an EditorRenderData object with
three fields:
| Field | Type | Description |
|---|---|---|
value | string | Current code. |
onChange | (value: string) => void | Commit an edit — wire this into your editing surface's own change handler. |
formatCode | (code: string) => Promise<string> | The same prettier-based formatting the built-in editor's Cmd+S uses. Call it to offer format-on-save without reimplementing prettier wiring yourself. |
Wire value/onChange into any editing surface you like (a <textarea>,
Monaco, your own component) — the shared preview stays in sync through
Live's context. formatCode is entirely optional; the example above skips
it and just does a raw <textarea> with no formatting.