function Editor(opt = {}) {
const {language, styles, value, label, lineNumbers, codeJarOpts, instant, debounced, highlight} = {
language: 'plaintext',
styles: defaultStyles,
value: '',
label: '',
lineNumbers: false,
instant: false,
highlight: highlighter,
debounced: 0,
codeJarOpts: { preserveIdent: false },
...opt
};
const container = html`<div>`
const run = html`<div style="display: ${"none"}; position: absolute; right: 10px; cursor: pointer; top: ${label && typeof label == "string" ? "32px" : "7px"}; z-index: 1;">${svg`<svg width=12 height=12 viewbox="0 0 14 14">${runButton}`}`;
container.addEventListener('mouseenter', (e) => {
run.style.display = "inline-block";
})
container.addEventListener('mouseleave', (e) => {
run.style.display = "none";
})
container.append(run)
let shiftDown = false;
let lb;
if (label) {
const isString = typeof label == "string";
lb = html`${isString ? `<label style="display: block; font-family: sans-serif; color: #333; font-size: 0.9em;">${label}:` : label}`;
container.append(lb);
}
container.append(html`<span style="${languageLabelStyles}
top: ${label && typeof label == "string" ? `35px` : "10px"}">${language}`)
const ed = html`<div style="${styles} padding-left: ${lineNumbers ? '45px' : '10px'};" class="language-${language}">${value}`;
container.appendChild(ed);
container.value = value;
let jar = CodeJar(ed, lineNumbers ? withLineNumbers(highlight, {
// unclear why but this makes line numbers black
color: '#fff'
}) : highlight, codeJarOpts);
let settingInternally = false
// support sending and receiving updates as per https://observablehq.com/@tophtucker/custom-input-example
Object.defineProperty(container, "value", {
get() {
// console.log("editor.get called:", ed.textContent)
return ed.textContent;
},
set(v) {
// console.log("editor.set called with: ",v)
// Only set this when we are receiving an external message, otherwise it moves the cursor within the input
if (!settingInternally) {
ed.textContent = v;
jar.updateCode(v);
}
settingInternally = false
}
});
if (lineNumbers) {
const lineNumberContainer = container.querySelector('.codejar-linenumbers');
lineNumberContainer.style.textAlign = "center";
lineNumberContainer.style.fontFamily = "monospace";
lineNumberContainer.style.paddingTop = "10px";
lineNumberContainer.style.fontSize = "13px";
}
ed.addEventListener('input', (e) => {
e.stopPropagation();
})
ed.addEventListener('keydown', (e) => {
if (e.key == "Shift") shiftDown = true;
if (e.key == "Enter") {
if (shiftDown) {
e.preventDefault();
container.value = ed.textContent;
container.dispatchEvent(new CustomEvent("input"));
}
}
})
run.addEventListener('click', (e) => {
container.value = ed.textContent;
container.dispatchEvent(new CustomEvent("input"));
})
ed.addEventListener('keyup', (e) => {
if (e.key == "Shift") shiftDown = false;
})
const debouncedUpdate = debounce((code) => {
settingInternally = true;
container.value = code;
container.dispatchEvent(new CustomEvent("input"));
}, debounced);
jar.onUpdate(code => {
if (instant || debounced > 0) {
debouncedUpdate(code);
}
})
const wrap = container.querySelector('.codejar-wrap');
return container;
}