0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-03-22 11:08:10 +00:00

basic css changes

This commit is contained in:
Víctor Losada Hernández
2026-03-21 22:53:38 +01:00
parent 3785d5808f
commit 42e254c9c7
8 changed files with 216 additions and 166 deletions

View File

@@ -6,138 +6,153 @@ import { foldGutter, foldKeymap } from "@codemirror/language";
import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightActiveLine } from "@codemirror/view";
import { markdown } from "@codemirror/lang-markdown";
import { css } from "@codemirror/lang-css";
import { oneDark } from "@codemirror/theme-one-dark";
const CodeEditor = forwardRef(({ value = "", onChange = () => {} }, ref) => {
const editorRef = useRef(null);
const viewRef = useRef(null);
const CodeEditor = forwardRef(
({ value = "", onChange = () => {}, language, editorTheme, tab, view, style, ...props }, ref) => {
const editorRef = useRef(null);
const viewRef = useRef(null);
// --- init editor ---
useEffect(() => {
if (!editorRef.current) return;
console.log(props);
const updateListener = EditorView.updateListener.of((update) => {
if (update.docChanged) {
onChange(update.state.doc.toString());
// --- init editor ---
useEffect(() => {
if (!editorRef.current) return;
const updateListener = EditorView.updateListener.of((update) => {
if (update.docChanged) {
onChange(update.state.doc.toString());
}
});
const boldCommand = (view) => {
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
const text = `**${selected}**`;
view.dispatch({
changes: { from, to, insert: text },
selection: { anchor: from + text.length },
});
return true;
};
const italicCommand = (view) => {
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
const text = `*${selected}*`;
view.dispatch({
changes: { from, to, insert: text },
selection: { anchor: from + text.length },
});
return true;
};
const customKeymap = keymap.of([
{ key: "Mod-b", run: boldCommand },
{ key: "Mod-i", run: italicCommand },
]);
const languageExtension = () => {
switch (language) {
case "gfm":
return markdown({ codeLanguages: [] }); // GitHub-flavored Markdown
case "css":
return css();
default:
return markdown();
}
};
const state = EditorState.create({
doc: value,
extensions: [
history(),
keymap.of(defaultKeymap),
customKeymap,
updateListener,
languageExtension(),
highlightActiveLine(),
highlightActiveLineGutter(),
keymap.of(foldKeymap),
foldGutter(),
lineNumbers(),
oneDark,
],
});
viewRef.current = new EditorView({
state,
parent: editorRef.current,
});
return () => viewRef.current?.destroy();
}, []);
// --- sync external value ---
useEffect(() => {
const view = viewRef.current;
if (!view) return;
const current = view.state.doc.toString();
if (value !== current) {
view.dispatch({
changes: { from: 0, to: current.length, insert: value },
});
}
});
}, [value]);
const boldCommand = (view) => {
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
const text = `**${selected}**`;
// --- exposed API ---
useImperativeHandle(ref, () => ({
getValue: () => viewRef.current.state.doc.toString(),
view.dispatch({
changes: { from, to, insert: text },
selection: { anchor: from + text.length },
});
setValue: (text) => {
const view = viewRef.current;
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: text },
});
},
return true;
};
injectText: (text) => {
const view = viewRef.current;
const { from, to } = view.state.selection.main;
const italicCommand = (view) => {
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
const text = `*${selected}*`;
view.dispatch({
changes: { from, to, insert: text },
selection: { anchor: from + text.length },
});
view.dispatch({
changes: { from, to, insert: text },
selection: { anchor: from + text.length },
});
view.focus();
},
return true;
};
getCursorPosition: () => viewRef.current.state.selection.main.head,
const customKeymap = keymap.of([
{ key: "Mod-b", run: boldCommand },
{ key: "Mod-i", run: italicCommand },
]);
setCursorPosition: (pos) => {
viewRef.current.dispatch({ selection: { anchor: pos } });
viewRef.current.focus();
},
const state = EditorState.create({
doc: value,
extensions: [
history(),
keymap.of(defaultKeymap),
customKeymap,
updateListener,
markdown(),
css(),
highlightActiveLine(),
highlightActiveLineGutter(),
keymap.of(foldKeymap),
foldGutter(),
lineNumbers(),
],
});
undo: () => undo(viewRef.current),
redo: () => redo(viewRef.current),
viewRef.current = new EditorView({
state,
parent: editorRef.current,
});
historySize: () => {
const view = viewRef.current;
if (!view) return { done: 0, undone: 0 };
return () => viewRef.current?.destroy();
}, []);
const h = view.state.field(historyField, false);
if (!h) return { done: 0, undone: 0 };
// --- sync external value ---
useEffect(() => {
const view = viewRef.current;
if (!view) return;
return { done: h.done.length, undone: h.undone.length };
},
const current = view.state.doc.toString();
if (value !== current) {
view.dispatch({
changes: { from: 0, to: current.length, insert: value },
});
}
}, [value]);
focus: () => viewRef.current.focus(),
}));
// --- exposed API ---
useImperativeHandle(ref, () => ({
getValue: () => viewRef.current.state.doc.toString(),
return <div className="codeEditor" ref={editorRef} style={style} />;
},
);
setValue: (text) => {
const view = viewRef.current;
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: text },
});
},
injectText: (text) => {
const view = viewRef.current;
const { from, to } = view.state.selection.main;
view.dispatch({
changes: { from, to, insert: text },
selection: { anchor: from + text.length },
});
view.focus();
},
getCursorPosition: () => viewRef.current.state.selection.main.head,
setCursorPosition: (pos) => {
viewRef.current.dispatch({ selection: { anchor: pos } });
viewRef.current.focus();
},
undo: () => undo(viewRef.current),
redo: () => redo(viewRef.current),
historySize: () => {
const view = viewRef.current;
if (!view) return { done: 0, undone: 0 };
const h = view.state.field(historyField, false);
if (!h) return { done: 0, undone: 0 };
return { done: h.done.length, undone: h.undone.length };
},
focus: () => viewRef.current.focus(),
}));
return <div ref={editorRef} style={{ height: "100%" }} />;
});
export default CodeEditor;
export default CodeEditor;