npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pgwidgets

v0.2.1

Published

A native JavaScript widget library with Qt/GTK-style layout and controls

Readme


What is PGWidgets?

pgwidgets is a pure JavaScript widget library that brings desktop-style UI controls to the browser. If you've used Qt, GTK, or Tkinter, the API will feel familiar: create widgets, pack them into layout containers, and wire up callbacks.

import { Widgets } from "./Widgets.js";

let top = new Widgets.TopLevel({title: "Hello", resizable: true});
top.resize(400, 300);

let vbox = new Widgets.VBox();
vbox.set_spacing(8);
vbox.set_padding(10);

let label = new Widgets.Label("Click the button!");
let button = new Widgets.Button("Click me");
button.add_callback('activated', () => label.set_text("Clicked!"));

vbox.add_widget(button, 0);
vbox.add_widget(label, 1);
top.set_widget(vbox);
top.show();

Features

  • Zero dependencies -- pure JavaScript ES modules, works directly in the browser
  • No build step -- just include Widgets.js and Widgets.css
  • Desktop-style layouts -- VBox, HBox, GridBox, Splitter, TabWidget, ScrollArea
  • MDI workspace -- multiple draggable, resizable sub-windows with cascade/tile
  • Remote interface -- drive the UI over WebSocket from Python or any language
  • Familiar API -- callbacks, containers, and widget hierarchy inspired by Qt/GTK

Widgets

Layout & Containers

| Widget | Description | |--------|-------------| | TopLevel | Top-level window with optional title bar, dragging, and resize grips | | VBox / HBox | Vertical and horizontal box layouts with spacing and stretch factors | | GridBox | Grid layout with row/column placement | | Splitter | Resizable split pane (horizontal or vertical) | | TabWidget | Tabbed container with switchable pages | | StackWidget | Stacked pages without tab headers | | ScrollArea | Scrollable viewport with custom scrollbars | | Frame | Titled border container | | Expander | Collapsible section with a clickable header | | MDIWidget | Multiple Document Interface workspace with sub-windows | | ButtonBox | Box layout for buttons with uniform sizing and alignment | | AbstractScrollArea | Low-level scrollable viewport with custom scrollbars |

Controls

| Widget | Description | |--------|-------------| | Button | Push button with optional icon | | ToggleButton | Two-state button, supports exclusive groups | | CheckBox | Checkbox with label | | RadioButton | Radio button with exclusive group support | | ComboBox | Dropdown with optional editable text, filtering, and scroll limit | | Slider | Range slider (integer or float) | | SpinBox | Numeric input with increment/decrement buttons | | Dial | Rotary knob control | | ScrollBar | Standalone scrollbar with draggable thumb | | ProgressBar | Determinate progress indicator | | StatusBar | Horizontal status bar with message sections |

Text & Display

| Widget | Description | |--------|-------------| | Label | Static text with alignment, color, and font options | | TextEntry | Single-line text input with line history | | TextEntrySet | Text entry with a submit button | | TextArea | Multi-line text editor | | Image | Image display widget | | Canvas | HTML5 canvas for custom drawing | | TreeView | Hierarchical tree/table with columns, sorting, icons, and multi-selection | | HtmlView | Rich HTML content display | | TableView | Flat table with columns, sorting, and multi-selection | | VideoWidget | Video playback with controls | | ExternalWidget | Embed third-party content (Plotly, Bokeh, etc.) in layout containers |

Menus & Toolbars

| Widget | Description | |--------|-------------| | MenuBar | Horizontal menu bar | | Menu | Dropdown menu with actions | | ToolBar | Toolbar with buttons, toggles, and separators | | ToolBarAction | Individual toolbar button/toggle with icon support |

Dialogs

| Widget | Description | |--------|-------------| | Dialog | Modal or non-modal dialog with configurable buttons | | ColorDialog | Color picker with SV plane, hue strip, and RGB/HSV/hex inputs | | FileDialog | Browser file open/save dialog |

Non-Visual

| Widget | Description | |--------|-------------| | Timer | Non-visual timer for delayed and periodic actions |

