Files
pyscript/pyscriptjs/src/components/pywidget.ts
Madhur Tandon 727267ae22 split interpreter class (#1218)
* split interpreter class

* add new files

* add newlines

* disable eslint for run

* remove usage of interpreter from unit test

* delete fakeinterpreter class

* fix unit tests

* add comments

* remove interpreter.ts and pyodide.ts files

* suggested changes
2023-03-03 22:23:52 +05:30

103 lines
3.3 KiB
TypeScript

import type { PyProxy } from 'pyodide';
import { getLogger } from '../logger';
import { robustFetch } from '../fetch';
import { InterpreterClient } from '../interpreter_client';
const logger = getLogger('py-register-widget');
function createWidget(interpreter: InterpreterClient, name: string, code: string, klass: string) {
class CustomWidget extends HTMLElement {
shadow: ShadowRoot;
wrapper: HTMLElement;
name: string = name;
klass: string = klass;
code: string = code;
proxy: PyProxy;
proxyClass: any;
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);
}
async connectedCallback() {
await interpreter.runButDontRaise(this.code);
this.proxyClass = interpreter.globals.get(this.klass);
this.proxy = this.proxyClass(this);
this.proxy.connect();
this.registerWidget();
}
registerWidget() {
logger.info('new widget registered:', this.name);
interpreter.globals.set(this.id, this.proxy);
}
}
/* eslint-disable @typescript-eslint/no-unused-vars */
const xPyWidget = customElements.define(name, CustomWidget);
/* eslint-enable @typescript-eslint/no-unused-vars */
}
export function make_PyWidget(interpreter: InterpreterClient) {
class PyWidget extends HTMLElement {
shadow: ShadowRoot;
name: string;
klass: string;
outputElement: HTMLElement;
errorElement: HTMLElement;
wrapper: HTMLElement;
theme: string;
source: string;
code: 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);
this.addAttributes('src', 'name', 'klass');
}
addAttributes(...attrs: string[]) {
for (const each of attrs) {
const property = each === 'src' ? 'source' : each;
if (this.hasAttribute(each)) {
this[property] = this.getAttribute(each);
}
}
}
async connectedCallback() {
if (this.id === undefined) {
throw new ReferenceError(
`No id specified for component. Components must have an explicit id. Please use id="" to specify your component id.`,
);
}
const mainDiv = document.createElement('div');
mainDiv.id = this.id + '-main';
this.appendChild(mainDiv);
logger.debug('PyWidget: reading source', this.source);
this.code = await this.getSourceFromFile(this.source);
createWidget(interpreter, this.name, this.code, this.klass);
}
async getSourceFromFile(s: string): Promise<string> {
const response = await robustFetch(s);
return await response.text();
}
}
return PyWidget;
}