sideview_widget() and save_sideview() take
max_rows = 5000. A longer data-frame table is cut to its first rows, its card
says "First N of M rows" and one message names the tables cut (silent while
knitting). max_rows = Inf embeds everything. Lazy tables are unchanged.viewer =, sideview() and sideview_addin() open the
browser in Positron, which has no dialog viewer; viewer = "dialog" there also
opens the browser, with one message.sv_load_state() and state = read a
file without a version as 0.2.0 and upgrade older files (stamped 0.3.0); a file
from a newer sideview loads with one warning.sideviewUI() / sideviewServer() put an R-backed canvas into your own Shiny
app, several per page. The server returns a proxy with the reactives code(),
pipeline(), state() and cards(), and sideviewProxy(id) reaches the same
canvas from elsewhere in the session. cards = can be a reactive; req() in it
means "no cards yet". Lazy (arrow / duckdb) cards in a module show their true
size, not "First 500 of ...", because R serves the whole table.sv_add_card(), sv_replace_card(), sv_remove_card(),
sv_set_state() and sv_highlight(), which pipe. A replace keeps the card's
place and size, re-checks the join keys, and disables, not deletes, any
pipeline step that names a column the new table lacks (a mutate expression
that uses it included), with one toast. A replace also keeps the card's header
sort and filter, so the canvas still agrees with the code.$code() is composed in the browser: treat it as untrusted text.llm_fn is given.inst/examples/proxy/app.R has two canvases and a button for
each verb. The gadget and the widget are unchanged.A join step can carry a date rule, so "labs within 7 days of the visit" is a
join and not a hand-written filter. Click the calendar button on a join step to
open the rule row. The shapes are Between (a date inside the other table's
start and end), Window (within a number of days before and after),
Nearest before, Nearest after and Overlaps. Date, date-time and
numeric columns work. The code uses join_by() and, for a window, two helper
columns (.sv_lo, .sv_hi) that it drops again.
sv_join_diagnostics() has a new
rule argument, and the gadget, the saved widget and duckdb/arrow cards all
agree.relationship = and
unmatched = arguments taken from the join check, so the join stops with
dplyr's own error if the data changes under it. Strict is R-only for duckdb
and arrow tables. The check looks at the two original tables, so Strict
applies only to a join on them: when an earlier step on the left table
changes its rows (a filter, another join, a summary, a pivot), or the right
table has steps of its own, the checkbox is greyed with the reason, keeps its
setting, and the code is the plain join.na_matches = "never". sideview writes
na_matches = "never" on every rule join (dplyr's default would match NA
to NA), so a key that is NA never matches another NA and the key check
counts them the same way when a rule is set.TimeZone setting a boundary
can move. Running the code in R on a mixed arrow/data-frame and duckdb chain
may leave temporary dbplyr_* tables on your connection until it closes.lubridate::days(), so run it with
lubridate installed (it is in Suggests; Date and numeric windows do not need it).Arrow tables, datasets and queries and duckdb tables (dplyr::tbl()) used to
keep only their first 50 rows, so a sort, a join check or a codebook looked
complete when it was not. They now use the whole table.
sv_join_diagnostics() accepts duckdb and
Arrow tables, sv_column_profile() has a new column argument for them, and
sv_codebook() accepts them and has a progress argument. Arrow tables go
through a private duckdb connection that closes with the session.rows_profiled, after n. n is the
table's true row count and rows_profiled is how many rows the profile used.
They are equal except for a preview-only card.collect(). Joins across
duckdb, arrow and data frames are written so they run, a "contains" filter is
stringr::str_detect(col, "<escaped literal>") (stringr is in Suggests), and
a reshape on arrow collects first. If Run in R fails, the message adds
"This step may need data in R: move collect() above it.">, >=, <, <= or = filter on an Arrow
date-time column with a time zone matched no rows. duckdb 2.0 turns that
comparison into a filter inside the Arrow scan, which loses every row.count() and range()) made the
lazy join check, filters and "contains" fail."yes" on a
logical, "abc" on a date) matches no rows, as on a data frame, instead of
failing.200,000, not 200000
or 2e+05; a widget codebook gives a lazy card's true row count as n." or \ gets code that parses; a
saved state never holds a card's lazy table.Known differences from an in-memory card:
.0, but in generated code duckdb writes a double as "130.0" where R writes
"130", and float noise or scientific notation can differ.-0, can print differently.TIMESTAMPTZ columns show in UTC. duckdb
ordered factors report class "factor".arrow::to_duckdb() then dplyr::compute()), which uses memory. A data
frame joined into duckdb is copied as sideview_<table>.NA. sideview decodes these columns itself, but generated code that calls
arrow::to_duckdb() on one may hit it: convert the factor to character first.A full pass over the user interface, tested in a real browser and in RStudio (dialog, Viewer pane, external browser, the addin, a saved HTML file and a Quarto page), plus new features for clinical data work.
Ctrl+Z / Ctrl+Y) and
a choice of %>% or |>. The drawer has real builder tabs: Join, Filter
(several conditions, AND/OR), Arrange, Mutate, Recode, Reshape and Summarise.sv_join_diagnostics().sv_column_profile() and sv_codebook() do the same from R.sideview(..., state =)
and sideview_widget(..., state =) restore card positions, zoom, sorts,
filters, joins and the pipeline, and sv_load_state(launch = TRUE) now
really launches.M hides it), Ctrl+K to
find a card or column, and double-click a card title to zoom to it. Fit
and Arrange buttons, and a tidy grid layout at launch.theme = "auto" (follows RStudio or the browser), "light",
"dark", sv_theme() or a bslib::bs_theme(). Every text colour meets
WCAG AA contrast.? lists them), real buttons with
labels and visible focus rings, and the OS "reduce motion" setting is
respected.sv_llm_models() lists the models an Ollama or OpenAI-compatible server
offers. AI errors now say how to fix them, and options(sideview.llm_think)
controls Ollama reasoning models. See ?sideview for all options.viewer = "browser" works again. Closing or reloading the tab no longer
leaves the console busy or kills the app (options(sideview.session_grace)).%> instead of %>%.NULL;
"Run in R" keeps its result in a named object (sv_result by default), in
the environment sideview() was called from (new env argument; the
workspace when called from the console).dplyr::case_when() (case_match() is deprecated
in dplyr 1.2).sideview-core HTML dependency with a content-based version, so browsers
never use stale JavaScript or CSS. The bundled pan/zoom code is now honestly
named sv-panzoom.js.tests/testthat/test-layout-browser.R, run with
NOT_CRAN=true) checks layout and behaviour with real mouse and keyboard
input.VirtualTable in sideview.js and sideview.css, bounding active table DOM nodes to ~30 rows with dynamic spacer elements and supporting 100k+ rows at 60 FPS scrolling.sv_normalize.arrow_table(), sv_normalize.Dataset(), sv_normalize.tbl_duckdb_connection()) with soft-dependency guards in Suggests:.sv_code_join() and server reactivity to support vector keys (by = c("key1" = "key1", "key2" = "key2")) and relational multi-table pipeline chaining.sv_code_pivot_longer() and sv_code_pivot_wider() with full syntactic backtick escaping and custom values_fn aggregation.sv_code_group_summarize() generating reproducible dplyr::group_by(...) %>% dplyr::summarise(..., .groups = 'drop') workflows.<svg class="sideview-sparkline">), categorical frequency distribution bars (.sideview-cat-profile), and color-coded missingness badges (.sideview-na-badge) with 25k-sample performance optimization.new_sideview_state(), sv_save_state(), and sv_load_state() supporting both portable .json and native R .rds workspace serialization for canvas pan/zoom, card coordinates, splines, and pipelines.sv_suggest_mappings() computing 3-part composite scores (name similarity with ID suffix detection, type compatibility, and Jaccard overlap) with precomputed unique sets and logical column exclusion..sideview-spline-suggested dashMove) with click-to-accept join mapping, and sv_auto_clean_rules() / sv_code_auto_clean() for automatic dplyr::case_match() crosswalk synthesis.sv_build_chat_prompt()), turn-based history sliding window (20 turns), and active pipeline code guards.tests/testthat/test-computer-use-gui.R and headless DOM test runner gui-test-runner.js verifying 6 core interaction scenarios (canvas coordinates, dragging, port click / spline connect, suggested spline acceptance, sorting/filtering, drawer action dispatch) with diagnostic dumps in tempdir().[🔗] link icon in card headers) now synchronously locks both vertical rows (scrollTop) and horizontal columns (scrollLeft) in proportional lockstep across wide datasets.column_disconnected to dynamically update code generation and downstream operations.clearOperations() to reliably purge active connecting port states (this.activePort) and strip visual .connecting classes when resetting the canvas.tests/testthat/test-assets.R to ensure zero runtime script syntax errors.▲ Ascending, ▼ Descending, original).dplyr::arrange() pipelines in the Action Drawer.🔍).>, >=, <, <=), exact matches (==, !=), and text substring filters (contains).dplyr::filter() pipelines.escapeColIdentifier() in sideview.js so column names with spaces or symbols (e.g. Patient ID, Glucose (mg/dL)) are safely wrapped in backticks across filter and arrange pipelines.sideview_ui() to handle nested list-columns and vectors safely with a [list] placeholder, avoiding length > 1 evaluation errors under R 4.2+.Insert Script: Pastes code at the current cursor location in the active RStudio script document via rstudioapi::insertText().Run & Exit: Sends code to the R console and closes the gadget immediately.Run in R: Evaluates code directly inside the current R environment (.GlobalEnv) with live row/column toast feedback.Run Console: Previews and buffers code for the RStudio console.Clear button in the Action Drawer to reset all active splines, sort orders, and filters.[✓] Auto-clear toggle to automatically reset canvas interactions upon code insertion or copy.gemma4:26b and llama3.2 with zero data leakage (http://localhost:11434).sideview: Multi-Table 2D Infinite Canvas for interactive data exploration, visual field mapping, and LLM-assisted Tidyverse code generation.sv_normalize()) supporting data.frame, tibble, base::table, matrix, gt, flextable, and htmlwidgets.save_sideview().sideview(), sideview_addin()).