Documentation

Full documentation is available at pgwidgets-js.readthedocs.io.

Installation

Standalone (no tooling)

Copy the repository and include it directly:

<link rel="stylesheet" href="path/to/Widgets.css" />
<script type="module">
  import { Widgets } from "path/to/Widgets.js";
  // ...
</script>

npm

npm install pgwidgets          # once published
# or install directly from GitHub:
npm install github:naojsoft/pgwidgets-js

Then in your bundled app:

import { Widgets } from "pgwidgets";
import "pgwidgets/Widgets.css";

Using from Python (Pyodide / PyScript)

pgwidgets can be used directly from Python in the browser via Pyodide or PyScript. The pgwidgets_js.pyodide module provides Pythonic wrappers with normal construction syntax, automatic type conversion, and callback management.

from pgwidgets_js.pyodide import Widgets

top = Widgets.TopLevel(title="Hello", resizable=True)
top.resize(400, 300)

vbox = Widgets.VBox(spacing=8, padding=10)

label = Widgets.Label("Click the button!")
button = Widgets.Button("Click me")
button.on("activated", lambda: label.set_text("Clicked!"))

vbox.add_widget(button, 0)
vbox.add_widget(label, 1)
top.set_widget(vbox)
top.show()

No WebSocket server needed -- everything runs in the browser. The same Python code works with both Pyodide and PyScript; only the HTML loader differs. See examples/pyodide_demo.html for a minimal Pyodide example, examples/all_widgets_pyodide.html for a full demo via Pyodide, and examples/all_widgets_pyscript.html for the same demo via PyScript.

Remote Interface (WebSocket)

pgwidgets can also be controlled from a Python server over WebSocket using the pgwidgets-python package. The browser page connects to the server, which sends JSON messages to create widgets, call methods, and receive callbacks.

from pgwidgets.sync import Application

app = Application()

@app.on_connect
def setup(session):
    W = session.get_widgets()

    top = W.TopLevel(title="Remote App", resizable=True)
    top.resize(400, 300)

    vbox = W.VBox(spacing=8)
    btn = W.Button("Click me")
    status = W.Label("Ready")

    btn.on("activated", lambda: status.set_text("Clicked!"))

    vbox.add_widget(btn, 0)
    vbox.add_widget(status, 1)
    top.set_widget(vbox)
    top.show()

app.run()

Sessions persist independently of browser connections. Refresh the page and the UI is automatically reconstructed. Open the same session URL in multiple browser tabs and they stay synchronized in real time -- slider moves, tab switches, tree expand/collapse, and more are pushed to all connected browsers.

See examples/remote_demo.py and examples/remote_demo_async.py for complete working examples.

Building Desktop Apps with Electron

Because pgwidgets is just a browser library with no dependencies, it runs unchanged inside an Electron renderer process. This lets you ship pgwidgets UIs as native desktop apps with their own window chrome, system menus, and access to the file system.

A minimal example lives in examples/electron/:

cd examples/electron
npm install     # one-time, installs Electron locally
npm start       # launches the all_widgets demo in an Electron window

The Electron entry point (main.js) is about 20 lines and simply creates a BrowserWindow that loads an HTML file -- no Electron-specific changes are needed in pgwidgets itself. To use your own UI, edit main.js to point at a different HTML file.

Embedding Third-Party Libraries

The ExternalWidget class lets you embed content from third-party JavaScript libraries -- Plotly charts, Bokeh plots, Leaflet maps, D3 visualizations, and more -- into pgwidgets layout containers. The widget participates in pgwidgets layout (stretch factors, splitters, tabs) while its content area is managed by the external library.

let chart = new Widgets.ExternalWidget();
vbox.add_widget(chart, 1);  // stretch=1 fills available space

Plotly.newPlot(chart.get_content_element(), data, layout,
               {responsive: true});

See the documentation for full examples with Plotly, Bokeh, and other libraries.

Running the Examples

Start a local web server from the repository root:

python -m http.server --bind localhost 8000

Then open any example in your browser:

And many more in the examples/ directory.

License

BSD 3-Clause