Changelog
blockr.dag 0.1.5
CRAN release: 2026-07-30
Breaking changes
new_context_menu_entry()andnew_toolbar_item()no longer take asidebarargument. An entry that fills a sidebar panel no longer names it:blockr.dockstamps the writing action onto the panel as it writes (blockr.dock#391), and ownership is read back withblockr.dock::sidebar_owned_by()rather than tracked here.retarget = TRUEis now the whole declaration, and an entry that fills a panel without re-targeting declares nothing at all. Requires ablockr.dockcarryingsidebar_owned_by().The DAG extension no longer ingests or emits a full g6 graph object (#119).
new_dag_extension()drops thegraphargument in favour ofpositions, a named list keyed by block id (list(a = list(x = 100, y = 200))) carrying only the board-independent view attributes the extension owns. The board is now the single source of truth: nodes, edges, combos and all styling (icons, labels, colors, ports) are always regenerated from it, and supplied positions are overlaid onto the corresponding nodes’ coordinates. Serialization shrinks to positions only; no board-derived styling is persisted. The g6 graph wire format and its board/g6 converters (new_graph(),as_graph(),g6_from_graph(), …) are now internal and no longer exported. This mirrors the dockview wire-format decoupling inblockr.dock. Note: the auto-layout still computes final node placement at cold start, so supplied positions are not yet honored over it; making positions pin over the layout is a planned follow-up (see #141).
New features
The DAG node context menu offers an “Edit inputs” entry (#158). Right-clicking a node and choosing “Edit inputs” opens
blockr.dock’s per-block input editor, so a block’s incoming links can be renamed, reordered and removed together instead of one edge at a time – the per-node counterpart to “Edit link”. It fills the shared actions sidebar and re-targets like the other editors (#162): while pinned, clicking another node re-points it at that block’s inputs.Selecting an element re-points a pinned sidebar editor at it (#162). When a sidebar is pinned open on an editor, clicking another element of the kind that editor operates on re-targets it there, with no second trip through the context menu – the stack editor (Edit stack) follows combo clicks, and the node-anchored editors (Create link, Append block) follow node clicks. Each editor decides via its own context-menu condition, so a pinned editor is never taken over by a selection of a kind it does not handle. Re-targeting also stops as soon as anything else fills the panel: opening Create stack or the toolbar’s Add stack in a pinned sidebar releases it, so a later selection leaves the newly opened form alone.
The DAG edge context menu offers an “Edit link” entry (#154). Right-clicking an edge and choosing “Edit link” opens
blockr.dock’s link editor for that link, so renaming a positional input, switching its slot or redirecting an endpoint no longer means removing the edge and drawing it again. It fills the shared actions sidebar and re-targets like the other editors (#162): while pinned, clicking another edge re-points it at that link.The DAG canvas now reflects in-place link edits (#156). A board update whose only link change is a modification (
links$mod) – redirecting an endpoint, switching a finite input’s slot, or renaming a variadic input, as the “Edit link” action emits – redraws the affected edge from the updated board: it moves to its new source, target and port and relabels, rather than leaving the stale edge on screen until an unrelated redraw.The node status badge reflects a block’s full eval status, not just error conditions (#145). The badge is derived by
blockr.dock::block_status_badge()– the single derivation the dock card icon and the DAG node badge share – so a node shows the same amberwaiting, yellowunsetor redfaileddot as the dock, with identical colour and geometry. Any error condition still shows red (a render-phase error leaves a blockreadybut errored). Areadynode carries no badge; adormantnode – one whose status is not currently computed because nothing renders its output – keeps its last-known badge rather than dropping it, so every invalid block stays flagged even after it leaves the eval set.Pasted blocks keep their original names; the
" (copy)"suffix is gone from blocks. A pasted group is offset on the canvas and selected, so the label carried no extra information, and mass-renaming made copying larger app parts painful. Stacks keep the suffix (Cohort (copy)) as group-level provenance.Node positions are externally controllable (#120). The
positionshandle is registered viaexternal_ctrl, so positions can be set programmatically (e.g. by an AI assistant) through the board update lifecycle:update(list(extensions = list(mod = list(<ext_id> = list(positions = list(<block-id> = list(x = , y = )))))))moves the corresponding nodes. The handle is bidirectional: it tracks live user drags (debounced) and pushes external writes to the client, with a whole-pixel-rounded equality guard that prevents the set/echo feedback loop.
Internal changes
- The DAG now renders with G6’s default canvas renderer instead of the SVG renderer. The SVG element reports
offsetWidth == 0, which brokeg-lite’s client/canvas coordinate scaling under browser zoom other than 100% (drops and port grabs silently failed below 100%). The SVG renderer is still used forshinytest2end-to-end tests via the newblockr.dag.svg_rendereroption (see?new_dag_extension). Requiresg6R (>= 0.6.5), which keeps the create-edge assist node from crashing the canvas renderer and fixes a combo/layout crash when a stack is created at runtime. - Reworked block ports: ports are now always visible (rather than hover-only) with a fixed radius, and the output port uses the
label-bottomplacement. Pairs with g6R’s port-grab tolerance so a near-miss on a port still starts an edge. - Fix stack renames/recolors not reflecting in the DAG:
update_observer()still expectedstacks$modto carry fullstacksobjects after blockr.core switched the delta to partial-argument lists; the deltas are now resolved against the board before updating the combos. - Fix links between stacked blocks being unselectable: edges render at
zIndex = -1(under nodes) while combos sat at G6’s default0, so a stack’s rectangle swallowed every click aimed at the edges between its member nodes. Combos now render atzIndex = -2(node > edge > combo), keeping the stack itself clickable in its padding area. - Fix #123: renaming a block now relabels its DAG node instead of erroring.
update_observer()handed blockr.core’s partial-argumentblocks$moddelta straight toupdate_nodes()(which needs fullblockobjects); it now updates the node label directly from the delta. - Fix #144: copy/paste no longer corrupts
NULL-valued block state.copy_selection_to_clipboard()serialized the clipboard withtoJSON()’s defaultnull = "list", encodingNULLas{}and deserializing it back intolist(); pasted blocks then errored on first data (e.g.nzchar(list())-> “argument is of length zero” in the chart and table blocks). Now passesnull = "null"to match blockr.core’s save/restore serialization, round-trippingNULLfaithfully. - Fix blockr.dock#308: single-clicking a DAG node opens the block’s panel again.
blockr.dockretired the livedockhandle from the extension server surface, which the node-select observer passed toblockr.dock::show_panel(). The observer now emits aviewsupdate delta built withblockr.dock’s panel-op grammar (select, oradd+selectwhen absent) to reveal the block’s panel in the current view, adding it there if the view does not already hold it — without switching to another view. - Track
blockr.dock’s extension-identity redesign. An extension’s runtime id is now the container-assigned key (its class minus the_extensionsuffix, or an explicit list name), and extension results reach actions and block callbacks as oneextensionsbundle keyed by that id rather than a splatted argument named after the id. The DAG actions and the block-status callback now resolve their result withblockr.dock::extension_ids(board$board, "dag_extension")and index the bundle explicitly, instead of binding adag_extensionformal.
blockr.dag 0.1.2
CRAN release: 2026-04-29
Internal changes
- Label observers for OTEL support.
- Add support for collapsible nodes and combos, through g6R.
- Reworked actions. Inherits from
blockr.dock. - Added support for node ports from g6R.
- Fix #86: links can now be drawn repeatedly; previously the create-link gesture only worked once.
- Fix #110: copy/cut keyboard shortcuts no longer hijack plain text selections (column names, error messages, etc.).