| Type: | Package |
| Title: | Build Formula-Driven 'shiny' Apps for 'ggplot2' |
| Version: | 0.11.1 |
| Description: | Turns a single 'ggplot2'-style formula string into a small 'shiny' application. Placeholder tokens in the formula become input widgets automatically; the package completes the expression with the current input values, renders the plot, shows the generated code, and supports uploaded datasets in different formats. |
| License: | GPL-3 |
| URL: | https://willju-wangqian.github.io/ggpaintr/, https://github.com/willju-wangqian/ggpaintr |
| BugReports: | https://github.com/willju-wangqian/ggpaintr/issues |
| Depends: | R (≥ 4.1.0), ggplot2 (≥ 3.3.0) |
| Imports: | assertthat (≥ 0.2.0), cli (≥ 2.2.0), htmltools, rlang (≥ 1.0.0), shiny (≥ 1.6.0), shinyWidgets (≥ 0.6.4) |
| Suggests: | bslib (≥ 0.5.0), dplyr, ellmer, jsonlite, knitr, miniUI, pkgdown, plotly, purrr, readxl, rmarkdown, rstudioapi, shinytest2, testthat (≥ 3.1.7), withr, writexl, xaringanExtra |
| VignetteBuilder: | knitr |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.3.3 |
| Config/testthat/edition: | 3 |
| Config/testthat/start-first: | e2e-vignette-examples-shinytest2, j12-spec-and-renderui-emission-journey, shared-source-panel-multi-instance, adr0024-companion-entry-point, prologue-reader-fn-mirror, j2-prologue-csv-upload-journey, j11-app-basic-journey, default-seeding-with-source-upstream, adr15-consumer-binding |
| NeedsCompilation: | no |
| Packaged: | 2026-07-02 06:36:08 UTC; willju |
| Author: | Wangqian Ju |
| Maintainer: | Wangqian Ju <wju@iastate.edu> |
| Repository: | CRAN |
| Date/Publication: | 2026-07-07 10:10:02 UTC |
ggpaintr: Formula-Driven ggplot Shiny Apps
Description
ggpaintr turns a single ggplot-like formula string into a small Shiny app
with generated controls, rendered plots, generated code, inline runtime
feedback, upload support for .csv, .tsv, .rds, .xlsx, .xls, and .json files, copy customization, and
per-app custom placeholder registries. It also provides lower-level helpers
for runtime inspection and column-name normalization for data used with the
built-in ppVar placeholder.
Author(s)
Maintainer: Wangqian Ju wju@iastate.edu (ORCID)
Authors:
Jinji Pang pjj0702@iastate.edu (ORCID)
Zhili Qiao zlqiao@iastate.edu (ORCID)
See Also
Useful links:
Report bugs at https://github.com/willju-wangqian/ggpaintr/issues
Build a Shiny UI Widget for a Typed-Tree Node
Description
S3 generic dispatched per node class. Resolves the human-readable label
through ptr_resolve_ui_text, namespaces the node's id (and any
shortcut_id for source nodes) via ns_fn, and forwards to the
registered build_ui hook for the placeholder's keyword.
Usage
build_ui_for(node, ...)
Arguments
node |
A typed AST node (e.g. |
... |
Additional arguments. Recognized by built-in methods:
|
Value
A shiny.tag (or NULL for nodes that emit no UI).
Built-in helpers for a placeholder's plain-R evaluation slot
Description
A placeholder-embellished ggplot expression must stay valid plain R that
renders the original plot with no app running. Each placeholder carries a
callable (the embellish_eval = argument of the
ptr_define_placeholder_*() constructors) that supplies its plain-R
meaning when the naked expression is evaluated outside ptr_app(). These
two factories are the built-in callables for that slot:
Usage
embellish_identity()
embellish_symbol_to_string()
Details
-
embellish_identity()returns the identityfunction(x, ...) x— the slot's default behaviour. The placeholder call becomes a no-op wrapper: it returns its argument unchanged. -
embellish_symbol_to_string()returns a function that captures its argument unevaluated and turns column references into a character vector of names. This is the pattern a column-selecting consumer needs so the naked expression works inside a tidyselect verb: tidyselect evaluates an unknown wrapper call in non-masked scope, where bare column symbols throw "object not found"; returning the names as strings sidesteps that because tidyselect accepts selection by name.
These helpers are author-controlled plain-R semantics, never derived — only the author knows the intended live-R meaning of a placeholder.
Value
Each factory returns a function of signature function(x, ...).
embellish_identity()'s function returns its first argument x
unchanged. embellish_symbol_to_string()'s function returns a character
vector of column names captured from the unevaluated x.
Examples
f <- embellish_identity()
f(5L)
g <- embellish_symbol_to_string()
g(c(mpg, hp))
g(mpg)
Off-by-default layer wrapper
Description
ADR-0020 structural keyword that marks a layer as off-by-default in
ptr_app(). Inside ptr_app() / ptr_server() the parser sees the
wrapper and unwraps it at translate time, stamping the boot-state
metadata on the resulting node: ppLayerOff(layer_expr, hide = TRUE)
becomes a ptr_layer with default_active = FALSE. The wrapper
itself never appears in the typed tree.
Usage
ppLayerOff(layer_expr, hide = TRUE)
Arguments
layer_expr |
A ggplot2 layer expression (e.g. |
hide |
A length-1 logical literal ( |
Details
Outside ptr_app() it behaves per its R semantics so naked-ggplot
scripts still render: ppLayerOff(geom_point(), TRUE) returns NULL
(so ggplot(mtcars, aes(x = mpg, y = wt)) + ppLayerOff(geom_point(), TRUE)
renders without the hidden layer); ppLayerOff(geom_point(), FALSE)
returns the layer.
For the pipeline-stage sibling that exposes a user-toggleable checkbox
(ADR-0021), see ppVerbSwitch().
Value
Outside ptr_app(): NULL when hide = TRUE, otherwise the
evaluated layer_expr.
Examples
library(ggplot2)
# Naked-R semantics: hide = TRUE drops the layer to NULL.
p1 <- ggplot(mtcars, aes(x = mpg, y = wt)) +
ppLayerOff(geom_point(), TRUE) # equivalent to no geom_point
p2 <- ggplot(mtcars, aes(x = mpg, y = wt)) +
ppLayerOff(geom_point(), FALSE) # the layer is added
# Inside ptr_app(), the wrapper becomes a node-level default and a
# boot-state-off checkbox:
if (interactive()) {
ptr_app(ggplot() + ppLayerOff(geom_point(aes(x = mpg, y = wt)), TRUE))
}
Placeholder Identity Helpers
Description
These are the plain-R callables returned by registering the five
built-in ggpaintr placeholders (ppVar, ppNum, ppText, ppExpr,
ppUpload). Inside a formula passed to ptr_app() / ptr_server()
the parser recognises calls to these names as placeholder invocations
and binds them to Shiny widgets (see vignette("ggpaintr-tutorial")).
Outside ptr_app() they behave as plain R functions: the first four
return their argument unchanged (identity), so a formula such as
aes(x = ppVar(mpg)) evaluates identically to aes(x = mpg) under
ggplot2's tidy-eval. ppUpload is identical when called with an
argument (ppUpload(penguins) returns penguins), so a formula such
as ppUpload(penguins) |> filter(...) |> ggplot(...) evaluates as
plain R when penguins is in scope. The no-arg form ppUpload()
aborts outside ptr_app() — it is meaningful only as a placeholder
slot.
Usage
ppVar(x = NULL, ...)
ppNum(x = NULL, ...)
ppText(x = NULL, ...)
ppExpr(x = NULL, ...)
ppUpload(x, ...)
Arguments
x |
A column name ( |
... |
Additional arguments (e.g. named arguments consumed by a
custom placeholder's |
Value
The input value unchanged. The no-arg form ppUpload() does
not return; it aborts with a guard message.
Examples
# Identity inside ggplot2's tidy-eval:
library(ggplot2)
p1 <- ggplot(mtcars, aes(x = mpg)) + geom_histogram(bins = 10)
p2 <- ggplot(mtcars, aes(x = ppVar(mpg))) + geom_histogram(bins = 10)
# p1 and p2 produce the same plot.
# Inside ptr_app() / ptr_server(), the same call binds to a column picker:
if (interactive()) {
ptr_app(ggplot(mtcars, aes(x = ppVar(mpg), y = ppVar(wt))) + geom_point())
}
Switchable pipeline-stage wrapper
Description
ADR-0021 structural keyword that marks a pipeline stage as user-
toggleable in ptr_app(). The boolean argument is switch_on
(positive sense: TRUE applies the verb, FALSE skips it) and an optional
label carries the UI text for the resulting checkbox. Inside
ptr_app() / ptr_server()
the parser sees the wrapper and unwraps it at translate time, stamping
the boot-state metadata + UI label onto the resulting node. The
wrapper itself never appears in the typed tree.
Usage
ppVerbSwitch(.data, verb_expr, switch_on = TRUE, label = NULL)
Arguments
.data |
A data frame or pipe-supplied dataset (the implicit
|
verb_expr |
A data-pipeline verb call (e.g. |
switch_on |
A length-1 non-NA logical literal. In |
label |
Optional length-1 character used as the checkbox label
inside |
Details
Outside ptr_app() it behaves per its R semantics so naked-dplyr
scripts still render: ppVerbSwitch(.data, mutate(x = 1), FALSE)
returns .data unchanged; ppVerbSwitch(.data, mutate(x = 1), TRUE)
routes .data through the verb call. label is metadata-only
outside ptr_app() (the naked-R path ignores it).
Value
Outside ptr_app(): returns .data unchanged when
switch_on = FALSE, otherwise the result of verb_expr applied to
.data.
Data-argument position
ppVerbSwitch(.data, verb_expr, switch_on = TRUE) inserts .data as
the first positional argument of verb_expr when switch_on is
TRUE. This matches the tidyverse convention and the translator's
pipeline-stage handling; non-tidyverse verbs that take data in a
later argument are not supported (use a lambda stage or a named
wrapper instead).
Examples
if (requireNamespace("dplyr", quietly = TRUE)) {
# Naked-R semantics: switch_on = FALSE leaves the data unchanged.
identical(
ppVerbSwitch(mtcars, dplyr::mutate(mpg = mpg + 100), FALSE),
mtcars
)
# switch_on = TRUE routes .data through the verb.
result <- ppVerbSwitch(mtcars, dplyr::filter(mpg > 20), TRUE)
nrow(result) # 14
}
# Inside ptr_app(), the wrapper becomes a node-level default + a
# labelled boot-state-on checkbox:
if (interactive()) {
ptr_app(
"mtcars |> ppVerbSwitch(dplyr::filter(mpg > 20), TRUE, label = 'Filter') |>
ggplot(aes(x = mpg, y = wt)) + geom_point()"
)
}
Build a Shiny App from a ggpaintr Formula
Description
Translates formula into the typed AST, builds the per-layer panel UI,
and wires the server end-to-end. Returns a shiny.appobj ready to be run.
This page is the canonical reference for the formula grammar and the
empty-call cleanup rule used by every public entry point.
Usage
ptr_app(
formula,
envir = parent.frame(),
ui_text = NULL,
expr_check = TRUE,
safe_to_remove = character(),
css = NULL,
spec = NULL
)
Arguments
formula |
Either a single character scalar containing a ggplot
expression with |
envir |
Environment used to resolve local data objects. |
ui_text |
Optional named list of copy overrides; see |
expr_check |
Controls formula-level |
safe_to_remove |
Character vector of additional function names whose
zero-argument calls should be dropped after placeholder substitution
leaves them empty. Defaults to |
css |
Optional character vector of paths to additional CSS files. Each
is served as a static resource and linked after |
spec |
An optional named list of fully-qualified Shiny input id -> value, used to override widget defaults at session boot. |
Value
A shiny.appobj.
Formula grammar
A ggpaintr formula is a single ggplot() call written as a string. Drop
one of five placeholder keywords anywhere a value would normally go, and
the runtime substitutes the user's input back into the expression at
render time.
ppVarColumn picker, data-aware. Renders as a
selectInputpopulated with the upstream data's column-name vector. Example:aes(x = ppVar).ppTextFree-text input. Renders as a
textInput. Example:labs(title = text).ppNumNumeric input. Renders as a
numericInput. Example:geom_point(size = ppNum).ppExprCode editor, validated by
expr_check. The only keyword that accepts arbitrary R code; for the safety model see the ggpaintr book's safety chapter (development-version docs, https://willju-wangqian.github.io/ggpaintr-book/safety.html). Example:facet_wrap(ppExpr).ppUploadFile picker, returns a data frame. Renders as a
fileInputplus an optional dataset-name textbox. Accepted formats:.csv,.tsv,.rds,.xlsx,.xls,.json. Uploaded data is normalized viaptr_normalize_column_names()automatically. Example:ggplot(ppUpload, ...).
Any keyword occurrence may carry shared = "<id>" to lift the widget out
of its per-layer panel into a top-level shared section. Used by
ptr_app_grid() to drive multiple plots from one control. See
vignette("ggpaintr-tutorial") for worked examples of each keyword.
Empty-call cleanup
When a placeholder resolves to "missing" (an empty ppVar pick, a blank
ppText, a cleared ppNum, an unchecked layer checkbox), its argument is
dropped from the generated code. If the surrounding call is left empty
and its bare name is in the curated cleanup list, the whole call
disappears too. This rule applies to both placeholder-driven empties and
user-authored literal empty calls like + labs().
Curated ggplot2 names that are dropped when empty:
theme, labs, xlab, ylab, ggtitle, facet_wrap, facet_grid, facet_null, xlim, ylim, lims, expand_limits, guides, annotate, annotation_custom, annotation_map, annotation_raster, aes, aes_, aes_q, aes_string, element_text, element_line, element_rect, element_point, element_polygon, element_geom
Empty calls to similar no-op helpers from dplyr, tidyr, tibble,
pillar, purrr, stringr, forcats, lubridate, and hms are
covered by the same rule.
geom_*() and stat_*() layers are never dropped, regardless of
whether they end up empty — they inherit their aesthetics from
ggplot() and remain meaningful with no arguments.
element_blank() is intentionally not in the cleanup list: its
empty form is a meaningful "suppress" directive, not a no-op.
Third-party helpers (e.g. pcp_theme() from ggpcp) are not in the
cleanup list — being absent is the "removal safety unknown" signal.
Use safe_to_remove = c("pcp_theme") to opt a specific name in.
See Also
ptr_app_bslib() for the same contract with a bslib theme;
ptr_app_grid() for multi-plot apps with shared widgets;
ptr_define_placeholder_value() et al. for registering custom
keywords; ptr_ui_text() for copy overrides; ptr_css() for the
css = argument and themable CSS custom properties;
vignette("ggpaintr-tutorial") for tutorial examples.
Examples
if (interactive()) {
# Expression mode (primary): pass the unquoted ggplot expression.
ptr_app(ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point())
# `!!` splices a value into the expression.
col <- rlang::sym("mpg")
ptr_app(ggplot(mtcars, aes(x = !!col, y = ppVar)) + geom_point())
# String mode (fallback): the same formula as text.
ptr_app("ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point()")
}
Bslib-Themed App: A Demonstration Wrapper
Description
A small wrapper that composes the public ggpaintr primitives
(ptr_ui_controls(), ptr_ui_plot(), ptr_ui_toggle_code(),
ptr_server()) inside a bslib::page_sidebar() shell. Exported
so users who want a quick
bslib-themed app can call it directly, but its primary purpose is to
illustrate the wrapper pattern: the
entire source is short enough to copy and adapt for any other layout or
theme.
Usage
ptr_app_bslib(
formula,
envir = parent.frame(),
ui_text = NULL,
expr_check = TRUE,
safe_to_remove = character(),
theme = NULL,
spec = NULL
)
Arguments
formula |
A single formula string using |
envir |
Environment used to resolve local data objects when building the app. |
ui_text |
Optional named list of copy overrides for UI labels, helper
text, and placeholders. The app title is read from
|
expr_check |
Controls formula-level |
safe_to_remove |
Character vector of additional function names whose
zero-argument calls should be dropped after placeholder substitution
leaves them empty. Defaults to |
theme |
A |
spec |
An optional named list of fully-qualified Shiny input id -> value, used to override widget defaults at session boot. For the formula grammar (placeholder keywords, shared annotation,
empty-call cleanup), see |
Details
For the recommended primary entry points, see ptr_app() and
ptr_app_grid(). Requires the bslib package
(install.packages("bslib")).
Single-formula ppVar(shared = "...") coordination is not supported on this
wrapper — the auto-built shared widgets ptr_app() provides require an
internal helper that is not part of the public API today. Use ptr_app()
for that case, or ptr_app_grid() for multi-formula shared coordination
(the shared widgets auto-render from each placeholder's own build_ui).
Value
A shiny.appobj.
Grid App: Multiple ggpaintr Plots With Shared Controls
Description
Builds a fluid layout of N plot modules with a top-level wellPanel for
shared input widgets and a "Draw all" button that triggers a redraw across
every plot. Each plot's shared = "..." placeholders collapse to one
widget in the top panel, rendered from the placeholder's own build_ui.
Usage
ptr_app_grid(
plots,
envir = parent.frame(),
ui_text = NULL,
draw_all_label = "Draw all",
expr_check = TRUE,
css = NULL,
ncol = NULL,
nrow = NULL,
spec = NULL
)
Arguments
plots |
A list of formula strings, one per plot. |
envir |
Environment used to resolve local data objects. |
ui_text |
Optional named list of copy overrides. The page header
reads |
draw_all_label |
Label for the draw-all action button. |
expr_check |
Controls formula-level |
css |
Optional character vector of paths to additional CSS files,
linked once at the page level after |
ncol |
Number of plot columns. Default |
nrow |
Number of plot rows. Default |
spec |
An optional named list of fully-qualified Shiny input id -> value, used to override widget defaults at session boot. The same flat spec is passed to every per-plot engine; each instance filters by its own namespace prefix. |
Details
For the formula grammar (placeholder keywords, shared = "<id>"
annotation, empty-call cleanup), see ptr_app().
Value
A shiny.appobj.
Removed shared_ui
The shared_ui argument is no longer supported (see ptr_shared() for the
full rationale). To customise the widget a shared key renders, define a
custom placeholder with the build_ui you want
(ptr_define_placeholder_*) and use it in the formula — the shared widget
auto-renders from that build_ui.
See Also
ptr_css() for the css = argument and themable CSS custom properties.
Argument validators for placeholder definitions (ptr_arg_*)
Description
These helpers are factories that return a closure of shape
function(arg_expr) -> canonical_value | abort(). The closure validates
the unevaluated R expression captured as a placeholder's positional default
argument and returns a canonical value, or aborts with a clear message.
Usage
ptr_arg_symbol_or_string(vector = FALSE)
ptr_arg_string(vector = FALSE)
ptr_arg_symbol(vector = FALSE)
ptr_arg_numeric(vector = FALSE, length = NULL)
ptr_arg_expression()
Arguments
vector |
Logical scalar (default |
length |
Optional integer length required of the resulting numeric
vector; honored only when |
Details
The validators operate on AST only: they do not call eval(), parse(),
or any deparse-and-reparse cycle on their input. The numeric helper
ptr_arg_numeric() (scalar by default, vector via vector = TRUE) walks
the AST
against the constant-fold allowlist registry (see
ptr_register_constant_fold()) and then evaluate in a sealed environment
whose only bindings are the registered names.
Symbol policy is per-helper:
-
ptr_arg_symbol_or_string()accepts a bareword symbol (returned as its character name, preserving non-syntactic / backticked names) or any single string literal (including the empty string). -
ptr_arg_symbol()accepts only a bareword symbol (returned as its character name); rejects string literals, numbers, and compound calls. -
ptr_arg_string()accepts only a single string literal (including the empty string); rejects symbols and numbers. -
ptr_arg_numeric()accepts any AST whose every node is a syntactic literal or a registered constant-fold name; in the default scalar mode the result must be a length-one non-NA numeric. For the vector form useptr_arg_numeric(vector = TRUE, length = NULL). -
ptr_arg_expression()is a verbatim store: it returns its input unchanged so it can later be evaluated in the data context. As a convenience it emits a one-shot warning if the user wraps the expression inquote(),bquote(),rlang::ppExpr(), orrlang::quo()(the wrapper is stored verbatim).
Each of ptr_arg_symbol_or_string(), ptr_arg_symbol(),
ptr_arg_string(), and ptr_arg_numeric() takes a vector flag. With
vector = FALSE (the default) the validator parses a single scalar element
and returns a length-one value. With vector = TRUE it parses a c(...)
literal element-by-element (each element subject to the helper's scalar
element rule) and returns the whole vector; a lone element is treated as a
length-one vector. For ptr_arg_numeric(vector = TRUE) the optional
length check (honored only in vector mode) asserts the parsed vector's
length.
Value
A closure that takes an unevaluated expression and returns the canonical default value, or aborts.
Examples
is_symbol_ok <- ptr_arg_symbol_or_string()
is_symbol_ok(quote(mpg))
is_symbol_ok("mpg")
is_num <- ptr_arg_numeric()
is_num(5)
is_num(quote(2 * pi))
is_vec <- ptr_arg_numeric(vector = TRUE, length = 2L)
is_vec(quote(c(0, 1)))
Remove user-registered placeholders
Description
Unregisters placeholders added with ptr_define_placeholder_value(),
ptr_define_placeholder_consumer(), or ptr_define_placeholder_source().
The five built-in placeholders (ppVar, ppText, ppNum, ppExpr,
ppUpload) and the two structural keywords (ppLayerOff, ppVerbSwitch)
are never removed.
Usage
ptr_clear_placeholder(keyword = NULL)
Arguments
keyword |
Optional single string. When supplied, only that placeholder is removed. When omitted (the default), every user-registered placeholder is removed. |
Value
The character vector of keywords that were removed, invisibly.
Examples
ptr_define_placeholder_value(
"demo_kw",
build_ui = function(node, ...) shiny::textInput(node$id, "demo"),
resolve_expr = function(value, node, ...) value
)
ptr_clear_placeholder("demo_kw")
Constant-fold allowlist registry
Description
The numeric default-argument validator ptr_arg_numeric() (scalar by
default, vector via vector = TRUE) walks the placeholder's
default-argument
AST against an allowlist of function and constant names. Authors can
extend the allowlist with ptr_register_constant_fold() when their
placeholder definitions need additional pure operators.
Usage
ptr_register_constant_fold(name, value)
ptr_clear_constant_fold(name = NULL)
ptr_constant_fold_keywords()
Arguments
name |
Character scalar function or constant name. |
value |
Function or numeric constant to bind under |
Details
Built-in entries seeded at package load:
Arithmetic:
-,+,*,/,^,%%,%/%Sequence constructors:
:,c,seq,seq.int,seq_len,seq_along
Syntactic literals (TRUE, FALSE, NA, NA_integer_, NA_real_,
Inf, NaN) are recognised by the walker directly and never need
registration. pi resolves through the registry's parent
(baseenv()).
Value
ptr_register_constant_fold() and ptr_clear_constant_fold()
return invisible(NULL). ptr_constant_fold_keywords() returns a
character vector of currently registered names.
Examples
ptr_register_constant_fold("log10", log10)
ptr_arg_numeric()(quote(log10(100)))
ptr_clear_constant_fold("log10")
CSS customisation hooks for ggpaintr apps
Description
Every raw-Shiny entry point (ptr_app(), ptr_app_grid(),
ptr_ui(), ptr_shared_panel()) accepts a css = argument: a character vector of
paths to .css files. Each path's parent directory is registered as a
Shiny resource under a hash-derived prefix, and one <link> tag is
emitted per file. User stylesheets are linked after ggpaintr's
bundled stylesheet, so rules at equal specificity win.
Details
The bundled stylesheet exposes its theme as CSS custom properties
under the .ptr-app selector. Override any subset of these in a
user-supplied stylesheet to retheme without touching individual rules.
Tokens
--ptr-bgApp background. Default
#fafbfc.--ptr-surfaceCard / sidebar background. Default
#ffffff.--ptr-borderStandard border colour. Default
#e7e9ee.--ptr-inkBody text colour. Default
#1f2530.--ptr-mutedMuted / secondary text. Default
#6b7280.--ptr-accentPrimary accent (action button bg). Default
#c1372c.--ptr-accent-strongHover / active accent. Default
#9a2b22.--ptr-accent-weakFaint accent tint. Default
rgba(193,55,44,0.13).--ptr-accent-lineAccent border. Default
rgba(193,55,44,0.22).--ptr-radiusLarge radius (cards, sidebar). Default
10px.--ptr-radius-smSmall radius (buttons, controls). Default
7px.--ptr-shadowCard shadow. Default two-layer drop.
--ptr-shadow-lgFloating-window shadow. Default two-layer drop.
--ptr-fontUI font stack. Default system-ui stack.
--ptr-monoMono font stack. Default system mono stack.
Specificity
Some rules use a doubly-scoped selector (e.g. .ptr-app .btn.action-button).
To override these, match or exceed that specificity in your stylesheet
(either with the same selector, or with !important).
Define a data-consumer placeholder (e.g. column picker)
Description
A consumer placeholder is a value placeholder that additionally
receives the columns of the upstream data frame — typically a column
picker. The built-in example is ppVar. See
vignette("ggpaintr-tutorial") § "Defining your own placeholders"
(consumer role).
Usage
ptr_define_placeholder_consumer(
keyword,
build_ui,
resolve_expr,
validate_session_input = NULL,
parse_positional_arg = NULL,
parse_named_args = list(),
embellish_eval = NULL,
ui_text_defaults = list(label = "Pick a column for {param}")
)
Arguments
keyword, ui_text_defaults |
|
build_ui |
Widget-seeding contract — Consumer-specific rule: filter through
|
resolve_expr |
|
validate_session_input |
Optional |
parse_positional_arg, parse_named_args |
See |
embellish_eval |
Optional |
Value
The runtime callable (identity by default; override with
embellish_eval = ...). Also called for its registration side effect; use
ptr_clear_placeholder() to remove it.
See Also
vignette("ggpaintr-tutorial") § "Defining your own placeholders";
ptr_define_placeholder_value(), ptr_define_placeholder_source().
Examples
# A consumer that picks a numeric-only column.
# Note: `selected = NULL` formal (per the seeding contract) plus
# intersect() filter (per the consumer-specific rule). Empty input
# renders empty; a stale pick after a data swap drops cleanly.
ptr_define_placeholder_consumer(
keyword = "numvar",
build_ui = function(node, cols, data, label = NULL,
selected = NULL, ...) {
numeric_cols <- if (is.null(data)) character(0) else
names(data)[vapply(data, is.numeric, logical(1))]
retained <- intersect(selected %||% character(0), numeric_cols)
shiny::selectInput(node$id, label = label %||% "Numeric column",
choices = numeric_cols, selected = retained)
},
resolve_expr = function(value, node, ...) {
if (length(value) != 1L || !nzchar(value)) return(NULL)
rlang::sym(value)
},
validate_session_input = function(value, ctx) {
if (length(value) == 1L && value %in% ctx$upstream_cols) TRUE
else "Pick a column that exists in the upstream data."
}
)
ptr_clear_placeholder("numvar")
Define a data-source placeholder (e.g. upload, database table)
Description
A source placeholder produces a data frame the rest of the formula
reads from. Built-in example: ppUpload. Custom examples: database
tables, built-in datasets, URL fetches.
Usage
ptr_define_placeholder_source(
keyword,
build_ui,
resolve_data,
resolve_expr = NULL,
shortcut = FALSE,
parse_positional_arg = NULL,
parse_named_args = list(),
embellish_eval = NULL,
ui_text_defaults = list(label = "Provide a data source for {param}")
)
Arguments
keyword, ui_text_defaults |
See |
build_ui |
Seeding — same opt-in shape as the other two helpers: declare an
optional |
resolve_data |
|
resolve_expr |
Optional. |
shortcut |
Single logical (default |
parse_positional_arg, parse_named_args |
See |
embellish_eval |
Optional |
Value
The runtime callable. Default for a source placeholder is a
guard that aborts when called outside an app context. Also called for
its registration side effect; use ptr_clear_placeholder() to remove
the entry.
spec= round-trip
The spec= mechanism (see ptr_app()) captures a sparse snapshot of
input values so the preserve-mode panel can publish a reproducible boot
state. For a source placeholder, ONE of two patterns must hold:
-
Shortcut pattern — set
shortcut = TRUE. The shortcut input's text value (typically the typed dataset name) carries the round-trip identity; the source's own value atnode$idis dropped from the spec, because it is typically a per-session Shiny artifact (afileInput()data.frame whosedatapathis a tempfile path that does not survive the session). The built-inppUploaduses this.Data-loading entry point (ADR 0024). When
shortcut = TRUE, the shortcut sibling is more than a name override for an uploaded frame — it is a typed-in shortcut for loading adata.framefrom the embedder's environment (envirpassed toptr_app()/ptr_server()). Any valid R name typed into the shortcut input (or seeded viaspec = list(<shortcut-id> = "df_name")) is looked up viaget(name, envir, inherits = TRUE)and bound as the resolved source frame, with OR withoutdefault=on the placeholder. The downstream pipeline, generated code panel, and consumer pickers all read the named frame fromstate$eval_envas if it had been uploaded. Failures surface on the inline error pane viaset_resolve_error:"Object 'x' not found in environment."/"Object 'x' is not a data frame."Lookup usesinherits = TRUE, so package exports become reachable — typing"plot"will resolve tographics::plotand then fail the "is not a data frame" check (loudly, not silently). -
Scalar pattern —
shortcut = FALSE. The widget's value atnode$idmust be a literal that round-trips throughdeparse()— a length-1 string / number / logical, or a simple atomic vector. TheselectInput-style example above qualifies (its value is a single string).
Source widgets whose primary value is a complex object (raw
fileInput() data.frame, environment, S4 instance, etc.) without
shortcut = TRUE cannot round-trip; opt into shortcut = TRUE and the
framework renders the sibling textInput(node$shortcut_id, ...) that
carries the binding name, mirroring ppUpload.
See Also
ptr_define_placeholder_value(), ptr_define_placeholder_consumer(),
ptr_clear_placeholder().
Examples
# A minimal in-memory dataset source (picks from pre-loaded data frames).
ptr_define_placeholder_source(
keyword = "dataset",
build_ui = function(node, label, ...) {
shiny::selectInput(node$id, label = label,
choices = c("mtcars", "iris"))
},
resolve_data = function(value, node, ...) {
if (length(value) != 1L || !nzchar(value)) return(NULL)
get(value, envir = as.environment("package:datasets"))
}
)
ptr_clear_placeholder("dataset")
Define a value placeholder
Description
Register a new keyword (e.g. pct, color, date) that ggpaintr will
recognise as a substitutable token in a formula. The keyword's widget
is built by build_ui; the widget's value is turned back into the R
code spliced into the rendered call by resolve_expr. See
vignette("ggpaintr-tutorial") § "Defining your own placeholders" for
the lifecycle walk-through, signatures table, and runnable
ptr_app() examples — this help page is reference.
Usage
ptr_define_placeholder_value(
keyword,
build_ui,
resolve_expr,
validate_session_input = NULL,
parse_positional_arg = NULL,
parse_named_args = list(),
embellish_eval = NULL,
ui_text_defaults = list(label = "Enter a value for {param}")
)
Arguments
keyword |
Single non-empty string. Must be a syntactically valid R
name (passes |
build_ui |
Widget-seeding contract — Declare
Because the framework omits the argument on the first-render-no-
default path, a hook signature without a formal default for
Render empty when Never read |
resolve_expr |
|
validate_session_input |
Optional |
parse_positional_arg |
Optional validator closure for the (single) positional
argument the keyword accepts inside a formula. |
parse_named_args |
Named list of validator closures for additional named
arguments beyond the reserved |
embellish_eval |
Optional |
ui_text_defaults |
Named list of single non-NA character defaults
feeding the |
Details
Three roles. Pick this constructor for a value placeholder (a
self-contained widget like a slider, color picker, or numeric input).
Use ptr_define_placeholder_consumer() when the widget needs the
upstream column names (column pickers). Use
ptr_define_placeholder_source() when the widget produces the data
the rest of the formula reads from (file upload, dataset chooser).
Value
The runtime callable. Default for a value placeholder is the
identity function(x, ...) x; override with embellish_eval = .... The
helper is also called for its registration side effect — use
ptr_clear_placeholder() to remove the entry.
See Also
vignette("ggpaintr-tutorial") § "Defining your own placeholders";
ptr_define_placeholder_consumer(), ptr_define_placeholder_source(),
ptr_clear_placeholder().
Examples
# A percentage placeholder: user types a number 0-100; we splice
# the fraction 0-1 into the rendered call. The hook reads `selected`
# to honor a formula default like `pct(75)` at boot and to keep a
# user-cleared widget empty across Update Plot fires (do NOT
# substitute a hardcoded fallback when selected is empty).
ptr_define_placeholder_value(
keyword = "pct",
build_ui = function(node, label = NULL, selected = NULL, ...) {
n <- suppressWarnings(as.numeric(selected))
initial <- if (length(n) == 1L && is.finite(n)) n else NA_real_
shiny::numericInput(node$id, label = label %||% "Percent",
value = initial, min = 0, max = 100, step = 1)
},
resolve_expr = function(value, node, ...) {
if (length(value) != 1L || !is.finite(value)) return(NULL)
value / 100
},
parse_positional_arg = ptr_arg_numeric(), # accept ppPct(50)-style defaults
ui_text_defaults = list(label = "Percent for {param}")
)
ptr_clear_placeholder("pct")
Extract Runtime Outputs From a ptr_state
Description
Read the latest plot object, error message, or generated code text from
the runtime result stored on a ptr_state. Use these to compose custom
UIs or to test the runtime in shiny::testServer.
Usage
ptr_extract_plot(state)
ptr_extract_error(state)
ptr_extract_code(state)
Arguments
state |
A |
Value
ptr_extract_plot returns a ggplot object (or NULL on
failure); ptr_extract_error returns a string or NULL;
ptr_extract_code returns a single string.
Reactive contexts
Each function wraps its read in shiny::isolate(), so it works in both
reactive and non-reactive contexts and returns the current value without
establishing a reactive dependency.
Do not call these inside a render*{} block if you want the output
to update when the plot rerenders. Because isolate() suppresses the
dependency on state$runtime(), the render block fires once on mount and
never again. Inside a reactive context, read state$runtime() directly —
that takes the dependency and re-fires on every Update plot click.
Reserve ptr_extract_* for non-reactive contexts: download handlers,
shiny::testServer() assertions, and one-shot reads outside any session.
Examples
shiny::isolate({
state <- ptr_init_state(
"ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()"
)
ptr_extract_code(state)
})
Add ggplot2 Layers Programmatically
Description
Evaluate one or more ggplot2 expressions and attach the results as
"extras" on the state. Extras are folded into the plot during the next
runtime cycle when state$runtime()$ok is TRUE. Eval failures leave
the existing extras untouched.
Usage
ptr_gg_extra(state, ...)
Arguments
state |
A |
... |
|
Value
state, invisibly.
Examples
shiny::isolate({
state <- ptr_init_state(
"ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()"
)
state <- ptr_gg_extra(state, ggplot2::theme_minimal())
ptr_extract_code(state)
})
Build a plotly Widget From a ggpaintr Instance, Wired for Linked Selection
Description
ptr_ggplotly() is the state-first counterpart to plotly::ggplotly() for
the supported L3 custom-render pattern (see ptr_server(), section "Custom
render (L3)"). Call it from inside plotly::renderPlotly() on the live
instance returned by ptr_server(): it reads the drawn plot off
state$runtime()$plot, mints a per-draw row key (the plotly key
aesthetic, on a widget-only copy of the data), sets dragmode = "select",
registers the plotly_selected / plotly_deselect events, and returns a
plain plotly object so your own plotly verbs stay composable after it.
Usage
ptr_ggplotly(state, ..., source = NULL)
Arguments
state |
A |
... |
Forwarded verbatim to |
source |
Character scalar for plotly's |
Details
The helper owns the shiny::req() pre-draw guard (it raises Shiny's silent
pre-draw condition before the first draw, exactly like a bare req(p)) and
derives plotly's source = channel from the instance namespace, so the
companion selection reader coordinates without extra wiring. The user's
drawn data is never mutated: keys are minted per draw on the widget copy
only.
plotly is an optional dependency (in Suggests). When it is not installed,
this function aborts, mirroring ptr_app_bslib()'s bslib guard.
Value
A plain plotly htmlwidget object (inherits class "plotly"), with
dragmode = "select" set and the plotly_selected / plotly_deselect
events registered.
See Also
ptr_server() for the L3 custom-render contract;
plotly::ggplotly().
Examples
if (interactive()) {
library(shiny)
library(plotly)
f <- rlang::expr(
ggplot(mtcars, aes(x = ppVar(wt), y = ppVar(mpg))) + geom_point()
)
ui <- ptr_ui_page(
ptr_ui_controls(formula = f, id = "p"),
plotly::plotlyOutput("plt")
)
server <- function(input, output, session) {
state <- ptr_server(f, "p")
output$plt <- plotly::renderPlotly({
# state-first: req() guard + key minting + select wiring are internal
ptr_ggplotly(state, tooltip = "all") |>
plotly::layout(legend = list(orientation = "h"))
})
}
shinyApp(ui, server)
}
Enumerate every Shiny id a ggpaintr formula produces
Description
Walks the typed AST of a single formula and returns one row per Shiny
id ever rendered by ptr_ui() / ptr_server() for that formula:
placeholder sleeves, inner widgets, source companions, layer-level
controls (checkbox, subtab, content container), pipeline stage
toggles, plus the static infrastructure ids (ptr_plot, ptr_error,
ptr_code, ptr_code_mode, ptr_update_plot).
Usage
ptr_id_table(formula, id = NULL)
Arguments
formula |
A single ggpaintr formula string (the same input you
would pass to |
id |
Optional outer namespace — the same string you pass to
|
Details
Advanced (L3) users call this to build their own UI by hand and still
get the server's bindings to match. The default-layout L2 path does
not need it; ptr_ui() emits these ids internally.
Value
A data.frame with one row per Shiny id and ten columns:
-
id— the Shiny id (prefixed whenid=is given andscope == "instance"). -
kind—"input_widget"or"output_slot". -
role— semantic role:"placeholder","source_companion","layer_checkbox","layer_subtab","layer_content","stage_enabled","ptr_plot","ptr_error","ptr_code","ptr_code_mode","ptr_update_plot". -
scope—"instance"(namespaced viashiny::NS(id)) or"global"(un-namespaced; only used by cross-formula shared-panel keys in aptr_shared()setup — see Single-formula section). -
include_in_ui—TRUEwhen the row is something the user places in their custom UI;FALSEwhen the server populates it inside a sleeve (<id>_ui) and the user must not place it manually. The twoFALSEcases are the inner placeholder widget andppUpload's file-name companion. -
layer— layer name ("ggplot","geom_point", …) orNA. -
keyword— placeholder keyword ("ppVar"/"ppText"/…) orNA. -
param— argument or aesthetic name ("x","color","data", …) orNA. -
parent_call— immediate enclosing call ("aes","head", or the layer itself when the placeholder is a direct layer arg) orNA. -
shared— shared key ("xcol", …) orNA.
Stability under formula edits
Adding a layer at the end keeps existing ids stable. Reordering
arguments inside aes() or a pipeline shifts positional paths and
therefore changes ids; renaming a placeholder keyword or its
shared= annotation also changes ids.
Single-formula
ptr_id_table() accepts a single formula. In multi-instance
(ptr_shared(formulas = list(…))) layouts the partition rule
decides whether shared_<key> lives in an instance's inline section
or the cross-formula panel. The scope column reflects the
single-formula interpretation ("instance"); when embedding into a
shared-panel context those rows are bare ("global") and you should
override accordingly.
Examples
ptr_id_table("ggplot(ppUpload, aes(x = ppVar, y = ppVar)) + geom_point(color = ppText)")
ptr_id_table("ggplot(ppUpload, aes(x = ppVar))", id = "myplot")
Construct the ggpaintr runtime state container
Description
Builds the ptr_state object — the translated typed AST (as a
reactiveVal), the runtime result, the per-layer resolved-data caches,
the eval environment, the input-snapshot machinery, and the shared
bindings / draw trigger — used by ptr_server() and the advanced-embedder
accessors (ptr_extract_plot() / ptr_extract_error() /
ptr_extract_code(), ptr_gg_extra()).
Usage
ptr_init_state(
formula,
envir = parent.frame(),
ui_text = NULL,
expr_check = TRUE,
safe_to_remove = character(),
shared = list(),
draw_trigger = NULL,
producer_debounce_ms = NULL,
ns = shiny::NS(NULL),
server_ns = ns,
auto_bind_shared = FALSE,
shared_resolutions = list(),
shared_stage_enabled = list(),
panel_sources = list(),
plots = NULL
)
Arguments
formula |
A single formula string with |
envir |
Environment used to resolve local data objects. |
ui_text |
Optional named list of copy overrides; see |
expr_check |
Controls formula-level |
safe_to_remove |
Character vector of additional function names whose zero-argument calls should be dropped after substitution. |
shared |
Named list of reactives (one per shared key) supplied by an
outer wrapper such as |
draw_trigger |
Optional reactive carrying a click counter — a numeric
scalar that is |
producer_debounce_ms |
Optional. Controls the debounce window applied
to producer-style placeholder inputs ( |
ns |
A namespace function used for rendered ids (UI side). |
server_ns |
A namespace function used for server-side input lookups.
Defaults to |
auto_bind_shared |
If |
shared_resolutions |
Named list (keyed by raw shared key) of
host-computed resolutions for shared data-consumer ( |
shared_stage_enabled |
Named list (keyed by raw shared key) of
reactives, each returning a logical, that toggle the orphan pipeline
stages owned by that shared key (as carried in a
|
panel_sources |
Named list (keyed by source-node id) of reactives,
each returning the host-loaded data for a panel-owned shared source
(ADR 0023). Populated by the host's |
plots |
Optional list of formula strings for grid contexts. When
supplied (typically by |
Details
This is a state container, not a from-scratch reactive-app builder: it
allocates the reactives but does not attach the pipeline / runtime
observers (those live in internal ptr_setup_* helpers wired by
ptr_server()). Reach for ptr_init_state() directly when you want to
drive the typed tree programmatically or exercise ggpaintr under
shiny::testServer(); for a fully wired app use ptr_server().
Value
A ptr_state list (S3 class c("ptr_state", "list")).
Examples
shiny::isolate({
state <- ptr_init_state(
"ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point()"
)
is.list(state)
})
Get the ggpaintr LLM system-prompt primer
Description
Returns the text of inst/llm/primer.md as a single string. Intended
for use as the system_prompt = (or equivalent) argument when wiring
ggpaintr into an LLM client such as ellmer, so the model knows when
to reach for ggpaintr and at which of the three integration levels.
Usage
ptr_llm_primer()
Details
The primer is short by design — it establishes the extensibility
model and points the model at ptr_llm_topic() for runnable
examples. A companion tool that exposes ptr_llm_topic() to the
model lets it pull only the example it needs, instead of loading
every topic into the system prompt.
Value
A single character string.
See Also
ptr_llm_topic(), ptr_llm_topics()
Examples
primer <- ptr_llm_primer()
cat(substr(primer, 1, 200))
Register ggpaintr with an ellmer chat session
Description
One-line registration of the ggpaintr docs tool on an existing
ellmer Chat object. The tool wraps
ptr_llm_topic() so the LLM can pull focused, runnable examples
on demand instead of loading every topic into the system prompt.
Usage
ptr_llm_register(chat, tool_name = "ggpaintr_docs")
Arguments
chat |
An ellmer |
tool_name |
String. The name the LLM will call the tool under.
Defaults to |
Details
The set of valid topic names is snapshotted at registration time
using ptr_llm_topics(), so the LLM cannot request a topic that
does not exist. If you upgrade ggpaintr in the same session and new
topics are added, call this again on a fresh chat.
This function does not set the chat's system prompt. Pass
ptr_llm_primer() to the system_prompt = argument of your
chat_*() constructor so the model knows when to reach for the tool.
Value
The chat object (invisibly), for piping.
See Also
ptr_llm_primer(), ptr_llm_topic(), ptr_llm_topics()
Examples
if (interactive()) {
library(ellmer)
chat <- chat_anthropic(system_prompt = ptr_llm_primer())
ptr_llm_register(chat)
chat$chat("Build a Shiny app where the user picks X and Y columns from mtcars.")
}
Fetch a ggpaintr LLM topic
Description
Returns the runnable example + commentary for one topic as a single
character string. Designed to back an LLM tool such as
ggpaintr_docs(topic): the model calls it when the user asks for
help with an interactive ggplot task, and receives exactly one
focused example instead of the entire manual.
Usage
ptr_llm_topic(topic)
Arguments
topic |
Topic name. Must be one of |
Details
Each topic is derived from (and kept in sync with) either
README.Rmd or the tutorial vignette
(ggpaintr-tutorial).
Value
A single character string.
See Also
ptr_llm_topics(), ptr_llm_primer()
Examples
cat(ptr_llm_topic("level1_ptr_app"))
List available ggpaintr LLM topic names
Description
Returns the character vector of topic names accepted by
ptr_llm_topic(). Matches the files in inst/llm/topics/ (stripped
of the .md extension), sorted alphabetically.
Usage
ptr_llm_topics()
Value
A character vector.
See Also
ptr_llm_topic(), ptr_llm_primer()
Examples
ptr_llm_topics()
Normalize Dataset Column Names for ggpaintr
Description
Normalize incoming column names so ppVar placeholders can require exact,
syntactic, unique column-name matches at runtime.
Usage
ptr_normalize_column_names(data)
Arguments
data |
A data frame or an object coercible with |
Details
Uploaded data is normalized automatically by the runtime — every
successful ppUpload placeholder passes through this function (or its
data.frame-coercing sibling for non-data.frame returns from
readRDS / readxl / jsonlite). Call ptr_normalize_column_names()
yourself only for in-session data frames you reference by name from
a formula. If a local data frame has spaces, reserved words, or
duplicates in its column names, pipe it through this function before
passing it to ptr_app().
Value
A tabular object with ggpaintr-safe column names. Existing
data.frame subclasses keep their class. Names are made syntactic, unique,
and safe against reserved-word collisions. Non-data.frame inputs return
the data.frame created by as.data.frame().
Examples
messy <- data.frame(
check.names = FALSE,
"first column" = 1:3,
"if" = 4:6
)
clean <- ptr_normalize_column_names(messy)
names(clean)
Get or Set ggpaintr Package Options
Description
Combined getter/setter for ggpaintr's global settings, modeled after base
base::options(). Calling with no arguments returns all current settings
as a named list. Passing one or more named logical arguments sets those
settings and invisibly returns the previous values, suitable for the
do.call(ptr_options, old) round-trip pattern used by
withr::with_options() and on.exit().
Usage
ptr_options(...)
Arguments
... |
Named logical arguments — one per setting to update. Setting names must match the registry above. |
Value
When called with no arguments, a named list of all current setting values. When called with named arguments, the previous values of the updated settings, returned invisibly.
Available settings
verbose-
Logical. When
TRUE, ggpaintr emits informative messages such as "Layer foo() removed (no arguments provided)." DefaultFALSE— these messages are intended for debugging the formula pipeline and are off by default. Underlying option:options(ggpaintr.verbose = ...). gate_draw-
Logical. When
TRUE(the default), the rendered plot updates only when the user clicks the "Update plot" button — every placeholder change is batched until the click. WhenFALSE, the button is omitted from the UI and the plot re-renders reactively on every placeholder change (live mode). Read once when the app is built, so set it before callingptr_app()/ptr_ui(). Underlying option:options(ggpaintr.gate_draw = ...). suppress_warnings-
Logical. When
TRUE, R warnings emitted while the plot is drawn (e.g.loessfit warnings such as "all data on boundary of neighborhood" or "Failed to fit group N") are silenced rather than printed to the console. DefaultFALSE— warnings surface as usual. Only the plot-drawing step is wrapped; errors still propagate to the inline error pane. Read once when the app is built, so set it before callingptr_app()/ptr_ui(). Underlying option:options(ggpaintr.suppress_warnings = ...).
Examples
# Inspect current values
ptr_options()
# Silence the "Layer ... removed" notice for one block
old <- ptr_options(verbose = FALSE)
on.exit(do.call(ptr_options, old), add = TRUE)
Read a ptr_ggplotly() Linked Selection As Rows or a Flag Column
Description
ptr_plotly_selection() is the companion reader for ptr_ggplotly(): it
returns a Shiny reactive carrying the current brush/lasso selection of the
plotly widget, projected one of two ways. Call it once in your server (not
inside a render) on the live instance returned by ptr_server() and feed
the returned reactive to a table, a second formula, or any downstream
consumer.
Usage
ptr_plotly_selection(state, mode = c("rows", "flag"), source = NULL)
Arguments
state |
A |
mode |
|
source |
Character scalar for plotly's |
Details
A selection names rows of the drawn data — state$runtime()$plot$data
of the draw that produced the widget — never "the original object". Keys are
minted per draw and are meaningless across draws, so the selection
resets to empty on every draw (a redraw after a filter()/mutate()
pipeline-head change or an upload swap starts the selection over). A
plotly_deselect event clears it likewise. Two projections of the one
selection:
-
mode = "rows"— the selected slice; a zero-row data frame with the drawn data's columns when nothing is selected (so ashiny::renderTable()consumer needs noreq()dance). -
mode = "flag"— the full drawn data plus a logical.ptr_selectedcolumn,TRUEexactly at the selected rows (allFALSEwhen empty).
.ptr_selected is a reserved name: a pre-existing .ptr_selected on the
drawn data is silently overwritten (the overwrite keeps chained
selection-fed instances correct). The internal .ptr_row key never appears
in either projection.
Pre-draw window: before the first draw there is no snapshot yet, so the
returned reactive raises Shiny's silent pre-draw condition (via
shiny::req()); under live mode a selection-fed instance shows its inline
pre-draw state for one flush. Live-mode key reset: changing a placeholder
widget re-draws the source plot, which re-mints the keys, so the selection
resets to empty on that picker change.
plotly is an optional dependency (in Suggests); this reader is only
meaningful alongside ptr_ggplotly(), which guards on plotly being
installed.
Value
A Shiny reactive. Its value is the rows projection (a data frame, the
selected slice; zero rows, same columns, when empty) or the flag projection
(the full drawn data plus a logical .ptr_selected), per mode.
See Also
ptr_ggplotly() for the widget side; ptr_server() for the L3
custom-render contract.
Examples
if (interactive()) {
library(shiny)
library(plotly)
f <- rlang::expr(
ggplot(mtcars, aes(x = ppVar(wt), y = ppVar(mpg))) + geom_point()
)
ui <- ptr_ui_page(
ptr_ui_controls(formula = f, id = "p"),
plotly::plotlyOutput("plt"),
tableOutput("sel")
)
server <- function(input, output, session) {
state <- ptr_server(f, "p")
output$plt <- plotly::renderPlotly({
ptr_ggplotly(state, tooltip = "all")
})
# Full loop: brush the plot -> the selected rows appear in the table.
sel <- ptr_plotly_selection(state, mode = "rows")
output$sel <- renderTable(sel())
}
shinyApp(ui, server)
}
Render a typed tree back to R source code
Description
Render a typed tree back to R source code
Usage
ptr_render(node, preserve_placeholders = FALSE)
Arguments
node |
Typed tree root (or any node) to render. |
preserve_placeholders |
If |
Value
Character scalar of R source code.
Resolve copy for one ggpaintr control or app element
Description
Looks up the effective label/help/placeholder for a single UI element,
applying the defaults -> params -> layers specificity chain and
interpolating the {param} / {layer} tokens. Placeholder authors can
call this inside a custom build_ui hook so their control is labelled
through the same override chain as the built-in controls.
Usage
ptr_resolve_ui_text(
component,
keyword = NULL,
param = NULL,
layer_name = NULL,
ui_text = NULL
)
Arguments
component |
One of |
keyword |
Placeholder keyword (e.g. |
param |
Optional parameter / aesthetic name (e.g. |
layer_name |
Optional layer name (e.g. |
ui_text |
|
Value
A named list with label, help, placeholder, and empty_text.
Examples
# Resolve copy for the title element
ptr_resolve_ui_text("title")
# Resolve copy for a var control on the x-axis
ptr_resolve_ui_text("control", keyword = "ppVar", param = "x")
# Inside a custom `build_ui` hook, label the control through the same
# override chain ggpaintr uses for built-in controls:
my_build_ui <- function(node, label, ...) {
copy <- ptr_resolve_ui_text(
"control",
keyword = node$keyword,
param = node$param,
ui_text = list(...)$ui_text
)
shiny::textInput(node$id, label = copy$label %||% label)
}
Server for a ggpaintr Formula
Description
The single public server-side entry point for a ggpaintr formula,
used identically at L2 (default layout via ptr_ui()) and L3 (your own
hand-composed layout from the bare ptr_ui_* pieces). It namespaces and
wires the whole reactive engine, registers the built-in ptr_plot /
ptr_error / ptr_code outputs (a piece you never place in the UI is a
harmless no-op), and returns the ptr_state so you can drive a
custom renderer. Additional arguments are forwarded to ptr_init_state()
(e.g. shared, draw_trigger, expr_check, safe_to_remove,
ui_text).
Usage
ptr_server(
formula,
id = NULL,
envir = parent.frame(),
...,
shared_state = NULL,
spec = NULL
)
Arguments
formula |
Either a single character scalar containing a ggplot
expression with |
id |
Optional module id; must match the id passed to |
envir |
Environment used to resolve local data objects. |
... |
Forwarded to |
shared_state |
Optional |
spec |
An optional named list of fully-qualified Shiny input id -> value, used to override widget defaults at session boot. |
Value
The ptr_state list from ptr_init_state(). This is the
supported L3 custom-render handle: state$runtime()$plot /
$code / $error. (Its server_ns_fn / ui_ns_fn slots are
internal plumbing — not a public escape hatch.)
Custom render (L3)
Custom rendering is UI-side: place your own output widget (e.g.
plotly::plotlyOutput()) at shiny::NS(id)("my_plot"), never place
ptr_ui_plot(), and read the live plot off the returned state — there
is no user-authored moduleServer wrapping any ggpaintr engine and
no lower-level server function to reach for:
# server:
state <- ptr_server(formula, "p")
output$my_plot <- plotly::renderPlotly(state$runtime()$plot)
# ui: plotly::plotlyOutput(shiny::NS("p")("my_plot"))
state$runtime() is reactive; $plot is the built ggplot/ggplot-like
object, $code the generated source string, $error any inline error.
See vignette("ggpaintr-tutorial").
For cross-formula coordination — multiple ggpaintr instances driven by
one widget — build the coordinator with ptr_shared_server() and pass
the returned ptr_shared_state as shared_state =. The state's
shared / draw_trigger / shared_resolutions slots are unpacked and
forwarded to ptr_init_state(); if an explicit shared = ... /
draw_trigger = ... / shared_resolutions = ... is also passed via
..., that explicit value wins. A single formula with shared = "..."
placeholders needs no shared_state — ptr_server() self-binds every
declared key under its own namespace, matching what ptr_app() does.
See Also
ptr_ui(), ptr_ui_plot(), ptr_shared(),
ptr_shared_panel(), ptr_shared_server().
Examples
if (interactive()) {
f <- rlang::expr(ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point())
# L2: default layout
shiny::shinyApp(
ui = shiny::fluidPage(ptr_ui(!!f, "p")),
server = function(input, output, session) {
ptr_server(!!f, "p")
}
)
# L3: own the render path off the returned state
shiny::shinyApp(
ui = ptr_ui_page(
ptr_ui_controls(formula = !!f, id = "p"),
plotly::plotlyOutput(shiny::NS("p")("my_plot"))
),
server = function(input, output, session) {
state <- ptr_server(!!f, "p")
output[[shiny::NS("p")("my_plot")]] <-
plotly::renderPlotly(state$runtime()$plot)
}
)
}
Build the Shared Coordinator for a Multi-Instance Embedding
Description
Constructs a single pure, non-reactive coordinator object from the full
set of plot formulas. The coordinator computes the cross-formula
partition – a shared key used by exactly one formula renders in that
formula's inline shared section; a key used by two or more formulas
renders in the one standalone ptr_shared_panel(). Because every
consumer derives its view from this one object, the UI and server can
never disagree about the partition.
Usage
ptr_shared(
formulas,
id = NULL,
ui_text = NULL,
expr_check = TRUE,
draw_all_label = "Draw all"
)
Arguments
formulas |
A non-empty character vector or list, one element per
embedded |
id |
Optional character scalar that namespaces every id this
coordinator emits, so two or more coordinators can coexist in one
Shiny session without colliding on shared |
ui_text |
Optional copy overrides forwarded to the auto-built
widgets (see |
expr_check |
Whether to validate |
draw_all_label |
Label for the "Draw all" button rendered in the panel when two or more formulas are supplied. |
Details
This is strictly multi-instance API: with a single ggpaintr instance all
shared widgets auto-render inline and no coordinator is needed. The
coordinator is consumed by exactly three functions, each taking only the
object: ptr_shared_panel(), ptr_ui_shared_panel(), and
ptr_shared_server().
Errors when no formula declares a shared = "..." annotation – building
the coordinator is a declaration of intent.
Value
A ptr_shared_spec S3 object. Public fields: panel_keys
(cross-formula keys), local_keys_by_formula (per-formula inline
keys). Deterministic and idempotent for a given formulas.
Removed shared_ui
shared_ui (a named list of function(id) -> shiny.tag builders) is no
longer supported. Its original intent was to let two placeholders that
share a key share the same UI settings. But each placeholder already
carries its own build_ui rule, and two shared= placeholders simply
reuse that one rule when their widget collapses to the panel. The
customisation therefore comes from the placeholder's build_ui
(ptr_define_placeholder_*(build_ui = ...)), not from a separate
shared_ui override — so the override was redundant, and for var
consumers it actively dropped the formula default and froze the column
list. To customise a shared widget, define a custom placeholder with the
build_ui you want and use it in the formula. Label-only divergence for
the shared widget still has its own channel (node$shared_label).
See Also
ptr_shared_panel(), ptr_ui_shared_panel(),
ptr_shared_server(), ptr_ui().
Examples
obj <- ptr_shared(c(
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_point()",
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_bar()"
))
obj$panel_keys # "x" — shared by both formulas
# Quoted expressions work too, and may be mixed with strings:
obj2 <- ptr_shared(list(
rlang::expr(ggplot(mtcars, aes(x = ppVar(shared = "x"), y = mpg)) + geom_point()),
"ggplot(mtcars, aes(x = ppVar(shared = 'x'), y = hp)) + geom_line()"
))
obj2$panel_keys # "x"
Render the Standalone Shared Panel (L2, Self-Contained)
Description
Renders the single page-level shiny::wellPanel() holding exactly the
coordinator's cross-formula keys (obj$panel_keys, referenced by two or
more formulas). The panel is self-contained: it owns its .ptr-app
theming scope and the bundled ggpaintr asset dependency, so it can be
dropped straight into a host layout. Its server counterpart
ptr_shared_server() must run at the top level.
Usage
ptr_shared_panel(obj, css = NULL)
Arguments
obj |
A |
css |
Optional character vector of paths to additional CSS files;
linked after |
Details
Namespacing is inherited from obj$id; supply it to ptr_shared().
Value
A shiny.tag div.ptr-app wrapping the wellPanel and the asset
bundle, suitable for direct placement in the embedder's UI, or NULL
when no panel keys exist.
See Also
ptr_shared(), ptr_ui_shared_panel(),
ptr_shared_server().
Examples
obj <- ptr_shared(c(
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_point()",
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_bar()"
))
ptr_shared_panel(obj)
Server-Side Counterpart to the Shared Coordinator
Description
Builds the shared input reactives and binds the host-level
ppVar(shared = "...") consumer pickers for the ptr_shared_panel().
Returns a ptr_shared_state that the embedder threads into each
ptr_server() via the shared_state argument.
Usage
ptr_shared_server(
obj,
envir = parent.frame(),
shared = list(),
draw_trigger = NULL,
spec = NULL
)
Arguments
obj |
A |
envir |
Environment used to resolve symbols in the shared
|
shared |
Optional named list overriding the auto-derived
reactives. Each named entry replaces the reactive for that key;
unsupplied keys keep the default that reads
|
draw_trigger |
Optional reactive overriding the auto-derived
"Draw all" trigger ( |
spec |
Optional named list of fully-qualified Shiny input id ->
value, used to override widget defaults at session boot for
host-owned panel-shared widgets ( |
Details
Namespacing is inherited from obj$id; supply it to ptr_shared().
Reads its session via shiny::getDefaultReactiveDomain() – call
it inside the top-level Shiny server function (or any reactive
context that inherits the session). Errors when called outside any
reactive domain.
Value
A ptr_shared_state S3 object with public fields shared,
draw_trigger, shared_resolutions, and shared_stage_enabled
(a named list of reactives, one per shared key, indicating whether
that key's shared stage is active for each embedded module).
See Also
ptr_shared(), ptr_shared_panel(),
ptr_server().
Examples
if (interactive()) {
obj <- ptr_shared(c(
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_point()",
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_bar()"
))
shiny::shinyApp(
ui = shiny::fluidPage(ptr_shared_panel(obj)),
server = function(input, output, session) {
ptr_shared_server(obj)
}
)
}
Signal a transient "partial input" failure from a placeholder hook
Description
Placeholder resolve_expr (and validate_input) hooks should call
ptr_signal_partial() – instead of rlang::abort() / stop() – when the
current widget value is incomplete or transiently unparseable. Typical
example: a free-text expr placeholder whose body has not finished being
typed (mpg /). The condition carries class "ptr_partial_input".
Usage
ptr_signal_partial(message, ...)
Arguments
message |
Diagnostic text. Surfaced on the gated plot path. |
... |
Additional named fields attached to the condition (forwarded
to |
Details
ggpaintr's live reactive boundaries (column-picker entry_reactives that
re-fire on every keystroke) catch this class and silently cancel the
current re-render, so the downstream picker keeps its previous state
instead of strobing blank and writing a Shiny warning to the R console.
The Update / Draw-gated plot path does not catch it, so a value that is
still partial when the user clicks "Update" still surfaces as a normal
inline error.
Use ordinary rlang::abort() for failures that are NOT user mid-typing
artifacts (security violations, real argument-shape errors, etc.).
Value
Never returns – always signals.
Examples
# A resolve hook that treats an unfinished expression as a transient,
# silently-cancelled partial input rather than a hard error:
my_expr_resolve <- function(value, node, ...) {
tryCatch(
rlang::parse_expr(value),
error = function(e) ptr_signal_partial(conditionMessage(e))
)
}
Self-contained UI for a ggpaintr Formula
Description
The L2 default-layout UI bundle for a ggpaintr formula: owns its own
.ptr-app theme scope + asset bundle (nothing else to remember) and is
namespaced by id. Pair with the single public ptr_server(). For a
hand-composed L3 layout, use the bare ptr_ui_* pieces instead and pair
them with the same ptr_server().
Usage
ptr_ui(
formula,
id = NULL,
envir = parent.frame(),
ui_text = NULL,
expr_check = TRUE,
css = NULL,
shared = NULL
)
Arguments
formula |
Either a single character scalar containing a ggplot
expression with |
id |
Optional module id; the namespace prefix for inputs and outputs.
Defaults to |
envir |
Environment used to resolve a |
ui_text |
Optional named list of copy overrides; see |
expr_check |
Controls formula-level |
css |
Optional character vector of paths to additional CSS files;
linked after |
shared |
Optional coordinator object from |
Value
A shiny.tag — a fluidPage shell containing the controls panel,
plot output, and asset bundle.
See Also
ptr_server(), ptr_css() for the css = argument and
themable CSS custom properties.
Examples
# Expression form (primary): an unquoted ggplot call.
ui <- ptr_ui(ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point(), "plot1")
# Stored in a variable, spliced with `!!` (paired with ptr_server(!!f, "plot1")).
f <- rlang::expr(ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point())
ui2 <- ptr_ui(!!f, "plot1")
# String form (fallback): equivalent.
ui3 <- ptr_ui("ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point()", "plot1")
Bundled CSS / JS Assets Piece for ggpaintr
Description
The full ggpaintr asset bundle as a shiny::tagList(): the
structural-layer dependency (ptr_set_class handler + stage CSS), the
cosmetic ggpaintr.css theme dependency + code-window JavaScript, and
any user override stylesheets. The CSS/JS ship as
htmltools::htmlDependency() objects, so emitting this anywhere on a
page — even several times — yields exactly one <head> injection of
each. The single-piece UI builders (ptr_ui_plot(),
ptr_ui_controls(), ...) emit no assets; an L3 page that composes
pieces by hand normally gets them from the page shell, or includes
this directly for a non-fluidPage root. The bundled apps and the
ptr_*_ui() composites inject it for you.
Usage
ptr_ui_assets(css = NULL)
Arguments
css |
Optional character vector of paths to additional CSS files;
linked after |
Value
See Also
ptr_ui_plot(), ptr_ui_controls(), ptr_ui_toggle_code(), ptr_css()
Examples
ptr_ui_assets()
Generated-Code Pane Piece for a ggpaintr Formula
Description
The generated-code output on its own: a shiny::verbatimTextOutput()
bound to the ptr_code id the server writes to (see ptr_server()).
One of the single-piece UI builders for the L3 "own every UI piece"
workflow.
Usage
ptr_ui_code(id = NULL, style = c("panel", "window"))
Arguments
id |
Optional module id; the namespace prefix for the output.
Defaults to |
style |
|
Value
A shiny::tag.
See Also
ptr_ui_toggle_code(), ptr_ui_plot(), ptr_server()
Examples
ptr_ui_code("myplot")
ptr_ui_code("myplot", style = "window")
Controls Piece for a ggpaintr Formula
Description
The generated control widgets (layer picker, per-layer parameter
panels, the "Update plot" button) as a bare shiny::tagList() with
no .ptr-app wrapper and no bundled assets. One of the
single-piece UI builders for the L3 "own every UI piece" workflow:
compose it with ptr_ui_assets() and the output pieces, place each
wherever you like, and wire the server with ptr_server() /
ptr_server().
Usage
ptr_ui_controls(
formula,
id = NULL,
envir = parent.frame(),
ui_text = NULL,
expr_check = TRUE,
shared = NULL
)
Arguments
formula |
Either a single character scalar containing a ggplot
expression with |
id |
Optional module id; the namespace prefix for inputs.
Defaults to |
envir |
Environment used to resolve a |
ui_text |
Optional named list of copy overrides; see
|
expr_check |
Controls formula-level |
shared |
Optional coordinator object from |
Details
Because the panel includes a shinyWidgets::pickerInput() (the layer
selector) and the Bootstrap grid, it must be rendered inside a
Bootstrap page that also carries the .ptr-app theme scope and the
asset bundle. Don't assemble that scaffolding by hand: wrap your
composed pieces in ptr_ui_page(), which is the Bootstrap page and
owns the single .ptr-app scope + the (deduped) assets. For a
navbarPage or bslib root (which ptr_ui_page() does not cover) see
vignette("ggpaintr-tutorial").
For finer control still — placing individual placeholder widgets
independently rather than the whole panel — register a custom placeholder
type; see ptr_define_placeholder_value().
Value
See Also
ptr_ui_page(), ptr_ui_assets(), ptr_ui_plot(),
ptr_ui_code(), ptr_shared(), ptr_server()
Examples
# Expression form (primary): an unquoted ggplot call.
ptr_ui_controls(
ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point(),
id = "p"
)
# String form (fallback): equivalent.
ptr_ui_controls(
"ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point()",
id = "p"
)
Inline Error Pane Piece for a ggpaintr Formula
Description
The inline error slot on its own: a shiny::uiOutput() bound to the
ptr_error id the server writes parse/runtime error alerts to (see
ptr_server()). One of the single-piece UI builders for the L3 "own
every UI piece" workflow.
Usage
ptr_ui_error(id = NULL)
Arguments
id |
Optional module id; the namespace prefix for the output.
Defaults to |
Value
A shiny::tag.
See Also
ptr_ui_plot(), ptr_ui_code(), ptr_ui_controls(), ptr_server()
Examples
ptr_ui_error("myplot")
App Header Piece for ggpaintr
Description
The slim branded header bar (logo + title) the polished default shell
uses in place of shiny::titlePanel(). One of the single-piece UI
builders for the L3 "own every UI piece" workflow.
Usage
ptr_ui_header(title = "ggpaintr")
Arguments
title |
Heading text. Defaults to |
Value
A shiny::tag.
See Also
ptr_ui_controls(), ptr_ui_plot(), ptr_app()
Examples
ptr_ui_header()
ptr_ui_header("My App")
Nest an Inline Error Slot in a Plot Piece
Description
Output combinator: takes an already-built bare plot piece
(ptr_ui_plot()) and an already-built bare error piece
(ptr_ui_error()) and returns the plot card with the error slot
rendered inline in the card body — the layout the bundled apps use.
Pure DOM structure; no server coupling (the server registers
ptr_plot / ptr_error regardless). Nestable inside
ptr_ui_toggle_code().
Usage
ptr_ui_inline_error(plot, error)
Arguments
plot |
A plot piece, typically |
error |
An error piece, typically |
Details
This combinator does not add the .ptr-output toggle scope (it has
no toggle, so it needs none); ptr_ui_toggle_code() owns that wrapper.
Value
A shiny::tag — the plot card with error nested in its body.
See Also
ptr_ui_plot(), ptr_ui_error(), ptr_ui_toggle_code()
Examples
ptr_ui_inline_error(ptr_ui_plot("p"), ptr_ui_error("p"))
Page shell for hand-composed ggpaintr UIs
Description
Wraps composed L3 pieces in a Bootstrap page + the single .ptr-app
theme scope + the (deduped) asset bundle. The only thing an L3 user
must remember.
Usage
ptr_ui_page(..., page = shiny::fluidPage, css = NULL)
Arguments
... |
UI children (pieces, layout, your own widgets). |
page |
A Bootstrap-3 page builder whose |
css |
Optional character vector of extra stylesheet paths,
linked after |
Value
A shiny.tag — the Bootstrap page node ready to pass to
shiny::shinyApp() as ui.
See Also
ptr_ui_plot(), ptr_ui_controls(), ptr_server(), ptr_css()
Examples
f <- rlang::expr(ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point())
ptr_ui_page(
shiny::sidebarLayout(
shiny::sidebarPanel(ptr_ui_controls(id = "p", formula = !!f)),
shiny::mainPanel(ptr_ui_plot("p"))
)
)
Plot Pane Piece for a ggpaintr Formula
Description
The plot card on its own: a shiny::plotOutput() bound to the
ptr_plot id the server writes to (see ptr_server()). One of the
single-piece UI builders for the L3 "own every UI piece" workflow;
place it anywhere in your own layout and wire the server with
ptr_server() / ptr_server().
Usage
ptr_ui_plot(id = NULL)
Arguments
id |
Optional module id; the namespace prefix for the output.
Defaults to |
Details
The piece is truly bare: just the plot card, with no error slot and
no show-code button. Behaviour is added compositionally by the
combinators ptr_ui_inline_error() (nests an error slot in the card
body) and ptr_ui_toggle_code() (adds the </> toggle + slide-out
code window) — not by flags on this function.
Value
A shiny::tag.
See Also
ptr_ui_error(), ptr_ui_code(), ptr_ui_inline_error(),
ptr_ui_toggle_code(), ptr_ui_controls(), ptr_server()
Examples
ptr_ui_plot("myplot")
Render the Standalone Shared Panel (L3, Bare)
Description
The bare counterpart to ptr_shared_panel(): identical inner markup
(the wellPanel holding obj$panel_keys) with no .ptr-app shell and
no asset bundle. The L3 user supplies their own shell / assets (e.g.
via ptr_ui_page()).
Usage
ptr_ui_shared_panel(obj)
Arguments
obj |
A |
Details
Namespacing is inherited from obj$id; supply it to ptr_shared().
Value
A shiny.tag wellPanel with no wrapper and no injected assets, or
NULL when no panel keys exist.
See Also
ptr_shared(), ptr_shared_panel(),
ptr_shared_server().
Examples
obj <- ptr_shared(c(
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_point()",
"ggplot(mtcars, aes(x = ppVar(shared='x'), y = ppVar)) + geom_bar()"
))
ptr_ui_shared_panel(obj)
Inspect, validate, and pre-merge ggpaintr UI copy
Description
Returns the effective copy tree ggpaintr uses to label every generated
control. Call it with no arguments to see the current defaults, or pass
ui_text = a list of overrides to get back a validated, merged
ptr_ui_text object. That object can be reused across ptr_app() /
ptr_server() calls — those entry points short-circuit when handed an
already-merged ptr_ui_text, so the overrides are validated once.
Usage
ptr_ui_text(ui_text = NULL)
Arguments
ui_text |
|
Details
Use it to (1) discover the override schema (names(ptr_ui_text()) and
the section below), and (2) fail fast on a malformed override list before
launching an app — ptr_ui_text() raises on unknown sections, keywords,
or leaf fields.
Value
A ptr_ui_text object containing the merged copy rules.
UI text schema
Override lists mirror the structure of ptr_ui_text(). Recognised paths
(every leaf is a named list of the fields below):
-
shell$title$<leaf> -
shell$draw_button$<leaf> -
shell$draw_all_button$<leaf> -
shell$layer_picker$<leaf> -
shell$data_subtab$<leaf> -
shell$controls_subtab$<leaf> -
upload$file$<leaf> -
upload$name$<leaf> -
layer_checkbox$<leaf> -
defaults$<keyword>$<leaf>— per placeholder keyword (ppVar,ppText,ppNum,ppExpr,ppUpload, ...) -
params$<param>$<keyword>$<leaf>— per aesthetic/argument name (x,y,color, ...); aliases (colour,size) are normalized -
layers$<layer_name>$<keyword>$<param>$<leaf>— per layer override (use__unnamed__as<param>for positional arguments)
Leaf fields are label, help, placeholder, and empty_text. Leaf
strings may use the {param} and {layer} tokens, which are interpolated
at resolve time.
Examples
# Default rules
rules <- ptr_ui_text()
rules$shell$title$label
# Override the draw button label
rules <- ptr_ui_text(
ui_text = list(shell = list(draw_button = list(label = "Render")))
)
rules$shell$draw_button$label
Wire a Plot-ish Piece to a Slide-Out Code Window via the </> Toggle
Description
Output combinator: wraps a plot-ish tag (a bare ptr_ui_plot() or the
output of ptr_ui_inline_error()) and a bare code piece
(ptr_ui_code()) in the single .ptr-output scope the bundled
JavaScript needs, injecting the </> show-code button into the plot
card head and presenting the code inside the draggable slide-out
.ptr-code-window (with Copy / Close). The button hides/shows that
window purely DOM-locally — no Shiny input/output is involved. This is
the toggle layout ptr_app() / ptr_ui() render internally.
Usage
ptr_ui_toggle_code(plotish, code)
Arguments
plotish |
A plot-ish tag. The designed input is a bare
|
code |
A code piece, typically |
Details
Use this when you want the familiar toggle behaviour while still owning
the surrounding layout. For fully independent placement of the plot and
code panes (no toggle), keep the bare pieces uncombined — a standalone
ptr_ui_code() is always visible and needs no wiring.
Value
A shiny::tag — one .ptr-output containing plotish (with
the toggle button) and the .ptr-code-window-wrapped code.
See Also
ptr_ui_plot(), ptr_ui_code(), ptr_ui_inline_error(),
ptr_ui_controls(), ptr_server()
Examples
ptr_ui_toggle_code(
ptr_ui_inline_error(ptr_ui_plot("p"), ptr_ui_error("p")),
ptr_ui_code("p", style = "window")
)
RStudio addin: wrap a selection in a ggpaintr placeholder
Description
Interactive RStudio addin. Highlight a token in your ggplot expression
(e.g. mpg in aes(x = mpg)), run the addin, and pick a placeholder from
a command-palette gadget; the selection is rewritten to ppVar(mpg). With
nothing highlighted the same palette opens and inserts ppVar() with the
caret between the parens. The placeholder list is read live from the
registry, so custom placeholders registered this session
(via ptr_define_placeholder_value() and friends) appear automatically.
Usage
ptr_wrap_placeholder_addin()
Details
The gadget's Wrap in app button (left of Insert) takes a different
action: instead of inserting a placeholder it wraps the whole selection in a
braced block piped into ptr_app() –
{ / <selection> / } |> / ptr_app() – turning a ggplot
expression into a runnable ggpaintr app skeleton.
Value
Invisibly NULL. Called for its side effect of editing the active
RStudio document.
Theme
By default the palette follows your RStudio editor theme (dark theme -> dark
palette, light -> light), via rstudioapi::getThemeInfo(). Force one with
options(ggpaintr.addin_theme = "dark"), "light", or "auto" (the
default).
Keyboard shortcut
For a highlight-then-keystroke flow, bind the addin once (RStudio reads
shortcuts only from your own keybindings, so packages cannot ship one). The
addin must be installed (not merely load_all()-ed) to appear in the
shortcut dialog:
-
Tools > Addins > Browse Addins..., then the Keyboard Shortcuts... button. (Or Tools > Modify Keyboard Shortcuts... and type "ggpaintr" in the search box.)
Find the ggpaintr placeholder row and click its Shortcut cell.
Press the recommended combination: Cmd+Shift+G on macOS, Ctrl+Shift+G on Windows/Linux. (Any free combination works; pick another if that one is already bound.)
-
Apply.
Requires rstudioapi and miniUI; it errors with a clear message when run outside RStudio.