Got Codemirror up and running

This commit is contained in:
Gregory Schier
2023-02-15 19:53:46 -08:00
parent f3fc1fc0c4
commit 2f1d3a5c60
11 changed files with 853 additions and 56 deletions

View File

@@ -1,53 +1,40 @@
import { useState } from "react";
import {useState} from "react";
import reactLogo from "./assets/react.svg";
import { invoke } from "@tauri-apps/api/tauri";
import {invoke} from "@tauri-apps/api/tauri";
import "./App.css";
import Editor from "./Editor";
function App() {
const [greetMsg, setGreetMsg] = useState("");
const [name, setName] = useState("");
const [responseBody, setResponseBody] = useState<string>("");
const [url, setUrl] = useState("");
async function greet() {
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
setGreetMsg(await invoke("greet", { name }));
}
async function sendRequest() {
const body = await invoke("send_request", {url: url}) as string;
setResponseBody(body);
}
return (
<div className="container">
<h1>Welcome to Tauri!</h1>
return (
<div className="container">
<h1>Welcome to Twosomnia!</h1>
<div className="row">
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" className="logo vite" alt="Vite logo" />
</a>
<a href="https://tauri.app" target="_blank">
<img src="/tauri.svg" className="logo tauri" alt="Tauri logo" />
</a>
<a href="https://reactjs.org" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<p>Click on the Tauri, Vite, and React logos to learn more.</p>
<div className="row">
<form
onSubmit={(e) => {
e.preventDefault();
greet();
}}
>
<input
id="greet-input"
onChange={(e) => setName(e.currentTarget.value)}
placeholder="Enter a name..."
/>
<button type="submit">Greet</button>
</form>
</div>
<p>{greetMsg}</p>
</div>
);
<div className="row">
<form
onSubmit={(e) => {
e.preventDefault();
sendRequest();
}}
>
<input
id="greet-input"
onChange={(e) => setUrl(e.currentTarget.value)}
placeholder="Enter a URL..."
/>
<button type="submit">Send</button>
<Editor value={responseBody}/>
</form>
</div>
</div>
);
}
export default App;

25
src/Editor.css Normal file
View File

@@ -0,0 +1,25 @@
.cm-editor {
height: 20rem;
background-color: #000;
border-radius: 0.5rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
text-align: left;
width: 100%;
font-size: 0.8rem;
padding: 0.3rem 0.5rem;
}
.cm-editor.cm-focused {
outline: 0;
box-shadow: 0 0 0 2pt rgba(180, 180, 180, 0.1);
}
.cm-editor .cm-content {
/*outline: 1px red;*/
border-color: red;
}
.cm-editor .cm-cursor {
border-left: 2px solid red;
}

13
src/Editor.tsx Normal file
View File

@@ -0,0 +1,13 @@
import useCodeMirror from "./hooks/useCodemirror";
import "./Editor.css";
interface Props {
value: string;
}
export default function Editor(props: Props) {
const {ref} = useCodeMirror({value: props.value});
return (
<div ref={ref} id="editor-yo" style={{height: '10rem'}}/>
)
}

View File

@@ -0,0 +1,57 @@
import {useEffect, useRef, useState} from "react";
import {EditorView, minimalSetup} from "codemirror";
import {javascript} from "@codemirror/lang-javascript";
import {json} from "@codemirror/lang-json";
import {html} from "@codemirror/lang-html";
import {tags} from "@lezer/highlight"
import {HighlightStyle, syntaxHighlighting} from "@codemirror/language"
export default function useCodeMirror({value}: { value: string }) {
const [cm, setCm] = useState<EditorView | null>(null);
const ref = useRef(null);
useEffect(() => {
if (ref.current === null) return;
const myHighlightStyle = HighlightStyle.define([
{
tag: [
tags.documentMeta,
tags.blockComment,
tags.lineComment,
tags.docComment,
tags.comment,
],
color: "#757b93"
},
{tag: tags.name, color: "#4b92ff"},
{tag: tags.variableName, color: "#4bff4e"},
{tag: tags.attributeName, color: "#b06fff"},
{tag: tags.attributeValue, color: "#ff964b"},
{tag: tags.keyword, color: "#fc6"},
{tag: tags.comment, color: "#f5d", fontStyle: "italic"}
])
const view = new EditorView({
extensions: [
minimalSetup,
syntaxHighlighting(myHighlightStyle),
html(),
javascript(),
json(),
],
parent: ref.current
});
setCm(view);
return () => view?.destroy();
}, [ref.current]);
useEffect(() => {
if (cm === null) return;
let transaction = cm.state.update({changes: {from: 0, to: cm.state.doc.length, insert: value}})
cm.dispatch(transaction)
}, [cm, value]);
return {ref, cm};
}

View File

@@ -14,13 +14,18 @@
-webkit-text-size-adjust: 100%;
}
div, form, p {
width: 100%;
}
.container {
margin: 0;
padding-top: 10vh;
margin: 0 auto;
padding-top: 2rem;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
width: 700px;
}
.logo {
@@ -37,6 +42,7 @@
.row {
display: flex;
justify-content: center;
width: 100%;
}
a {
@@ -87,16 +93,20 @@ button {
@media (prefers-color-scheme: dark) {
:root {
color: #f6f6f6;
background-color: #2f2f2f;
background-color: #181818;
}
a:hover {
color: #24c8db;
}
input,
button {
input {
color: #ffffff;
background-color: #0f0f0f98;
}
button {
color: #ffffff;
background-color: rgba(137, 98, 255, 0.6);
}
}