@jupyter-kit/widgets
Renders application/vnd.jupyter.widget-view+json outputs via
@jupyter-widgets/html-manager. Works in two modes:
- Static (no executor) — hydrates
metadata.widgets["application/vnd.jupyter.widget-state+json"]from the notebook. Shows saved values, non-interactive. - Live (paired with
executor-pyodide) — sliders drive Python callbacks, outputs re-render.
WidgetsPluginOptions
| Option | Type | Notes |
|---|---|---|
loader | (moduleName: string, moduleVersion: string) => Promise<unknown> | Called when a widget references a module outside @jupyter-widgets/{base,controls,output}. Return the module exports containing view/model classes. |
Usage
Static
import { Notebook } from '@jupyter-kit/react';import { createWidgetsPlugin } from '@jupyter-kit/widgets';
<Notebook plugins={[createWidgetsPlugin()]} ipynb={nb} />;Live (Pyodide)
import { createPyodideExecutor } from '@jupyter-kit/executor-pyodide';import { createWidgetsPlugin } from '@jupyter-kit/widgets';
<Notebook executor={createPyodideExecutor({ packages: ['ipywidgets'] })} plugins={[createWidgetsPlugin()]} ipynb={nb}/>;The executor’s commProvider is auto-detected — no extra wiring.
Bundler config (Vite, Rollup, webpack)
@jupyter-widgets/* ship as ESM that still calls require() at runtime
in a few spots — a webpack-era hybrid pattern. This is upstream
behaviour, not something @jupyter-kit can normalize from this side —
the require() calls live inside the published @jupyter-widgets builds.
Modern bundlers don’t inject a CJS shim for ESM by default, so without
the right config you’ll see one of these in the browser console:
Uncaught ReferenceError: require is not definedUncaught ReferenceError: __webpack_public_path__ is not definedVite (and Astro)
// vite.config.ts (or `vite:` block in astro.config)export default defineConfig({ build: { commonjsOptions: { // Rewrites `require()` calls inside ESM-flagged files into static // imports at build time. Required for @jupyter-widgets/*. transformMixedEsModules: true, }, }, define: { // The widget bundle references `__webpack_public_path__` for chunk // URLs. Vite has no such global; replace with an empty string. __webpack_public_path__: '""', },});@jupyter-kit/[email protected]+ already sets
globalThis.__webpack_public_path__ = '' at module init as a runtime
shim, so the define is belt-and-suspenders for older versions or
unusual bundle splits.
webpack
webpack handles both natively — no extra config required. Just install
@jupyter-kit/widgets and use the <Notebook> component.
Rollup (without Vite)
@rollup/plugin-commonjs with transformMixedEsModules: true. Pair with
@rollup/plugin-replace for __webpack_public_path__: '""'.
Bundle cost
The plugin pulls in a fairly large dependency graph:
| Package | Minified | Notes |
|---|---|---|
@jupyter-widgets/{base,base-manager,controls,html-manager,output} | ~600 KB – 1 MB | The widget runtime itself |
jquery | ~85 KB | Peer of @jupyter-widgets/controls slider widgets |
jquery-ui | ~250 KB | Transitive — provides $.ui.{mouse,slider,draggable,...} |
Total: ~1.0 – 1.4 MB minified. Everything is dynamic-imported the
first time the plugin’s setup() runs, so the initial render path stays
light — notebooks without widgets don’t pay any of this cost. The
plugin is a separate package on purpose for the same reason.
Limitations
- Requires
@jupyter-kit/executor-pyodide(or any other executor that implementscommProvider) for interactivity. - The ipywidgets
Outputwidget’s automatic matplotlib capture relies on IPython’s display hooks. We monkey-patchinteractive.updateto approximate it, so@interact(...)style demos refresh their plot on every slider change. More exoticOutputuse-cases (multi-widget display,clear_output(wait=True)interleaving) may not match classic-Jupyter behaviour. widget-viewoutputs referencing a model-id that was never registered (e.g. notebook cached outputs where the original kernel state wasn’t saved) render as a muted[widget — run the cell to render]placeholder.