wapyt 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wapyt-0.1.0/MANIFEST.in +1 -0
- wapyt-0.1.0/PKG-INFO +79 -0
- wapyt-0.1.0/README.md +67 -0
- wapyt-0.1.0/pyproject.toml +25 -0
- wapyt-0.1.0/setup.cfg +4 -0
- wapyt-0.1.0/tests/cardpanel_demo.py +119 -0
- wapyt-0.1.0/tests/chat_demo.py +775 -0
- wapyt-0.1.0/tests/layout_demo.py +103 -0
- wapyt-0.1.0/tests/multiaiproxy.py +285 -0
- wapyt-0.1.0/tests/tabs_demo.py +30 -0
- wapyt-0.1.0/wapyt/__init__.py +44 -0
- wapyt-0.1.0/wapyt/_runtime.py +103 -0
- wapyt-0.1.0/wapyt/assets/__init__.py +1 -0
- wapyt-0.1.0/wapyt/assets/cardpanel.js +1064 -0
- wapyt-0.1.0/wapyt/assets/chat.js +3294 -0
- wapyt-0.1.0/wapyt/assets/fonts/.keep +1 -0
- wapyt-0.1.0/wapyt/assets/layout.js +441 -0
- wapyt-0.1.0/wapyt/assets/modal.js +204 -0
- wapyt-0.1.0/wapyt/assets/resourceboard.js +465 -0
- wapyt-0.1.0/wapyt/assets/sidebar.js +281 -0
- wapyt-0.1.0/wapyt/assets/tabwidget.js +374 -0
- wapyt-0.1.0/wapyt/assets/wapyt.css +225 -0
- wapyt-0.1.0/wapyt/cardpanel/__init__.py +4 -0
- wapyt-0.1.0/wapyt/cardpanel/cardpanel.py +208 -0
- wapyt-0.1.0/wapyt/cardpanel/cardpanel_config.py +130 -0
- wapyt-0.1.0/wapyt/chat/__init__.py +4 -0
- wapyt-0.1.0/wapyt/chat/chat.py +392 -0
- wapyt-0.1.0/wapyt/chat/chat_config.py +157 -0
- wapyt-0.1.0/wapyt/layout/__init__.py +4 -0
- wapyt-0.1.0/wapyt/layout/layout.py +260 -0
- wapyt-0.1.0/wapyt/layout/layout_config.py +93 -0
- wapyt-0.1.0/wapyt/modal/__init__.py +3 -0
- wapyt-0.1.0/wapyt/modal/modal.py +65 -0
- wapyt-0.1.0/wapyt/resourceboard/__init__.py +4 -0
- wapyt-0.1.0/wapyt/resourceboard/resourceboard.py +106 -0
- wapyt-0.1.0/wapyt/resourceboard/resourceboard_config.py +81 -0
- wapyt-0.1.0/wapyt/sidebar/__init__.py +4 -0
- wapyt-0.1.0/wapyt/sidebar/sidebar.py +81 -0
- wapyt-0.1.0/wapyt/sidebar/sidebar_config.py +65 -0
- wapyt-0.1.0/wapyt/tabwidget/__init__.py +3 -0
- wapyt-0.1.0/wapyt/tabwidget/tabwidget.py +192 -0
- wapyt-0.1.0/wapyt.egg-info/PKG-INFO +79 -0
- wapyt-0.1.0/wapyt.egg-info/SOURCES.txt +44 -0
- wapyt-0.1.0/wapyt.egg-info/dependency_links.txt +1 -0
- wapyt-0.1.0/wapyt.egg-info/requires.txt +2 -0
- wapyt-0.1.0/wapyt.egg-info/top_level.txt +4 -0
wapyt-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include wapyt/assets *
|
wapyt-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wapyt
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: DHTMLX-free PyTincture widgetset with layout, chat, card panel, and tab widgets.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: homepage, https://github.com/schapman1974/wA_pytincture_widgetset
|
|
7
|
+
Keywords: pytincture,widgetset,pyodide,wapyt
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: pyodide-py>=0.28.0
|
|
11
|
+
Requires-Dist: itsdangerous>=2.2.0
|
|
12
|
+
|
|
13
|
+
# wA PyTincture Widgetset (`wapyt`)
|
|
14
|
+
|
|
15
|
+
`wapyt` is a lightweight widgetset for [pyTincture](https://github.com/schapman1974/pytincture) that avoids the commercial DHTMLX dependency used by the legacy package. It focuses on a DOM-driven layout engine and a set of first-class widgets that can be composed entirely from Python when running inside Pyodide.
|
|
16
|
+
|
|
17
|
+
## Highlights
|
|
18
|
+
- **Theme-aware layout**: Flexbox-based layout manager that mirrors the familiar `LayoutConfig`/`CellConfig` API, supports nested rows/columns, and exposes helper methods such as `attach_html`, `collapse`, `toggle`, `hide`, etc.
|
|
19
|
+
- **Widgets that don’t require DHTMLX**: Native Chat, CardPanel, TabWidget, Sidebar, ModalWindow, and ResourceBoard implementations with the streaming/events helpers the PyTincture samples expect.
|
|
20
|
+
- **`MainWindow` wrapper**: Thin helper built on top of `Layout` so existing apps can continue to expose a `MainWindow` class with no additional boilerplate.
|
|
21
|
+
- **PyTincture metadata**: Exposes `__widgetset__ = "wapyt"` so the platform can auto-discover the package name/version during `***WIDGETSET***` substitution.
|
|
22
|
+
- **Test/demo apps**: Located under `tests/` to show how to embed the widgets inside PyTincture applications.
|
|
23
|
+
|
|
24
|
+
## Widget Catalog
|
|
25
|
+
- `Layout` / `MainWindow`: Flexbox-driven layout primitives plus a drop-in `MainWindow` helper that mirrors the legacy PyTincture entrypoint.
|
|
26
|
+
- `Chat`: Streaming chat surface with agent metadata, artifact events, and helpers for incremental responses.
|
|
27
|
+
- `CardPanel`: Searchable, template-driven card grid with add/view/action callbacks and custom renderers.
|
|
28
|
+
- `TabWidget`: Lightweight tab host that supports badges, closable tabs, and attaching HTML or PyTincture components per tab.
|
|
29
|
+
- `Sidebar`: Collapsible navigation rail with badges, icons, and selection events for driving the rest of your layout.
|
|
30
|
+
- `ModalWindow`: Simple modal shell that can host arbitrary Layout instances or HTML snippets.
|
|
31
|
+
- `ResourceBoard`: Master/detail resource explorer with selectable rows, action hooks, and optional add button wiring.
|
|
32
|
+
|
|
33
|
+
## Runtime Architecture
|
|
34
|
+
- Layouts and widgets are declared in Python but render as DOM nodes through the JavaScript bundles under `wapyt/assets/`. Each helper (e.g., `Layout.add_chat`) forwards config dictionaries directly to the matching JS constructor.
|
|
35
|
+
- The `wapyt/_runtime.py` bridge exposes `require_js` to lazily inject JS/CSS exactly once per interpreter and `create_proxy` to keep Pyodide callback proxies alive for event handlers.
|
|
36
|
+
- Layout cells are plain flexbox containers (`wapyt/assets/layout.js` + `wapyt/assets/wapyt.css`), so attaching raw HTML or third-party widgets is as simple as calling `layout.attach_html(cell_id, markup)`.
|
|
37
|
+
- Because everything routes through `window.wapyt`, you can add new widgets by dropping a JS file into `wapyt/assets/`, exporting a constructor, and calling `require_js("MyWidget")` before instantiating it from Python.
|
|
38
|
+
|
|
39
|
+
## Getting Started
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cd wapyt
|
|
43
|
+
uv venv --python 3.13 && source .venv/bin/activate
|
|
44
|
+
uv pip install -e .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Then run a PyTincture example pointing at this widgetset:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cd ../pytincture
|
|
51
|
+
uv run pytincture launch_service --modules_folder ../wA_pytincture_widgetset/tests --port 8070
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Open http://localhost:8070/layout_demo in your browser to see the native layout, and swap in `chat_demo` / `cardpanel_demo` / `tabs_demo` to explore the specialized widgets.
|
|
55
|
+
|
|
56
|
+
## Package Layout
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
wapyt/
|
|
60
|
+
├── chat/ # Chat widget config + wrapper
|
|
61
|
+
├── cardpanel/ # CardPanel widget config + wrapper
|
|
62
|
+
├── layout/ # Layout/MainWindow helpers
|
|
63
|
+
├── modal/ # ModalWindow + config
|
|
64
|
+
├── resourceboard/ # ResourceBoard widget + config
|
|
65
|
+
├── sidebar/ # Sidebar widget config + wrapper
|
|
66
|
+
├── tabwidget/ # Tab widget config + wrapper
|
|
67
|
+
└── assets/ # JS + CSS evaluated automatically by PyTincture
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## Development Notes
|
|
72
|
+
|
|
73
|
+
- The JavaScript bundles define the `window.wapyt` namespace and are evaluated automatically by PyTincture’s loader (see `pytincture/frontend/pytincture.js`).
|
|
74
|
+
- Layout styles live in `assets/wapyt.css`; adjust tokens there to integrate with your design system.
|
|
75
|
+
- The tests are intentionally small, framework-free PyTincture apps so you can copy/paste into your own projects.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT – see `pyproject.toml` for details.
|
wapyt-0.1.0/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# wA PyTincture Widgetset (`wapyt`)
|
|
2
|
+
|
|
3
|
+
`wapyt` is a lightweight widgetset for [pyTincture](https://github.com/schapman1974/pytincture) that avoids the commercial DHTMLX dependency used by the legacy package. It focuses on a DOM-driven layout engine and a set of first-class widgets that can be composed entirely from Python when running inside Pyodide.
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
- **Theme-aware layout**: Flexbox-based layout manager that mirrors the familiar `LayoutConfig`/`CellConfig` API, supports nested rows/columns, and exposes helper methods such as `attach_html`, `collapse`, `toggle`, `hide`, etc.
|
|
7
|
+
- **Widgets that don’t require DHTMLX**: Native Chat, CardPanel, TabWidget, Sidebar, ModalWindow, and ResourceBoard implementations with the streaming/events helpers the PyTincture samples expect.
|
|
8
|
+
- **`MainWindow` wrapper**: Thin helper built on top of `Layout` so existing apps can continue to expose a `MainWindow` class with no additional boilerplate.
|
|
9
|
+
- **PyTincture metadata**: Exposes `__widgetset__ = "wapyt"` so the platform can auto-discover the package name/version during `***WIDGETSET***` substitution.
|
|
10
|
+
- **Test/demo apps**: Located under `tests/` to show how to embed the widgets inside PyTincture applications.
|
|
11
|
+
|
|
12
|
+
## Widget Catalog
|
|
13
|
+
- `Layout` / `MainWindow`: Flexbox-driven layout primitives plus a drop-in `MainWindow` helper that mirrors the legacy PyTincture entrypoint.
|
|
14
|
+
- `Chat`: Streaming chat surface with agent metadata, artifact events, and helpers for incremental responses.
|
|
15
|
+
- `CardPanel`: Searchable, template-driven card grid with add/view/action callbacks and custom renderers.
|
|
16
|
+
- `TabWidget`: Lightweight tab host that supports badges, closable tabs, and attaching HTML or PyTincture components per tab.
|
|
17
|
+
- `Sidebar`: Collapsible navigation rail with badges, icons, and selection events for driving the rest of your layout.
|
|
18
|
+
- `ModalWindow`: Simple modal shell that can host arbitrary Layout instances or HTML snippets.
|
|
19
|
+
- `ResourceBoard`: Master/detail resource explorer with selectable rows, action hooks, and optional add button wiring.
|
|
20
|
+
|
|
21
|
+
## Runtime Architecture
|
|
22
|
+
- Layouts and widgets are declared in Python but render as DOM nodes through the JavaScript bundles under `wapyt/assets/`. Each helper (e.g., `Layout.add_chat`) forwards config dictionaries directly to the matching JS constructor.
|
|
23
|
+
- The `wapyt/_runtime.py` bridge exposes `require_js` to lazily inject JS/CSS exactly once per interpreter and `create_proxy` to keep Pyodide callback proxies alive for event handlers.
|
|
24
|
+
- Layout cells are plain flexbox containers (`wapyt/assets/layout.js` + `wapyt/assets/wapyt.css`), so attaching raw HTML or third-party widgets is as simple as calling `layout.attach_html(cell_id, markup)`.
|
|
25
|
+
- Because everything routes through `window.wapyt`, you can add new widgets by dropping a JS file into `wapyt/assets/`, exporting a constructor, and calling `require_js("MyWidget")` before instantiating it from Python.
|
|
26
|
+
|
|
27
|
+
## Getting Started
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cd wapyt
|
|
31
|
+
uv venv --python 3.13 && source .venv/bin/activate
|
|
32
|
+
uv pip install -e .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then run a PyTincture example pointing at this widgetset:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd ../pytincture
|
|
39
|
+
uv run pytincture launch_service --modules_folder ../wA_pytincture_widgetset/tests --port 8070
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Open http://localhost:8070/layout_demo in your browser to see the native layout, and swap in `chat_demo` / `cardpanel_demo` / `tabs_demo` to explore the specialized widgets.
|
|
43
|
+
|
|
44
|
+
## Package Layout
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
wapyt/
|
|
48
|
+
├── chat/ # Chat widget config + wrapper
|
|
49
|
+
├── cardpanel/ # CardPanel widget config + wrapper
|
|
50
|
+
├── layout/ # Layout/MainWindow helpers
|
|
51
|
+
├── modal/ # ModalWindow + config
|
|
52
|
+
├── resourceboard/ # ResourceBoard widget + config
|
|
53
|
+
├── sidebar/ # Sidebar widget config + wrapper
|
|
54
|
+
├── tabwidget/ # Tab widget config + wrapper
|
|
55
|
+
└── assets/ # JS + CSS evaluated automatically by PyTincture
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Development Notes
|
|
60
|
+
|
|
61
|
+
- The JavaScript bundles define the `window.wapyt` namespace and are evaluated automatically by PyTincture’s loader (see `pytincture/frontend/pytincture.js`).
|
|
62
|
+
- Layout styles live in `assets/wapyt.css`; adjust tokens there to integrate with your design system.
|
|
63
|
+
- The tests are intentionally small, framework-free PyTincture apps so you can copy/paste into your own projects.
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
MIT – see `pyproject.toml` for details.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "wapyt"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "DHTMLX-free PyTincture widgetset with layout, chat, card panel, and tab widgets."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.13"
|
|
12
|
+
keywords = ["pytincture", "widgetset", "pyodide", "wapyt"]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"pyodide-py>=0.28.0",
|
|
15
|
+
"itsdangerous>=2.2.0",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
homepage = "https://github.com/schapman1974/wA_pytincture_widgetset"
|
|
20
|
+
|
|
21
|
+
[tool.setuptools]
|
|
22
|
+
include-package-data = true
|
|
23
|
+
|
|
24
|
+
[tool.setuptools.packages.find]
|
|
25
|
+
where = ["."]
|
wapyt-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from wapyt.cardpanel import CardPanelConfig, CardPanelCardConfig
|
|
4
|
+
from wapyt.layout import Layout, MainWindow, LayoutConfig, CellConfig
|
|
5
|
+
from wapyt.modal import ModalWindow, ModalConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class cardpanel_demo(MainWindow):
|
|
9
|
+
layout_config = LayoutConfig(rows=[CellConfig(id="cards", grow=1)])
|
|
10
|
+
|
|
11
|
+
def load_ui(self):
|
|
12
|
+
self._modal = ModalWindow(ModalConfig(title="Add Provider", width=520, height=380))
|
|
13
|
+
self._modal_layout = Layout(LayoutConfig(rows=[CellConfig(id="form", grow=1)]))
|
|
14
|
+
self._modal.set_content(self._modal_layout.layout)
|
|
15
|
+
self._render_modal_form()
|
|
16
|
+
|
|
17
|
+
config = CardPanelConfig(
|
|
18
|
+
title="Data Sources",
|
|
19
|
+
description="A minimal card panel rendered without DHTMLX.",
|
|
20
|
+
search_placeholder="Search connectors…",
|
|
21
|
+
add_button_text="New Source",
|
|
22
|
+
card_columns=3,
|
|
23
|
+
card_height=200,
|
|
24
|
+
card_template={
|
|
25
|
+
"class": "card-card",
|
|
26
|
+
"children": [
|
|
27
|
+
{
|
|
28
|
+
"class": "card-head",
|
|
29
|
+
"children": [
|
|
30
|
+
{"class": "card-icon", "text": "{extra.initial}"},
|
|
31
|
+
{
|
|
32
|
+
"children": [
|
|
33
|
+
{"tag": "h3", "class": "card-title", "text": "{title}"},
|
|
34
|
+
{"tag": "p", "class": "card-sub", "text": "{subtitle}"},
|
|
35
|
+
{"tag": "span", "class": "card-pill", "text": "{pill}"},
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{"class": "card-content", "text": "Status: {extra.status}"},
|
|
41
|
+
{
|
|
42
|
+
"class": "card-foot",
|
|
43
|
+
"children": [
|
|
44
|
+
{
|
|
45
|
+
"tag": "button",
|
|
46
|
+
"class": "card-action",
|
|
47
|
+
"text": "View",
|
|
48
|
+
"attrs": {"data-card-action": "view"},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"tag": "button",
|
|
52
|
+
"class": "card-action",
|
|
53
|
+
"text": "Sync",
|
|
54
|
+
"attrs": {"data-card-action": "sync"},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
cards=[
|
|
61
|
+
CardPanelCardConfig(
|
|
62
|
+
id="duckdb",
|
|
63
|
+
title="DuckDB",
|
|
64
|
+
subtitle="Fast OLAP engine",
|
|
65
|
+
pill="Warehouse",
|
|
66
|
+
extra={"status": "Healthy", "initial": "D"},
|
|
67
|
+
),
|
|
68
|
+
CardPanelCardConfig(
|
|
69
|
+
id="snowflake",
|
|
70
|
+
title="Snowflake",
|
|
71
|
+
subtitle="Elastic cloud analytics",
|
|
72
|
+
pill="Warehouse",
|
|
73
|
+
extra={"status": "Syncing", "initial": "S"},
|
|
74
|
+
),
|
|
75
|
+
CardPanelCardConfig(
|
|
76
|
+
id="lakehouse",
|
|
77
|
+
title="Lakehouse",
|
|
78
|
+
subtitle="S3 compatible store",
|
|
79
|
+
pill="Lake",
|
|
80
|
+
extra={"status": "Healthy", "initial": "L"},
|
|
81
|
+
),
|
|
82
|
+
],
|
|
83
|
+
)
|
|
84
|
+
panel = self.add_cardpanel("cards", config)
|
|
85
|
+
panel.on_card_click(lambda payload: print("Card clicked:", payload))
|
|
86
|
+
panel.on_add(lambda: self._show_modal())
|
|
87
|
+
panel.on_action(lambda payload: self._show_modal(payload.get("cardId")))
|
|
88
|
+
|
|
89
|
+
def _render_modal_form(self, provider_id: str = "", status: str = ""):
|
|
90
|
+
form_html = f"""
|
|
91
|
+
<form style="display:flex;flex-direction:column;gap:12px;">
|
|
92
|
+
<label>Provider ID
|
|
93
|
+
<input type="text" value="{provider_id}" style="width:100%;padding:8px;" />
|
|
94
|
+
</label>
|
|
95
|
+
<label>Status
|
|
96
|
+
<input type="text" value="{status}" style="width:100%;padding:8px;" />
|
|
97
|
+
</label>
|
|
98
|
+
<label>Models<br/>
|
|
99
|
+
<textarea style="width:100%;height:120px;padding:8px;">gpt-4o-mini</textarea>
|
|
100
|
+
</label>
|
|
101
|
+
<div style="display:flex;justify-content:flex-end;gap:8px;">
|
|
102
|
+
<button type="button" style="padding:8px 12px;">Cancel</button>
|
|
103
|
+
<button type="submit" style="padding:8px 12px;background:#2563eb;color:#fff;border:none;border-radius:8px;">Save</button>
|
|
104
|
+
</div>
|
|
105
|
+
</form>
|
|
106
|
+
"""
|
|
107
|
+
self._modal_layout.attach_html("form", form_html)
|
|
108
|
+
|
|
109
|
+
def _show_modal(self, provider_id: str = None):
|
|
110
|
+
title = "Add Provider" if not provider_id else f"Configure {provider_id}"
|
|
111
|
+
self._modal.set_title(title)
|
|
112
|
+
self._render_modal_form(provider_id or "", "Healthy")
|
|
113
|
+
self._modal.show()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == "__main__" and sys.platform != "emscripten":
|
|
117
|
+
from pytincture import launch_service
|
|
118
|
+
|
|
119
|
+
launch_service(modules_folder=".")
|