UNPKG

@uiw/react-codemirror

Version:
171 lines (155 loc) 4.06 kB
import { useEffect, useState } from 'react'; import { EditorState, StateEffect } from '@codemirror/state'; import { indentWithTab } from '@codemirror/commands'; import { EditorView, keymap, placeholder } from '@codemirror/view'; import { oneDark } from '@codemirror/theme-one-dark'; import { basicSetup } from './basicSetup'; export function useCodeMirror(props) { var { value, selection, onChange, onUpdate, extensions = [], autoFocus, theme = 'light', height = '', minHeight = '', maxHeight = '', placeholder: placeholderStr = '', width = '', minWidth = '', maxWidth = '', editable = true, readOnly = false, indentWithTab: defaultIndentWithTab = true, basicSetup: defaultBasicSetup = true, root } = props; var [container, setContainer] = useState(); var [view, setView] = useState(); var [state, setState] = useState(); var defaultLightThemeOption = EditorView.theme({ '&': { backgroundColor: '#fff' } }, { dark: false }); var defaultThemeOption = EditorView.theme({ '&': { height, minHeight, maxHeight, width, minWidth, maxWidth } }); var updateListener = EditorView.updateListener.of(vu => { if (vu.docChanged && typeof onChange === 'function') { var doc = vu.state.doc; var _value = doc.toString(); onChange(_value, vu); } }); var getExtensions = [updateListener, defaultThemeOption]; if (defaultIndentWithTab) { getExtensions.unshift(keymap.of([indentWithTab])); } if (defaultBasicSetup) { if (typeof defaultBasicSetup === 'boolean') { getExtensions.unshift(basicSetup()); } else { getExtensions.unshift(basicSetup(defaultBasicSetup)); } } if (placeholderStr) { getExtensions.unshift(placeholder(placeholderStr)); } switch (theme) { case 'light': getExtensions.push(defaultLightThemeOption); break; case 'dark': getExtensions.push(oneDark); break; default: getExtensions.push(theme); break; } if (editable === false) { getExtensions.push(EditorView.editable.of(false)); } if (readOnly) { getExtensions.push(EditorState.readOnly.of(true)); } if (onUpdate && typeof onUpdate === 'function') { getExtensions.push(EditorView.updateListener.of(onUpdate)); } getExtensions = getExtensions.concat(extensions); useEffect(() => { if (container && !state) { var stateCurrent = EditorState.create({ doc: value, selection, extensions: getExtensions }); setState(stateCurrent); if (!view) { var viewCurrent = new EditorView({ state: stateCurrent, parent: container, root }); setView(viewCurrent); } } return () => { if (view) { setState(undefined); setView(undefined); } }; }, [container, state]); useEffect(() => setContainer(props.container), [props.container]); useEffect(() => () => { if (view) { view.destroy(); setView(undefined); } }, [view]); useEffect(() => { if (autoFocus && view) { view.focus(); } }, [autoFocus, view]); useEffect(() => { if (view) { view.dispatch({ effects: StateEffect.reconfigure.of(getExtensions) }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [theme, extensions, height, minHeight, maxHeight, width, minWidth, maxWidth, placeholderStr, editable, readOnly, defaultIndentWithTab, defaultBasicSetup, onChange, onUpdate]); useEffect(() => { var currentValue = view ? view.state.doc.toString() : ''; if (view && value !== currentValue) { view.dispatch({ changes: { from: 0, to: currentValue.length, insert: value || '' } }); } }, [value, view]); return { state, setState, view, setView, container, setContainer }; } //# sourceMappingURL=useCodeMirror.js.map