Changelog
Source:NEWS.md
blockr.core 0.1.3
Board options contributed by blocks or the registry (e.g. the preview-row count) are no longer reset to their defaults on save and reload. The settings sidebar manages the wider
blockr_app_options()set, but a board carried only its ownboard_options(), and that narrow set is whatserialize_board()persisted — so a user’s change to a block-backed option was dropped.resolve_board()now augments the board it returns with the managed option set, so the UI, the server and serialization all operate on the same options (#238).The board to build for an incoming request is now resolved by an app-level board loader, passed to
serve()as its newloaderargument (default:local_loader(), an in-process save/restore handoff). Aboard_loader()pairs aresolve(query, session)— returning the board to build, orNULLfor theserve()default — with astage(board, session), which persists a board and returns the URL query parameters referencing it.serve()uses that one loader to resolve the board at the UI (GET, wheresessionisNULL) and server (WS connect) builds; when a restore fires,board_server()exposes the board to restore as aboard_refreshreactive, andserve()stages it through the loader, writes the parameters into the URL and drivessession$reload()— so the reload stays a guaranteed core mechanism and thepreserve_boardplugin (unchanged at{server, ui}) neither holds the loader nor reloads. This removes the process-global slot core used to stage a board across a reload: the exportedget_serve_obj(), the old board-server reload producer,rv$reload_metaand therestore_board()metaargument are gone. The default loader keeps its handoff in a per-loader store (single-process); a downstream loader (e.g. blockr.session) resolves from the URL query against a shared backend, which is multi-process-safe (#214).New exported
trim_rv()removes entries from areactiveValuesobject, which assigningNULLdoes not do – the key lingers innames()with aNULLvalue. Unlinking a variadic block argument now drops it from the block’s...argsoutright rather than leaving a phantomNULLentry behind (#227).Boards can be deployed read-only via the
blockr.lockedoption, enforced server-side rather than by UI hiding (which a forgedShiny.setInputValuebypasses). While locked, the two channels every mutation funnels through – theboard_updatelifecycle andset_board_option_value()– refuse to apply changes.is_board_locked()is an S3 generic (the default method reads the option; a subclass can source the state differently, e.g. an authenticated unlock).set_board_option_value()gains a requiredboardargument so the option channel can resolve the lock. Locking is not a defense against arbitrary R executing in the session – which can flip the flag or edit the board directly – so untrusted deployments must be isolated at the deployment layer (#229).The default
notify_user()plugin now tracks each block’s conditions individually rather than re-deriving the whole board’s condition frame on every change. A single block’s condition change updates only the notifications it affects, restoring O(block)-per-change work and an O(N) rather than O(N^2) cost when a condition cascade touches many blocks on a large board.board$conditions()is unchanged for programmatic consumers (#222).notify()gainsglueandlogarguments (bothTRUEby default, so existing behaviour is unchanged).glue = FALSEsurfaces literal text without [cli::pluralize()] interpolation — so caught condition messages containing brace characters no longer error — andlog = FALSEskips the log entry for already-logged text. The board update, link and stack error toasts now pass condition messages through withglue = FALSE, and the defaultnotify_user()plugin renders throughnotify()(#222).Active block conditions (errors, warnings and messages captured during evaluation) are now emitted as tidy data frames. Each block server returns its conditions as a reactive
server$conditions(one row per active condition, columnsblock,phase,severity,messageandid), andboard_server()combines these into a board-level reactiveboard$conditions()on the read-only board handed to plugins and callbacks. A consumer reads one reactive — a single block’s frame for fine-grained updates, or the whole board — instead of walking the nested per-block condition state, and the defaultnotify_user()plugin surfaces them to the user as toasts. The block server no longer returns its rawcondreactive values object — readserver$conditions()instead (#217).str_value()now covers every domain class that has a full-tierformat()/print()counterpart, completing the compact rendering tier: the scalarslink,board_option,llm_model_optionandplugin; the containersblocks,stacks,links,board_optionsandplugins; and the wholeboard. Each class also gains autils::str()method that thinly displays itsstr_value(); a container or board renders one element per line below a<class[n]>header (#212).New exported generic
external_ctrl_vars()(with ablockmethod) and predicatehas_external_ctrl()provide a public, polymorphic API for resolving a board component’sexternal_ctrldeclaration into the set of externally controllable variable names. This promotes the previously internalblock_external_ctrl_vars(), letting dependent packages dispatch on it (e.g. for dock extensions) instead of re-reading the rawexternal_ctrlattribute (#192).blockr_deser.list()now forwards...to the dispatched per-class method, so callers can thread additional context (e.g. a producer version) down to nested deserializers. Previously such arguments were silently dropped at the list-dispatch boundary (#186).
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.