pgwidgets-js 0.1.2__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.
- pgwidgets_js-0.1.2/.flake8 +3 -0
- pgwidgets_js-0.1.2/.gitignore +38 -0
- pgwidgets_js-0.1.2/.readthedocs.yaml +16 -0
- pgwidgets_js-0.1.2/LICENSE.md +29 -0
- pgwidgets_js-0.1.2/MANIFEST.in +7 -0
- pgwidgets_js-0.1.2/PKG-INFO +298 -0
- pgwidgets_js-0.1.2/README.md +271 -0
- pgwidgets_js-0.1.2/Widgets.css +1 -0
- pgwidgets_js-0.1.2/Widgets.js +1 -0
- pgwidgets_js-0.1.2/docs/Makefile +15 -0
- pgwidgets_js-0.1.2/docs/callbacks.rst +94 -0
- pgwidgets_js-0.1.2/docs/conf.py +17 -0
- pgwidgets_js-0.1.2/docs/electron.rst +204 -0
- pgwidgets_js-0.1.2/docs/external-widgets.rst +229 -0
- pgwidgets_js-0.1.2/docs/frameworks.rst +237 -0
- pgwidgets_js-0.1.2/docs/getting-started.rst +117 -0
- pgwidgets_js-0.1.2/docs/index.rst +42 -0
- pgwidgets_js-0.1.2/docs/pyodide.rst +92 -0
- pgwidgets_js-0.1.2/docs/remote.rst +90 -0
- pgwidgets_js-0.1.2/docs/styling.rst +218 -0
- pgwidgets_js-0.1.2/docs/widgets/controls.rst +384 -0
- pgwidgets_js-0.1.2/docs/widgets/dialogs.rst +144 -0
- pgwidgets_js-0.1.2/docs/widgets/display.rst +376 -0
- pgwidgets_js-0.1.2/docs/widgets/index.rst +65 -0
- pgwidgets_js-0.1.2/docs/widgets/layout.rst +437 -0
- pgwidgets_js-0.1.2/docs/widgets/menus.rst +186 -0
- pgwidgets_js-0.1.2/docs/widgets/nonvisual.rst +57 -0
- pgwidgets_js-0.1.2/docs/widgets/text.rst +307 -0
- pgwidgets_js-0.1.2/examples/all_widgets.html +716 -0
- pgwidgets_js-0.1.2/examples/all_widgets_pyodide.html +79 -0
- pgwidgets_js-0.1.2/examples/all_widgets_pyodide.py +594 -0
- pgwidgets_js-0.1.2/examples/all_widgets_pyscript.html +31 -0
- pgwidgets_js-0.1.2/examples/all_widgets_pyscript.py +603 -0
- pgwidgets_js-0.1.2/examples/box.html +36 -0
- pgwidgets_js-0.1.2/examples/button.html +78 -0
- pgwidgets_js-0.1.2/examples/canvas.html +71 -0
- pgwidgets_js-0.1.2/examples/checkbox.html +44 -0
- pgwidgets_js-0.1.2/examples/colordialog.html +68 -0
- pgwidgets_js-0.1.2/examples/combobox.html +83 -0
- pgwidgets_js-0.1.2/examples/debug_spinbox.html +49 -0
- pgwidgets_js-0.1.2/examples/dial.html +113 -0
- pgwidgets_js-0.1.2/examples/dialog.html +105 -0
- pgwidgets_js-0.1.2/examples/electron/.gitignore +2 -0
- pgwidgets_js-0.1.2/examples/electron/.npmrc +3 -0
- pgwidgets_js-0.1.2/examples/electron/index.html +99 -0
- pgwidgets_js-0.1.2/examples/electron/main.js +28 -0
- pgwidgets_js-0.1.2/examples/electron/package.json +13 -0
- pgwidgets_js-0.1.2/examples/expander.html +46 -0
- pgwidgets_js-0.1.2/examples/external_widgets.html +89 -0
- pgwidgets_js-0.1.2/examples/frame.html +57 -0
- pgwidgets_js-0.1.2/examples/gridbox.html +76 -0
- pgwidgets_js-0.1.2/examples/htmlview.html +129 -0
- pgwidgets_js-0.1.2/examples/image.html +55 -0
- pgwidgets_js-0.1.2/examples/label.html +113 -0
- pgwidgets_js-0.1.2/examples/mdi_widget.html +49 -0
- pgwidgets_js-0.1.2/examples/menu.html +147 -0
- pgwidgets_js-0.1.2/examples/progressbar.html +90 -0
- pgwidgets_js-0.1.2/examples/pyodide_demo.html +154 -0
- pgwidgets_js-0.1.2/examples/pyscript.toml +5 -0
- pgwidgets_js-0.1.2/examples/radiobutton.html +84 -0
- pgwidgets_js-0.1.2/examples/remote.html +25 -0
- pgwidgets_js-0.1.2/examples/remote_demo.py +243 -0
- pgwidgets_js-0.1.2/examples/remote_demo_async.py +231 -0
- pgwidgets_js-0.1.2/examples/scroll_area.html +44 -0
- pgwidgets_js-0.1.2/examples/scrollable.html +31 -0
- pgwidgets_js-0.1.2/examples/scrollbar.html +86 -0
- pgwidgets_js-0.1.2/examples/slider.html +76 -0
- pgwidgets_js-0.1.2/examples/spinbox.html +70 -0
- pgwidgets_js-0.1.2/examples/splitter.html +39 -0
- pgwidgets_js-0.1.2/examples/tab_widget.html +94 -0
- pgwidgets_js-0.1.2/examples/tableview.html +139 -0
- pgwidgets_js-0.1.2/examples/text_entry.html +43 -0
- pgwidgets_js-0.1.2/examples/textarea.html +65 -0
- pgwidgets_js-0.1.2/examples/textentryset.html +77 -0
- pgwidgets_js-0.1.2/examples/textsource.html +139 -0
- pgwidgets_js-0.1.2/examples/togglebutton.html +77 -0
- pgwidgets_js-0.1.2/examples/toolbar.html +125 -0
- pgwidgets_js-0.1.2/examples/treeview.html +95 -0
- pgwidgets_js-0.1.2/examples/videowidget.html +103 -0
- pgwidgets_js-0.1.2/package.json +35 -0
- pgwidgets_js-0.1.2/pgwidgets_js/__init__.py +25 -0
- pgwidgets_js-0.1.2/pgwidgets_js/defs.py +772 -0
- pgwidgets_js-0.1.2/pgwidgets_js/pyodide/__init__.py +42 -0
- pgwidgets_js-0.1.2/pgwidgets_js/pyodide/widget.py +194 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/Widgets.css +42 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/Widgets.js +69 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Box.css +26 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Button.css +24 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/CheckBox.css +8 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ColorDialog.css +53 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ComboBox.css +63 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Dial.css +47 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Dialog.css +24 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Expander.css +44 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ExternalWidget.css +11 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Frame.css +30 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/GridBox.css +11 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/HtmlView.css +49 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Image.css +6 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/MDIWidget.css +202 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Menu.css +107 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ProgressBar.css +39 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/RadioButton.css +45 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ScrollArea.css +45 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ScrollBar.css +34 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Slider.css +21 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/SpinBox.css +63 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Splitter.css +56 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/TabWidget.css +148 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Text.css +8 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/TextArea.css +52 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/TextEntrySet.css +38 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/TextSource.css +130 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ToggleButton.css +21 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/ToolBar.css +95 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/TopLevel.css +90 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/TreeView.css +230 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/VideoWidget.css +19 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/css/Widget.css +4 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/icons/file.svg +100 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/icons/folder.svg +65 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/icons/hdots.svg +44 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/icons/pgicon.svg +95 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/icons/pgwidgets-logo.svg +273 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/icons/vdots.svg +44 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Box.js +137 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Button.js +102 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Callback.js +150 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Canvas.js +154 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/CheckBox.js +66 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ColorDialog.js +99 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ColorWidget.js +464 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ComboBox.js +293 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ComboBoxNative.js +174 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Dial.js +408 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Dialog.js +103 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Expander.js +111 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ExternalWidget.js +73 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/FileDialog.js +185 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Frame.js +73 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/GridBox.js +272 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/HtmlView.js +171 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Image.js +155 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Label.js +79 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/MDIWidget.js +750 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Menu.js +137 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/MenuAction.js +142 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/MenuBar.js +169 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Page.js +52 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ProgressBar.js +65 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/RadioButton.js +119 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/RemoteInterface.js +395 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ScrollArea.js +154 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ScrollBar.js +187 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Slider.js +162 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/SpinBox.js +205 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Splitter.js +229 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TabWidget.js +373 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TableView.js +41 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TextArea.js +160 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TextEntry.js +143 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TextEntrySet.js +67 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TextSource.js +1170 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TextWidget.js +67 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Timer.js +152 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ToggleButton.js +128 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ToolBar.js +87 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/ToolBarAction.js +180 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TopLevel.js +337 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/TreeView.js +1410 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/VideoWidget.js +259 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/modules/Widget.js +900 -0
- pgwidgets_js-0.1.2/pgwidgets_js/static/remote.html +29 -0
- pgwidgets_js-0.1.2/pgwidgets_js.egg-info/PKG-INFO +298 -0
- pgwidgets_js-0.1.2/pgwidgets_js.egg-info/SOURCES.txt +183 -0
- pgwidgets_js-0.1.2/pgwidgets_js.egg-info/dependency_links.txt +1 -0
- pgwidgets_js-0.1.2/pgwidgets_js.egg-info/requires.txt +7 -0
- pgwidgets_js-0.1.2/pgwidgets_js.egg-info/top_level.txt +1 -0
- pgwidgets_js-0.1.2/pyproject.toml +45 -0
- pgwidgets_js-0.1.2/setup.cfg +4 -0
- pgwidgets_js-0.1.2/setup.py +2 -0
- pgwidgets_js-0.1.2/tests/__init__.py +1 -0
- pgwidgets_js-0.1.2/tests/test_consistency.py +141 -0
- pgwidgets_js-0.1.2/tests/test_defs.py +110 -0
- pgwidgets_js-0.1.2/tests/test_static_assets.py +58 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# ignore some commonly problematic files
|
|
2
|
+
|
|
3
|
+
# python compiled files
|
|
4
|
+
*.py[co]
|
|
5
|
+
|
|
6
|
+
# emacs backups
|
|
7
|
+
*~
|
|
8
|
+
\#*\#
|
|
9
|
+
|
|
10
|
+
# Compiled files
|
|
11
|
+
__pycache__
|
|
12
|
+
|
|
13
|
+
# Other generated files
|
|
14
|
+
version.py
|
|
15
|
+
|
|
16
|
+
# Sphinx
|
|
17
|
+
_build
|
|
18
|
+
|
|
19
|
+
# Packages/installer info
|
|
20
|
+
*.egg
|
|
21
|
+
*.egg-info
|
|
22
|
+
dist
|
|
23
|
+
build
|
|
24
|
+
eggs
|
|
25
|
+
sdist
|
|
26
|
+
develop-eggs
|
|
27
|
+
.installed.cfg
|
|
28
|
+
distribute-*.tar.gz
|
|
29
|
+
|
|
30
|
+
# Other
|
|
31
|
+
.*.swp
|
|
32
|
+
|
|
33
|
+
# Node
|
|
34
|
+
node_modules
|
|
35
|
+
|
|
36
|
+
# Mac OSX
|
|
37
|
+
.DS_Store
|
|
38
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, PGWidgets developers
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pgwidgets-js
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: pgwidgets JavaScript widget library — static assets for use with Python servers
|
|
5
|
+
Author: PGWidgets Developers
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/naojsoft/pgwidgets-js
|
|
8
|
+
Project-URL: Repository, https://github.com/naojsoft/pgwidgets-js
|
|
9
|
+
Keywords: widgets,ui,gui,javascript,websocket
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Programming Language :: JavaScript
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE.md
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: sphinx; extra == "dev"
|
|
23
|
+
Requires-Dist: furo; extra == "dev"
|
|
24
|
+
Provides-Extra: test
|
|
25
|
+
Requires-Dist: pytest; extra == "test"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
<p align="center">
|
|
29
|
+
<img src="pgwidgets_js/static/icons/pgwidgets-logo.svg" alt="pgwidgets logo" width="300">
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
A native JavaScript widget toolkit with Qt/GTK-style layout and controls.<br>
|
|
34
|
+
No frameworks. No build step. No dependencies.
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## What is PGWidgets?
|
|
40
|
+
|
|
41
|
+
pgwidgets is a pure JavaScript widget library that brings desktop-style UI
|
|
42
|
+
controls to the browser. If you've used Qt, GTK, or Tkinter, the API will
|
|
43
|
+
feel familiar: create widgets, pack them into layout containers, and wire
|
|
44
|
+
up callbacks.
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
import { Widgets } from "./Widgets.js";
|
|
48
|
+
|
|
49
|
+
let top = new Widgets.TopLevel({title: "Hello", resizable: true});
|
|
50
|
+
top.resize(400, 300);
|
|
51
|
+
|
|
52
|
+
let vbox = new Widgets.VBox();
|
|
53
|
+
vbox.set_spacing(8);
|
|
54
|
+
vbox.set_padding(10);
|
|
55
|
+
|
|
56
|
+
let label = new Widgets.Label("Click the button!");
|
|
57
|
+
let button = new Widgets.Button("Click me");
|
|
58
|
+
button.add_callback('activated', () => label.set_text("Clicked!"));
|
|
59
|
+
|
|
60
|
+
vbox.add_widget(button, 0);
|
|
61
|
+
vbox.add_widget(label, 1);
|
|
62
|
+
top.set_widget(vbox);
|
|
63
|
+
top.show();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
- **Zero dependencies** -- pure JavaScript ES modules, works directly in the browser
|
|
69
|
+
- **No build step** -- just include `Widgets.js` and `Widgets.css`
|
|
70
|
+
- **Desktop-style layouts** -- VBox, HBox, GridBox, Splitter, TabWidget, ScrollArea
|
|
71
|
+
- **MDI workspace** -- multiple draggable, resizable sub-windows with cascade/tile
|
|
72
|
+
- **Remote interface** -- drive the UI over WebSocket from Python or any language
|
|
73
|
+
- **Familiar API** -- callbacks, containers, and widget hierarchy inspired by Qt/GTK
|
|
74
|
+
|
|
75
|
+
## Widgets
|
|
76
|
+
|
|
77
|
+
### Layout & Containers
|
|
78
|
+
|
|
79
|
+
| Widget | Description |
|
|
80
|
+
|--------|-------------|
|
|
81
|
+
| **TopLevel** | Top-level window with optional title bar, dragging, and resize grips |
|
|
82
|
+
| **VBox / HBox** | Vertical and horizontal box layouts with spacing and stretch factors |
|
|
83
|
+
| **GridBox** | Grid layout with row/column placement |
|
|
84
|
+
| **Splitter** | Resizable split pane (horizontal or vertical) |
|
|
85
|
+
| **TabWidget** | Tabbed container with switchable pages |
|
|
86
|
+
| **StackWidget** | Stacked pages without tab headers |
|
|
87
|
+
| **ScrollArea** | Scrollable viewport with custom scrollbars |
|
|
88
|
+
| **Frame** | Titled border container |
|
|
89
|
+
| **Expander** | Collapsible section with a clickable header |
|
|
90
|
+
| **MDIWidget** | Multiple Document Interface workspace with sub-windows |
|
|
91
|
+
|
|
92
|
+
### Controls
|
|
93
|
+
|
|
94
|
+
| Widget | Description |
|
|
95
|
+
|--------|-------------|
|
|
96
|
+
| **Button** | Push button with optional icon |
|
|
97
|
+
| **ToggleButton** | Two-state button, supports exclusive groups |
|
|
98
|
+
| **CheckBox** | Checkbox with label |
|
|
99
|
+
| **RadioButton** | Radio button with exclusive group support |
|
|
100
|
+
| **ComboBox** | Dropdown with optional editable text, filtering, and scroll limit |
|
|
101
|
+
| **Slider** | Range slider (integer or float) |
|
|
102
|
+
| **SpinBox** | Numeric input with increment/decrement buttons |
|
|
103
|
+
| **Dial** | Rotary knob control |
|
|
104
|
+
| **ScrollBar** | Standalone scrollbar with draggable thumb |
|
|
105
|
+
| **ProgressBar** | Determinate progress indicator |
|
|
106
|
+
|
|
107
|
+
### Text & Display
|
|
108
|
+
|
|
109
|
+
| Widget | Description |
|
|
110
|
+
|--------|-------------|
|
|
111
|
+
| **Label** | Static text with alignment, color, and font options |
|
|
112
|
+
| **TextEntry** | Single-line text input with line history |
|
|
113
|
+
| **TextEntrySet** | Text entry with a submit button |
|
|
114
|
+
| **TextArea** | Multi-line text editor |
|
|
115
|
+
| **Image** | Image display widget |
|
|
116
|
+
| **Canvas** | HTML5 canvas for custom drawing |
|
|
117
|
+
| **TreeView** | Hierarchical tree/table with columns, sorting, icons, and multi-selection |
|
|
118
|
+
|
|
119
|
+
### Menus & Toolbars
|
|
120
|
+
|
|
121
|
+
| Widget | Description |
|
|
122
|
+
|--------|-------------|
|
|
123
|
+
| **MenuBar** | Horizontal menu bar |
|
|
124
|
+
| **Menu** | Dropdown menu with actions |
|
|
125
|
+
| **ToolBar** | Toolbar with buttons, toggles, and separators |
|
|
126
|
+
|
|
127
|
+
### Dialogs
|
|
128
|
+
|
|
129
|
+
| Widget | Description |
|
|
130
|
+
|--------|-------------|
|
|
131
|
+
| **Dialog** | Modal or non-modal dialog with configurable buttons |
|
|
132
|
+
| **ColorDialog** | Color picker with SV plane, hue strip, and RGB/HSV/hex inputs |
|
|
133
|
+
|
|
134
|
+
## Installation
|
|
135
|
+
|
|
136
|
+
### Standalone (no tooling)
|
|
137
|
+
|
|
138
|
+
Copy the repository and include it directly:
|
|
139
|
+
|
|
140
|
+
```html
|
|
141
|
+
<link rel="stylesheet" href="path/to/Widgets.css" />
|
|
142
|
+
<script type="module">
|
|
143
|
+
import { Widgets } from "path/to/Widgets.js";
|
|
144
|
+
// ...
|
|
145
|
+
</script>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### npm
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm install pgwidgets # once published
|
|
152
|
+
# or install directly from GitHub:
|
|
153
|
+
npm install github:naojsoft/pgwidgets-js
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Then in your bundled app:
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
import { Widgets } from "pgwidgets";
|
|
160
|
+
import "pgwidgets/Widgets.css";
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Using from Python (Pyodide / PyScript)
|
|
164
|
+
|
|
165
|
+
pgwidgets can be used directly from Python in the browser via
|
|
166
|
+
[Pyodide](https://pyodide.org) or [PyScript](https://pyscript.net).
|
|
167
|
+
The `pgwidgets_js.pyodide` module provides Pythonic wrappers with
|
|
168
|
+
normal construction syntax, automatic type conversion, and callback
|
|
169
|
+
management.
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from pgwidgets_js.pyodide import Widgets
|
|
173
|
+
|
|
174
|
+
top = Widgets.TopLevel(title="Hello", resizable=True)
|
|
175
|
+
top.resize(400, 300)
|
|
176
|
+
|
|
177
|
+
vbox = Widgets.VBox(spacing=8, padding=10)
|
|
178
|
+
|
|
179
|
+
label = Widgets.Label("Click the button!")
|
|
180
|
+
button = Widgets.Button("Click me")
|
|
181
|
+
button.on("activated", lambda: label.set_text("Clicked!"))
|
|
182
|
+
|
|
183
|
+
vbox.add_widget(button, 0)
|
|
184
|
+
vbox.add_widget(label, 1)
|
|
185
|
+
top.set_widget(vbox)
|
|
186
|
+
top.show()
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
No WebSocket server needed -- everything runs in the browser. The same
|
|
190
|
+
Python code works with both Pyodide and PyScript; only the HTML loader
|
|
191
|
+
differs. See `examples/pyodide_demo.html` for a minimal Pyodide example,
|
|
192
|
+
`examples/all_widgets_pyodide.html` for a full demo via Pyodide, and
|
|
193
|
+
`examples/all_widgets_pyscript.html` for the same demo via PyScript.
|
|
194
|
+
|
|
195
|
+
## Remote Interface (WebSocket)
|
|
196
|
+
|
|
197
|
+
pgwidgets can also be controlled from a Python server over WebSocket
|
|
198
|
+
using the [pgwidgets-python](https://github.com/naojsoft/pgwidgets-python)
|
|
199
|
+
package. The browser page connects to the server, which sends JSON
|
|
200
|
+
messages to create widgets, call methods, and receive callbacks.
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from pgwidgets.sync import Application
|
|
204
|
+
|
|
205
|
+
app = Application()
|
|
206
|
+
app.start()
|
|
207
|
+
W = app.get_widgets()
|
|
208
|
+
app.wait_for_connection()
|
|
209
|
+
|
|
210
|
+
top = W.TopLevel(title="Remote App", resizable=True)
|
|
211
|
+
top.resize(400, 300)
|
|
212
|
+
|
|
213
|
+
vbox = W.VBox(spacing=8)
|
|
214
|
+
btn = W.Button("Click me")
|
|
215
|
+
status = W.Label("Ready")
|
|
216
|
+
|
|
217
|
+
btn.on("activated", lambda: status.set_text("Clicked!"))
|
|
218
|
+
|
|
219
|
+
vbox.add_widget(btn, 0)
|
|
220
|
+
vbox.add_widget(status, 1)
|
|
221
|
+
top.set_widget(vbox)
|
|
222
|
+
top.show()
|
|
223
|
+
|
|
224
|
+
app.run()
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
See `examples/remote_demo.py` and `examples/remote_demo_async.py`
|
|
228
|
+
for complete working examples.
|
|
229
|
+
|
|
230
|
+
## Building Desktop Apps with Electron
|
|
231
|
+
|
|
232
|
+
Because pgwidgets is just a browser library with no dependencies, it
|
|
233
|
+
runs unchanged inside an [Electron](https://electronjs.org) renderer
|
|
234
|
+
process. This lets you ship pgwidgets UIs as native desktop apps with
|
|
235
|
+
their own window chrome, system menus, and access to the file system.
|
|
236
|
+
|
|
237
|
+
A minimal example lives in `examples/electron/`:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
cd examples/electron
|
|
241
|
+
npm install # one-time, installs Electron locally
|
|
242
|
+
npm start # launches the all_widgets demo in an Electron window
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The Electron entry point (`main.js`) is about 20 lines and simply
|
|
246
|
+
creates a `BrowserWindow` that loads an HTML file -- no
|
|
247
|
+
Electron-specific changes are needed in pgwidgets itself. To use your
|
|
248
|
+
own UI, edit `main.js` to point at a different HTML file.
|
|
249
|
+
|
|
250
|
+
## Embedding Third-Party Libraries
|
|
251
|
+
|
|
252
|
+
The `ExternalWidget` class lets you embed content from third-party
|
|
253
|
+
JavaScript libraries -- Plotly charts, Bokeh plots, Leaflet maps, D3
|
|
254
|
+
visualizations, and more -- into pgwidgets layout containers. The
|
|
255
|
+
widget participates in pgwidgets layout (stretch factors, splitters,
|
|
256
|
+
tabs) while its content area is managed by the external library.
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
let chart = new Widgets.ExternalWidget();
|
|
260
|
+
vbox.add_widget(chart, 1); // stretch=1 fills available space
|
|
261
|
+
|
|
262
|
+
Plotly.newPlot(chart.get_content_element(), data, layout,
|
|
263
|
+
{responsive: true});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
See the [documentation](docs/external-widgets.rst) for full examples
|
|
267
|
+
with Plotly, Bokeh, and other libraries.
|
|
268
|
+
|
|
269
|
+
## Running the Examples
|
|
270
|
+
|
|
271
|
+
Start a local web server from the repository root:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
python -m http.server --bind localhost 8000
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Then open any example in your browser:
|
|
278
|
+
|
|
279
|
+
- [all_widgets.html](http://localhost:8000/examples/all_widgets.html) -- MDI workspace showcasing every widget (JavaScript)
|
|
280
|
+
- [all_widgets_pyodide.html](http://localhost:8000/examples/all_widgets_pyodide.html) -- Same demo, written entirely in Python via Pyodide
|
|
281
|
+
- [all_widgets_pyscript.html](http://localhost:8000/examples/all_widgets_pyscript.html) -- Same demo via PyScript
|
|
282
|
+
- [pyodide_demo.html](http://localhost:8000/examples/pyodide_demo.html) -- Minimal Pyodide example
|
|
283
|
+
- [treeview.html](http://localhost:8000/examples/treeview.html) -- TreeView with icons, sorting, and multi-selection
|
|
284
|
+
- [mdi_widget.html](http://localhost:8000/examples/mdi_widget.html) -- MDI with cascade/tile
|
|
285
|
+
- [dialog.html](http://localhost:8000/examples/dialog.html) -- Modal and non-modal dialogs
|
|
286
|
+
- [colordialog.html](http://localhost:8000/examples/colordialog.html) -- Color picker dialog
|
|
287
|
+
- [combobox.html](http://localhost:8000/examples/combobox.html) -- ComboBox variants
|
|
288
|
+
- [splitter.html](http://localhost:8000/examples/splitter.html) -- Resizable split panes
|
|
289
|
+
- [tab_widget.html](http://localhost:8000/examples/tab_widget.html) -- Tabbed interface
|
|
290
|
+
- [htmlview.html](http://localhost:8000/examples/htmlview.html) -- Rich HTML content display
|
|
291
|
+
- [videowidget.html](http://localhost:8000/examples/videowidget.html) -- Video playback with controls
|
|
292
|
+
- [external_widgets.html](http://localhost:8000/examples/external_widgets.html) -- Plotly and Bokeh in a splitter
|
|
293
|
+
|
|
294
|
+
And many more in the `examples/` directory.
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
BSD 3-Clause
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="pgwidgets_js/static/icons/pgwidgets-logo.svg" alt="pgwidgets logo" width="300">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
A native JavaScript widget toolkit with Qt/GTK-style layout and controls.<br>
|
|
7
|
+
No frameworks. No build step. No dependencies.
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## What is PGWidgets?
|
|
13
|
+
|
|
14
|
+
pgwidgets is a pure JavaScript widget library that brings desktop-style UI
|
|
15
|
+
controls to the browser. If you've used Qt, GTK, or Tkinter, the API will
|
|
16
|
+
feel familiar: create widgets, pack them into layout containers, and wire
|
|
17
|
+
up callbacks.
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import { Widgets } from "./Widgets.js";
|
|
21
|
+
|
|
22
|
+
let top = new Widgets.TopLevel({title: "Hello", resizable: true});
|
|
23
|
+
top.resize(400, 300);
|
|
24
|
+
|
|
25
|
+
let vbox = new Widgets.VBox();
|
|
26
|
+
vbox.set_spacing(8);
|
|
27
|
+
vbox.set_padding(10);
|
|
28
|
+
|
|
29
|
+
let label = new Widgets.Label("Click the button!");
|
|
30
|
+
let button = new Widgets.Button("Click me");
|
|
31
|
+
button.add_callback('activated', () => label.set_text("Clicked!"));
|
|
32
|
+
|
|
33
|
+
vbox.add_widget(button, 0);
|
|
34
|
+
vbox.add_widget(label, 1);
|
|
35
|
+
top.set_widget(vbox);
|
|
36
|
+
top.show();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **Zero dependencies** -- pure JavaScript ES modules, works directly in the browser
|
|
42
|
+
- **No build step** -- just include `Widgets.js` and `Widgets.css`
|
|
43
|
+
- **Desktop-style layouts** -- VBox, HBox, GridBox, Splitter, TabWidget, ScrollArea
|
|
44
|
+
- **MDI workspace** -- multiple draggable, resizable sub-windows with cascade/tile
|
|
45
|
+
- **Remote interface** -- drive the UI over WebSocket from Python or any language
|
|
46
|
+
- **Familiar API** -- callbacks, containers, and widget hierarchy inspired by Qt/GTK
|
|
47
|
+
|
|
48
|
+
## Widgets
|
|
49
|
+
|
|
50
|
+
### Layout & Containers
|
|
51
|
+
|
|
52
|
+
| Widget | Description |
|
|
53
|
+
|--------|-------------|
|
|
54
|
+
| **TopLevel** | Top-level window with optional title bar, dragging, and resize grips |
|
|
55
|
+
| **VBox / HBox** | Vertical and horizontal box layouts with spacing and stretch factors |
|
|
56
|
+
| **GridBox** | Grid layout with row/column placement |
|
|
57
|
+
| **Splitter** | Resizable split pane (horizontal or vertical) |
|
|
58
|
+
| **TabWidget** | Tabbed container with switchable pages |
|
|
59
|
+
| **StackWidget** | Stacked pages without tab headers |
|
|
60
|
+
| **ScrollArea** | Scrollable viewport with custom scrollbars |
|
|
61
|
+
| **Frame** | Titled border container |
|
|
62
|
+
| **Expander** | Collapsible section with a clickable header |
|
|
63
|
+
| **MDIWidget** | Multiple Document Interface workspace with sub-windows |
|
|
64
|
+
|
|
65
|
+
### Controls
|
|
66
|
+
|
|
67
|
+
| Widget | Description |
|
|
68
|
+
|--------|-------------|
|
|
69
|
+
| **Button** | Push button with optional icon |
|
|
70
|
+
| **ToggleButton** | Two-state button, supports exclusive groups |
|
|
71
|
+
| **CheckBox** | Checkbox with label |
|
|
72
|
+
| **RadioButton** | Radio button with exclusive group support |
|
|
73
|
+
| **ComboBox** | Dropdown with optional editable text, filtering, and scroll limit |
|
|
74
|
+
| **Slider** | Range slider (integer or float) |
|
|
75
|
+
| **SpinBox** | Numeric input with increment/decrement buttons |
|
|
76
|
+
| **Dial** | Rotary knob control |
|
|
77
|
+
| **ScrollBar** | Standalone scrollbar with draggable thumb |
|
|
78
|
+
| **ProgressBar** | Determinate progress indicator |
|
|
79
|
+
|
|
80
|
+
### Text & Display
|
|
81
|
+
|
|
82
|
+
| Widget | Description |
|
|
83
|
+
|--------|-------------|
|
|
84
|
+
| **Label** | Static text with alignment, color, and font options |
|
|
85
|
+
| **TextEntry** | Single-line text input with line history |
|
|
86
|
+
| **TextEntrySet** | Text entry with a submit button |
|
|
87
|
+
| **TextArea** | Multi-line text editor |
|
|
88
|
+
| **Image** | Image display widget |
|
|
89
|
+
| **Canvas** | HTML5 canvas for custom drawing |
|
|
90
|
+
| **TreeView** | Hierarchical tree/table with columns, sorting, icons, and multi-selection |
|
|
91
|
+
|
|
92
|
+
### Menus & Toolbars
|
|
93
|
+
|
|
94
|
+
| Widget | Description |
|
|
95
|
+
|--------|-------------|
|
|
96
|
+
| **MenuBar** | Horizontal menu bar |
|
|
97
|
+
| **Menu** | Dropdown menu with actions |
|
|
98
|
+
| **ToolBar** | Toolbar with buttons, toggles, and separators |
|
|
99
|
+
|
|
100
|
+
### Dialogs
|
|
101
|
+
|
|
102
|
+
| Widget | Description |
|
|
103
|
+
|--------|-------------|
|
|
104
|
+
| **Dialog** | Modal or non-modal dialog with configurable buttons |
|
|
105
|
+
| **ColorDialog** | Color picker with SV plane, hue strip, and RGB/HSV/hex inputs |
|
|
106
|
+
|
|
107
|
+
## Installation
|
|
108
|
+
|
|
109
|
+
### Standalone (no tooling)
|
|
110
|
+
|
|
111
|
+
Copy the repository and include it directly:
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<link rel="stylesheet" href="path/to/Widgets.css" />
|
|
115
|
+
<script type="module">
|
|
116
|
+
import { Widgets } from "path/to/Widgets.js";
|
|
117
|
+
// ...
|
|
118
|
+
</script>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### npm
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm install pgwidgets # once published
|
|
125
|
+
# or install directly from GitHub:
|
|
126
|
+
npm install github:naojsoft/pgwidgets-js
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Then in your bundled app:
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
import { Widgets } from "pgwidgets";
|
|
133
|
+
import "pgwidgets/Widgets.css";
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Using from Python (Pyodide / PyScript)
|
|
137
|
+
|
|
138
|
+
pgwidgets can be used directly from Python in the browser via
|
|
139
|
+
[Pyodide](https://pyodide.org) or [PyScript](https://pyscript.net).
|
|
140
|
+
The `pgwidgets_js.pyodide` module provides Pythonic wrappers with
|
|
141
|
+
normal construction syntax, automatic type conversion, and callback
|
|
142
|
+
management.
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from pgwidgets_js.pyodide import Widgets
|
|
146
|
+
|
|
147
|
+
top = Widgets.TopLevel(title="Hello", resizable=True)
|
|
148
|
+
top.resize(400, 300)
|
|
149
|
+
|
|
150
|
+
vbox = Widgets.VBox(spacing=8, padding=10)
|
|
151
|
+
|
|
152
|
+
label = Widgets.Label("Click the button!")
|
|
153
|
+
button = Widgets.Button("Click me")
|
|
154
|
+
button.on("activated", lambda: label.set_text("Clicked!"))
|
|
155
|
+
|
|
156
|
+
vbox.add_widget(button, 0)
|
|
157
|
+
vbox.add_widget(label, 1)
|
|
158
|
+
top.set_widget(vbox)
|
|
159
|
+
top.show()
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
No WebSocket server needed -- everything runs in the browser. The same
|
|
163
|
+
Python code works with both Pyodide and PyScript; only the HTML loader
|
|
164
|
+
differs. See `examples/pyodide_demo.html` for a minimal Pyodide example,
|
|
165
|
+
`examples/all_widgets_pyodide.html` for a full demo via Pyodide, and
|
|
166
|
+
`examples/all_widgets_pyscript.html` for the same demo via PyScript.
|
|
167
|
+
|
|
168
|
+
## Remote Interface (WebSocket)
|
|
169
|
+
|
|
170
|
+
pgwidgets can also be controlled from a Python server over WebSocket
|
|
171
|
+
using the [pgwidgets-python](https://github.com/naojsoft/pgwidgets-python)
|
|
172
|
+
package. The browser page connects to the server, which sends JSON
|
|
173
|
+
messages to create widgets, call methods, and receive callbacks.
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from pgwidgets.sync import Application
|
|
177
|
+
|
|
178
|
+
app = Application()
|
|
179
|
+
app.start()
|
|
180
|
+
W = app.get_widgets()
|
|
181
|
+
app.wait_for_connection()
|
|
182
|
+
|
|
183
|
+
top = W.TopLevel(title="Remote App", resizable=True)
|
|
184
|
+
top.resize(400, 300)
|
|
185
|
+
|
|
186
|
+
vbox = W.VBox(spacing=8)
|
|
187
|
+
btn = W.Button("Click me")
|
|
188
|
+
status = W.Label("Ready")
|
|
189
|
+
|
|
190
|
+
btn.on("activated", lambda: status.set_text("Clicked!"))
|
|
191
|
+
|
|
192
|
+
vbox.add_widget(btn, 0)
|
|
193
|
+
vbox.add_widget(status, 1)
|
|
194
|
+
top.set_widget(vbox)
|
|
195
|
+
top.show()
|
|
196
|
+
|
|
197
|
+
app.run()
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
See `examples/remote_demo.py` and `examples/remote_demo_async.py`
|
|
201
|
+
for complete working examples.
|
|
202
|
+
|
|
203
|
+
## Building Desktop Apps with Electron
|
|
204
|
+
|
|
205
|
+
Because pgwidgets is just a browser library with no dependencies, it
|
|
206
|
+
runs unchanged inside an [Electron](https://electronjs.org) renderer
|
|
207
|
+
process. This lets you ship pgwidgets UIs as native desktop apps with
|
|
208
|
+
their own window chrome, system menus, and access to the file system.
|
|
209
|
+
|
|
210
|
+
A minimal example lives in `examples/electron/`:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
cd examples/electron
|
|
214
|
+
npm install # one-time, installs Electron locally
|
|
215
|
+
npm start # launches the all_widgets demo in an Electron window
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The Electron entry point (`main.js`) is about 20 lines and simply
|
|
219
|
+
creates a `BrowserWindow` that loads an HTML file -- no
|
|
220
|
+
Electron-specific changes are needed in pgwidgets itself. To use your
|
|
221
|
+
own UI, edit `main.js` to point at a different HTML file.
|
|
222
|
+
|
|
223
|
+
## Embedding Third-Party Libraries
|
|
224
|
+
|
|
225
|
+
The `ExternalWidget` class lets you embed content from third-party
|
|
226
|
+
JavaScript libraries -- Plotly charts, Bokeh plots, Leaflet maps, D3
|
|
227
|
+
visualizations, and more -- into pgwidgets layout containers. The
|
|
228
|
+
widget participates in pgwidgets layout (stretch factors, splitters,
|
|
229
|
+
tabs) while its content area is managed by the external library.
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
let chart = new Widgets.ExternalWidget();
|
|
233
|
+
vbox.add_widget(chart, 1); // stretch=1 fills available space
|
|
234
|
+
|
|
235
|
+
Plotly.newPlot(chart.get_content_element(), data, layout,
|
|
236
|
+
{responsive: true});
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
See the [documentation](docs/external-widgets.rst) for full examples
|
|
240
|
+
with Plotly, Bokeh, and other libraries.
|
|
241
|
+
|
|
242
|
+
## Running the Examples
|
|
243
|
+
|
|
244
|
+
Start a local web server from the repository root:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
python -m http.server --bind localhost 8000
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Then open any example in your browser:
|
|
251
|
+
|
|
252
|
+
- [all_widgets.html](http://localhost:8000/examples/all_widgets.html) -- MDI workspace showcasing every widget (JavaScript)
|
|
253
|
+
- [all_widgets_pyodide.html](http://localhost:8000/examples/all_widgets_pyodide.html) -- Same demo, written entirely in Python via Pyodide
|
|
254
|
+
- [all_widgets_pyscript.html](http://localhost:8000/examples/all_widgets_pyscript.html) -- Same demo via PyScript
|
|
255
|
+
- [pyodide_demo.html](http://localhost:8000/examples/pyodide_demo.html) -- Minimal Pyodide example
|
|
256
|
+
- [treeview.html](http://localhost:8000/examples/treeview.html) -- TreeView with icons, sorting, and multi-selection
|
|
257
|
+
- [mdi_widget.html](http://localhost:8000/examples/mdi_widget.html) -- MDI with cascade/tile
|
|
258
|
+
- [dialog.html](http://localhost:8000/examples/dialog.html) -- Modal and non-modal dialogs
|
|
259
|
+
- [colordialog.html](http://localhost:8000/examples/colordialog.html) -- Color picker dialog
|
|
260
|
+
- [combobox.html](http://localhost:8000/examples/combobox.html) -- ComboBox variants
|
|
261
|
+
- [splitter.html](http://localhost:8000/examples/splitter.html) -- Resizable split panes
|
|
262
|
+
- [tab_widget.html](http://localhost:8000/examples/tab_widget.html) -- Tabbed interface
|
|
263
|
+
- [htmlview.html](http://localhost:8000/examples/htmlview.html) -- Rich HTML content display
|
|
264
|
+
- [videowidget.html](http://localhost:8000/examples/videowidget.html) -- Video playback with controls
|
|
265
|
+
- [external_widgets.html](http://localhost:8000/examples/external_widgets.html) -- Plotly and Bokeh in a splitter
|
|
266
|
+
|
|
267
|
+
And many more in the `examples/` directory.
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
BSD 3-Clause
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "pgwidgets_js/static/Widgets.css";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Widgets } from "./pgwidgets_js/static/Widgets.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
|
|
3
|
+
SPHINXOPTS ?=
|
|
4
|
+
SPHINXBUILD ?= sphinx-build
|
|
5
|
+
SOURCEDIR = .
|
|
6
|
+
BUILDDIR = _build
|
|
7
|
+
|
|
8
|
+
help:
|
|
9
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
10
|
+
|
|
11
|
+
.PHONY: help Makefile
|
|
12
|
+
|
|
13
|
+
# Catch-all target: route all unknown targets to Sphinx
|
|
14
|
+
%: Makefile
|
|
15
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|