mirror of
https://github.com/pyscript/pyscript.git
synced 2026-02-17 19:00:39 -05:00
Remove deprecated elements and adds deprecation banner to pys-on (#1084)
* Show deprecation banner * Add test for deprecation warning * Remove deprecated elements * Add entry in changelog * Update test_style * Remove random color rule * Add PR link to changelog
This commit is contained in:
@@ -1,24 +1,14 @@
|
||||
import type { Runtime } from '../runtime';
|
||||
import { make_PyRepl } from './pyrepl';
|
||||
import { PyBox } from './pybox';
|
||||
import { make_PyButton } from './pybutton';
|
||||
import { PyTitle } from './pytitle';
|
||||
import { make_PyInputBox } from './pyinputbox';
|
||||
import { make_PyWidget } from './pywidget';
|
||||
|
||||
function createCustomElements(runtime: Runtime) {
|
||||
const PyInputBox = make_PyInputBox(runtime);
|
||||
const PyButton = make_PyButton(runtime);
|
||||
const PyWidget = make_PyWidget(runtime);
|
||||
const PyRepl = make_PyRepl(runtime);
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
const xPyRepl = customElements.define('py-repl', PyRepl);
|
||||
const xPyBox = customElements.define('py-box', PyBox);
|
||||
const xPyTitle = customElements.define('py-title', PyTitle);
|
||||
const xPyWidget = customElements.define('py-register-widget', PyWidget);
|
||||
const xPyInputBox = customElements.define('py-inputbox', PyInputBox);
|
||||
const xPyButton = customElements.define('py-button', PyButton);
|
||||
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
import { getAttribute, addClasses, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
|
||||
const logger = getLogger('py-box');
|
||||
|
||||
export class PyBox extends HTMLElement {
|
||||
shadow: ShadowRoot;
|
||||
wrapper: HTMLElement;
|
||||
theme: string;
|
||||
widths: 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);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage =
|
||||
'The element <py-box> is deprecated, you should create a ' +
|
||||
'div with "py-box" class name instead. For example: <div class="py-box">';
|
||||
createDeprecationWarning(deprecationMessage, 'py-box');
|
||||
const mainDiv = document.createElement('div');
|
||||
addClasses(mainDiv, ['py-box']);
|
||||
|
||||
// Hack: for some reason when moving children, the editor box duplicates children
|
||||
// meaning that we end up with 2 editors, if there's a <py-repl> inside the <py-box>
|
||||
// so, if we have more than 2 children with the cm-editor class, we remove one of them
|
||||
while (this.childNodes.length > 0) {
|
||||
if (this.firstChild.nodeName == 'PY-REPL') {
|
||||
// in this case we need to remove the child and create a new one from scratch
|
||||
const replDiv = document.createElement('div');
|
||||
// we need to put the new repl inside a div so that if the repl has auto-generate true
|
||||
// it can replicate itself inside that constrained div
|
||||
replDiv.appendChild(this.firstChild.cloneNode());
|
||||
mainDiv.appendChild(replDiv);
|
||||
this.firstChild.remove();
|
||||
} else {
|
||||
if (this.firstChild.nodeName != '#text') {
|
||||
mainDiv.appendChild(this.firstChild);
|
||||
} else {
|
||||
this.firstChild.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we need to set widths
|
||||
this.widths = [];
|
||||
|
||||
const widthsAttr = getAttribute(this, 'widths');
|
||||
if (widthsAttr) {
|
||||
for (const w of widthsAttr.split(';')) {
|
||||
if (w.includes('/')) {
|
||||
this.widths.push(w.split('/')[0]);
|
||||
} else {
|
||||
this.widths.push(w);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.widths = Array<string>(mainDiv.children.length).fill('1 1 0');
|
||||
}
|
||||
|
||||
this.widths.forEach((width, index) => {
|
||||
const node: ChildNode = mainDiv.childNodes[index];
|
||||
(<HTMLElement>node).style.flex = width;
|
||||
addClasses(<HTMLElement>node, ['py-box-child']);
|
||||
});
|
||||
|
||||
this.appendChild(mainDiv);
|
||||
logger.info('py-box connected');
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
import type { Runtime } from '../runtime';
|
||||
|
||||
const logger = getLogger('py-button');
|
||||
|
||||
export function make_PyButton(runtime: Runtime) {
|
||||
class PyButton extends HTMLElement {
|
||||
widths: string[] = [];
|
||||
label: string | undefined = undefined;
|
||||
class: string[];
|
||||
defaultClass: string[];
|
||||
mount_name: string | undefined = undefined;
|
||||
code: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.defaultClass = ['py-button'];
|
||||
|
||||
const label = getAttribute(this, 'label');
|
||||
if (label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
// Styling does the same thing as class in normal HTML. Using the name "class" makes the style to malfunction
|
||||
const styling = getAttribute(this, 'styling');
|
||||
if (styling) {
|
||||
const klass = styling.trim();
|
||||
if (klass === '') {
|
||||
this.class = this.defaultClass;
|
||||
} else {
|
||||
// trim each element to remove unnecessary spaces which makes the button style to malfunction
|
||||
this.class = klass
|
||||
.split(' ')
|
||||
.map(x => x.trim())
|
||||
.filter(x => x !== '');
|
||||
}
|
||||
} else {
|
||||
this.class = this.defaultClass;
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage =
|
||||
'The element <py-button> is deprecated, create a function with your ' +
|
||||
'inline code and use <button py-click="function()" class="py-button"> instead.';
|
||||
createDeprecationWarning(deprecationMessage, 'py-button');
|
||||
|
||||
ensureUniqueId(this);
|
||||
this.code = htmlDecode(this.innerHTML) || '';
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.innerHTML = '';
|
||||
|
||||
const mainDiv = document.createElement('button');
|
||||
mainDiv.innerHTML = this.label;
|
||||
addClasses(mainDiv, this.class);
|
||||
|
||||
mainDiv.id = this.id;
|
||||
this.id = `${this.id}-container`;
|
||||
|
||||
this.appendChild(mainDiv);
|
||||
this.code = this.code.split('self').join(this.mount_name);
|
||||
let registrationCode = `from pyodide.ffi import create_proxy`;
|
||||
registrationCode += `\n${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.addEventListener('focus', create_proxy(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.addEventListener('click', create_proxy(on_click_${this.mount_name}))`;
|
||||
}
|
||||
|
||||
// now that we appended and the element is attached, lets connect with the event handlers
|
||||
// defined for this widget
|
||||
runtime.runButDontRaise(this.code);
|
||||
runtime.runButDontRaise(registrationCode);
|
||||
logger.debug('py-button connected');
|
||||
}
|
||||
}
|
||||
|
||||
return PyButton;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
import type { Runtime } from '../runtime';
|
||||
|
||||
const logger = getLogger('py-inputbox');
|
||||
|
||||
export function make_PyInputBox(runtime: Runtime) {
|
||||
class PyInputBox extends HTMLElement {
|
||||
widths: string[] = [];
|
||||
label: string | undefined = undefined;
|
||||
mount_name: string | undefined = undefined;
|
||||
code: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const label = getAttribute(this, 'label');
|
||||
if (label) {
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage =
|
||||
'The element <py-input> is deprecated, ' + 'use <input class="py-input"> instead.';
|
||||
createDeprecationWarning(deprecationMessage, 'py-input');
|
||||
ensureUniqueId(this);
|
||||
this.code = htmlDecode(this.innerHTML);
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.innerHTML = '';
|
||||
|
||||
const mainDiv = document.createElement('input');
|
||||
mainDiv.type = 'text';
|
||||
addClasses(mainDiv, ['py-input']);
|
||||
|
||||
mainDiv.id = this.id;
|
||||
this.id = `${this.id}-container`;
|
||||
this.appendChild(mainDiv);
|
||||
|
||||
// now that we appended and the element is attached, lets connect with the event handlers
|
||||
// defined for this widget
|
||||
this.appendChild(mainDiv);
|
||||
this.code = this.code.split('self').join(this.mount_name);
|
||||
let registrationCode = `from pyodide.ffi import create_proxy`;
|
||||
registrationCode += `\n${this.mount_name} = Element("${mainDiv.id}")`;
|
||||
if (this.code.includes('def on_keypress')) {
|
||||
this.code = this.code.replace('def on_keypress', `def on_keypress_${this.mount_name}`);
|
||||
registrationCode += `\n${this.mount_name}.element.addEventListener('keypress', create_proxy(on_keypress_${this.mount_name}))`;
|
||||
}
|
||||
|
||||
runtime.runButDontRaise(this.code);
|
||||
runtime.runButDontRaise(registrationCode);
|
||||
logger.debug('py-inputbox connected');
|
||||
}
|
||||
}
|
||||
|
||||
return PyInputBox;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { htmlDecode, ensureUniqueId, showWarning } from '../utils';
|
||||
import { htmlDecode, ensureUniqueId, showWarning, createDeprecationWarning } from '../utils';
|
||||
import type { Runtime } from '../runtime';
|
||||
import { getLogger } from '../logger';
|
||||
import { pyExec } from '../pyexec';
|
||||
@@ -165,9 +165,10 @@ function createElementsWithEventListeners(runtime: Runtime, pyAttribute: string)
|
||||
const event = pyAttributeToEvent.get(pyAttribute);
|
||||
|
||||
if (pyAttribute === 'pys-onClick' || pyAttribute === 'pys-onKeyDown') {
|
||||
console.warn(
|
||||
'Use of pys-onClick and pys-onKeyDown attributes is deprecated in favor of py-onClick() and py-onKeyDown(). pys-on* attributes will be deprecated in a future version of PyScript.',
|
||||
);
|
||||
const msg =
|
||||
`The attribute 'pys-onClick' and 'pys-onKeyDown' are deprecated. Please 'py-click="myFunction()"' ` +
|
||||
` or 'py-keydown="myFunction()"' instead.`;
|
||||
createDeprecationWarning(msg, msg);
|
||||
const source = `
|
||||
from pyodide.ffi import create_proxy
|
||||
Element("${el.id}").element.addEventListener("${event}", create_proxy(${handlerCode}))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import { addClasses, htmlDecode, createDeprecationWarning } from '../utils';
|
||||
|
||||
export class PyTitle extends HTMLElement {
|
||||
widths: string[];
|
||||
label: string;
|
||||
mount_name: string;
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage = 'The element <py-title> is deprecated, please use an <h1> tag instead.';
|
||||
createDeprecationWarning(deprecationMessage, 'py-title');
|
||||
this.label = htmlDecode(this.innerHTML);
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.innerHTML = '';
|
||||
|
||||
const mainDiv = document.createElement('div');
|
||||
const divContent = document.createElement('h1');
|
||||
|
||||
addClasses(mainDiv, ['py-title']);
|
||||
divContent.innerHTML = this.label;
|
||||
|
||||
mainDiv.id = this.id;
|
||||
this.id = `${this.id}-container`;
|
||||
mainDiv.appendChild(divContent);
|
||||
this.appendChild(mainDiv);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user