mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
Deprecate py-button, py-inputbox, py-box and py-title (#931)
This commit is contained in:
@@ -417,11 +417,11 @@ The following tags can be used to add visual attributes to your HTML page.
|
||||
|
||||
| Tag | Description |
|
||||
| --- | ----------- |
|
||||
| `<py-inputbox>` | Adds an input box that can be used to prompt users to enter input values. |
|
||||
| `<py-box>` | Creates a container object that can be used to host one or more visual components that define how elements of `<py-box>` should align and show on the page. |
|
||||
| `<py-button>` | Adds a button to which authors can add labels and event handlers for actions on the button, such as `on_focus` or `on_click`. |
|
||||
| `<py-title>` | Adds a static text title component that styles the text inside the tag as a page title. |
|
||||
| `<py-inputbox>` | (Deprecated) Adds an input box that can be used to prompt users to enter input values. |
|
||||
| `<py-box>` | (Deprecated) Creates a container object that can be used to host one or more visual components that define how elements of `<py-box>` should align and show on the page. |
|
||||
| `<py-button>` | (Deprecated) Adds a button to which authors can add labels and event handlers for actions on the button, such as `on_focus` or `on_click`. |
|
||||
| `<py-title>` | (Deprecated) Adds a static text title component that styles the text inside the tag as a page title. |
|
||||
|
||||
```{note}
|
||||
All the elements above are experimental and not implemented at their full functionality. Use them with the understanding that the APIs or full support might change or be removed until the visual components are more mature.
|
||||
These elements have been deprecated, we suggest that you use native elements and attach the respective `py-` attribute. For example for `<py-button>` you can write `<button py-click="function()">`
|
||||
```
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
[[fetch]]
|
||||
files = ["./utils.py", "./antigravity.py"]
|
||||
</py-config>
|
||||
<py-box widths="2/3;1/3">
|
||||
<div>
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
<div id="output" class="p-4"></div>
|
||||
</py-box>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -17,8 +17,12 @@
|
||||
</py-config>
|
||||
|
||||
<py-script>
|
||||
from js import document
|
||||
from pyodide.ffi.wrappers import add_event_listener
|
||||
|
||||
def add_task(*ags, **kws):
|
||||
# create a new dictionary representing the new task
|
||||
new_task_content = Element("new-task-content")
|
||||
task = { "content": new_task_content.value, "done": False, "created_at": dt.now() }
|
||||
|
||||
# add a new task to the list and tell it to use the `content` key to show in the UI
|
||||
@@ -28,22 +32,28 @@
|
||||
# clear the inputbox element used to create the new task
|
||||
new_task_content.clear()
|
||||
|
||||
def on_click(evt):
|
||||
add_task()
|
||||
|
||||
def handle_keypress(evt):
|
||||
if evt.key == "Enter":
|
||||
add_task()
|
||||
|
||||
add_event_listener(
|
||||
document.getElementById("new-task-content"),
|
||||
"keypress",
|
||||
handle_keypress
|
||||
)
|
||||
|
||||
</py-script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<py-title>To Do List</py-title>
|
||||
<py-box widths="4/5;1/5">
|
||||
<py-inputbox id="new-task-content">
|
||||
def on_keypress(e):
|
||||
if (e.code == "Enter"):
|
||||
add_task()
|
||||
</py-inputbox>
|
||||
<py-button id="new-task-btn" label="Add Task!">
|
||||
def on_click(evt):
|
||||
add_task()
|
||||
</py-button>
|
||||
</py-box>
|
||||
<h1>To Do List</h1>
|
||||
<div class="py-box">
|
||||
<input id="new-task-content" />
|
||||
<button py-click="add_task()" id="new-task-btn" class="py-button">Add Task!</button>
|
||||
</div>
|
||||
|
||||
<py-list id="myList"></py-list>
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getAttribute, addClasses } from '../utils';
|
||||
import { getAttribute, addClasses, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
|
||||
const logger = getLogger('py-box');
|
||||
@@ -20,6 +20,11 @@ export class PyBox extends HTMLElement {
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage = (
|
||||
'<p>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']);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId } from '../utils';
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
import type { Runtime } from '../runtime';
|
||||
|
||||
@@ -42,6 +42,12 @@ export function make_PyButton(runtime: Runtime) {
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
const deprecationMessage = (
|
||||
'<p>The element <py-button> is deprecated, create a function with your ' +
|
||||
'inline code and use <button py-click="function()" class="py-button"> instead.</p>'
|
||||
)
|
||||
createDeprecationWarning(deprecationMessage, "py-button")
|
||||
|
||||
ensureUniqueId(this);
|
||||
this.code = htmlDecode(this.innerHTML) || '';
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId } from '../utils';
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
import type { Runtime } from '../runtime';
|
||||
|
||||
@@ -21,6 +21,11 @@ export function make_PyInputBox(runtime: Runtime) {
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
const deprecationMessage = (
|
||||
'<p>The element <py-input> is deprecated, ' +
|
||||
'use <input class="py-input"> instead.</p>'
|
||||
)
|
||||
createDeprecationWarning(deprecationMessage, "py-input")
|
||||
ensureUniqueId(this);
|
||||
this.code = htmlDecode(this.innerHTML);
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { addClasses, htmlDecode } from '../utils';
|
||||
import { addClasses, htmlDecode, createDeprecationWarning } from '../utils';
|
||||
|
||||
export class PyTitle extends HTMLElement {
|
||||
widths: string[];
|
||||
@@ -9,6 +9,10 @@ export class PyTitle extends HTMLElement {
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage = (
|
||||
'<p>The element <py-title> is deprecated, please use an <h1> tag instead.</p>'
|
||||
)
|
||||
createDeprecationWarning(deprecationMessage, "py-title")
|
||||
this.label = htmlDecode(this.innerHTML);
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.innerHTML = '';
|
||||
|
||||
@@ -293,6 +293,7 @@ input {
|
||||
border-color: rgba(37, 99, 235, var(--tw-border-opacity));
|
||||
border-width: 1px;
|
||||
border-radius: 0.25rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.py-li-element p {
|
||||
|
||||
@@ -111,3 +111,16 @@ export function joinPaths(parts: string[], separator = '/') {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export function createDeprecationWarning(msg: string, elementName: string): void {
|
||||
const banners = document.getElementsByClassName('alert-banner py-warning');
|
||||
let bannerCount = 0;
|
||||
for (const banner of banners) {
|
||||
if (banner.innerHTML.includes(elementName)) {
|
||||
bannerCount++;
|
||||
}
|
||||
}
|
||||
if (bannerCount == 0) {
|
||||
_createAlertBanner(msg, "warning");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,3 +16,19 @@ class TestPyButton(PyScriptTest):
|
||||
|
||||
assert len(pybox_element) == 2
|
||||
assert pybox_element[1].get_attribute("class") == "py-box-child"
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-box>
|
||||
</py-box>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-box> is deprecated, you should create a div "
|
||||
'with "py-box" class name instead. For example: <div class="py-box">'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
|
||||
@@ -16,3 +16,44 @@ class TestPyButton(PyScriptTest):
|
||||
self.page.locator("text=my button").click()
|
||||
self.page.locator("text=my button").click()
|
||||
assert self.console.log.lines == [self.PY_COMPLETE, "clicked!", "clicked!"]
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-button label="my button">
|
||||
import js
|
||||
def on_click(evt):
|
||||
js.console.log('clicked!')
|
||||
</py-button>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-button> is deprecated, create a function with your "
|
||||
'inline code and use <button py-click="function()" class="py-button"> instead.'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
|
||||
def test_creates_single_deprecation_banner(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-button label="my button">
|
||||
import js
|
||||
def on_click(evt):
|
||||
js.console.log('clicked!')
|
||||
</py-button>
|
||||
<py-button label="another button!">
|
||||
</py-button>
|
||||
"""
|
||||
)
|
||||
banner = self.page.query_selector_all(".py-warning")
|
||||
assert len(banner) == 1
|
||||
banner_content = banner[0].inner_text()
|
||||
expected = (
|
||||
"The element <py-button> is deprecated, create a function with your "
|
||||
'inline code and use <button py-click="function()" class="py-button"> instead.'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
|
||||
@@ -20,3 +20,23 @@ class TestPyInputBox(PyScriptTest):
|
||||
input.press("Enter")
|
||||
|
||||
assert self.console.log.lines == [self.PY_COMPLETE, "Hello"]
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-inputbox label="my input">
|
||||
import js
|
||||
def on_keypress(evt):
|
||||
if evt.key == "Enter":
|
||||
js.console.log(evt.target.value)
|
||||
</py-inputbox>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-input> is deprecated, "
|
||||
'use <input class="py-input"> instead.'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
|
||||
@@ -14,3 +14,17 @@ class TestPyTitle(PyScriptTest):
|
||||
# py_title will be none
|
||||
assert py_title
|
||||
assert py_title.text_content() == "Hello, World!"
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-title>Hello, world!</py-title>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-title> is deprecated, please use an <h1> tag instead."
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
|
||||
@@ -282,7 +282,7 @@ class TestExamples(PyScriptTest):
|
||||
self.page.locator("py-repl").type("import utils\ndisplay(utils.now())")
|
||||
self.page.locator("button").click()
|
||||
# Make sure the output is in the page
|
||||
self.page.wait_for_selector("#output")
|
||||
self.page.wait_for_selector("#my-repl-1-1")
|
||||
# utils.now returns current date time
|
||||
content = self.page.content()
|
||||
pattern = "\\d+/\\d+/\\d+, \\d+:\\d+:\\d+" # e.g. 08/09/2022 15:57:32
|
||||
|
||||
@@ -11,6 +11,11 @@ describe('PyButton', () => {
|
||||
let instance;
|
||||
beforeEach(() => {
|
||||
instance = new PyButton();
|
||||
// Remove all the alert banners created when calling `connectedCallback`
|
||||
const banners = document.getElementsByClassName("alert-banner")
|
||||
for (const banner of banners) {
|
||||
banner.remove()
|
||||
}
|
||||
});
|
||||
|
||||
it('should get the Button to just instantiate', async () => {
|
||||
@@ -65,4 +70,19 @@ describe('PyButton', () => {
|
||||
expect(instanceId).toMatch(/py-(\w+-){1,5}container/);
|
||||
expect(instance.mount_name).toBe(instanceId.replace('-container', '').split('-').join('_'));
|
||||
});
|
||||
|
||||
it('should create a single deprecation banner', async () => {
|
||||
document.body.innerHTML = ""
|
||||
let alertBanners = document.getElementsByClassName('alert-banner');
|
||||
expect(alertBanners.length).toBe(0);
|
||||
|
||||
instance.connectedCallback();
|
||||
expect(alertBanners.length).toBe(1);
|
||||
expect(alertBanners[0].innerHTML).toContain("<py-button> is deprecated");
|
||||
|
||||
// Calling `connectedCallback` again should not create a new banner
|
||||
instance.connectedCallback();
|
||||
alertBanners = document.getElementsByClassName('alert-banner');
|
||||
expect(alertBanners.length).toBe(1);
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user