myIO (development version)
New features
- New
setTransition(duration, easing, stagger)configures chart animations:durationin milliseconds,easing(one of"linear","quad","cubic","sin","exp","circle","back","bounce","elastic", mapped to the corresponding d3 easing), andstagger(per-element cascade delay in ms). All arguments are optional and additive; unset values keep each renderer’s existing defaults, so the change is fully backward compatible.setTransitionSpeed()is now a thin wrapper oversetTransition(duration = ). Animation stays fully opt-out-able:duration = 0disables it, and easing and stagger automatically no-op when the effective duration is 0, including under the viewer’sprefers-reduced-motion: reducesystem setting. A Playwright e2e spec verifies animate-when-on, still-when-off, and still-under-reduced-motion. - New opt-in
"lttb"transform forlinelayers downsamples a large series with Largest-Triangle-Three-Buckets, shipping at mostoptions$thresholdpoints (default 2000) while preserving the visual shape:addIoLayer(type = "line", transform = "lttb", options = list(threshold = 1000)). Off by default (identity); runs on the in-memory/SVG path and is independent of the DuckDB-WASM engine’s own SQL-side LTTB, so it never double-downsamples. - New
myIOProxy()+updateMyIOData()update a rendered chart’s layer data in place from the Shiny server without re-runningrenderMyIO(). Layers are matched by label and swapped through the existing data-join path, so only the changed marks transition and brush/zoom/toggle state is preserved (the full re-render destroyed and recreated the chart, flickering and dropping state):myIOProxy("chart") |> updateMyIOData(series = new_df).
Performance and tooling
- The production JavaScript bundle is now minified. The shipped
inst/htmlwidgets/myIO/myIOapi.jsdrops from 2.32 MB to 1.20 MB raw (398,650 to 298,757 bytes gzipped, -25%) with no behavior change; the developmentwatchbuild stays unminified for debugging. - End-to-end tests now run from a committed
playwright.config.tsand a newe2eCI workflow. The suite builds and loads the minifiedmyIOapi.js, guarding the production bundle that source-importing unit tests cannot catch. - Touch interaction is now verified end-to-end: a touch-emulation Playwright spec on iOS- and Android-class viewports confirms a
touchstarton a bar surfaces the tooltip with the datum’s content andtouchenddismisses it, guarding the mobile hover path against the production bundle. - The
file://deployment e2e (self-contained widget opened directly from disk) is now exercised for real: its fixture loads the IIFE bundle via a classic<script src>rather than an ES module, so the file-protocol → SVG-engine fallback is verified underfile://instead of skipped.
Improved error messages and API ergonomics
Argument names are now consistently camelCase across setters.
setBrush(onSelect),setFacet(minWidth, labelPosition),setTheme(textColor, gridColor), andsetBigData(rowkeyCol)are the canonical forms (matchingcolorScheme,xAxis, etc.). The previous snake_case names (on_select,min_width,label_position,text_color,grid_color,rowkey_col) keep working as deprecated aliases that emit a one-line warning; existing code is unaffected aside from the warning. When both forms are supplied the camelCase value wins.setFacet(),setLayerOpacity(), andsetTheme(mode = )now report invalid arguments with consistent, actionable messages (e.g.setFacet(): \scales` must be “fixed”, “free_x”, “free_y”, “free”, not “x”.) instead of barestopifnot()failures.setColorScheme()` errors are likewise function-prefixed. No change to which inputs are accepted.setTheme()now warns when passed an unknown argument that lacks the required--prefix (e.g. a misspelledtext_colour) and suggests the intended argument, instead of silently dropping it. Valid---prefixed CSS overrides are unaffected.setTheme()documents the namedpresetvalues ("midnight","ocean","forest","sunset","monochrome","neon","corporate","academic","nature","minimal","retro","warm", plus"light"/"dark"); thepresetargument was already functional.setLinked()andlinkCharts()now cross-reference each other in their documentation to clarify when to use the Crosstalk path versus the group-identifier path. ## DocumentationNew “Theme Gallery” article renders the same chart under all named presets (
midnight,ocean,forest,sunset,monochrome,neon,corporate,academic,nature,minimal,retro,warm, pluslight/dark) as live, side-by-side previews, and shows how to layer custom CSS overrides on top of a preset. ## Performance and reliabilityInline Arrow IPC payloads now decode via the native
Uint8Array.fromBase64when the browser provides it (falling back to the previousatobloop), avoiding a per-character JavaScript callback over large payloads in the in-memory and DuckDB-WASM engines.Added a regression test confirming charts that already render an inline legend are not given a duplicated legend on image/SVG export (GH #64).
Layer-data serialization (
addIoLayer()) is faster for large data: the row-rectangling step now extracts columns once and indexes per row instead of subsetting the data frame on every row, roughly 5x faster at 100k rows. The emitted JSON is byte-identical to before (pinned by tests across numeric, integer, character, logical, factor, Date, and POSIXct columns), so every chart type renders exactly as it did.
myIO 1.2.0
CRAN release: 2026-06-11
LLM tool-calling schema
- New machine-readable chart specification schema (
inst/myio-schema.json) describing all chart types, required mappings, valid transforms, and function signatures, generated from the package’s own contracts. - Six exported R tools let large language model agents author and verify charts against that schema:
myio_list_chart_types(),myio_chart_schema(),myio_validate_spec(),myio_list_functions(),myio_function_signature(), andmyio_validate_call(). A Model Context Protocol server in the package’s source repository exposes the same six tools to MCP-compatible clients. - New vignette
llm-tool-callingdemonstrates a generate-validate-repair loop.
Uncertainty visualizations
- New
quantile_dotschart type andquantile_dotstransform render a Wilkinson dot plot of predictive quantiles for communicating uncertainty. - New
fancomposite renders a fan chart of nested prediction intervals around a central estimate.
Gallery and chart context
-
myIO(title = ...)andsetTitle()add a backward-compatible chart title surface rendered inside the SVG. Existing charts that omit a title are unchanged. - Axis titles from
setAxisFormat(xLabel = ..., yLabel = ...)now render in the chart SVG, and multi-series charts get a compact visible legend while preserving the existing action-sheet legend. - The gallery now carries chart titles across examples, repairs horizontal bars, mean-CI, heatmap margins, gauge thresholds, treemap labels, date-based finance examples, and shows themes across a small grid of representative charts.
Crosstalk: expanded chart-type coverage
-
setLinked()now linkswaffle,beeswarm,lollipop, anddumbbelllayers in addition to the previously supportedpoint,bar,groupedBar,histogram, andhexbin. Selection dims non-matching elements; filter hides them. Aggregate chart types (boxplot,violin,qq,regression,density,ridgeline,survfit,comparison) remain outside crosstalk in v1.2. - New vignette
crosstalk-linkingdemonstrates linking myIO withDT::datatable()andreactable::reactable(), with code listings for plotly and leaflet.
bslib and Quarto Dashboards integration
-
myIO()widgets now declare a sizing policy withbrowser.fill = TRUEand are tagged ashtml-fill-itemviahtmltools::bindFillRole(), so they fill container height insidebslib::card(), Quarto Dashboard{.fill}cards, and flexdashboard layouts. Rendering in plain RMarkdown and Shiny at the default 400px height is unchanged. - Widget resize is now guarded against zero-dimension containers that can appear briefly during fill-layout transitions.
Calendar heatmap
- New
calendarHeatmapchart type — GitHub-contributions-style grid of daily cells over a single calendar year. Usage:addIoLayer(type = "calendarHeatmap", data, mapping = list(date = "day", value = "x")). Supports Sunday or Monday week starts viaoptions$weekStart, continuous color legend, and linked-cursor sync across two linked calendars. Multi-year data is rejected in v1.2; multi-year layouts are planned for v1.3. New CSS variables:--chart-calendar-cell-gap,--chart-calendar-cell-stroke,--chart-calendar-empty-fill.
Theme gallery
- 12 named theme presets:
setTheme(preset = "midnight"). Available presets: midnight, ocean, forest, sunset, monochrome, neon, corporate, academic, nature, minimal, retro, warm. Plus light/dark via mode parameter.
Linked brushing
-
linkCharts(chart1, chart2, on = "column")enables cross-chart selection. Brush in one chart highlights matching rows in linked charts. Works in Shiny and static HTML. Aggregation-to-source-row key resolution for summary views.
Linked cursor
-
linkCharts()andsetLinked()gain acursor = TRUEargument that draws a synchronized vertical crosshair on every linked chart when the user hovers any chart in the group. Supports point, bar, line, area, groupedBar, hexbin, and histogram layers (donut and treemap are excluded — no x-axis to sync on). Off by default; enable per-link or retrofit withsetLinkedCursor()on a pre-linked widget. New--chart-cursor-rule-color/-width/-dasharrayCSS variables theme the crosshair.
Group-by auto-series
- Pass a
dplyr::group_by()tibble toaddIoLayer()and it auto-creates one layer per group with colors from the Okabe-Ito palette. Soft dplyr dependency.
Survival curves (Kaplan-Meier)
-
addIoLayer(type = "survfit", mapping = list(time = "time", status = "status"))computes Kaplan-Meier estimator with Greenwood CI using base R only (nosurvivalpackage dependency). Composite expands to step-curve line, CI band, and censored-observation markers. Group stratification supported.
Distribution fitting overlay
-
addIoLayer(type = "histogram_fit", mapping = list(value = "x"), options = list(family = "normal"))fits normal, lognormal, or exponential distributions via MLE. Composite renders histogram + fitted density curve + optional parameter annotation.
Layer opacity control
-
setLayerOpacity(label, opacity)sets per-layer opacity (0-1). Critical for CI bands overlaying scatter data.
SVG accessibility
- ARIA roles (
graphics-document,graphics-object,graphics-symbol) applied to SVG chart structure for screen reader navigation. - Keyboard navigation: arrow keys traverse layers and data points, with live region announcements (150ms debounce).
- Hidden data table fallback for screen reader access to raw data (capped at 500 rows).
- Focus ring styling and screen-reader-only utility class.
New chart types
-
lollipop— vertical stem with circle head, supportsmeanandsummarytransforms. Compatible with categorical x-axis charts. -
dumbbell— connected dots showing a range betweenlow_yandhigh_y. -
waffle— 10x10 grid of colored squares representing proportions. Standalone. -
beeswarm— dodge-positioned points to avoid overlap. Inline dodge algorithm. -
bump— smooth S-curves showing rank/value changes over time with grouped lines. -
radar— spider/radar chart with radial axes and polygon data fill. -
funnel— narrowing horizontal bars for conversion pipeline data. -
parallel— parallel coordinates for multivariate exploration. All new types support themed colors and standard tooltip formatting.
Small multiples / faceting
-
setFacet(var, ncol, scales)splits charts into a CSS grid of panels, one per unique value of the faceting variable. Supports fixed and free scale modes, auto-layout with configurable minimum panel width, and responsive breakpoints.
Export enhancements
-
setExportOptions()controls which export buttons appear in the toolbar (PNG, SVG, clipboard, CSV). New SVG download button and clipboard copy (SVG + PNG) via the Clipboard API. - CSS custom properties resolved in exported SVGs for correct dark-mode colors.
Dark mode / theme system
-
setTheme(mode = "dark")applies a WCAG AA-verified dark palette across all chart elements. Also supports"light"and"auto"(detects OS preference and Quarto/Bootstrapdata-bs-theme). - Backward compatible: existing
setTheme(bg = "#fff")calls still work. - New
overridesparameter for fine-grained CSS custom property control. - High-contrast and reduced-motion CSS media query support.
Sparkline mode
-
myIO(sparkline = TRUE)renders a compact, axes-free chart suitable for embedding in table cells (reactable, DT, gt). Strips legend, axes, reference lines, and all interactions. Default height 20px. Supports line, bar, and area layer types.
Bug fixes
-
myio_validate_spec()and the chart specification schema no longer reject valid specs for chart types with a single required mapping (for examplehistogram,gauge, andqq). The schema now always represents list-typed fields as arrays.
myIO 1.1.0
I/O interaction system
myIO now supports bidirectional data flow — user interactions return structured data, not just visual feedback.
-
setBrush(): rectangle brush selection on point, bar, histogram, hexbin, and grouped bar charts. Selected points available as Shiny reactive input or scoped CSV export in static HTML. -
setAnnotation(): click any data point to attach a label. Annotations stored as structured data (source key, coordinates, label, category color, timestamp) and exportable as CSV. Supports preset label dropdowns and color category pickers. -
setLinked(): CrosstalkSharedDataintegration for cross-widget linked brushing. Selection dims non-matching points; optional filter mode hides them. Supports source, target, or bidirectional modes. -
setSlider(): parameter sliders below the chart that trigger Shiny re-rendering with configurable debounce. Renders disabled with tooltip in static HTML.
Bug fixes
-
dragPoints()now correctly emits thedragEndevent to Shiny (input$myIO-{id}-dragEnd), which was previously registered but never fired.
myIO 1.0.0
Statistical transforms
- New composable transform pipeline:
type + transform = layer. Transforms compute statistics in R; renderers display them in D3.js. - Transforms:
lm,loess,polynomial,ci,smooth,mean,mean_ci,residuals,summary,pairwise_test,qq. - Composite chart expansion: complex charts decompose into primitive layers.
Chart types (20)
- Basic:
line,point,bar,area,groupedBar. - Statistical:
histogram,hexbin,regression,qq. - Distribution:
boxplot,violin,ridgeline,comparison. - Financial:
candlestick,waterfall,heatmap. - Standalone:
donut,gauge,treemap,sankey.
Composites
-
boxplot: expands into IQR box + whisker caps + median + outliers. -
violin: expands into density area + IQR box + median point. -
ridgeline: density curves stacked vertically by group. -
regression: scatter + trend line + CI band + R-squared annotation. -
qq: Q-Q scatter + reference line + confidence envelope. -
comparison: boxplots + pairwise significance brackets.
Interactions
- Tooltips with automatic formatting via
setToolTipOptions(). - Drag interaction via
dragPoints(). - CSV, SVG, and PNG export buttons.
- Reference lines via
setReferenceLines(). - Y-variable toggle via
setToggle().
Infrastructure
- Responsive sizing that adapts to container dimensions.
- Shiny integration with
myIOOutput()andrenderMyIO(). - Pipe-friendly API using native
|>. - Theming via CSS custom properties with
setTheme(). - Okabe-Ito colorblind-safe default palette.
