@dodona/papyros
Version:
Scratchpad for multiple programming languages in the browser.
170 lines (165 loc) • 6.67 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { customElement, state } from "lit/decorators.js";
import { PapyrosElement } from "./PapyrosElement";
import { css, html } from "lit";
import { createRef, ref } from "lit/directives/ref.js";
import { CODE_TAB } from "../state/InputOutput";
import { arrayBufferToBase64, isTextMimeType } from "../../util/Util";
import "./code_runner/Code";
import "./code_runner/RunState";
import "./code_runner/ButtonLint";
import "./EditorTabs";
import "./FileViewer";
let CodeRunner = class CodeRunner extends PapyrosElement {
constructor() {
super(...arguments);
this.dragOver = false;
this.dropZoneRef = createRef();
this.onDragOver = (e) => {
e.preventDefault();
e.stopPropagation();
if (this.papyros.debugger.active)
return;
if (!this.dragOver)
this.dragOver = true;
};
this.onDragLeave = (e) => {
const dropZone = this.dropZoneRef.value;
// Only react if leaving the drop zone, not moving between children
if (e.relatedTarget && (dropZone === null || dropZone === void 0 ? void 0 : dropZone.contains(e.relatedTarget)))
return;
this.dragOver = false;
};
this.onDrop = (e) => {
e.preventDefault();
e.stopPropagation();
this.dragOver = false;
if (this.papyros.debugger.active || !e.dataTransfer)
return;
for (const file of Array.from(e.dataTransfer.files)) {
this.readAndAddFile(file);
}
if (e.dataTransfer.types.includes("text/uri-list")) {
const uriList = e.dataTransfer.getData("text/uri-list");
const urls = uriList
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line && !line.startsWith("#"));
for (const url of urls) {
void this.papyros.runner.fetchAndAddUrl(url);
}
}
};
}
static get styles() {
return css `
:host {
width: 100%;
display: flex;
flex-direction: column;
border-radius: 0.5rem;
}
.drop-zone {
display: flex;
flex-direction: column;
flex-grow: 1;
min-height: 0;
position: relative;
}
.drop-zone.drag-over::after {
content: "";
position: absolute;
inset: 0;
border: 2px dashed var(--md-sys-color-primary);
border-radius: 0.5rem;
background-color: color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent);
pointer-events: none;
z-index: 10;
}
.editor {
flex-grow: 1;
min-height: 0;
position: relative;
}
p-run-state {
position: absolute;
bottom: 0;
right: 6px;
background-color: var(--md-sys-color-surface-container);
padding: 0.25rem 1rem;
border-top-right-radius: 1rem;
border-top-left-radius: 1rem;
}
p-button-lint {
background-color: var(--md-sys-color-surface-container);
}
`;
}
firstUpdated() {
const dropZone = this.dropZoneRef.value;
if (!dropZone)
return;
// Use capture phase so we intercept before CodeMirror handles the drop
dropZone.addEventListener("dragover", this.onDragOver, true);
dropZone.addEventListener("dragleave", this.onDragLeave, true);
dropZone.addEventListener("drop", this.onDrop, true);
}
disconnectedCallback() {
super.disconnectedCallback();
const dropZone = this.dropZoneRef.value;
if (!dropZone)
return;
dropZone.removeEventListener("dragover", this.onDragOver, true);
dropZone.removeEventListener("dragleave", this.onDragLeave, true);
dropZone.removeEventListener("drop", this.onDrop, true);
}
readAndAddFile(file) {
const reader = new FileReader();
if (isTextMimeType(file.type)) {
reader.onload = () => {
this.papyros.runner.upsertFile(file.name, reader.result, false);
};
reader.readAsText(file);
}
else {
reader.onload = () => {
this.papyros.runner.upsertFile(file.name, arrayBufferToBase64(reader.result), true);
};
reader.readAsArrayBuffer(file);
}
}
render() {
const files = this.papyros.debugger.active ? this.papyros.debugger.debugFiles : this.papyros.io.files;
const activeTab = this.papyros.io.activeEditorTab;
const activeFile = files.find((f) => f.name === activeTab);
return html `
<div ${ref(this.dropZoneRef)} class="drop-zone ${this.dragOver ? "drag-over" : ""}">
<p-editor-tabs .papyros=${this.papyros} .files=${files}></p-editor-tabs>
<div class="editor">
${activeTab === CODE_TAB
? html `<p-code .papyros=${this.papyros}></p-code>`
: html `<p-file-viewer .papyros=${this.papyros} .file=${activeFile}></p-file-viewer>`}
${this.papyros.runner.stateMessage
? html `<p-run-state .papyros=${this.papyros}></p-run-state>`
: ""}
</div>
<p-button-lint .papyros=${this.papyros}>
<slot name="buttons"></slot>
</p-button-lint>
</div>
`;
}
};
__decorate([
state()
], CodeRunner.prototype, "dragOver", void 0);
CodeRunner = __decorate([
customElement("p-code-runner")
], CodeRunner);
export { CodeRunner };
//# sourceMappingURL=CodeRunner.js.map