add line numbers to code editor

this is the sort of fancy stuff we can do now
This commit is contained in:
liquidex 2024-09-05 22:05:15 +02:00
parent 09a81ec032
commit 92e3b8fcb7
3 changed files with 95 additions and 10 deletions

View file

@ -11,6 +11,9 @@
--color-shaded-background: rgba(0, 0, 0, 5%);
--dialog-backdrop: rgba(255, 255, 255, 0.5);
--font-body: "Atkinson Hyperlegible", sans-serif;
--font-monospace: "Iosevka Hyperlegible", monospace;
}
/* Reset */
@ -24,7 +27,7 @@ body {
/* Fonts */
:root {
font-family: "Atkinson Hyperlegible", sans-serif;
font-family: var(--font-body);
}
button, textarea, input {
@ -33,7 +36,7 @@ button, textarea, input {
}
pre, code, textarea {
font-family: "Iosevka Hyperlegible", monospace;
font-family: var(--font-monospace);
line-height: 1.5;
}

View file

@ -6,6 +6,9 @@ export class CodeEditor extends HTMLElement {
connectedCallback() {
this.indentWidth = 2;
this.layerGutter = this.appendChild(document.createElement("pre"));
this.layerGutter.classList.add("layer", "layer-gutter");
this.textArea = this.appendChild(document.createElement("textarea"));
this.textArea.spellcheck = false;
this.textArea.rows = 1;
@ -29,13 +32,17 @@ export class CodeEditor extends HTMLElement {
this.#textAreaAutoSizingBehaviour();
this.#keyShortcutBehaviours();
this.#renderLayers();
}
get code() {
return this.textArea.value;
}
#sendCodeChanged() {
#codeChanged() {
this.#resizeTextArea();
this.#renderLayers();
this.dispatchEvent(
Object.assign(new Event(".codeChanged"), {
newCode: this.code,
@ -45,14 +52,14 @@ export class CodeEditor extends HTMLElement {
setCode(value) {
this.textArea.value = value;
this.#resizeTextArea();
this.#sendCodeChanged();
this.#codeChanged();
}
// Resizing the text area
#textAreaAutoSizingBehaviour() {
this.textArea.addEventListener("input", () => {
this.#resizeTextArea();
this.#sendCodeChanged();
this.#codeChanged();
});
this.#resizeTextArea();
document.fonts.addEventListener("loadingdone", () => this.#resizeTextArea());
@ -84,6 +91,24 @@ export class CodeEditor extends HTMLElement {
this.textArea.style.height = `${this.textArea.scrollHeight}px`;
}
// Layers
#renderLayers() {
this.#renderGutter();
}
#renderGutter() {
this.layerGutter.replaceChildren();
for (let line of this.code.split("\n")) {
let lineElement = this.layerGutter.appendChild(document.createElement("span"));
lineElement.classList.add("line");
lineElement.textContent = line;
}
}
// Text editing
#keyShortcutBehaviours() {
this.textArea.addEventListener("keydown", (event) => {
let keyComponents = [];

View file

@ -169,15 +169,72 @@ rkgk-reticle-cursor {
/* Code editor */
rkgk-code-editor {
--gutter-width: 2.5em;
display: block;
position: relative;
width: 100%;
&>.layer {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
margin: 0;
pointer-events: none;
display: flex;
flex-direction: column;
&>.line {
white-space: pre-wrap;
}
}
&>.layer-gutter {
user-select: none;
counter-reset: line;
color: transparent;
&>.line {
display: flex;
flex-direction: row;
counter-increment: line;
&::before {
display: block;
width: var(--gutter-width);
flex-shrink: 0;
padding-right: 0.5em;
box-sizing: border-box;
content: counter(line);
text-align: right;
color: var(--color-text);
opacity: 40%;
}
}
}
&>textarea {
display: block;
width: 100%;
width: calc(100% - var(--gutter-width));
margin: 0;
margin-left: var(--gutter-width);
padding: 0;
box-sizing: border-box;
overflow: hidden;
resize: none;
white-space: pre-wrap;
border: none;
overflow: hidden;
box-sizing: border-box;
}
}