+
`
@@ -117,15 +141,19 @@ export default class LightEditor extends BaseElement {
}
const textarea = element
- const self = this
- this.textareaObserver = new MutationObserver((mutationRecords) => {
+ this.textareaResizeObserver = new ResizeObserver((entries) => this.handleTextAreaResize(entries))
+
+ this.textareaResizeObserver.observe(textarea)
+
+ this.textareaMutationObserver = new MutationObserver((mutationRecords) => {
+ // We actually don't care about what the mutation is, just update and move on.
// for (const mutation of mutationRecords) {
// }
this.value = textarea.value
})
- this.textareaObserver.observe(textarea, {
+ this.textareaMutationObserver.observe(textarea, {
characterData: true,
subtree: true
})
@@ -162,6 +190,12 @@ export default class LightEditor extends BaseElement {
pre.scrollLeft = textarea.scrollLeft;
}
+ disconnectedCallback () {
+ this.textareaResizeObserver?.disconnect()
+ this.textareaMutationObserver?.disconnect()
+ super.disconnectedCallback()
+ }
+
/**
* @param {KeyboardEvent} evt
*/
diff --git a/exports/light-editor.styles.js b/exports/light-editor.styles.js
index 0fe6a5c4..5b375377 100644
--- a/exports/light-editor.styles.js
+++ b/exports/light-editor.styles.js
@@ -1,7 +1,7 @@
import { css } from "lit"
export const styles = css`
- [part~="editor"] {
+ [part~="base"] {
display:grid;
grid-template-columns: minmax(0, 1fr);
grid-template-rows: minmax(0, 1fr);
@@ -50,10 +50,22 @@ export const styles = css`
background-color: #f7f7f7;
}
+ [part~="pre"] {
+ height: var(--textarea-height, auto);
+ max-height: var(--textarea-height, auto);
+ width: var(--textarea-width, auto);
+ max-width: var(--textarea-width, auto);
+ }
+
[part~="pre"],
[part~="code"],
[part~="textarea"] {
font-family: Menlo, Monaco, "Courier New", monospace;
font-size: 0.875rem;
}
+
+ [part~="textarea"]::selection {
+ color: inherit;
+ background-color: rgba(0,0,0,0.15);
+ }
`
diff --git a/exports/light-pen.js b/exports/light-pen.js
index 0b568786..0c7578f8 100644
--- a/exports/light-pen.js
+++ b/exports/light-pen.js
@@ -4,14 +4,6 @@ import { html } from "lit"
import { styles } from "./light-pen.styles.js"
import { when } from "lit/directives/when.js";
-import { theme } from './default-theme.styles.js'
-
-import HighlightJS from 'highlight.js/lib/core';
-import JavaScript from 'highlight.js/lib/languages/javascript';
-import HTML from 'highlight.js/lib/languages/xml';
-import CSS from 'highlight.js/lib/languages/css';
-import { unsafeHTML } from "lit/directives/unsafe-html.js";
-import { ref } from "lit/directives/ref.js";
import { baseStyles, buttonStyles } from "./base-styles.js";
import { clamp } from '../internal/clamp.js'
@@ -22,11 +14,6 @@ import { resizeIcon } from "../internal/resize-icon.js";
import { BaseElement } from "../internal/base-element.js";
import LightEditor from "./light-editor.js";
-// Then register the languages you need
-HighlightJS.registerLanguage('javascript', JavaScript);
-HighlightJS.registerLanguage('xml', HTML);
-HighlightJS.registerLanguage('css', CSS);
-
/**
* @typedef {"html" | "css" | "js"} SupportedLanguages
* @typedef {HTMLTextAreaElement | HTMLScriptElement | HTMLTemplateElement} SafeTemplateElements
@@ -69,7 +56,7 @@ export default class LightPen extends BaseElement {
htmlResizeObserver: { attribute: false },
jsResizeObserver: { attribute: false },
cssResizeObserver: { attribute: false },
- resizing: { attribute: false },
+ _resizing: { attribute: false },
}
static {
@@ -98,24 +85,6 @@ export default class LightPen extends BaseElement {
*/
this.resizeObserver = new ResizeObserver((entries) => this.handleResize(entries));
- /**
- * @property
- * @type {ResizeObserver}
- */
- this.htmlResizeObserver = new ResizeObserver((entries) => this.handleTextAreaResize(entries))
-
- /**
- * @property
- * @type {ResizeObserver}
- */
- this.jsResizeObserver = new ResizeObserver((entries) => this.handleTextAreaResize(entries))
-
- /**
- * @property
- * @type {ResizeObserver}
- */
- this.cssResizeObserver = new ResizeObserver((entries) => this.handleTextAreaResize(entries))
-
/**
* @attribute
* @reflect
@@ -152,27 +121,6 @@ export default class LightPen extends BaseElement {
*/
this.consoleText = ""
- /**
- * What to reset the HTML to.
- * @property
- * @type {string}
- */
- this.htmlReset = ""
-
- /**
- * What to reset the CSS to.
- * @property
- * @type {string}
- */
- this.cssReset = ""
-
- /**
- * What to reset the JS to.
- * @property
- * @type {string}
- */
- this.jsReset = ""
-
/**
* @property
* @internal
@@ -189,7 +137,33 @@ export default class LightPen extends BaseElement {
/**
* @internal
*/
- this.resizing = false
+ this._resizing = false
+
+ this.cssCode = ""
+ this.htmlCode = ""
+ this.jsCode = ""
+ }
+
+
+ /**
+ * @type {undefined | null | LightEditor}
+ */
+ get jsEditor () {
+ return this.shadowRoot?.querySelector("#editor-js")
+ }
+
+ /**
+ * @type {undefined | null | LightEditor}
+ */
+ get cssEditor () {
+ return this.shadowRoot?.querySelector("#editor-css")
+ }
+
+ /**
+ * @type {undefined | null | LightEditor}
+ */
+ get htmlEditor () {
+ return this.shadowRoot?.querySelector("#editor-html")
}
/**
@@ -202,35 +176,9 @@ export default class LightPen extends BaseElement {
this.updateComplete.then(() => {
this.resizeObserver.observe(this)
-
- /*
- * Grab reset values so we can reset the inputs
- */
- this.htmlReset = this.htmlTextArea?.value || ""
- this.cssReset = this.cssTextArea?.value || ""
- this.jsReset = this.jsTextArea?.value || ""
});
}
- /**
- * @param {ResizeObserverEntry[]} entries
- */
- handleTextAreaResize (entries) {
- const { target } = entries[0]
- const {
- // left, right,
- top, bottom
- } = entries[0].contentRect;
- // const width = left + right
- const height = top + bottom
-
- // @ts-expect-error
- target.parentElement.style.setProperty("--textarea-height", `${height}px`)
-
- // One day we'll allow the textarea to resize the width.
- // target.parentElement.style.setProperty("--textarea-width", `${width}px`)
- }
-
/**
* Sets an initial width so we dont need to keep computing getBoundingClientRect
*/
@@ -260,9 +208,6 @@ export default class LightPen extends BaseElement {
return this.shadowRoot?.querySelector("iframe")
}
- handleEditorInput () {
- }
-
updateIframeContent () {
const iframeElem= this.iframeElem
if (iframeElem == null) return
@@ -288,10 +233,6 @@ export default class LightPen extends BaseElement {
iframeElem.contentWindow?.document.close()
}
- inputHandler () {
- this.updateCode()
- }
-
/**
* @param {import("lit").PropertyValues} changedProperties
*/
@@ -310,37 +251,7 @@ export default class LightPen extends BaseElement {
disconnectedCallback() {
super.disconnectedCallback()
-
- this.htmlTextArea && this.htmlResizeObserver.disconnect()
- this.cssTextArea && this.cssResizeObserver.disconnect()
- this.jsTextArea && this.jsResizeObserver.disconnect()
- }
-
- /**
- * @param {HTMLTextAreaElement} textarea
- */
- htmlTextAreaChanged (textarea) {
- if (!textarea) return
- this.htmlTextArea = textarea
- this.htmlResizeObserver.observe(textarea)
- }
-
- /**
- * @param {HTMLTextAreaElement} textarea
- */
- cssTextAreaChanged (textarea) {
- if (!textarea) return
- this.cssTextArea = textarea
- this.cssResizeObserver.observe(textarea)
- }
-
- /**
- * @param {HTMLTextAreaElement} textarea
- */
- jsTextAreaChanged (textarea) {
- if (!textarea) return
- this.jsTextArea = textarea
- this.jsResizeObserver.observe(textarea)
+ this.resizeObserver.disconnect()
}
/**
@@ -384,30 +295,12 @@ export default class LightPen extends BaseElement {
}
- /**
- * Lovely helper to scoop up our html, css, and js code
- */
- updateCode () {
- this.cssCode = this.cssTextArea?.value
- this.htmlCode = this.htmlTextArea?.value
- this.jsCode = this.jsTextArea?.value
- }
-
resetValues () {
- if (this.htmlTextArea) {
- this.htmlCode = this.htmlReset
- this.htmlTextArea.value = this.htmlReset
- }
-
- if (this.cssTextArea) {
- this.cssCode = this.cssReset
- this.cssTextArea.value = this.cssReset
- }
+ this.htmlCode = this.htmlEditor?.getAttribute("value") || ""
+ this.cssCode = this.cssEditor?.getAttribute("value") || ""
+ this.jsCode = this.cssEditor?.getAttribute("value") || ""
+ this.requestUpdate()
- if (this.jsTextArea) {
- this.jsCode = this.jsReset
- this.jsTextArea.value = this.jsReset
- }
}
// setupIframeLogging() {
@@ -462,9 +355,10 @@ export default class LightPen extends BaseElement {
this[`${codeType}Code`] = code
- const textArea = this[`${codeType}TextArea`]
+ const textArea = this[`${codeType}Editor`]
if (textArea && code) {
+ textArea.setAttribute("value", code)
textArea.value = code
}
}
@@ -494,7 +388,7 @@ export default class LightPen extends BaseElement {
-