fix: codemirror util

This commit is contained in:
2026-03-12 20:23:39 +01:00
parent e9ed508bfc
commit 35b2e9d538
4 changed files with 94 additions and 85 deletions

View File

@@ -0,0 +1,51 @@
import { useCallback } from 'react'
/**
* Ref shape for @uiw/react-codemirror (view/state not in package types).
* Use with: ref={editorRef} and type editorRef as React.MutableRefObject<CodeMirrorEditorRef | null>.
*/
export type CodeMirrorEditorRef = {
view: {
state: {
doc: { length: number; toString(): string }
selection: { main: { from: number } }
}
dispatch: (arg: { changes: { from: number; to: number; insert: string } }) => void
}
}
export type InsertPosition = 'prepend' | 'append' | 'cursor'
/**
* Returns a stable insertAt(insertText, mode) that inserts text into the CodeMirror
* editor at the given position (prepend, append, or cursor), then calls onChange
* with the new content. Falls back to string concatenation when the editor ref
* is not yet mounted.
*/
export function useCodeMirrorInsert(
editorRef: React.RefObject<CodeMirrorEditorRef | null>,
currentContent: string,
onChange: (value: string) => void
): (insertText: string, mode: InsertPosition) => void {
return useCallback(
(insertText: string, mode: InsertPosition) => {
const ref = editorRef.current
if (ref?.view) {
const view = ref.view
const doc = view.state.doc
const len = doc.length
const from =
mode === 'prepend' ? 0 : mode === 'append' ? len : view.state.selection.main.from
view.dispatch({ changes: { from, to: from, insert: insertText } })
onChange(view.state.doc.toString())
return
}
if (mode === 'prepend') {
onChange(insertText + currentContent)
} else {
onChange(currentContent + insertText)
}
},
[currentContent, onChange]
)
}