Conversation
Renders anywidget instances natively via ReactiveESM, extracting ESM/CSS and mapping traitlets to param Parameters with bidirectional sync. Uses duck-typing detection (priority 0.8 > IPyWidget 0.6) and eager component creation for immediate param.watch/pn.bind/.rx support. Includes 20 unit tests, 12 example scripts, upstream issue drafts for drawdata/wigglystuff/anymap-ts, and GitHub issue + PR descriptions. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8428 +/- ##
===========================================
- Coverage 86.11% 70.87% -15.24%
===========================================
Files 349 350 +1
Lines 54841 55897 +1056
===========================================
- Hits 47227 39618 -7609
- Misses 7614 16279 +8665 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add 14 new example scripts for the most popular anywidgets from the community gallery: altair, rerun, mosaic, lonboard, jupyter-scatter, quak, jupyter-tldraw, pyobsplot, vizarr, ipyaladin, higlass, pygv, vitessce, and cev. Includes workable bidirectional sync demos for widgets with small ESM bundles and documentation-only examples for widgets with known limitations (large bundles, binary serialization). Also adds iteration_plan.md detailing the 4 remaining iterations: edge cases & hardening, third-party smoke tests, gallery examples, and documentation. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Reorder Instance check after TRAITLET_MAP walk (fixes Set/List/Tuple/Dict) - Add Enum→Selector, Instance→ClassSelector, Set→List, Union→Parameter mappings - Convert set defaults to list for param.List compatibility - Add _resolve_text() helper for ESM/CSS from Path, FileContents, str - Bounded OrderedDict cache with LRU eviction (max 256) - BkSpacer for None objects, tightened applies() duck-typing - Specific TraitError catch + logging for unexpected sync errors - 39 tests (20 existing + 19 new) all passing Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Allow underscore-prefixed sync traits (fixes Altair reembed TypeError) _vl_selections and _params were filtered out; now only _FRAMEWORK_TRAITS excluded - Rename third-party examples with ext_ prefix for easy identification - Remove try/except ImportError wrappers (Panel handles import errors natively) - Add all third-party anywidget deps to pixi.toml anywidget-examples feature - Fix ipymario sizing (min_height=200) - Add test for underscore-prefixed sync traits (40 tests total) Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Fix cache comment: eviction is LRU (move_to_end on hit), not FIFO - Update pr.md with current stats (40 tests, ~495 lines, type mapping table) - Update issue.md with current stats (26 examples, reference notebook) - Update todo.md to mark completed iterations Co-Authored-By: Claude Opus 4.6 <[email protected]>
## Issue 1: Mosaic view.model.send is not a function Mosaic's ESM code expects to access the model adapter via view.model, but it was only passed as a prop. Now we expose the adapter on the view object while keeping the Bokeh model accessible internally. Changes in anywidget_component.ts _render_code(): - Store original Bokeh model before render - Expose adapter as view.model for widgets using anywidget protocol - Restore Bokeh model after render via finally() block ## Issue 2: Quak SyntaxError: Unexpected token ',' Quak's bundled ESM module failed to parse through es-module-shims. Now we use native import() first for bundled URLs, avoiding the shims parser which rejects certain modern JS syntax patterns. Changes in reactive_esm.ts recompile(): - Try native import(url) for bundled URLs - Fall back to importShim only if native import fails - Skips es-module-shims parsing for pre-bundled code Both fixes maintain backward compatibility and enable proper rendering of DuckDB-based widgets (Mosaic, Quak). Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
I will leave this for now. I will wait for your feedback @philippjfr :
Please explore by running pixi run -e anywidget panel serve research/anywidget/examples/*.pyTry the altair and ipyaladin examples. They work for me. Please fix a few issues and report back 😄 |
|
Looks very promising, but it's a big PR and I've got a long two weeks coming up so can't promise quick review. |
|
A deep review is not needed. But an ok that this is moving in right direction would be helpful. Note most files are just temporary research files in research folder. They would not go into final PR. |
|
I've further enhanced this PR - many more anywidgets now working including lonboard which needed a widget manager and anywidgets that needed array buffer support. I've simplified this PR by moving tests of dependent anywidgets to https://github.com/panel-extensions/panel-anywidget-gallery. I've updated the initial post above to the current status. There is still a lot to do:
|
panel-anywidget-poc.mp4
Add native AnyWidget pane
Summary
Adds a new
pn.pane.AnyWidgetthat renders anyanywidget.AnyWidgetsubclass nativelythrough Panel's ReactiveESM pipeline, bypassing
ipywidgets_bokehentirely. This givesPanel users access to the entire AnyWidget ecosystem (75+ widgets) with full Param
reactivity (
param.watch,pn.bind,.rx).How it works
_esm+ traitlets) at priority 0.8, above IPyWidget's 0.6param.Parameterwithbidirectional sync and re-entrancy guards
_esm/_cssare serialized and rendered through adynamically-generated
AnyWidgetComponent(ReactiveESM subclass)width,height,name, etc.) get aw_prefix; the JS adapter transparently maps them backa
_pnl_bytesmarker for recursive encoding/decodingmodel.get/set/on/off/send/save_changesAPI,including
experimental.invoke()RPC and generic"change"eventsKey features
pane.componentcreation enables reactive programming before first renderpane.trait_name_mapproperty for discovering renamed traitsmsg:customqueuing for handlers registered duringinitialize()before view exists_collect_child_widgetsand_serialize_child_stateFiles changed
New files
panel/pane/anywidget.pypanel/tests/pane/test_anywidget.pypanel/tests/ui/anywidget/examples/reference/panes/AnyWidget.ipynbModified files
panel/models/anywidget_component.tspanel/pane/__init__.pyAnyWidgetpanel/custom.py__css_raw__for inline CSS injectionpanel/io/datamodel.py_pnl_bytesnested encodingpanel/io/document.pypanel/models/reactive_esm.ts_render_codehook for AnyWidget adapterpanel/tests/pane/test_base.pyAnyWidgettoSKIP_PANESpixi.tomlanywidgetdependency toanywidget-examplesfeatureTest plan
Compatibility with third-party widgets
Extensive testing against 48 real-world anywidget packages is maintained in a separate
repository: panel-anywidget-gallery.
The gallery contains:
cosmograph, d2widget, graphviz, ipyaladin, ipyclipboard, ipymafs, ipymolstar, ipyscore,
itables, mapwidget, modraw, mopaint, mosaic, moutils, navio, periodictable, pglite,
pyobsplot, tesseract, vitessce, weaswidget, wigglystuff
pynodewidget, quak, tldraw, vizarr, xarray_repr
jbar, jupyter_scatter, lonboard, rerun, soupernova
This separation keeps the Panel PR focused on the core implementation while the gallery
serves as a comprehensive compatibility test suite with Playwright tests, screenshots,
and upstream issue documentation for each widget.
When to use
AnyWidgetvsIPyWidgetanywidget.AnyWidgetsubclasspn.pane.AnyWidgetIPY_MODEL_child refs (lonboard, higlass)pn.pane.IPyWidget+pn.extension("ipywidgets")ipywidgets.DOMWidget/VBox/HBoxpn.pane.IPyWidget+pn.extension("ipywidgets")Known limitations
IPY_MODEL_refs)pn.pane.IPyWidgetpn.serve(transforms=[SecurityHeadersTransform])render()width/heighton pane