add line numbers to code editor
this is the sort of fancy stuff we can do now
This commit is contained in:
parent
09a81ec032
commit
92e3b8fcb7
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = [];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue