Changelog
Source:NEWS.md
blockr.core 0.1.4
-
apply_board_update()is now a real reducer rather than a no-op: its default.boardmethod applies the core delta (block, link and stack mutations) to the supplied board and returns it, and update validation now checks that applying the delta yields a valid board instead of re-deriving the merged references. Extensions overridingapply_board_update()must compose withNextMethod()to pick up the core apply before layering their own payload slots (as blockr.dock does for views). Breaking for front-ends that override the apply generic (#311). - Block result previews now dispatch through a tabular display: an S3 object bundling the output container, render function, render trigger and board options for a single result class, kept in sync by living on one object. The active display is read from the
blockr.tabular_displayoption (viablockr_option()) and defaults tominimal_display, a compact preview of the topn_rowsrows (tibble-formatted when the suggested tibble package is installed) that reflows to the width of its panel. Setoptions(blockr.tabular_display = dt_display)to restore the previous paginated, searchable DT table. Data, parser and transform blocks render through whichever display is active; downstream packages add their own by definingtabular_ui(),tabular_output(),tabular_trigger()andtabular_options()methods on atabular_displaysub-class and having users opt in via the option. Breaking for front-ends that relied on the DT preview by default (#129). -
DTmoves from Imports to Suggests. It now backs only the opt-indt_displaypreview and themanage_links/manage_stacksreference plugins – which typical front-ends (e.g. blockr.dock) replace with their own UI – so a bare core install no longer pulls it in. InstallDTalongside if you use either (#129). - The default board plugin set (
board_plugins()) no longer includes themanage_linksandmanage_stackseditor plugins, which render their tables throughDT. Including them by default made a bare core board fail withthere is no package called 'DT'onceDTbecame a Suggest, breaking consumer test apps built on the default board. Add them back withc(board_plugins(x), manage_links(), manage_stacks())to restore interactive link and stack editing; both constructors now raise a clear error whenDTis missing. Breaking for front-ends that relied on the core editors in the default board (#297). - A board’s
blockr_app_ui()andblockr_app_server()methods now receive the request’s parsed URL query parameters as aqueryargument, at both the GET and the websocket phase. A board subclass reads it to make the rendered UI and the server URL-aware from one source – for example opening on the view named by?view=– so the initial render and the server agree without a custom loader. The defaultboardmethods ignore it. Breaking for front-ends: ablockr_app_ui()/blockr_app_server()method that forwards its...into the returned UI must add aqueryformal, or the threaded argument lands in...and renders as stray content (#291). - Cleanup of a removed block, stack or view now uses shiny’s public
session$destroy(id)(requires shiny >= 1.14.0) rather than reaching into undocumented shiny internals to tear down a module’s inputs, outputs and observers. The exporteddestroy_module()and theobserve()trace hook that captured per-module observers are removed; callsession$destroy(id)directly instead. Breaking (#202). - The board callback now gates block construction, evaluation and rendering through per-block
reactiveValchannels it receives asvisibility–required(which blocks are needed) andvisible(which are on screen) – in place of the singlevisiblewrite-channel. Breaking for front-ends. - The
visiblechannel is now logical, mirroringrequired: a front-end writesTRUEonce a block is painted,FALSEonce it is built but off screen, and leavesNAuntil it is first built (it previously carried the rendered view id, orNA_character_off screen). The extra state lets a front-end distinguish “never built” from “built, off screen” on this one channel, so it no longer has to reset the slot to unbuilt when a card leaves the screen – which would erase the “was built” fact the render gate needs.is_visible()is accordinglyisTRUE()rather than!is.na(). Breaking for front-ends that wrote a view id (#306). - The
visibilitybundle carries a third channel,frozen, letting a front-end freeze a block’s inputs server-side: settingvisibility$frozen[[id]](TRUE)– for example for a locked board that shows outputs but hides controls – holds the block’s expression, state readiness and serialized state at their last editable values and drops the input trigger, so a forgedShiny.setInputValue(which still fires the block’s own observer) reaches neither the expression, the block’s status, a re-evaluation, nor a saved board. Externally controllable inputs are held too – a high-priority observer reverts any write while frozen – so a frozen block is fully read-only. Upstream-data-driven re-evaluation still runs, and unfreezing resumes normal input handling (#231). -
background_construction_delaynow acceptsInf, skipping the background construction pass so a block is built only once it becomes required. Code export (“Show code”) then marks every block required, so the exported script covers the whole board; an off-screen block that is not fully configured holds the export back instead of emitting broken code (#269). - Code export gates on the set of blocks that actually carry an expression, not on eval status alone, so a board with unbuilt blocks can no longer emit a script that assigns to a variable named
NA. “Show code” always opens the modal, which reports “Preparing code…” while the board materializes and a not-ready note when a block is left unconfigured, rather than silently producing nothing (#300). -
blockr_ser()accepts a partial block-state snapshot: a board block omitted fromblocks(or mapped toNULL) serializes from its constructor scope instead of aborting withlength(blocks) == length(x). Saving a board under deferred construction, where off-screen blocks are never built and carry no live state, no longer fails – unbuilt blocks round-trip from their constructors rather than being dropped (#279). - With a finite
background_construction_delay, the staggered builder now prioritizes the on-screen view: each tick builds the next block needed by the visible set before the rest of the backlog, so switching view re-prioritizes construction toward what is now on screen and the newly-visible blocks come up progressively instead of in one blocking build (#275). - The staggered builder no longer monopolizes the event loop while it runs. Each tick’s pacing delay now begins once the just-built block has flushed rather than while its reactive graph is still flushing, so pending user input is serviced within one tick instead of behind the entire backlog (#276).
- With a finite
background_construction_delay(the default), a downstream block’s data input no longer latches atNULLwhen its input reactive runs before the upstream is built. The input read the upstream server underisolate()and never re-resolved once that server registered a moment later; it now re-fires when the upstream is constructed, so the block picks up its data instead of starving for the rest of the session (#298). - Captured block conditions are no longer glue-interpolated when logged, so a block whose warning or error text contains braces – e.g. the
{summary_fun}/{data}placeholders intidyr::pivot_wider()’s duplicate-value warning – no longer aborts the reactive with “Failed to evaluate glue component”. This extends thenotify()toast path’suse_glue = FALSEtreatment to thecapture_conditions()handlers and thereplay()methods (#268). - Switching the active panel or view no longer re-evaluates blocks whose needed status is unchanged. Each block gates its data inputs and eval status on its own per-block
neededslot rather than the whole needed set, and skips re-evaluation when its interpolated expression and input data are unchanged, so switching panel or view re-evaluates only the newly-visible block, not the entire shared upstream pipeline (#271). - Board deserialization can degrade gracefully instead of aborting the whole load when a block cannot be restored – its constructor or the providing package is unavailable, its payload cannot be reconstructed, or the round-trip class check fails.
blockr_deser()forblocksgains anon_errorargument ("abort"or"drop"), defaulting toblockr_option("deser_on_error", "abort")so a deployment can opt into dropping offending blocks (with a warning) viaoptions(blockr.deser_on_error = "drop")or theBLOCKR_DESER_ON_ERRORenvironment variable. Links and stacks referencing a dropped block are pruned so the surrounding board still loads (#264). - A
links$modboard update that changes a link to a different value (for example switching amerge_block’s input fromxtoy) now applies instead of being silently discarded. Folding the modified link into theaddaccumulator with basec()dropped thelinksclass when the accumulator was empty, so the downstream link setup ran without itsto/inputarguments and aborted withmissing subscript, rolling back the whole update; it now concatenates withvec_c()(#287). - A
req()– or any silent flow-control throw with an empty message – evaluated while a block’s conditions are captured is no longer recorded as a block error, so a block that is merely not currently needed no longer flashes a text-less red error band (and a false error count) in deployed apps. Empty-message conditions are filtered by emptiness rather than class, so avalidate(need(x, "msg"))message still surfaces (#289). - The structured argument-spec API is renamed to a block-neutral stem, so a non-block consumer – an extension documenting its externally controllable variables – no longer reads as describing a block.
new_block_arg()/new_block_args()becomenew_arg_spec()/new_arg_specs()(classesarg_spec/arg_specs), and theblock_arg_description()/block_arg_example()/block_arg_type()getters becomearg_spec_description()/arg_spec_example()/arg_spec_type(). Thearg_*()type constructors,register_block()’sargumentsargument and theblock_meta_arguments()accessor keep their names, being genuinely about a block’s arguments. The old names remain as deprecated wrappers that warn once and forward to the new ones, so existingregister_block(arguments = new_block_args(...))call sites keep working; migrate them to thearg_specfamily (#295). - A block constructed for a class with no registry entry is now imputed a class-derived default metadata record at construction (name from the class, default category and icon) instead of being left without one. It still warns, but the block is then self-describing:
block_metadata()and theblock_meta_*()accessors report those defaults rather than a metadata read aborting – so a cosmetic lookup can no longer take down a board whose registry has been curated (#299).
blockr.core 0.1.3
CRAN release: 2026-07-12
- Block-server construction is now ordered by visibility – on-screen blocks and their upstream closure build first, the rest in the background (option
background_construction_delay, default 50 ms; 0 opts out). - Blocks now carry an eval status (
dormant,waiting,unset,failed,ready) that gates evaluation, rendering and downstream data, so a block never evaluates against missing inputs or shows a stale result. - Code export (
generate_code()) now waits until every block is settled, showing a “board not ready” note instead of a partial script. - Block conditions (errors, warnings, messages) are exposed as tidy data frames via
server$conditionsandboard$conditions(); the block server no longer returns its rawcondobject. - The
notify()helper gainsglueandlogarguments for literal (brace-safe) text and skipping redundant logging. - The
allow_empty_stateargument ofnew_block()now accepts a structuredlist(input = ..., data = ...)form to relax required inputs and the variadic minimum per input kind. - Boards for incoming requests are now resolved by an app-level
loaderargument toserve()(defaultlocal_loader()); this drops the process-global staging slot, soget_serve_obj()andrestore_board()’smetaargument are gone. - Block- and registry-contributed board options (e.g. the table preview
page_size,n_rows,filter_rows) are now saved and restored, not reset to defaults on reload. - Boards can be deployed read-only via the server-enforced
blockr.lockedoption, which refuses every mutation while set. - Block registration metadata can now be declared with roxygen2 tags (
@block,@blockArg, …), collected by the newblock_registration_roclet(); extension packages register via the exportedregister_package_blocks(). - Block registry entries gain a structured argument spec (
new_block_args(),new_block_arg()) with JSON-Schema-subsettypedescriptors (arg_string(),arg_enum(), …), read viablock_metadata();registry_metadata()is deprecated. - The manage-links and manage-stacks plugins no longer flicker cell inputs, clobber staged edits, or needlessly re-render on a board re-emit.
- Board accessors (
board_blocks(),board_links(),board_stacks()) are now pure reads, removing quadratic re-validation that dominated large-board startup. - New exported generic
external_ctrl_vars()and predicatehas_external_ctrl()expose a component’s externally controllable variables. - New exported
trim_rv()fully removes entries from areactiveValuesobject (assigningNULLleaves the key behind); unlinking a variadic argument now drops it outright. - The
str_value()compact printer, with matchingutils::str()methods, now covers all remaining domain classes and containers. - The
blockr_deser.list()method now forwards...to per-class deserializers, letting callers thread context to nested deserializers.
blockr.core 0.1.2
CRAN release: 2026-04-28
- The
modslots inupdate(...)payloads for blocks, links and stacks now uniformly expect a delta shape: a named list keyed by entry ID, where each entry is a named list of argument values to apply on top of the live entry.- For
blocks, keys must be inblock_external_ctrl_vars(blk)— non-ctrl-able changes go throughrm+add. Ctrl-arg writes hit the correspondingreactiveValin place;block_name(always treated as ctrl-able) updates the block’s registry attribute. - For
linksandstacks, deltas are merged onto the current entry via the newupdate_link()/update_stack()S3 generics. The default methods reconstruct the entry through its stored constructor, preserving sub-class attributes. Sub-class owners (e.g.dock_stackaddingcolor) only need to register a method when their constructor deviates from the convention (#175).
- For
-
block_external_ctrl_vars()always includes"block_name"— every block can be renamed throughupdate(...)regardless of itsexternal_ctrlopt-in. The default ctrl plugin panel renders ablock_namefield on every block card alongside any opted-in ctrl vars.block_supports_external_ctrl()(which would now beTRUEfor every block) has been removed; the gates that used to call it have been simplified accordingly. - The default
block_server.blocknow constructs ablock_namereactiveValper block and appends it to thevarslist passed to the ctrl plugin. Two guarded observers keep thatreactiveValin sync with the block’sblock_nameattribute on the board (one emits anupdate(mod = ...)when the ctrl plugin writes the rv; the other pulls registry-attr changes back into the rv). Thectrl_block_serverplugin signature is unchanged — block authors and custom ctrl plugins see uniformvarsreactiveVals. - A blockr option
attach_default_packagescan be set to opt into evaluating block expressions with objects from default packages directly available. - Add
ctrl_block()plugin for external block control, allowing blocks to be driven programmatically from outside the standard block UI. - Add
clear_board()for removing all blocks/stacks from a board. - Add
bbquote()and helpers (.,..) for cleaner code generation viabquote()-based quasiquotation. - Export
custom_plugins()andcustom_options()for easier board customization. - Add
block_metadata()for retrieving per-block metadata and attach block metadata with defaults to block objects. - Export test utilities (
blockr_test_exports(),new_mock_session(),export_safely()) for use in downstream package tests.
blockr.core 0.1.1
CRAN release: 2025-12-06
- Add Block-level notifications via (optional)
exprserver return value componentcond. - Export
get_board_option_value()to make available current option settings viasession$UserData. - Introduce (optional) dependency on thematic to auto-style plots.
- Export
toolbar_ui()which takes case of the “core” toolbar UI component. - Utility functions
chr_ply()and related, as well as miscellaneous utilities such asset_names(),coal(), etc. are now exported for use in dependent packages. - Export
export_code()to make it easier for third-partygenerate_code()plugin implementations. - Use
evaluate::evaluate()to capture plots. - Add
new_fixed_block()for applying a fixed (i.e. non-paramtetrized) transformation to data input. - Board server callbacks are invoked with an additional argument
session. - Export assertion utilities such as
is_string(),is_count(), etc. - Improved ser/des, which now includes package/constructor information for all board, blocks, stacks and options. The corresponding infra
- Board options now contain UI/server components to provide more options for customization. Also blocks can require certain options to be available.
- Introduces
block_render_trigger()to control per block class when to re-render the block output. - Rework of block notifications to provide a
reactiveValues()object containing notification types a separate components. - Auto-ID generation can now be customized with a default provided by the ids package (if available).
- Use the glue package for logging/block notifications; add a glue-based text block.
- New board restore mechanism based on
session$reload(). - Improvements to the registry: block icons and a fixed set of categories.