explodemap >= 0.4.0
requirement before launch. This prevents older released explodemap
versions from failing later with missing spatial-grouping, palette,
simplification, state-bridge, or diagnostic functions.dragmapr_ prefix to the compact d_ prefix. For example,
dragmapr_state(), dragmapr_edit(), and dragmapr_widget() are now
d_state(), d_edit(), and d_widget(). The old function names are no
longer exported. Serialized class names and state schema identifiers are
unchanged, so existing state/project files remain readable.compose_offsets() /
effective_offsets(). Algorithmic base movement, inherited ancestor
movement, and local manual movement remain separately inspectable and sum to
canonical effective offsets. apply_dragmapr_state() can now materialize all
three layers directly into projected sf geometry.d_relationships() defines normalized parent-child edges with generic
children_of(), parent_of(), descendants_of(), ancestors_of(), and
hierarchy_path() queries. Active/parent state, branch movement, inherited
effective offsets, and snapshot/restore operations are provided by the new
d_* hierarchy helpers, unifying branch composition with the existing
state and inheritance model.d_styles() and
merge_dragmapr_styles(). Fill, stroke, stroke width, opacity, label
visibility, and highlight state now round-trip through state schema 1.2.0,
the native widget, static rendering, and project bundles; thematic
classification remains application-owned.d_interaction_options() now controls browser state emission with
state_emit = "end", "throttled", or "continuous", plus local live-drag
rendering and a throttle interval. Full composition snapshots are emitted at
meaningful endpoints by default, while optional live drag messages contain
only the changed ID and offset. The widget now preserves real
expanded_groups instead of emitting an empty placeholder.build_transition_plan() to align renderer-neutral movement tables
from explodemap with dragmapr timing, easing, stagger, and overshoot
semantics. Project bundles can now persist state.json, hierarchy.json,
and styles.csv, together with schema, CRS, geometry, and package-version
provenance.later now reads Shiny inputs and reactive state inside an isolated
reactive context, preventing Operation not allowed without an active reactive context during layout builds, uploads, simplification, and state
restores. The processing-overlay counter is likewise safe when a deferred
callback completes, with server-level regression coverage for the deferred
execution path.keep_spatial_features() so an empty id vector correctly returns an
empty sf object instead of retaining every feature.sf validation to reject an active geometry column that is not
an sfc vector, including at the start of render_dragged_map().Release A of the Pipeline Studio extraction adds state comparison helpers:
d_state_diff() reports changed regions, labels, and interaction
fields, while d_state_equal() provides the matching predicate with
composition/interaction/all comparison modes. summary.dragmapr_state() now
reports moved region and label counts, selected feature, CRS, geometry ID,
and revision.
Spatial feature editing is now first-class. New helpers
spatial_feature_table() / view_spatial_features(),
remove_spatial_features() / delete_spatial_features(),
keep_spatial_features(), add_spatial_features(), and
replace_spatial_features() let Shiny apps inspect, remove, keep, add, or
replace source sf geography without hand-editing geometry columns.
updateDragmapr() can now send remove_features = or
delete_selected = TRUE to the native widget; the browser removes the
geography from the live editor and emits input$<id>_feature_delete.
Pipeline Studio exposes this in the Refine tab with source-row inspection
and Undo/Redo so accidental deletions can be reversed.
d_widget() now accepts a direct region_palette = argument, matching
render_dragged_map() and updateDragmapr(region_palette = ) while keeping
the existing d_display_options(region_palette = ) route intact.
New inst/shiny/pipeline-studio Shiny app (shipped with both dragmapr and
explodemap) demonstrates the full cross-package workflow on real US geography:
an explodemap national HHS map and county drill-down, the draggable editor
with dragmapr_state round-trip, and a combined compute -> compose -> render
-> persist studio. Run with
shiny::runApp(system.file("shiny/pipeline-studio", package = "dragmapr")).
Added inst/examples/explodemap_dragmapr_pipeline.R, a complete
cross-package example covering explodemap layout optimization and
diagnostics, editable dragmapr_state, JSON persistence, focus_map(), and
render_dragged_map().
dragmapr_state carries a view (viewport) field that round-trips through
JSON and the widget snapshot. It is preserved as composition metadata;
restoring the browser to a saved viewport on load is intentionally left for a
future release (selection restoration is the clean first cut).
Every public entry point that accepts sf geometry (d_widget(),
d_edit(), apply_offsets(), apply_dragmapr_state(),
render_dragged_map()) now validates the active sf geometry column up front
via a shared check, so a malformed sf fails with one clear message instead
of a deep, cryptic error.
New d_edit() is a friendly front-door to the interactive editor and
the composition step of the state-first workflow. It accepts a projected
sf, an explodemap grouped_exploded_map, or a dragmapr_layout (plus an
optional dragmapr_state) and returns a configured d_widget().
Capture edits back into a state with d_widget_state().
d_state() gains three optional, back-compatible fields that make a
saved composition durable across sessions: crs (the projected CRS the
metre offsets are expressed in, stored as an EPSG integer or WKT string so it
round-trips through JSON), geometry_id (a provenance tag identifying the
geometry the state was composed against), and selected_feature (the feature
focused in an editor or dashboard). The fields are threaded through
validate_, merge_, snapshot_/restore_, inherit_drag_offsets() and
collapse_drag_offsets(); selected_feature is dropped on a level change.
apply_dragmapr_state() now warns when a state's crs differs from the
target geometry. Older state JSON written before these fields still restores.
explodemap::as_dragmapr_state() is the matching producer: it converts a
grouped layout's absolute anchors into dx_m/dy_m deltas and emits a
dragmapr_state, keeping the computed layout and the editorial state as
separate objects.
The native widget bridge now carries crs, geometry_id and
selected_feature. They are surfaced at the top of the widget payload, the
browser highlights the selected region (.is-selected), a region click
updates the selection and reports it back to Shiny, and the round-trip state
snapshot includes all three fields. updateDragmapr() gains live
selected_feature updates (pass NULL or "" to clear).
New d_widget_state() is the inbound half of the bridge: it
reconstructs a dragmapr_state from the paste0(outputId, "_state") Shiny
input the widget emits, so server code can persist, merge, or re-render a
live composition. The browser's revision is preserved as the state
version (the client owns the live counter).
New inst/examples/full_state_roundtrip.R Shiny app walks the whole state
contract: an upstream layout state is edited in the native widget, every edit
is rebuilt server-side with d_widget_state(), a selection is pushed
back from R with updateDragmapr(), and the live dragmapr_state drives both
a saved JSON file and a static render_dragged_map() re-render.
render_dragged_map() now accepts state = a dragmapr_state, using its
region and label offsets for static output while preserving the existing
region_offsets / label_offsets table arguments as explicit overrides.
Revision semantics are now monotonic: merge_dragmapr_state(),
inherit_drag_offsets() and collapse_drag_offsets() bump version to one
past the highest input revision (via the internal bump_revision()), so a
state produced by an accepted edit always sorts after its inputs. Previously
merge_dragmapr_state() took the maximum of the two revisions unchanged.
drag_map_prototype() gains an optional transition argument: the browser
helper runs one client-side leaf-flip branch animation for parent-to-child
bloom and child-to-parent unbloom, and draws a dotted group-drag boundary per
expanded group. Clicking a boundary posts a
dragmapr-collapse-branch message to the embedding page, or resets the
branch when the helper runs standalone; a plain click on a region posts
dragmapr-region-click.inst/examples/branch-bloom-tester.R Shiny example isolates the
branch-bloom helper so clean bloom and leaf-flip behavior can be tested
without the full Spatial Studio shell.inst/cheatsheets/ covers the core workflow,
labels, static rendering, Spatial Studio, hierarchy/bloom helpers, CRS
diagnostics, layout snapshots, and transition utilities.detect_hierarchy_columns(),
recommend_dragmapr_hierarchy(), validate_bloom_hierarchy(),
build_branch_transition_data(), make_branch_bloom_labels(),
summarise_spatial_crs(), and profile_spatial_upload() move
parent/child detection, CRS meaning, branch-bloom data prep, and safe
parent-first label setup into reusable package functions.COUNTY_NAM instead of COUNTY).Initial CRAN release.
drag_map_prototype() writes a self-contained D3 browser helper where
grouped sf regions, labels, and annotation boxes can be dragged freely.
It exports region and label offset CSVs.render_dragged_map() reconstructs the dragged layout as a ggplot2 image
from the source geometry plus offset tables.render_dragmapr_project() renders a complete Spatial Studio project bundle
(ZIP) in one call.make_region_labels(), as_drag_labels(), and as_drag_annotations()
build label tables; read_label_state() and apply_label_state() restore
saved label positions.read_offsets() and apply_offsets() handle region offset I/O.read_dragmapr_sf_upload(), read_dragmapr_sf_url(), and
prepare_dragmapr_sf() read and normalise spatial files for Shiny workflows.d_iframe_bridge() provides the JavaScript bridge for relaying drag
state from the helper iframe back to Shiny inputs.d_addin() registers an RStudio gadget under Addins > Launch
dragmapr that embeds the prototype in the viewer pane and assigns
region_offsets and label_offsets to the target environment on completion
(.GlobalEnv when launched from the RStudio Addins menu).legend_values and label_values, preserving stored offsets for hidden
labels.%||% is defined for the RStudio addin,
prototype output defaults to a temporary HTML file unless file is supplied,
connector linetypes are validated in static exports, the Shiny iframe bridge
stops polling on disconnect/unload, CRS-less inputs warn before assuming the
target CRS, legacy label helper aliases emit deprecation warnings, and the
bundled D3 license is included under inst/prototype/.