@trailstash/ultra
Version:
A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc
106 lines (102 loc) • 2.92 kB
JavaScript
import { h } from "../lib/dom.js";
const style = new CSSStyleSheet();
style.replace(`
:host {
display: block;
}
textarea {
display: block;
height: 100%;
width: 100%;
margin: 0;
padding: 5px;
border: 0;
box-sizing: border-box;
}
`);
export class CodeEditor extends HTMLElement {
static observedAttributes = ["source"];
get source() {
return this.getAttribute("source");
}
set source(value) {
return this.setAttribute("source", value);
}
constructor() {
super();
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue != newValue) {
this.dispatchEvent(new Event("change"));
}
if (this.refs && this.refs.textarea.value !== newValue) {
this.refs.textarea.value = newValue;
}
}
connectedCallback() {
const shadow = this.attachShadow({ mode: "open" });
shadow.adoptedStyleSheets.push(style);
const textarea = h("textarea", {
autofocus: this.autofocus,
spellcheck: false,
autocapitalize: "off",
value: this.source,
});
this.refs = { textarea };
this.refs.textarea.selectionStart = 0;
this.refs.textarea.selectionEnd = 0;
shadow.appendChild(textarea);
textarea.addEventListener("dragenter", (e) => {
e.preventDefault();
});
textarea.addEventListener("dragover", (e) => {
e.preventDefault();
});
textarea.addEventListener("drop", async (e) => {
e.preventDefault();
const item = e.dataTransfer.items[0];
if (item.kind === "file") {
this.source = await item.getAsFile().text();
} else {
this.source = e.dataTransfer.getData("text/plain");
}
});
textarea.addEventListener("keydown", (e) => {
const start = e.target.selectionStart;
const end = e.target.selectionEnd;
const textFromLastNewLine =
start === 0
? ""
: e.target.value.slice(
e.target.value.slice(0, start).lastIndexOf("\n") + 1,
);
const leadingWhitespace =
textFromLastNewLine.match(/^([ \t])+/)?.[0] || "";
if (e.key == "Tab") {
e.preventDefault();
e.target.value =
e.target.value.substring(0, start) +
" " +
e.target.value.substring(end);
e.target.selectionStart = e.target.selectionEnd = start + 2;
}
if (e.key == "Enter") {
e.preventDefault();
if (e.ctrlKey) {
this.dispatchEvent(new Event("run"));
} else {
e.target.value =
e.target.value.substring(0, start) +
"\n" +
leadingWhitespace +
e.target.value.substring(end);
e.target.selectionStart = e.target.selectionEnd =
start + 1 + leadingWhitespace.length;
}
}
});
textarea.addEventListener("keyup", (e) => {
this.source = e.target.value;
});
}
}