irid 0.3.0
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.eventand.prevent_defaultprops are removed, along withevent_immediate()/event_throttle()/event_debounce()— replaced by the pure timing shapeswire_immediate()/wire_throttle(ms, leading)/wire_debounce(ms)(withcoalescehoisted ontowire) andwire_dom_opts(prevent_default, stop_propagation, capture, passive). A bare handler/reactive in a slot still works as sugar forwire(callable). - A DOM event is now bound or handled, never both. Combining a
value/checkedbinding with an expliciton*handler for the same event (e.g.value = rv, onInput = ...) is an error; usevalue = 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 (mirroringshiny::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 DOMvalue/checked): a callable prop reads inbound and accepts write-back when the widget JS callssetProp(key, value). Genuine notifications flow back viaevents(sendEvent). Composes insideWhen,Each, andMatchlike any other irid construct. Seeinst/examples/codemirror/app.R.PlotlyOutput()— a plotly component built onIridWidget(). UI state (axis ranges, drag mode, selection, trace visibility) is exposed as two-way reactive props; discrete interactions (clicks, hovers, legend) areon*callbacks. Data changes diff viaPlotly.react(), preserving zoom, pan, and selection. Seeinst/examples/plotly/app.R.Per-item (
Each) and per-case (Match)reactiveVals are now reclaimed on unmount, rather than leaking until session end.make_scopefeature-detects shiny#4372’s scoped-teardown API at runtime: on a Shiny that carries it,scope$destroy()reclaims the per-item / per-case observers andreactiveVals — plus any userobserve()in a component body. Pre-#4372 Shiny (including current CRAN) is unchanged; no irid change is required at upgrade time.
irid 0.2.0
Breaking changes
Auto-bind:
valueandcheckedaccept 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 expliciton*handler on the same event, the auto-bind write always lands first regardless of attribute order. Works on<input>,<textarea>,<select>forvalue; checkboxes and radios forchecked.-
event_immediate()/event_throttle()/event_debounce()no longer wrap a handler. They return a config used with the element-level.eventprop. Per-handler timing is gone:# OLD tags$input(value = field, onInput = event_debounce(\(e) field(e$value), ms = 500)) # NEW tags$input(value = field, .event = event_debounce(500)).eventtakes a single config or a named list keyed by lowercase DOM event for per-event overrides. prevent_defaultmoved off the event constructors onto the element as.prevent_default. Logical scalar broadcasts; named list overrides per event; unmapped events default toFALSE.Each()redesigned. The callback receives a per-item callable (mini- store for records, scalar accessor for atomics) and an optionalpos. Reconciliation moves toby:NULL(default) for positional,\(x) x$idfor keyed. In-place value changes update accessors without DOM recreation; keyed reorders move DOM nodes.Match()projects the bound value as a mini-store for the active case’s body (records) or the bare callable (scalars). Active-case change fully tears down the previous case and mounts the new one fresh.When()is a fixed-shape binary specialization ofMatch().yes/otherwisemust be 0-arg functions returning tag trees; each activation builds a fresh tree.Index()removed. Covered byEach(items, fn)with defaultby = NULL.
New features
-
reactiveProxy()— callable built from agetreader and optionalsetwriter for validation, transforms, and read-only views at component boundaries. -
reactiveStore()— hierarchical reactive state container. Bare named lists become navigable sub-nodes; everything else (includingI()-wrapped lists) is areactiveValleaf. Branch writes replace and must list every locked key;node$key(value)is the single-slot path. -
innerHTMLis now a DOM property, so reactive writes hit the IDL property directly.
irid 0.1.0
Initial release.
Features
- Reactive attributes and children — pass functions to any tag attribute or text child for fine-grained DOM updates without re-rendering
- Controlled inputs — bind
valuedirectly to areactiveValfor two-way binding withoutupdate*Input()callbacks - Composable components — plain functions that accept
reactiveVals for natural state sharing - Control flow primitives:
When(),Each(),Index(),Match() - Output bindings:
Output(),PlotOutput(),TableOutput(),DTOutput() - Event handling with
event_immediate(),event_throttle(),event_debounce() - Embed in existing Shiny apps via
iridOutput()/renderIrid(), or build standalone apps withiridApp() - Optimistic updates with sequence-number tracking
