From 3aa3ba02be47dbfcfb2b5e6eee5f4ef1922a97d2 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 20 Apr 2022 15:41:51 -0500 Subject: [PATCH] add pybutton and pytitle --- pyscriptjs/examples/todo-pylist.html | 21 +++++---- pyscriptjs/src/components/pybutton.ts | 64 +++++++++++++++++++++++++++ pyscriptjs/src/components/pytitle.ts | 37 ++++++++++++++++ pyscriptjs/src/main.ts | 4 ++ pyscriptjs/src/utils.ts | 27 ++++++++++- 5 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 pyscriptjs/src/components/pybutton.ts create mode 100644 pyscriptjs/src/components/pytitle.ts diff --git a/pyscriptjs/examples/todo-pylist.html b/pyscriptjs/examples/todo-pylist.html index 9a8e2cb..e38be33 100644 --- a/pyscriptjs/examples/todo-pylist.html +++ b/pyscriptjs/examples/todo-pylist.html @@ -18,28 +18,27 @@ - - -
- - -
-

To Do List

-
+ To Do List
-
+ + - +
diff --git a/pyscriptjs/src/components/pybutton.ts b/pyscriptjs/src/components/pybutton.ts new file mode 100644 index 0000000..452ee43 --- /dev/null +++ b/pyscriptjs/src/components/pybutton.ts @@ -0,0 +1,64 @@ +import { BaseEvalElement } from './base'; +import { addClasses, ltrim, htmlDecode } from '../utils'; + +export class PyButton extends BaseEvalElement { + shadow: ShadowRoot; + wrapper: HTMLElement; + theme: string; + widths: Array; + label: string; + mount_name: string; + constructor() { + super(); + + // attach shadow so we can preserve the element original innerHtml content + // this.shadow = this.attachShadow({ mode: 'open'}); + + // this.wrapper = document.createElement('slot'); + // this.shadow.appendChild(this.wrapper); + if (this.hasAttribute('label')) { + this.label = this.getAttribute('label'); + } + } + + + connectedCallback() { + this.code = htmlDecode(this.innerHTML); + this.mount_name = this.id.split("-").join("_"); + this.innerHTML = ''; + + let mainDiv = document.createElement('button'); + mainDiv.innerHTML = this.label; + addClasses(mainDiv, ["p-2", "text-white", "bg-blue-600", "border", "border-blue-600", "rounded"]); + + mainDiv.id = this.id; + this.id = `${this.id}-container`; + + this.appendChild(mainDiv); + this.code = this.code.split("self").join(this.mount_name); + let registrationCode = `${this.mount_name} = Element("${ mainDiv.id }")`; + if (this.code.includes("def on_focus")){ + this.code = this.code.replace("def on_focus", `def on_focus_${this.mount_name}`); + registrationCode += `\n${this.mount_name}.element.onfocus = on_focus_${this.mount_name}` + } + + if (this.code.includes("def on_click")){ + this.code = this.code.replace("def on_click", `def on_click_${this.mount_name}`); + registrationCode += `\n${this.mount_name}.element.onclick = on_click_${this.mount_name}` + } + + // now that we appended and the element is attached, lets connect with the event handlers + // defined for this widget + setTimeout(() => { + this.eval(this.code).then(() => { + this.eval(registrationCode).then(() => { + console.log('registered handlers'); + }); + }); + }, 4000); + + console.log('py-button connected'); + } + } + + \ No newline at end of file diff --git a/pyscriptjs/src/components/pytitle.ts b/pyscriptjs/src/components/pytitle.ts new file mode 100644 index 0000000..633fff6 --- /dev/null +++ b/pyscriptjs/src/components/pytitle.ts @@ -0,0 +1,37 @@ +import { BaseEvalElement } from './base'; +import { addClasses, ltrim, htmlDecode } from '../utils'; + +export class PyTitle extends BaseEvalElement { + shadow: ShadowRoot; + wrapper: HTMLElement; + theme: string; + widths: Array; + label: string; + mount_name: string; + constructor() { + super(); + } + + + connectedCallback() { + this.label = htmlDecode(this.innerHTML); + this.mount_name = this.id.split("-").join("_"); + this.innerHTML = ''; + + let mainDiv = document.createElement('div'); + let divContent = document.createElement('h1') + + addClasses(mainDiv, ["text-center", "w-full", "mb-8"]); + addClasses(divContent, ["text-3xl", "font-bold", "text-gray-800", "uppercase", "tracking-tight"]); + divContent.innerHTML = this.label; + + mainDiv.id = this.id; + this.id = `${this.id}-container`; + mainDiv.appendChild(divContent); + this.appendChild(mainDiv); + + console.log('py-title connected'); + } + } + + \ No newline at end of file diff --git a/pyscriptjs/src/main.ts b/pyscriptjs/src/main.ts index 1dfbf9b..6eb5679 100644 --- a/pyscriptjs/src/main.ts +++ b/pyscriptjs/src/main.ts @@ -4,12 +4,16 @@ import { PyScript } from "./components/pyscript"; import { PyRepl } from "./components/pyrepl"; import { PyEnv } from "./components/pyenv"; import { PyBox } from "./components/pybox"; +import { PyButton } from "./components/pybutton"; +import { PyTitle } from "./components/pytitle"; import { PyWidget } from "./components/base"; let xPyScript = customElements.define('py-script', PyScript); let xPyRepl = customElements.define('py-repl', PyRepl); let xPyEnv = customElements.define('py-env', PyEnv); let xPyBox = customElements.define('py-box', PyBox); +let xPyButton = customElements.define('py-button', PyButton); +let xPyTitle = customElements.define('py-title', PyTitle); let xPyWidget = customElements.define('py-register-widget', PyWidget); diff --git a/pyscriptjs/src/utils.ts b/pyscriptjs/src/utils.ts index d9912bf..ac9f83d 100644 --- a/pyscriptjs/src/utils.ts +++ b/pyscriptjs/src/utils.ts @@ -9,4 +9,29 @@ const getLastPath = function (str) { return str.split('\\').pop().split('/').pop(); } -export {addClasses, getLastPath} +function htmlDecode(input) { + var doc = new DOMParser().parseFromString(input, "text/html"); + return ltrim(doc.documentElement.textContent); +} + +function ltrim(code: string): string { + const lines = code.split("\n") + if (lines.length == 0) + return code + + const lengths = lines + .filter((line) => line.trim().length != 0) + .map((line) => { + const [prefix] = line.match(/^\s*/) + return prefix.length + }) + + const k = Math.min(...lengths) + + if (k != 0) + return lines.map((line) => line.substring(k)).join("\n") + else + return code +} + +export {addClasses, getLastPath, ltrim, htmlDecode}