Changes in version 0.3.0 (2026-08-02)
Breaking changes
- Event and binding dispatch config now rides the slot it configures
via a single carrier, wire(subject, timing, coalesce, dom_opts). The
element-level .event and .prevent_default props are removed, along
with event_immediate() / event_throttle() / event_debounce() —
replaced by the pure timing shapes wire_immediate() /
wire_throttle(ms, leading) / wire_debounce(ms) (with coalesce
hoisted onto wire) and wire_dom_opts(prevent_default,
stop_propagation, capture, passive). A bare handler/reactive in a
slot still works as sugar for wire(callable).
- A DOM event is now bound or handled, never both. Combining a
value/checked binding with an explicit on* handler for the same
event (e.g. value = rv, onInput = ...) is an error; use value =
reactiveProxy(get, set) for a synchronous write side-effect, or
observe the bound reactive for an async reaction. Two explicit
handlers on the same event also error (no composition).
New features
- iridExample() — run a shipped example app (mirroring
shiny::runExample(), source shown alongside via showcase mode by
default). Called with no argument it lists them; missing per-example
dependencies are reported up front.
- IridWidget() — wrap arbitrary JavaScript libraries (CodeMirror,
Plotly, Leaflet, ...) as reactive irid components. Props are
two-way-capable by default (symmetric with DOM value/checked): a
callable prop reads inbound and accepts write-back when the widget
JS calls setProp(key, value). Genuine notifications flow back via
events (sendEvent). Composes inside When, Each, and Match like any
other irid construct. See inst/examples/codemirror/app.R.
- PlotlyOutput() — a plotly component built on IridWidget(). UI state
(axis ranges, drag mode, selection, trace visibility) is exposed as
two-way reactive props; discrete interactions (clicks, hovers,
legend) are on* callbacks. Data changes diff via Plotly.react(),
preserving zoom, pan, and selection. See inst/examples/plotly/app.R.
- Per-item (Each) and per-case (Match) reactiveVals are now reclaimed
on unmount, rather than leaking until session end. make_scope
feature-detects shiny#4372's scoped-teardown API at runtime: on a
Shiny that carries it, scope$destroy() reclaims the per-item /
per-case observers and reactiveVals — plus any user observe() in a
component body. Pre-#4372 Shiny (including current CRAN) is
unchanged; no irid change is required at upgrade time.
Bug fixes
- Reactive bindings no longer flicker when user activity outpaces the
server's echo. The optimistic-update protocol's stale-echo skip used
to apply only to focused text inputs; it now covers all reactive
bindings.
Changes in version 0.2.0
Breaking changes
- Auto-bind: value and checked accept any callable (reactiveVal, store
leaf, reactiveProxy, plain function) and two-way bind automatically.
Reads populate the IDL property; DOM events write back through the
same callable. When auto-bind coexists with an explicit on* handler
on the same event, the auto-bind write always lands first regardless
of attribute order. Works on ,