Compare commits

..

8 Commits

Author SHA1 Message Date
Carson
1c252987a3 shiny-insert-tab can now accommodate a JSXTag 2022-03-02 13:49:39 -06:00
Kathryn Doering
5c03326a8c Use HEAD for ref instead of master in runGitHub() (#3564)
Co-authored-by: Kathryn Doering <kathryn.doering@noaa.gov>
2022-02-14 15:53:33 -05:00
Barret Schloerke
2c82ee0235 Bump dev version (#3588) 2022-02-14 15:24:47 -05:00
Barret Schloerke
ac84be956a Opt-in to C collate order in test snapshots (#3515) 2022-02-14 14:12:25 -05:00
Winston Chang
0fb154cc1e Trigger input event even when there is no input binding (#3584)
Co-authored-by: Winston Chang <winston@stdout.org>
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
2022-02-14 13:45:59 -05:00
Carson Sievert
837e8d33f6 Update stack trace test expectations (#3550) 2022-02-14 13:14:10 -05:00
Winston Chang
3365bfc395 Merge pull request #3583 from ismirsehregal/main 2022-02-09 17:27:18 -06:00
ismirsehregal
135fe21278 Update runapp.R
Fixed typo
2022-02-09 15:11:34 +01:00
82 changed files with 1565 additions and 1539 deletions

View File

@@ -1,7 +1,7 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 1.7.1.9002
Version: 1.7.1.9003
Authors@R: c(
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@rstudio.com", comment = c(ORCID = "0000-0002-1576-2126")),
person("Joe", "Cheng", role = "aut", email = "joe@rstudio.com"),

10
NEWS.md
View File

@@ -1,14 +1,20 @@
shiny 1.7.1.9001
shiny development
================
## Full changelog
### Breaking changes
### Minor new features and improvements
* Shiny's internal HTML dependencies are now mounted dynamically instead of statically. (#3537)
* HTML dependencies that are sent to dynamic UI now have better type checking, and no longer require a `dep.src.href` field. (#3537)
* Default for `ref` input in `runGithub()` changed from `"master"` to `"HEAD"`. (#3346)
* When taking a test snapshot, the sort order of the json keys of the `input`, `output`, and `export` fields is currently sorted using the locale of the machine. This can lead to inconsistent test snapshot results. To opt-in to a consistent ordering of snapshot fields with `{shinytest}`, please set the global option `options(shiny.snapshotsortc = TRUE)`. `{shinytest2}` users do not need to set this value. (#3515)
### Bug fixes
* Closed tidyverse/dplyr#5552: Compatibility of dplyr 1.0 (and rlang chained errors in general) with `req()`, `validate()`, and friends.
@@ -17,6 +23,8 @@ shiny 1.7.1.9001
* Closed tidyverse/dplyr#6154: Values from an `actionButton()` had S3 classes in the incorrect order.
* Fixed a bug where updating an input value without a corresponding Input binding element did not trigger a JavaScript `shiny:inputchanged` event. Now, if no Input binding element is found, the `shiny:inputchanged` event is triggered on `window.document`. (#3584)
shiny 1.7.1
===========

View File

@@ -1,4 +1,87 @@
#' @rdname bootstrapPage
#' Create a page with fluid layout
#'
#' Functions for creating fluid page layouts. A fluid page layout consists of
#' rows which in turn include columns. Rows exist for the purpose of making sure
#' their elements appear on the same line (if the browser has adequate width).
#' Columns exist for the purpose of defining how much horizontal space within a
#' 12-unit wide grid it's elements should occupy. Fluid pages scale their
#' components in realtime to fill all available browser width.
#'
#' @param ... Elements to include within the page
#' @param title The browser window title (defaults to the host URL of the page).
#' Can also be set as a side effect of the [titlePanel()] function.
#' @inheritParams bootstrapPage
#'
#' @return A UI defintion that can be passed to the [shinyUI] function.
#'
#' @details To create a fluid page use the `fluidPage` function and include
#' instances of `fluidRow` and [column()] within it. As an
#' alternative to low-level row and column functions you can also use
#' higher-level layout functions like [sidebarLayout()].
#'
#' @note See the [
#' Shiny-Application-Layout-Guide](https://shiny.rstudio.com/articles/layout-guide.html) for additional details on laying out fluid
#' pages.
#'
#' @family layout functions
#' @seealso [column()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' # Example of UI with fluidPage
#' ui <- fluidPage(
#'
#' # Application title
#' titlePanel("Hello Shiny!"),
#'
#' sidebarLayout(
#'
#' # Sidebar with a slider input
#' sidebarPanel(
#' sliderInput("obs",
#' "Number of observations:",
#' min = 0,
#' max = 1000,
#' value = 500)
#' ),
#'
#' # Show a plot of the generated distribution
#' mainPanel(
#' plotOutput("distPlot")
#' )
#' )
#' )
#'
#' # Server logic
#' server <- function(input, output) {
#' output$distPlot <- renderPlot({
#' hist(rnorm(input$obs))
#' })
#' }
#'
#' # Complete app with UI and server components
#' shinyApp(ui, server)
#'
#'
#' # UI demonstrating column layouts
#' ui <- fluidPage(
#' title = "Hello Shiny!",
#' fluidRow(
#' column(width = 4,
#' "4"
#' ),
#' column(width = 3, offset = 2,
#' "3 offset 2"
#' )
#' )
#' )
#'
#' shinyApp(ui, server = function(input, output) { })
#' }
#' @rdname fluidPage
#' @export
fluidPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
bootstrapPage(div(class = "container-fluid", ...),
@@ -8,13 +91,62 @@ fluidPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
}
#' @rdname column
#' @rdname fluidPage
#' @export
fluidRow <- function(...) {
div(class = "row", ...)
}
#' @rdname bootstrapPage
#' Create a page with a fixed layout
#'
#' Functions for creating fixed page layouts. A fixed page layout consists of
#' rows which in turn include columns. Rows exist for the purpose of making sure
#' their elements appear on the same line (if the browser has adequate width).
#' Columns exist for the purpose of defining how much horizontal space within a
#' 12-unit wide grid it's elements should occupy. Fixed pages limit their width
#' to 940 pixels on a typical display, and 724px or 1170px on smaller and larger
#' displays respectively.
#'
#' @param ... Elements to include within the container
#' @param title The browser window title (defaults to the host URL of the page)
#' @inheritParams bootstrapPage
#'
#' @return A UI defintion that can be passed to the [shinyUI] function.
#'
#' @details To create a fixed page use the `fixedPage` function and include
#' instances of `fixedRow` and [column()] within it. Note that
#' unlike [fluidPage()], fixed pages cannot make use of higher-level
#' layout functions like `sidebarLayout`, rather, all layout must be done
#' with `fixedRow` and `column`.
#'
#' @note See the [
#' Shiny Application Layout Guide](https://shiny.rstudio.com/articles/layout-guide.html) for additional details on laying out fixed
#' pages.
#'
#' @family layout functions
#'
#' @seealso [column()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fixedPage(
#' title = "Hello, Shiny!",
#' fixedRow(
#' column(width = 4,
#' "4"
#' ),
#' column(width = 3, offset = 2,
#' "3 offset 2"
#' )
#' )
#' )
#'
#' shinyApp(ui, server = function(input, output) { })
#' }
#'
#' @rdname fixedPage
#' @export
fixedPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
bootstrapPage(div(class = "container", ...),
@@ -23,39 +155,28 @@ fixedPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
lang = lang)
}
#' @rdname column
#' @rdname fixedPage
#' @export
fixedRow <- function(...) {
div(class = "row", ...)
}
#' Responsive row-column based layout
#' Create a column within a UI definition
#'
#' Layout UI components using Bootstrap's grid layout system. Use
#' `fluidRow()` to group elements that should appear on the same line (if the
#' browser has adequate width) and `column()` to define how much horizontal
#' space within a 12-unit wide grid each on of these elements should occupy. See
#' the [layout guide](https://shiny.rstudio.com/articles/layout-guide.html) for
#' more context and examples.
#' Create a column for use within a [fluidRow()] or
#' [fixedRow()]
#'
#' To work properly, these functions need [Bootstrap](https://getbootstrap.com)
#' included on the page. Since most Shiny apps use [bootstrapPage()]
#' under-the-hood, this is usually the case, but custom page containers (i.e.,
#' [htmlTemplate()]) may need to explicitly include [bootstrapLib()]
#' dependencies.
#'
#' @param width The grid width of the column (must be between 1 and 12). When
#' the device width is small (e.g., the viewer is on a mobile phone), the
#' width is always 12. For more control over these responsive breakpoints, use
#' Bootstrap's grid system more directly (e.g., `fluidRow(div(class =
#' "col-lg-2", ...))`).
#' @param ... UI elements (i.e., [tags]). For `fluidRow()`, `...` should be a set of `column()`s.
#' @param width The grid width of the column (must be between 1 and 12)
#' @param ... Elements to include within the column
#' @param offset The number of columns to offset this column from the end of the
#' previous column.
#'
#' @return A UI element (i.e., [tags]).
#' @return A column that can be included within a
#' [fluidRow()] or [fixedRow()].
#'
#' @seealso [fluidPage()]
#'
#' @seealso [fluidRow()], [fixedRow()].
#'
#' @examples
#' ## Only run examples in interactive R sessions
@@ -81,10 +202,16 @@ fixedRow <- function(...) {
#'
#' shinyApp(ui, server)
#'
#'
#'
#' ui <- fluidPage(
#' fluidRow(
#' column(width = 4, "4"),
#' column(width = 3, offset = 2, "3 offset 2")
#' column(width = 4,
#' "4"
#' ),
#' column(width = 3, offset = 2,
#' "3 offset 2"
#' )
#' )
#' )
#' shinyApp(ui, server = function(input, output) { })

View File

@@ -1,84 +1,36 @@
#' @include utils.R
NULL
#' Create a Bootstrap UI page container
#' Create a Bootstrap page
#'
#' @description
#' Create a user interface (UI) page container based on
#' [Bootstrap](https://getbootstrap.com/)'s CSS and JavaScript. Most Shiny apps
#' should use [fluidPage()] (or [navbarPage()]) to get a page container with a
#' responsive page width, but in some cases you may want a fixed width container
#' (`fixedPage()`) or just a bare `<body>` container (`bootstrapPage()`).
#' Create a Shiny UI page that loads the CSS and JavaScript for
#' [Bootstrap](https://getbootstrap.com/), and has no content in the page
#' body (other than what you provide).
#'
#' Most Shiny apps make use of other Shiny UI functions for [managing
#' layout](https://shiny.rstudio.com/articles/layout-guide.html) (e.g.,
#' [sidebarLayout()], [fluidRow()], etc), navigation (e.g., [tabPanel()]), and
#' other styling (e.g., [wellPanel()], [inputPanel()]). A good portion of these
#' Shiny UI functions require Bootstrap to work properly (so most Shiny apps
#' should use these functions to start their UI definitions), but more advanced
#' usage (i.e., custom HTML/CSS/JS) can avoid Bootstrap entirely by using
#' [htmlTemplate()] and/or HTML [tags].
#' This function is primarily intended for users who are proficient in HTML/CSS,
#' and know how to lay out pages in Bootstrap. Most applications should use
#' [fluidPage()] along with layout functions like
#' [fluidRow()] and [sidebarLayout()].
#'
#' @param ... UI elements (i.e., [tags]).
#' @param title The browser window title (defaults to the host URL of the page).
#' Can also be set as a side effect of the [titlePanel()] function.
#' @param ... The contents of the document body.
#' @param title The browser window title (defaults to the host URL of the page)
#' @param theme One of the following:
#' * `NULL` (the default), which implies a "stock" build of Bootstrap 3.
#' * A [bslib::bs_theme()] object. This can be used to replace a stock
#' build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
#' * A character string pointing to an alternative Bootstrap stylesheet
#' (normally a css file within the www directory, e.g. `www/bootstrap.css`).
#' This option is here mainly for legacy reasons.
#' @param lang ISO 639-1 language code for the HTML page, such as "en" or "ko".
#' This will be used as the lang in the `<html>` tag, as in `<html lang="en">`.
#' This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
#' The default (NULL) results in an empty string.
#'
#' @return A UI definition (i.e., a [tags] object) that can be passed to [shinyApp()].
#' @return A UI defintion that can be passed to the [shinyUI] function.
#'
#' @seealso [navbarPage()], [fillPage()], [column()], [tabPanel()]
#' @note The `basicPage` function is deprecated, you should use the
#' [fluidPage()] function instead.
#'
#' @seealso [fluidPage()], [fixedPage()]
#' @export
#' @examples
#'
#' # First create some UI content.
#' # See the layout guide to learn more about creating different layouts
#' # https://shiny.rstudio.com/articles/layout-guide.html
#' ui <- sidebarLayout(
#' sidebarPanel(sliderInput("obs", "Number of observations:", 0, 1000, 500)),
#' mainPanel(plotOutput("distPlot"))
#' )
#' server <- function(input, output) {
#' output$distPlot <- renderPlot(hist(rnorm(input$obs)))
#' }
#'
#' # Demonstrating difference between fluidPage(), fixedPage(), bootstrapPage()
#' if (interactive()) {
#' # Container width scales _fluidly_ with window size
#' shinyApp(fluidPage(ui), server)
#' # Container width changes with window size at fixed breakpoints
#' shinyApp(fixedPage(ui), server)
#' # Container width is equal to the window's width
#' shinyApp(bootstrapPage(ui), server)
#' }
#'
#' # The default look is provided by Bootstrap 3, but {bslib} can be
#' # used to customize the Bootstrap version and its default styling
#' theme <- bslib::bs_theme(
#' version = 5,
#' bg = "#101010",
#' fg = "#FDF7F7",
#' primary = "#ED79F9",
#' base_font = bslib::font_google("Prompt"),
#' code_font = bslib::font_google("JetBrains Mono")
#' )
#' if (interactive()) {
#' # Call thematic::thematic_shiny(font = "auto") to automatically
#' # translate the theme/CSS to the R plot
#' shinyApp(
#' fluidPage(ui, theme = theme, title = "Hello Bootstrap 5"),
#' server
#' )
#' }
#'
bootstrapPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
args <- list(
@@ -282,12 +234,14 @@ bootstrapDependency <- function(theme) {
bootstrapVersion <- "3.4.1"
#' @rdname bootstrapPage
#' @export
basicPage <- function(...) {
bootstrapPage(div(class="container-fluid", list(...)))
}
#' Create a page that fills the window
#'
#' `fillPage` creates a page whose height and width always fill the

View File

@@ -121,7 +121,8 @@ runGist <- function(gist, destdir = NULL, ...) {
#' @param username GitHub username. If `repo` is of the form
#' `"username/repo"`, `username` will be taken from `repo`.
#' @param ref Desired git reference. Could be a commit, tag, or branch name.
#' Defaults to `"master"`.
#' Defaults to `"HEAD"`, which means the default branch on GitHub, typically
#' `"main"` or `"master"`.
#' @export
#' @examples
#' ## Only run this example in interactive R sessions
@@ -133,7 +134,7 @@ runGist <- function(gist, destdir = NULL, ...) {
#' runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
#' }
runGitHub <- function(repo, username = getOption("github.user"),
ref = "master", subdir = NULL, destdir = NULL, ...) {
ref = "HEAD", subdir = NULL, destdir = NULL, ...) {
if (grepl('/', repo)) {
res <- strsplit(repo, '/')[[1]]

View File

@@ -28,7 +28,7 @@
#' ports will be tried.
#' @param launch.browser If true, the system's default web browser will be
#' launched automatically after the app is started. Defaults to true in
#' interactive sessions only. This value of this parameter can also be a
#' interactive sessions only. The value of this parameter can also be a
#' function to call with the application's URL.
#' @param host The IPv4 address that the application should listen on. Defaults
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not. See

View File

@@ -125,6 +125,9 @@ getShinyOption <- function(name, default = NULL) {
#' console.}
#' \item{shiny.testmode (defaults to `FALSE`)}{If `TRUE`, then various features for testing Shiny
#' applications are enabled.}
#' \item{shiny.snapshotsortc (defaults to `FALSE`)}{If `TRUE`, test snapshot keys
#' for \pkg{shinytest} will be sorted consistently using the C locale. Snapshots
#' retrieved by \pkg{shinytest2} will always sort using the C locale.}
#' \item{shiny.trace (defaults to `FALSE`)}{Print messages sent between the R server and the web
#' browser client to the R console. This is useful for debugging. Possible
#' values are `"send"` (only print messages sent to the client),

View File

@@ -478,6 +478,35 @@ ShinySession <- R6Class(
# "json" unless requested otherwise. The only other valid value is
# "rds".
format <- params$format %||% "json"
# Machines can test their snapshot under different locales.
# R CMD check runs under the `C` locale.
# However, before this parameter, existing snapshots were most likely not
# under the `C` locale is would cause failures. This parameter allows
# users to opt-in to the `C` locale.
# From ?sort:
# However, there are some caveats with the radix sort:
# If x is a character vector, all elements must share the
# same encoding. Only UTF-8 (including ASCII) and Latin-1
# encodings are supported. Collation always follows the "C"
# locale.
# {shinytest2} will always set `sortC=1`
# {shinytest} does not have `sortC` functionality.
# Users should set `options(shiny.snapshotsortc = TRUE)` within their app.
# The sortingMethod should always be `radix` going forward.
sortMethod <-
if (!is.null(params$sortC)) {
if (params$sortC != "1") {
stop("The `sortC` parameter can only be `1` or not supplied")
}
"radix"
} else {
# Allow users to set an option for {shinytest2}.
if (isTRUE(getShinyOption("snapshotsortc", default = FALSE))) {
"radix"
} else {
"auto"
}
}
values <- list()
@@ -520,7 +549,7 @@ ShinySession <- R6Class(
}
)
values$input <- sortByName(values$input)
values$input <- sortByName(values$input, method = sortMethod)
}
if (!is.null(params$output)) {
@@ -548,7 +577,7 @@ ShinySession <- R6Class(
}
)
values$output <- sortByName(values$output)
values$output <- sortByName(values$output, method = sortMethod)
}
if (!is.null(params$export)) {
@@ -569,7 +598,7 @@ ShinySession <- R6Class(
)
}
values$export <- sortByName(values$export)
values$export <- sortByName(values$export, method = sortMethod)
}
# Make sure input, output, and export are all named lists (at this
@@ -1719,7 +1748,7 @@ ShinySession <- R6Class(
},
getTestSnapshotUrl = function(input = TRUE, output = TRUE, export = TRUE,
format = "json") {
format = "json", sortC = FALSE) {
reqString <- function(group, value) {
if (isTRUE(value))
paste0(group, "=1")
@@ -1733,6 +1762,7 @@ ShinySession <- R6Class(
reqString("input", input),
reqString("output", output),
reqString("export", export),
reqString("sortC", sortC),
paste0("format=", format),
sep = "&"
)

View File

@@ -162,7 +162,7 @@ mergeVectors <- function(a, b) {
# Sort a vector by the names of items. If there are multiple items with the
# same name, preserve the original order of those items. For empty
# vectors/lists/NULL, return the original value.
sortByName <- function(x) {
sortByName <- function(x, method = "auto") {
if (any_unnamed(x))
stop("All items must be named")
@@ -170,7 +170,19 @@ sortByName <- function(x) {
if (length(x) == 0)
return(x)
x[order(names(x))]
# Must provide consistent sort order
# https://github.com/rstudio/shinytest/issues/409
# Using a flag in the snapshot url to determine the method
# `method="radix"` uses `C` locale, which is consistent across platforms
# Even if two platforms share `en_us.UTF-8`, they may not sort consistently
# https://blog.zhimingwang.org/macos-lc_collate-hunt
# (macOS) $ LC_ALL=en_US.UTF-8 sort <<<$'python-dev\npython3-dev'
# python-dev
# python3-dev
# (Linux) $ LC_ALL=en_US.UTF-8 sort <<<$'python-dev\npython3-dev'
# python3-dev
# python-dev
x[order(names(x), method = method)]
}
# Sort a vector. If a character vector, sort using C locale, which is consistent

View File

@@ -1,3 +1,3 @@
/*! shiny 1.7.1.9002 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
(function(){var t="ws:";window.location.protocol==="https:"&&(t="wss:");var o=window.location.pathname;/\/$/.test(o)||(o+="/");o+="autoreload/";var n=new WebSocket(t+"//"+window.location.host+o);n.onmessage=function(a){a.data==="autoreload"&&window.location.reload()};})();
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LWF1dG9yZWxvYWQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qIGVzbGludC1kaXNhYmxlIHVuaWNvcm4vZmlsZW5hbWUtY2FzZSAqL1xudmFyIHByb3RvY29sID0gXCJ3czpcIjtcbmlmICh3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgPT09IFwiaHR0cHM6XCIpIHByb3RvY29sID0gXCJ3c3M6XCI7XG52YXIgZGVmYXVsdFBhdGggPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWU7XG5pZiAoIS9cXC8kLy50ZXN0KGRlZmF1bHRQYXRoKSkgZGVmYXVsdFBhdGggKz0gXCIvXCI7XG5kZWZhdWx0UGF0aCArPSBcImF1dG9yZWxvYWQvXCI7XG52YXIgd3MgPSBuZXcgV2ViU29ja2V0KHByb3RvY29sICsgXCIvL1wiICsgd2luZG93LmxvY2F0aW9uLmhvc3QgKyBkZWZhdWx0UGF0aCk7XG5cbndzLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICBpZiAoZXZlbnQuZGF0YSA9PT0gXCJhdXRvcmVsb2FkXCIpIHtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG4gIH1cbn07XG5cbmV4cG9ydCB7fTsiXSwKICAibWFwcGluZ3MiOiAiO1lBQ0EsR0FBSSxHQUFXLE1BQ2YsQUFBSSxPQUFPLFNBQVMsV0FBYSxVQUFVLEdBQVcsUUFDdEQsR0FBSSxHQUFjLE9BQU8sU0FBUyxTQUNsQyxBQUFLLE1BQU0sS0FBSyxJQUFjLElBQWUsS0FDN0MsR0FBZSxjQUNmLEdBQUksR0FBSyxHQUFJLFdBQVUsRUFBVyxLQUFPLE9BQU8sU0FBUyxLQUFPLEdBRWhFLEVBQUcsVUFBWSxTQUFVLEVBQU8sQ0FDOUIsQUFBSSxFQUFNLE9BQVMsY0FDakIsT0FBTyxTQUFTIiwKICAibmFtZXMiOiBbXQp9Cg==

View File

@@ -1,2 +1,2 @@
/*! shiny 1.7.1.9002 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
#showcase-well{border-radius:0}.shiny-code{background-color:#fff;margin-bottom:0}.shiny-code code{font-family:Menlo,Consolas,"Courier New",monospace}.shiny-code-container{margin-top:20px;clear:both}.shiny-code-container h3{display:inline;margin-right:15px}.showcase-header{font-size:16px;font-weight:normal}.showcase-code-link{text-align:right;padding:15px}#showcase-app-container{vertical-align:top}#showcase-code-tabs{margin-right:15px}#showcase-code-tabs pre{border:none;line-height:1em}#showcase-code-tabs .nav{margin-bottom:0}#showcase-code-tabs ul{margin-bottom:0}#showcase-code-tabs .tab-content{border-style:solid;border-color:#e5e5e5;border-width:0px 1px 1px 1px;overflow:auto;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#showcase-app-code{width:100%}#showcase-code-position-toggle{float:right}#showcase-sxs-code{padding-top:20px;vertical-align:top}.showcase-code-license{display:block;text-align:right}#showcase-code-content pre{background-color:#fff}

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
/*! shiny 1.7.1.9002 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
(function(){var a=eval;window.addEventListener("message",function(i){var e=i.data;e.code&&a(e.code)});})();
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvc3JjL3V0aWxzL2V2YWwudHMiLCAiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LXRlc3Rtb2RlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvL2VzYnVpbGQuZ2l0aHViLmlvL2NvbnRlbnQtdHlwZXMvI2RpcmVjdC1ldmFsXG4vL3RsL2RyO1xuLy8gKiBEaXJlY3QgdXNhZ2Ugb2YgYGV2YWwoXCJ4XCIpYCBpcyBiYWQgd2l0aCBidW5kbGVkIGNvZGUuXG4vLyAqIEluc3RlYWQsIHVzZSBpbmRpcmVjdCBjYWxscyB0byBgZXZhbGAgc3VjaCBhcyBgaW5kaXJlY3RFdmFsKFwieFwiKWBcbi8vICAgKiBFdmVuIGp1c3QgcmVuYW1pbmcgdGhlIGZ1bmN0aW9uIHdvcmtzIHdlbGwgZW5vdWdoLlxuLy8gPiBUaGlzIGlzIGtub3duIGFzIFwiaW5kaXJlY3QgZXZhbFwiIGJlY2F1c2UgZXZhbCBpcyBub3QgYmVpbmcgY2FsbGVkIGRpcmVjdGx5LCBhbmQgc28gZG9lcyBub3QgdHJpZ2dlciB0aGUgZ3JhbW1hdGljYWwgc3BlY2lhbCBjYXNlIGZvciBkaXJlY3QgZXZhbCBpbiB0aGUgSmF2YVNjcmlwdCBWTS4gWW91IGNhbiBjYWxsIGluZGlyZWN0IGV2YWwgdXNpbmcgYW55IHN5bnRheCBhdCBhbGwgZXhjZXB0IGZvciBhbiBleHByZXNzaW9uIG9mIHRoZSBleGFjdCBmb3JtIGV2YWwoJ3gnKS4gRm9yIGV4YW1wbGUsIHZhciBldmFsMiA9IGV2YWw7IGV2YWwyKCd4JykgYW5kIFtldmFsXVswXSgneCcpIGFuZCB3aW5kb3cuZXZhbCgneCcpIGFyZSBhbGwgaW5kaXJlY3QgZXZhbCBjYWxscy5cbi8vID4gV2hlbiB5b3UgdXNlIGluZGlyZWN0IGV2YWwsIHRoZSBjb2RlIGlzIGV2YWx1YXRlZCBpbiB0aGUgZ2xvYmFsIHNjb3BlIGluc3RlYWQgb2YgaW4gdGhlIGlubGluZSBzY29wZSBvZiB0aGUgY2FsbGVyLlxudmFyIGluZGlyZWN0RXZhbCA9IGV2YWw7XG5leHBvcnQgeyBpbmRpcmVjdEV2YWwgfTsiLCAiLyogZXNsaW50LWRpc2FibGUgdW5pY29ybi9maWxlbmFtZS1jYXNlICovXG5pbXBvcnQgeyBpbmRpcmVjdEV2YWwgfSBmcm9tIFwiLi4vc3JjL3V0aWxzL2V2YWxcIjsgLy8gTGlzdGVuIGZvciBtZXNzYWdlcyBmcm9tIHBhcmVudCBmcmFtZS4gVGhpcyBmaWxlIGlzIG9ubHkgYWRkZWQgd2hlbiB0aGVcbi8vIHNoaW55LnRlc3Rtb2RlIG9wdGlvbiBpcyBUUlVFLlxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHtcbiAgdmFyIG1lc3NhZ2UgPSBlLmRhdGE7XG4gIGlmIChtZXNzYWdlLmNvZGUpIGluZGlyZWN0RXZhbChtZXNzYWdlLmNvZGUpO1xufSk7Il0sCiAgIm1hcHBpbmdzIjogIjtZQU9BLEdBQUksR0FBZSxLQ0huQixPQUFPLGlCQUFpQixVQUFXLFNBQVUsRUFBRyxDQUM5QyxHQUFJLEdBQVUsRUFBRSxLQUNoQixBQUFJLEVBQVEsTUFBTSxFQUFhLEVBQVEiLAogICJuYW1lcyI6IFtdCn0K

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -14,7 +14,6 @@ bootstrapLib(theme = NULL)
build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
\item A character string pointing to an alternative Bootstrap stylesheet
(normally a css file within the www directory, e.g. \code{www/bootstrap.css}).
This option is here mainly for legacy reasons.
}}
}
\description{

View File

@@ -1,25 +1,18 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bootstrap-layout.R, R/bootstrap.R
\name{fluidPage}
\alias{fluidPage}
\alias{fixedPage}
% Please edit documentation in R/bootstrap.R
\name{bootstrapPage}
\alias{bootstrapPage}
\alias{basicPage}
\title{Create a Bootstrap UI page container}
\title{Create a Bootstrap page}
\usage{
fluidPage(..., title = NULL, theme = NULL, lang = NULL)
fixedPage(..., title = NULL, theme = NULL, lang = NULL)
bootstrapPage(..., title = NULL, theme = NULL, lang = NULL)
basicPage(...)
}
\arguments{
\item{...}{UI elements (i.e., \link{tags}).}
\item{...}{The contents of the document body.}
\item{title}{The browser window title (defaults to the host URL of the page).
Can also be set as a side effect of the \code{\link[=titlePanel]{titlePanel()}} function.}
\item{title}{The browser window title (defaults to the host URL of the page)}
\item{theme}{One of the following:
\itemize{
@@ -28,74 +21,30 @@ Can also be set as a side effect of the \code{\link[=titlePanel]{titlePanel()}}
build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
\item A character string pointing to an alternative Bootstrap stylesheet
(normally a css file within the www directory, e.g. \code{www/bootstrap.css}).
This option is here mainly for legacy reasons.
}}
\item{lang}{ISO 639-1 language code for the HTML page, such as "en" or "ko".
This will be used as the lang in the \verb{<html>} tag, as in \verb{<html lang="en">}.
This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
The default (NULL) results in an empty string.}
}
\value{
A UI definition (i.e., a \link{tags} object) that can be passed to \code{\link[=shinyApp]{shinyApp()}}.
A UI defintion that can be passed to the \link{shinyUI} function.
}
\description{
Create a user interface (UI) page container based on
\href{https://getbootstrap.com/}{Bootstrap}'s CSS and JavaScript. Most Shiny apps
should use \code{\link[=fluidPage]{fluidPage()}} (or \code{\link[=navbarPage]{navbarPage()}}) to get a page container with a
responsive page width, but in some cases you may want a fixed width container
(\code{fixedPage()}) or just a bare \verb{<body>} container (\code{bootstrapPage()}).
Most Shiny apps make use of other Shiny UI functions for \href{https://shiny.rstudio.com/articles/layout-guide.html}{managing layout} (e.g.,
\code{\link[=sidebarLayout]{sidebarLayout()}}, \code{\link[=fluidRow]{fluidRow()}}, etc), navigation (e.g., \code{\link[=tabPanel]{tabPanel()}}), and
other styling (e.g., \code{\link[=wellPanel]{wellPanel()}}, \code{\link[=inputPanel]{inputPanel()}}). A good portion of these
Shiny UI functions require Bootstrap to work properly (so most Shiny apps
should use these functions to start their UI definitions), but more advanced
usage (i.e., custom HTML/CSS/JS) can avoid Bootstrap entirely by using
\code{\link[=htmlTemplate]{htmlTemplate()}} and/or HTML \link{tags}.
Create a Shiny UI page that loads the CSS and JavaScript for
\href{https://getbootstrap.com/}{Bootstrap}, and has no content in the page
body (other than what you provide).
}
\examples{
# First create some UI content.
# See the layout guide to learn more about creating different layouts
# https://shiny.rstudio.com/articles/layout-guide.html
ui <- sidebarLayout(
sidebarPanel(sliderInput("obs", "Number of observations:", 0, 1000, 500)),
mainPanel(plotOutput("distPlot"))
)
server <- function(input, output) {
output$distPlot <- renderPlot(hist(rnorm(input$obs)))
\details{
This function is primarily intended for users who are proficient in HTML/CSS,
and know how to lay out pages in Bootstrap. Most applications should use
\code{\link[=fluidPage]{fluidPage()}} along with layout functions like
\code{\link[=fluidRow]{fluidRow()}} and \code{\link[=sidebarLayout]{sidebarLayout()}}.
}
# Demonstrating difference between fluidPage(), fixedPage(), bootstrapPage()
if (interactive()) {
# Container width scales _fluidly_ with window size
shinyApp(fluidPage(ui), server)
# Container width changes with window size at fixed breakpoints
shinyApp(fixedPage(ui), server)
# Container width is equal to the window's width
shinyApp(bootstrapPage(ui), server)
}
# The default look is provided by Bootstrap 3, but {bslib} can be
# used to customize the Bootstrap version and its default styling
theme <- bslib::bs_theme(
version = 5,
bg = "#101010",
fg = "#FDF7F7",
primary = "#ED79F9",
base_font = bslib::font_google("Prompt"),
code_font = bslib::font_google("JetBrains Mono")
)
if (interactive()) {
# Call thematic::thematic_shiny(font = "auto") to automatically
# translate the theme/CSS to the R plot
shinyApp(
fluidPage(ui, theme = theme, title = "Hello Bootstrap 5"),
server
)
}
\note{
The \code{basicPage} function is deprecated, you should use the
\code{\link[=fluidPage]{fluidPage()}} function instead.
}
\seealso{
\code{\link[=navbarPage]{navbarPage()}}, \code{\link[=fillPage]{fillPage()}}, \code{\link[=column]{column()}}, \code{\link[=tabPanel]{tabPanel()}}
\code{\link[=fluidPage]{fluidPage()}}, \code{\link[=fixedPage]{fixedPage()}}
}

View File

@@ -1,45 +1,26 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bootstrap-layout.R
\name{fluidRow}
\alias{fluidRow}
\alias{fixedRow}
\name{column}
\alias{column}
\title{Responsive row-column based layout}
\title{Create a column within a UI definition}
\usage{
fluidRow(...)
fixedRow(...)
column(width, ..., offset = 0)
}
\arguments{
\item{...}{UI elements (i.e., \link{tags}). For \code{fluidRow()}, \code{...} should be a set of \code{column()}s.}
\item{width}{The grid width of the column (must be between 1 and 12)}
\item{width}{The grid width of the column (must be between 1 and 12). When
the device width is small (e.g., the viewer is on a mobile phone), the
width is always 12. For more control over these responsive breakpoints, use
Bootstrap's grid system more directly (e.g., \code{fluidRow(div(class = "col-lg-2", ...))}).}
\item{...}{Elements to include within the column}
\item{offset}{The number of columns to offset this column from the end of the
previous column.}
}
\value{
A UI element (i.e., \link{tags}).
A column that can be included within a
\code{\link[=fluidRow]{fluidRow()}} or \code{\link[=fixedRow]{fixedRow()}}.
}
\description{
Layout UI components using Bootstrap's grid layout system. Use
\code{fluidRow()} to group elements that should appear on the same line (if the
browser has adequate width) and \code{column()} to define how much horizontal
space within a 12-unit wide grid each on of these elements should occupy. See
the \href{https://shiny.rstudio.com/articles/layout-guide.html}{layout guide} for
more context and examples.
}
\details{
To work properly, these functions need \href{https://getbootstrap.com}{Bootstrap}
included on the page. Since most Shiny apps use \code{\link[=bootstrapPage]{bootstrapPage()}}
under-the-hood, this is usually the case, but custom page containers (i.e.,
\code{\link[=htmlTemplate]{htmlTemplate()}}) may need to explicitly include \code{\link[=bootstrapLib]{bootstrapLib()}}
dependencies.
Create a column for use within a \code{\link[=fluidRow]{fluidRow()}} or
\code{\link[=fixedRow]{fixedRow()}}
}
\examples{
## Only run examples in interactive R sessions
@@ -65,15 +46,21 @@ server <- function(input, output) {
shinyApp(ui, server)
ui <- fluidPage(
fluidRow(
column(width = 4, "4"),
column(width = 3, offset = 2, "3 offset 2")
column(width = 4,
"4"
),
column(width = 3, offset = 2,
"3 offset 2"
)
)
)
shinyApp(ui, server = function(input, output) { })
}
}
\seealso{
\code{\link[=fluidPage]{fluidPage()}}
\code{\link[=fluidRow]{fluidRow()}}, \code{\link[=fixedRow]{fixedRow()}}.
}

View File

@@ -37,11 +37,10 @@ shown in the document).}
build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
\item A character string pointing to an alternative Bootstrap stylesheet
(normally a css file within the www directory, e.g. \code{www/bootstrap.css}).
This option is here mainly for legacy reasons.
}}
\item{lang}{ISO 639-1 language code for the HTML page, such as "en" or "ko".
This will be used as the lang in the \verb{<html>} tag, as in \verb{<html lang="en">}.
This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
The default (NULL) results in an empty string.}
}
\description{
@@ -102,7 +101,9 @@ fillPage(
}
\seealso{
Other layout functions:
\code{\link{fixedPage}()},
\code{\link{flowLayout}()},
\code{\link{fluidPage}()},
\code{\link{navbarPage}()},
\code{\link{sidebarLayout}()},
\code{\link{splitLayout}()},

85
man/fixedPage.Rd Normal file
View File

@@ -0,0 +1,85 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bootstrap-layout.R
\name{fixedPage}
\alias{fixedPage}
\alias{fixedRow}
\title{Create a page with a fixed layout}
\usage{
fixedPage(..., title = NULL, theme = NULL, lang = NULL)
fixedRow(...)
}
\arguments{
\item{...}{Elements to include within the container}
\item{title}{The browser window title (defaults to the host URL of the page)}
\item{theme}{One of the following:
\itemize{
\item \code{NULL} (the default), which implies a "stock" build of Bootstrap 3.
\item A \code{\link[bslib:bs_theme]{bslib::bs_theme()}} object. This can be used to replace a stock
build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
\item A character string pointing to an alternative Bootstrap stylesheet
(normally a css file within the www directory, e.g. \code{www/bootstrap.css}).
}}
\item{lang}{ISO 639-1 language code for the HTML page, such as "en" or "ko".
This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
The default (NULL) results in an empty string.}
}
\value{
A UI defintion that can be passed to the \link{shinyUI} function.
}
\description{
Functions for creating fixed page layouts. A fixed page layout consists of
rows which in turn include columns. Rows exist for the purpose of making sure
their elements appear on the same line (if the browser has adequate width).
Columns exist for the purpose of defining how much horizontal space within a
12-unit wide grid it's elements should occupy. Fixed pages limit their width
to 940 pixels on a typical display, and 724px or 1170px on smaller and larger
displays respectively.
}
\details{
To create a fixed page use the \code{fixedPage} function and include
instances of \code{fixedRow} and \code{\link[=column]{column()}} within it. Note that
unlike \code{\link[=fluidPage]{fluidPage()}}, fixed pages cannot make use of higher-level
layout functions like \code{sidebarLayout}, rather, all layout must be done
with \code{fixedRow} and \code{column}.
}
\note{
See the \href{https://shiny.rstudio.com/articles/layout-guide.html}{ Shiny Application Layout Guide} for additional details on laying out fixed
pages.
}
\examples{
## Only run examples in interactive R sessions
if (interactive()) {
ui <- fixedPage(
title = "Hello, Shiny!",
fixedRow(
column(width = 4,
"4"
),
column(width = 3, offset = 2,
"3 offset 2"
)
)
)
shinyApp(ui, server = function(input, output) { })
}
}
\seealso{
\code{\link[=column]{column()}}
Other layout functions:
\code{\link{fillPage}()},
\code{\link{flowLayout}()},
\code{\link{fluidPage}()},
\code{\link{navbarPage}()},
\code{\link{sidebarLayout}()},
\code{\link{splitLayout}()},
\code{\link{verticalLayout}()}
}
\concept{layout functions}

View File

@@ -34,6 +34,8 @@ shinyApp(ui, server = function(input, output) { })
\seealso{
Other layout functions:
\code{\link{fillPage}()},
\code{\link{fixedPage}()},
\code{\link{fluidPage}()},
\code{\link{navbarPage}()},
\code{\link{sidebarLayout}()},
\code{\link{splitLayout}()},

119
man/fluidPage.Rd Normal file
View File

@@ -0,0 +1,119 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bootstrap-layout.R
\name{fluidPage}
\alias{fluidPage}
\alias{fluidRow}
\title{Create a page with fluid layout}
\usage{
fluidPage(..., title = NULL, theme = NULL, lang = NULL)
fluidRow(...)
}
\arguments{
\item{...}{Elements to include within the page}
\item{title}{The browser window title (defaults to the host URL of the page).
Can also be set as a side effect of the \code{\link[=titlePanel]{titlePanel()}} function.}
\item{theme}{One of the following:
\itemize{
\item \code{NULL} (the default), which implies a "stock" build of Bootstrap 3.
\item A \code{\link[bslib:bs_theme]{bslib::bs_theme()}} object. This can be used to replace a stock
build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
\item A character string pointing to an alternative Bootstrap stylesheet
(normally a css file within the www directory, e.g. \code{www/bootstrap.css}).
}}
\item{lang}{ISO 639-1 language code for the HTML page, such as "en" or "ko".
This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
The default (NULL) results in an empty string.}
}
\value{
A UI defintion that can be passed to the \link{shinyUI} function.
}
\description{
Functions for creating fluid page layouts. A fluid page layout consists of
rows which in turn include columns. Rows exist for the purpose of making sure
their elements appear on the same line (if the browser has adequate width).
Columns exist for the purpose of defining how much horizontal space within a
12-unit wide grid it's elements should occupy. Fluid pages scale their
components in realtime to fill all available browser width.
}
\details{
To create a fluid page use the \code{fluidPage} function and include
instances of \code{fluidRow} and \code{\link[=column]{column()}} within it. As an
alternative to low-level row and column functions you can also use
higher-level layout functions like \code{\link[=sidebarLayout]{sidebarLayout()}}.
}
\note{
See the \href{https://shiny.rstudio.com/articles/layout-guide.html}{ Shiny-Application-Layout-Guide} for additional details on laying out fluid
pages.
}
\examples{
## Only run examples in interactive R sessions
if (interactive()) {
# Example of UI with fluidPage
ui <- fluidPage(
# Application title
titlePanel("Hello Shiny!"),
sidebarLayout(
# Sidebar with a slider input
sidebarPanel(
sliderInput("obs",
"Number of observations:",
min = 0,
max = 1000,
value = 500)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Server logic
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$obs))
})
}
# Complete app with UI and server components
shinyApp(ui, server)
# UI demonstrating column layouts
ui <- fluidPage(
title = "Hello Shiny!",
fluidRow(
column(width = 4,
"4"
),
column(width = 3, offset = 2,
"3 offset 2"
)
)
)
shinyApp(ui, server = function(input, output) { })
}
}
\seealso{
\code{\link[=column]{column()}}
Other layout functions:
\code{\link{fillPage}()},
\code{\link{fixedPage}()},
\code{\link{flowLayout}()},
\code{\link{navbarPage}()},
\code{\link{sidebarLayout}()},
\code{\link{splitLayout}()},
\code{\link{verticalLayout}()}
}
\concept{layout functions}

View File

@@ -71,7 +71,6 @@ layout.}
build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
\item A character string pointing to an alternative Bootstrap stylesheet
(normally a css file within the www directory, e.g. \code{www/bootstrap.css}).
This option is here mainly for legacy reasons.
}}
\item{windowTitle}{the browser window title (as a character string). The
@@ -80,7 +79,7 @@ default value, \code{NA}, means to use any character strings that appear in
default).}
\item{lang}{ISO 639-1 language code for the HTML page, such as "en" or "ko".
This will be used as the lang in the \verb{<html>} tag, as in \verb{<html lang="en">}.
This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
The default (NULL) results in an empty string.}
\item{menuName}{A name that identifies this \code{navbarMenu}. This
@@ -125,7 +124,9 @@ navbarPage("App Title",
Other layout functions:
\code{\link{fillPage}()},
\code{\link{fixedPage}()},
\code{\link{flowLayout}()},
\code{\link{fluidPage}()},
\code{\link{sidebarLayout}()},
\code{\link{splitLayout}()},
\code{\link{verticalLayout}()}

View File

@@ -37,7 +37,7 @@ ports will be tried.}
\item{launch.browser}{If true, the system's default web browser will be
launched automatically after the app is started. Defaults to true in
interactive sessions only. This value of this parameter can also be a
interactive sessions only. The value of this parameter can also be a
function to call with the application's URL.}
\item{host}{The IPv4 address that the application should listen on. Defaults

View File

@@ -13,7 +13,7 @@ runGist(gist, destdir = NULL, ...)
runGitHub(
repo,
username = getOption("github.user"),
ref = "master",
ref = "HEAD",
subdir = NULL,
destdir = NULL,
...
@@ -47,7 +47,8 @@ all valid values.}
\code{"username/repo"}, \code{username} will be taken from \code{repo}.}
\item{ref}{Desired git reference. Could be a commit, tag, or branch name.
Defaults to \code{"master"}.}
Defaults to \code{"HEAD"}, which means the default branch on GitHub, typically
\code{"main"} or \code{"master"}.}
}
\description{
\code{runUrl()} downloads and launches a Shiny application that is hosted at

View File

@@ -104,6 +104,9 @@ should only be used for debugging or demonstrations of reactivity at the
console.}
\item{shiny.testmode (defaults to \code{FALSE})}{If \code{TRUE}, then various features for testing Shiny
applications are enabled.}
\item{shiny.snapshotsortc (defaults to \code{FALSE})}{If \code{TRUE}, test snapshot keys
for \pkg{shinytest} will be sorted consistently using the C locale. Snapshots
retrieved by \pkg{shinytest2} will always sort using the C locale.}
\item{shiny.trace (defaults to \code{FALSE})}{Print messages sent between the R server and the web
browser client to the R console. This is useful for debugging. Possible
values are \code{"send"} (only print messages sent to the client),

View File

@@ -83,7 +83,9 @@ shinyApp(ui, server)
\seealso{
Other layout functions:
\code{\link{fillPage}()},
\code{\link{fixedPage}()},
\code{\link{flowLayout}()},
\code{\link{fluidPage}()},
\code{\link{navbarPage}()},
\code{\link{splitLayout}()},
\code{\link{verticalLayout}()}

View File

@@ -64,7 +64,9 @@ shinyApp(ui, server)
\seealso{
Other layout functions:
\code{\link{fillPage}()},
\code{\link{fixedPage}()},
\code{\link{flowLayout}()},
\code{\link{fluidPage}()},
\code{\link{navbarPage}()},
\code{\link{sidebarLayout}()},
\code{\link{verticalLayout}()}

View File

@@ -76,10 +76,10 @@ value when it is a single choice input and the empty string is not in the
The resulting server \code{input} value will be returned as:
\itemize{
\item A symbol if \code{multiple = FALSE}. The \code{input} value should be
used with rlang's \code{\link[rlang:nse-force]{rlang::!!()}}. For example,
used with rlang's \code{\link[rlang:injection-operator]{rlang::!!()}}. For example,
\code{ggplot2::aes(!!input$variable)}.
\item A list of symbols if \code{multiple = TRUE}. The \code{input} value
should be used with rlang's \code{\link[rlang:nse-force]{rlang::!!!()}} to expand
should be used with rlang's \code{\link[rlang:splice-operator]{rlang::!!!()}} to expand
the symbol list as individual arguments. For example,
\code{dplyr::select(mtcars, !!!input$variabls)} which is
equivalent to \code{dplyr::select(mtcars, !!input$variabls[[1]], !!input$variabls[[2]], ..., !!input$variabls[[length(input$variabls)]])}.

View File

@@ -33,7 +33,9 @@ shinyApp(ui, server = function(input, output) { })
\seealso{
Other layout functions:
\code{\link{fillPage}()},
\code{\link{fixedPage}()},
\code{\link{flowLayout}()},
\code{\link{fluidPage}()},
\code{\link{navbarPage}()},
\code{\link{sidebarLayout}()},
\code{\link{splitLayout}()}

View File

@@ -3,7 +3,7 @@
"homepage": "https://shiny.rstudio.com",
"repository": "github:rstudio/shiny",
"name": "@types/rstudio-shiny",
"version": "1.7.1-alpha.9002",
"version": "1.7.1-alpha.9003",
"license": "GPL-3.0-only",
"main": "",
"browser": "",
@@ -46,7 +46,8 @@
"@typescript-eslint/parser": "^4.25.0",
"autoprefixer": "^10.2.6",
"bootstrap-datepicker": "1.9.0",
"browserslist": "^4.16.6",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001312",
"core-js": "^3.13.0",
"esbuild": "^0.12.4",
"esbuild-plugin-babel": "https://github.com/schloerke/esbuild-plugin-babel#patch-2",

View File

@@ -22,7 +22,7 @@ class InputBinding {
return false;
el;
}
getValue(el: HTMLElement): unknown {
getValue(el: HTMLElement): any {
throw "Not implemented";
el; // unused var
}

View File

@@ -6,11 +6,11 @@ import type { ErrorsMessageValue } from "../shiny/shinyapp";
interface ShinyEventCommon extends JQuery.Event {
name: string;
value: unknown;
el: HTMLElement;
el: HTMLElement | null;
}
interface ShinyEventInputChanged extends ShinyEventCommon {
value: unknown;
binding: InputBinding;
binding: InputBinding | null;
inputType: string;
priority: EventPriority;
}

View File

@@ -14,7 +14,7 @@ function createClickInfo(
mousedown: (e: JQuery.MouseDownEvent) => void;
dblclickIE8: (e: JQuery.DoubleClickEvent) => void;
} {
let clickTimer = null;
let clickTimer: ReturnType<typeof setTimeout> = null;
let pendingE: JQuery.MouseDownEvent = null; // A pending mousedown2 event
// Create a new event of type eventType (like 'mousedown2'), and trigger

View File

@@ -7,6 +7,7 @@ import type { BoundsCss, Bounds, BrushOpts } from "./createBrush";
import type { Offset } from "./findbox";
import type { Coordmap } from "./initCoordmap";
import type { Panel } from "./initPanelScales";
import type { InputRatePolicy } from "../inputPolicies";
// ----------------------------------------------------------
// Handler creators for click, hover, brush.
@@ -83,7 +84,7 @@ function createHoverHandler(
nullOutside
);
let hoverInfoSender: Debouncer | Throttler;
let hoverInfoSender: InputRatePolicy<typeof sendHoverInfo>;
if (delayType === "throttle")
hoverInfoSender = new Throttler(null, sendHoverInfo, delay);

View File

@@ -118,7 +118,7 @@ type Coordmap = {
inputId: string,
clip?: boolean,
nullOutside?: boolean
) => (e: JQuery.MouseDownEvent) => void;
) => (e: JQuery.MouseDownEvent | JQuery.MouseMoveEvent) => void;
};
// This adds functions to the coordmap object to handle various

View File

@@ -5,8 +5,9 @@ import { InputRateDecorator } from "./inputRateDecorator";
import { InputDeferDecorator } from "./inputDeferDecorator";
import { InputValidateDecorator } from "./inputValidateDecorator";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy } from "./inputPolicy";
import type { EventPriority } from "./inputPolicy";
import type { InputRatePolicy } from "./inputRatePolicy";
export {
InputBatchSender,
@@ -15,7 +16,6 @@ export {
InputRateDecorator,
InputDeferDecorator,
InputValidateDecorator,
InputPolicy,
};
export type { EventPriority };
export type { InputPolicy, EventPriority, InputRatePolicy };

View File

@@ -1,27 +1,21 @@
import $ from "jquery";
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import type { ShinyApp } from "../shiny/shinyapp";
// Schedules data to be sent to shinyapp at the next setTimeout(0).
// Batches multiple input calls into one websocket message.
class InputBatchSender extends InputPolicy {
class InputBatchSender implements InputPolicy {
target!: InputPolicy; // We need this field to satisfy the InputPolicy interface
shinyapp: ShinyApp;
timerId: NodeJS.Timeout = null;
timerId: ReturnType<typeof setTimeout> | null = null;
pendingData: { [key: string]: unknown } = {};
reentrant = false;
lastChanceCallback: Array<() => void> = [];
constructor(shinyapp: ShinyApp) {
super();
this.shinyapp = shinyapp;
}
setInput(
nameType: string,
value: unknown,
opts: { priority: EventPriority }
): void {
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
this.pendingData[nameType] = value;
if (!this.reentrant) {
@@ -41,9 +35,7 @@ class InputBatchSender extends InputPolicy {
this.reentrant = true;
try {
this.timerId = null;
$.each(this.lastChanceCallback, (i, callback) => {
callback();
});
this.lastChanceCallback.forEach((callback) => callback());
const currentData = this.pendingData;
this.pendingData = {};

View File

@@ -1,21 +1,18 @@
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import { hasOwnProperty } from "../utils";
class InputDeferDecorator extends InputPolicy {
class InputDeferDecorator implements InputPolicy {
pendingInput: {
[key: string]: { value: unknown; opts: { priority: EventPriority } };
} = {};
target: InputPolicy;
constructor(target: InputPolicy) {
super();
this.target = target;
}
setInput(
nameType: string,
value: unknown,
opts: { priority: EventPriority }
): void {
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
if (/^\./.test(nameType)) this.target.setInput(nameType, value, opts);
else this.pendingInput[nameType] = { value, opts };
}

View File

@@ -1,25 +1,16 @@
import $ from "jquery";
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputBinding } from "../bindings";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import type { ShinyEventInputChanged } from "../events/shinyEvents";
import { splitInputNameType } from "./splitInputNameType";
class InputEventDecorator extends InputPolicy {
class InputEventDecorator implements InputPolicy {
target: InputPolicy;
constructor(target: InputPolicy) {
super();
this.target = target;
}
setInput(
nameType: string,
value: unknown,
opts: {
el: HTMLElement;
priority: EventPriority;
binding: InputBinding;
}
): void {
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
const evt = jQuery.Event("shiny:inputchanged") as ShinyEventInputChanged;
const input = splitInputNameType(nameType);
@@ -27,11 +18,15 @@ class InputEventDecorator extends InputPolicy {
evt.name = input.name;
evt.inputType = input.inputType;
evt.value = value;
evt.binding = opts.binding;
evt.el = opts.el;
evt.binding = opts.binding || null;
evt.el = opts.el || null;
evt.priority = opts.priority;
$(opts.el).trigger(evt);
// The `shiny:inputchanged` JavaScript event now triggers on the related
// input element instead of `document`. Existing event listeners bound to
// `document` will still detect the event due to event bubbling. #2446
// If no `el` exists, use `document` instead. #3584
$(opts.el || window.document).trigger(evt);
if (!evt.isDefaultPrevented()) {
let name = evt.name;

View File

@@ -1,24 +1,19 @@
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import { hasOwnProperty } from "../utils";
import { splitInputNameType } from "./splitInputNameType";
type LastSentValues = { [key: string]: { [key: string]: string } };
class InputNoResendDecorator extends InputPolicy {
lastSentValues: LastSentValues;
class InputNoResendDecorator implements InputPolicy {
target: InputPolicy;
lastSentValues: LastSentValues = {};
constructor(target: InputPolicy, initialValues: LastSentValues = {}) {
super();
this.target = target;
this.reset(initialValues);
}
setInput(
nameType: string,
value: unknown,
opts: { priority: EventPriority }
): void {
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
const { name: inputName, inputType: inputType } =
splitInputNameType(nameType);
const jsonValue = JSON.stringify(value);
@@ -34,13 +29,15 @@ class InputNoResendDecorator extends InputPolicy {
this.lastSentValues[inputName] = { jsonValue, inputType };
this.target.setInput(nameType, value, opts);
}
reset(values = {}): void {
reset(values: LastSentValues = {}): void {
// Given an object with flat name-value format:
// { x: "abc", "y.shiny.number": 123 }
// Create an object in cache format and save it:
// { x: { jsonValue: '"abc"', inputType: "" },
// y: { jsonValue: "123", inputType: "shiny.number" } }
const cacheValues = {};
const cacheValues: {
[key: string]: { jsonValue: string; inputType: string };
} = {};
for (const inputName in values) {
if (hasOwnProperty(values, inputName)) {

View File

@@ -1,21 +1,19 @@
import type { InputBinding } from "../bindings";
type EventPriority = "deferred" | "event" | "immediate";
type InputPolicyOpts = {
priority: EventPriority;
el?: HTMLElement;
binding?: InputBinding;
};
// Schedules data to be sent to shinyapp at the next setTimeout(0).
// Batches multiple input calls into one websocket message.
class InputPolicy {
interface InputPolicy {
target: InputPolicy;
setInput(
name: string,
value: unknown,
opts: { priority: EventPriority }
): void {
throw "not implemented";
name;
value;
opts;
}
setInput(name: string, value: unknown, opts: InputPolicyOpts): void;
}
export { InputPolicy };
export type { EventPriority };
export type { InputPolicy, EventPriority, InputPolicyOpts };

View File

@@ -1,14 +1,17 @@
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import { Debouncer, Invoker, Throttler } from "../time";
import { splitInputNameType } from "./splitInputNameType";
import type { InputRatePolicy } from "./inputRatePolicy";
type RatePolicyModes = "debounce" | "direct" | "throttle";
class InputRateDecorator extends InputPolicy {
inputRatePolicies = {};
class InputRateDecorator implements InputPolicy {
target: InputPolicy;
inputRatePolicies: {
[key: string]: InputRatePolicy<InputRateDecorator["_doSetInput"]>;
} = {};
constructor(target: InputPolicy) {
super();
this.target = target;
}
@@ -18,11 +21,7 @@ class InputRateDecorator extends InputPolicy {
// However, $ensureInit() and $doSetInput() are meant to be passed just
// the input name (i.e., inputId), which is why we distinguish between
// nameType and name.
setInput(
nameType: string,
value: unknown,
opts: { priority: EventPriority }
): void {
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
const { name: inputName } = splitInputNameType(nameType);
this._ensureInit(inputName);
@@ -60,7 +59,7 @@ class InputRateDecorator extends InputPolicy {
private _doSetInput(
nameType: string,
value: unknown,
opts: { priority: EventPriority }
opts: InputPolicyOpts
): void {
this.target.setInput(nameType, value, opts);
}

View File

@@ -0,0 +1,12 @@
import type { AnyVoidFunction } from "../utils/extraTypes";
import type { InputPolicy } from "./inputPolicy";
interface InputRatePolicy<X extends AnyVoidFunction> {
target: InputPolicy;
func: X;
normalCall(...args: Parameters<X>): void;
immediateCall(...args: Parameters<X>): void;
}
export type { InputRatePolicy };

View File

@@ -1,61 +1,43 @@
import $ from "jquery";
import type { EventPriority, InputPolicy } from "./inputPolicy";
type MaybeInputOpts = {
priority?: EventPriority;
binding?: unknown;
el?: HTMLElement;
};
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
// Merge opts with defaults, and return a new object.
function addDefaultInputOpts<T>(opts?: MaybeInputOpts & T): T & {
priority: EventPriority;
binding: unknown;
el?: HTMLElement;
} {
const newOpts = $.extend(
{
priority: "immediate",
binding: null,
el: null,
},
opts
);
function addDefaultInputOpts(opts: Partial<InputPolicyOpts>): InputPolicyOpts {
const newOpts: InputPolicyOpts = {
priority: "immediate",
...opts,
};
if (newOpts && typeof newOpts.priority !== "undefined") {
switch (newOpts.priority) {
case "deferred":
case "immediate":
case "event":
break;
default:
throw new Error(
"Unexpected input value mode: '" + newOpts.priority + "'"
);
}
switch (newOpts.priority) {
case "deferred":
case "immediate":
case "event":
break;
default:
throw new Error(
"Unexpected input value mode: '" + newOpts.priority + "'"
);
}
return newOpts;
}
class InputValidateDecorator {
target;
class InputValidateDecorator implements InputPolicy {
target: InputPolicy;
constructor(target: InputPolicy) {
this.target = target;
}
setInput = function <T>(
setInput(
nameType: string,
value: unknown,
opts?: MaybeInputOpts & T
opts: Partial<InputPolicyOpts> = {}
): void {
if (!nameType) throw "Can't set input with empty name.";
const newOpts = addDefaultInputOpts(opts);
this.target.setInput(nameType, value, newOpts);
};
}
}
export { InputValidateDecorator, addDefaultInputOpts };

View File

@@ -47,7 +47,7 @@ function bindInputs(
scope: BindScope = document.documentElement
): {
[key: string]: {
value: unknown;
value: ReturnType<InputBinding["getValue"]>;
opts: { immediate: boolean; binding: InputBinding; el: HTMLElement };
};
} {

View File

@@ -8,7 +8,7 @@ import {
InputRateDecorator,
InputValidateDecorator,
} from "../inputPolicies";
import type { EventPriority } from "../inputPolicies";
import type { InputPolicy } from "../inputPolicies";
import { addDefaultInputOpts } from "../inputPolicies/inputValidateDecorator";
import { debounce, Debouncer } from "../time";
import {
@@ -25,6 +25,7 @@ import { registerDependency } from "./render";
import { sendImageSizeFns } from "./sendImageSize";
import { ShinyApp } from "./shinyapp";
import { registerNames as singletonsRegisterNames } from "./singletons";
import type { InputPolicyOpts } from "../inputPolicies/inputPolicy";
// "init_shiny.js"
function initShiny(windowShiny: Shiny): void {
@@ -39,7 +40,7 @@ function initShiny(windowShiny: Shiny): void {
const inputsRate = new InputRateDecorator(inputsEvent);
const inputsDefer = new InputDeferDecorator(inputsEvent);
let target;
let target: InputPolicy;
if ($('input[type="submit"], button[type="submit"]').length > 0) {
// If there is a submit button on the page, use defer decorator
@@ -61,7 +62,7 @@ function initShiny(windowShiny: Shiny): void {
windowShiny.setInputValue = windowShiny.onInputChange = function (
name: string,
value: unknown,
opts?: { priority?: EventPriority }
opts: Partial<InputPolicyOpts> = {}
): void {
const newOpts = addDefaultInputOpts(opts);

View File

@@ -155,7 +155,8 @@ function addRemovalCallback(id, delay) {
// Clear a removal callback from a notification, if present.
function clearRemovalCallback(id) {
const $notification = get(id);
const oldRemovalCallback = $notification.data("removalCallback");
const oldRemovalCallback: ReturnType<typeof setTimeout> =
$notification.data("removalCallback");
if (oldRemovalCallback) {
clearTimeout(oldRemovalCallback);

View File

@@ -10,7 +10,7 @@ class SendImageSize {
setImageSend(
inputBatchSender: InputBatchSender,
doSendImageSize: () => void
): Debouncer {
): Debouncer<typeof doSendImageSize> {
const sendImageSizeDebouncer = new Debouncer(null, doSendImageSize, 0);
this.regular = function () {

View File

@@ -160,7 +160,7 @@ class ShinyApp {
return !!this.$socket;
}
private scheduledReconnect = null;
private scheduledReconnect: ReturnType<typeof setTimeout> = null;
reconnect(): void {
// This function can be invoked directly even if there's a scheduled
@@ -971,7 +971,37 @@ class ShinyApp {
position: "after" | "before" | void;
select: boolean;
menuName: string;
jsxTag: { html: string; deps: HtmlDep[] };
}) => {
if (message.jsxTag) {
// Render jsxTag (a <script> tag) inside a (temporary) hidden div and use
// the HTML results to populate liTag/divTag
const jsxContainerEl = document.createElement("div");
const jsxId = "shiny-jsx-container-" + message.inputId;
jsxContainerEl.style.display = "none";
jsxContainerEl.setAttribute("id", jsxId);
document.body.appendChild(jsxContainerEl);
const jsxContainer = document.body.querySelector("#" + jsxId);
// Use jQuery's .html() method since that has special handling to ensure
// <script> tags are evaluated.
$(jsxContainer).html(message.jsxTag.html);
message.liTag = {
html: jsxContainer.querySelector("ul.nav").innerHTML,
deps: [],
};
message.divTag = {
html: jsxContainer.querySelector("div.tab-content").innerHTML,
deps: message.jsxTag.deps,
};
jsxContainer.remove();
delete message.jsxTag;
}
const $parentTabset = getTabset(message.inputId);
let $tabset = $parentTabset;
const $tabContent = getTabContent($tabset);

View File

@@ -1,15 +1,15 @@
class Debouncer {
target: unknown;
func: (...args: unknown[]) => void;
delayMs: number;
timerId: NodeJS.Timeout;
args: unknown[];
import type { InputPolicy } from "../inputPolicies";
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
import type { AnyVoidFunction } from "../utils/extraTypes";
constructor(
target: unknown,
func: (...args: unknown[]) => void,
delayMs: number
) {
class Debouncer<X extends AnyVoidFunction> implements InputRatePolicy<X> {
target: InputPolicy;
func: X;
delayMs: number | undefined;
timerId: ReturnType<typeof setTimeout> | null;
args: Parameters<X> | null;
constructor(target: InputPolicy, func: X, delayMs: number | undefined) {
this.target = target;
this.func = func;
this.delayMs = delayMs;
@@ -18,7 +18,7 @@ class Debouncer {
this.args = null;
}
normalCall(...args: unknown[]): void {
normalCall(...args: Parameters<X>): void {
this.$clearTimer();
this.args = args;
@@ -30,7 +30,7 @@ class Debouncer {
this.$invoke();
}, this.delayMs);
}
immediateCall(...args: unknown[]): void {
immediateCall(...args: Parameters<X>): void {
this.$clearTimer();
this.args = args;
this.$invoke();
@@ -45,7 +45,11 @@ class Debouncer {
}
}
$invoke(): void {
this.func.apply(this.target, this.args);
if (this.args && this.args.length > 0) {
this.func.apply(this.target, this.args);
} else {
this.func.apply(this.target);
}
this.args = null;
}
}
@@ -62,13 +66,15 @@ class Debouncer {
// 900ms intervals will result in a single execution
// of the underlying function, 1000ms after the 17th
// call.
function debounce<T>(
threshold: number,
func: (...args: T[]) => void
): (...args: T[]) => void {
let timerId = null;
function debounce<T extends (...args: unknown[]) => void>(
threshold: number | undefined,
func: T
): (...args: Parameters<T>) => void {
let timerId: ReturnType<typeof setTimeout> | null = null;
return function (...args) {
// Do not alter `function()` into an arrow function.
// The `this` context needs to be dynamically bound
return function thisFunc(...args: Parameters<T>) {
if (timerId !== null) {
clearTimeout(timerId);
timerId = null;
@@ -78,7 +84,8 @@ function debounce<T>(
// check is needed
if (timerId === null) return;
timerId = null;
func.apply(this, args);
// Applying on `thisFunc` passes through the `this` context
func.apply(thisFunc, args);
}, threshold);
};
}

View File

@@ -1,5 +1,5 @@
import { Debouncer, debounce } from "./debounce";
import { Invoker } from "./invoke";
import { Throttler, throttle } from "./throttle";
import { Throttler } from "./throttle";
export { Debouncer, debounce, Invoker, Throttler, throttle };
export { Debouncer, debounce, Invoker, Throttler };

View File

@@ -1,19 +1,21 @@
import type { InputPolicy } from "../inputPolicies";
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
import type { AnyVoidFunction } from "../utils/extraTypes";
class Invoker<T> {
class Invoker<X extends AnyVoidFunction> implements InputRatePolicy<X> {
target: InputPolicy;
func: () => void;
func: X;
constructor(target: InputPolicy, func: (...args: T[]) => void) {
constructor(target: InputPolicy, func: X) {
this.target = target;
this.func = func;
}
// TODO-barret - Don't know how to define the method twice and still have access to "this"
normalCall(...args: T[]): void {
normalCall(...args: Parameters<X>): void {
this.func.apply(this.target, args);
}
immediateCall(...args: T[]): void {
immediateCall(...args: Parameters<X>): void {
this.func.apply(this.target, args);
}
}

View File

@@ -1,11 +1,16 @@
class Throttler<T = unknown> {
target: unknown;
func: (...args: T[]) => void;
delayMs: number;
timerId: NodeJS.Timeout;
args: T[];
/* eslint-disable indent */
import type { InputPolicy } from "../inputPolicies";
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
import type { AnyVoidFunction } from "../utils/extraTypes";
constructor(target: unknown, func: (...args: T[]) => void, delayMs: number) {
class Throttler<X extends AnyVoidFunction> implements InputRatePolicy<X> {
target: InputPolicy;
func: X;
delayMs: number | undefined;
timerId: ReturnType<typeof setTimeout> | null;
args: Parameters<X> | null;
constructor(target: InputPolicy, func: X, delayMs: number | undefined) {
this.target = target;
this.func = func;
this.delayMs = delayMs;
@@ -14,7 +19,7 @@ class Throttler<T = unknown> {
this.args = null;
}
normalCall(...args: T[]): void {
normalCall(...args: Parameters<X>): void {
this.args = args;
if (this.timerId === null) {
this.$invoke();
@@ -23,11 +28,11 @@ class Throttler<T = unknown> {
// check is needed
if (this.timerId === null) return;
this.$clearTimer();
if (args.length > 0) this.normalCall.apply(this, ...args);
if (args.length > 0) this.normalCall(...args);
}, this.delayMs);
}
}
immediateCall(...args: T[]): void {
immediateCall(...args: Parameters<X>): void {
this.$clearTimer();
this.args = args;
this.$invoke();
@@ -42,54 +47,61 @@ class Throttler<T = unknown> {
}
}
$invoke(): void {
this.func.apply(this.target, this.args);
if (this.args && this.args.length > 0) {
this.func.apply(this.target, this.args);
} else {
this.func.apply(this.target);
}
this.args = null;
}
}
// Returns a throttled version of the given function.
// Throttling means that the underlying function will
// be executed no more than once every `threshold`
// milliseconds.
//
// For example, if a function is throttled with a
// threshold of 1000ms, then calling it 17 times at
// 900ms intervals will result in something like 15
// or 16 executions of the underlying function.
// eslint-disable-next-line no-unused-vars
function throttle<T>(
threshold: number,
func: (...args: T[]) => void
): (...args: T[]) => void {
let executionPending = false;
let timerId = null;
let self, args: T[];
// // Returns a throttled version of the given function.
// // Throttling means that the underlying function will
// // be executed no more than once every `threshold`
// // milliseconds.
// //
// // For example, if a function is throttled with a
// // threshold of 1000ms, then calling it 17 times at
// // 900ms intervals will result in something like 15
// // or 16 executions of the underlying function.
// // eslint-disable-next-line no-unused-vars
// function throttle<T>(
// threshold: number,
// func: (...args: T[]) => void
// ): (...args: T[]) => void {
// let executionPending = false;
// let timerId: number | null = null;
// let self: unknown, args: T[] | null;
function throttled(...argumentVals: T[]) {
self = null;
args = null;
if (timerId === null) {
// Haven't seen a call recently. Execute now and
// start a timer to buffer any subsequent calls.
timerId = setTimeout(function () {
// When time expires, clear the timer; and if
// there has been a call in the meantime, repeat.
timerId = null;
if (executionPending) {
executionPending = false;
throttled.apply(self, args);
}
}, threshold);
func.apply(this, argumentVals);
} else {
// Something executed recently. Don't do anything
// except set up target/arguments to be called later
executionPending = true;
self = this;
args = argumentVals;
}
}
return throttled;
}
// function throttled(...argumentVals: T[]) {
// self = null;
// args = null;
// if (timerId === null) {
// // Haven't seen a call recently. Execute now and
// // start a timer to buffer any subsequent calls.
// timerId = setTimeout(function () {
// // When time expires, clear the timer; and if
// // there has been a call in the meantime, repeat.
// timerId = null;
// if (executionPending) {
// executionPending = false;
// throttled.apply(self, args || []);
// }
// }, threshold);
// func.apply(this, argumentVals);
// } else {
// // Something executed recently. Don't do anything
// // except set up target/arguments to be called later
// executionPending = true;
// self = this as unknown;
// args = argumentVals;
// }
// }
// return throttled;
// }
export { Throttler, throttle };
export {
Throttler,
// throttle
};

View File

@@ -0,0 +1,4 @@
type AnyFunction = (...args: any[]) => any;
type AnyVoidFunction = (...args: any[]) => void;
export type { AnyFunction, AnyVoidFunction };

View File

@@ -5,7 +5,7 @@ declare class InputBinding {
find(scope: BindScope): JQuery<HTMLElement>;
getId(el: HTMLElement): string;
getType(el: HTMLElement): string | false;
getValue(el: HTMLElement): unknown;
getValue(el: HTMLElement): any;
subscribe(el: HTMLElement, callback: (value: boolean) => void): void;
unsubscribe(el: HTMLElement): void;
receiveMessage(el: HTMLElement, data: unknown): void;

View File

@@ -6,11 +6,11 @@ import type { ErrorsMessageValue } from "../shiny/shinyapp";
interface ShinyEventCommon extends JQuery.Event {
name: string;
value: unknown;
el: HTMLElement;
el: HTMLElement | null;
}
interface ShinyEventInputChanged extends ShinyEventCommon {
value: unknown;
binding: InputBinding;
binding: InputBinding | null;
inputType: string;
priority: EventPriority;
}

View File

@@ -37,7 +37,7 @@ declare type Coordmap = {
cssToImgScalingRatio: () => Offset;
getPanelCss: (offsetCss: OffsetCss, expand?: number) => Panel;
isInPanelCss: (offsetCss: OffsetCss, expand?: number) => boolean;
mouseCoordinateSender: (inputId: string, clip?: boolean, nullOutside?: boolean) => (e: JQuery.MouseDownEvent) => void;
mouseCoordinateSender: (inputId: string, clip?: boolean, nullOutside?: boolean) => (e: JQuery.MouseDownEvent | JQuery.MouseMoveEvent) => void;
};
declare function initCoordmap($el: JQuery<HTMLElement>, coordmap_: CoordmapInit): Coordmap;
export type { Coordmap, CoordmapInit };

View File

@@ -4,7 +4,8 @@ import { InputEventDecorator } from "./inputEventDecorator";
import { InputRateDecorator } from "./inputRateDecorator";
import { InputDeferDecorator } from "./inputDeferDecorator";
import { InputValidateDecorator } from "./inputValidateDecorator";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy } from "./inputPolicy";
import type { EventPriority } from "./inputPolicy";
export { InputBatchSender, InputEventDecorator, InputNoResendDecorator, InputRateDecorator, InputDeferDecorator, InputValidateDecorator, InputPolicy, };
export type { EventPriority };
import type { InputRatePolicy } from "./inputRatePolicy";
export { InputBatchSender, InputEventDecorator, InputNoResendDecorator, InputRateDecorator, InputDeferDecorator, InputValidateDecorator, };
export type { InputPolicy, EventPriority, InputRatePolicy };

View File

@@ -1,19 +1,16 @@
/// <reference types="node" />
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import type { ShinyApp } from "../shiny/shinyapp";
declare class InputBatchSender extends InputPolicy {
declare class InputBatchSender implements InputPolicy {
target: InputPolicy;
shinyapp: ShinyApp;
timerId: NodeJS.Timeout;
timerId: ReturnType<typeof setTimeout> | null;
pendingData: {
[key: string]: unknown;
};
reentrant: boolean;
lastChanceCallback: Array<() => void>;
constructor(shinyapp: ShinyApp);
setInput(nameType: string, value: unknown, opts: {
priority: EventPriority;
}): void;
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
private _sendNow;
}
export { InputBatchSender };

View File

@@ -1,6 +1,6 @@
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
declare class InputDeferDecorator extends InputPolicy {
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
declare class InputDeferDecorator implements InputPolicy {
pendingInput: {
[key: string]: {
value: unknown;
@@ -9,10 +9,9 @@ declare class InputDeferDecorator extends InputPolicy {
};
};
};
target: InputPolicy;
constructor(target: InputPolicy);
setInput(nameType: string, value: unknown, opts: {
priority: EventPriority;
}): void;
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
submit(): void;
}
export { InputDeferDecorator };

View File

@@ -1,12 +1,7 @@
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputBinding } from "../bindings";
declare class InputEventDecorator extends InputPolicy {
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
declare class InputEventDecorator implements InputPolicy {
target: InputPolicy;
constructor(target: InputPolicy);
setInput(nameType: string, value: unknown, opts: {
el: HTMLElement;
priority: EventPriority;
binding: InputBinding;
}): void;
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
}
export { InputEventDecorator };

View File

@@ -1,17 +1,15 @@
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
declare type LastSentValues = {
[key: string]: {
[key: string]: string;
};
};
declare class InputNoResendDecorator extends InputPolicy {
declare class InputNoResendDecorator implements InputPolicy {
target: InputPolicy;
lastSentValues: LastSentValues;
constructor(target: InputPolicy, initialValues?: LastSentValues);
setInput(nameType: string, value: unknown, opts: {
priority: EventPriority;
}): void;
reset(values?: {}): void;
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
reset(values?: LastSentValues): void;
forget(name: string): void;
}
export { InputNoResendDecorator };

View File

@@ -1,9 +1,12 @@
import type { InputBinding } from "../bindings";
declare type EventPriority = "deferred" | "event" | "immediate";
declare class InputPolicy {
declare type InputPolicyOpts = {
priority: EventPriority;
el?: HTMLElement;
binding?: InputBinding;
};
interface InputPolicy {
target: InputPolicy;
setInput(name: string, value: unknown, opts: {
priority: EventPriority;
}): void;
setInput(name: string, value: unknown, opts: InputPolicyOpts): void;
}
export { InputPolicy };
export type { EventPriority };
export type { InputPolicy, EventPriority, InputPolicyOpts };

View File

@@ -1,12 +1,13 @@
import type { EventPriority } from "./inputPolicy";
import { InputPolicy } from "./inputPolicy";
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import type { InputRatePolicy } from "./inputRatePolicy";
declare type RatePolicyModes = "debounce" | "direct" | "throttle";
declare class InputRateDecorator extends InputPolicy {
inputRatePolicies: {};
declare class InputRateDecorator implements InputPolicy {
target: InputPolicy;
inputRatePolicies: {
[key: string]: InputRatePolicy<InputRateDecorator["_doSetInput"]>;
};
constructor(target: InputPolicy);
setInput(nameType: string, value: unknown, opts: {
priority: EventPriority;
}): void;
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
setRatePolicy(nameType: string, mode: RatePolicyModes, millis?: number): void;
private _ensureInit;
private _doSetInput;

View File

@@ -0,0 +1,9 @@
import type { AnyVoidFunction } from "../utils/extraTypes";
import type { InputPolicy } from "./inputPolicy";
interface InputRatePolicy<X extends AnyVoidFunction> {
target: InputPolicy;
func: X;
normalCall(...args: Parameters<X>): void;
immediateCall(...args: Parameters<X>): void;
}
export type { InputRatePolicy };

View File

@@ -1,17 +1,8 @@
import type { EventPriority, InputPolicy } from "./inputPolicy";
declare type MaybeInputOpts = {
priority?: EventPriority;
binding?: unknown;
el?: HTMLElement;
};
declare function addDefaultInputOpts<T>(opts?: MaybeInputOpts & T): T & {
priority: EventPriority;
binding: unknown;
el?: HTMLElement;
};
declare class InputValidateDecorator {
target: any;
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
declare function addDefaultInputOpts(opts: Partial<InputPolicyOpts>): InputPolicyOpts;
declare class InputValidateDecorator implements InputPolicy {
target: InputPolicy;
constructor(target: InputPolicy);
setInput: <T>(nameType: string, value: unknown, opts?: MaybeInputOpts & T) => void;
setInput(nameType: string, value: unknown, opts?: Partial<InputPolicyOpts>): void;
}
export { InputValidateDecorator, addDefaultInputOpts };

View File

@@ -13,7 +13,7 @@ declare type BindInputsCtx = {
};
declare function bindInputs(shinyCtx: BindInputsCtx, scope?: BindScope): {
[key: string]: {
value: unknown;
value: ReturnType<InputBinding["getValue"]>;
opts: {
immediate: boolean;
binding: InputBinding;

View File

@@ -3,7 +3,7 @@ import { Debouncer } from "../time";
declare class SendImageSize {
regular: () => void;
transitioned: () => void;
setImageSend(inputBatchSender: InputBatchSender, doSendImageSize: () => void): Debouncer;
setImageSend(inputBatchSender: InputBatchSender, doSendImageSize: () => void): Debouncer<typeof doSendImageSize>;
}
declare const sendImageSizeFns: SendImageSize;
export { sendImageSizeFns };

View File

@@ -1,16 +1,18 @@
/// <reference types="node" />
declare class Debouncer {
target: unknown;
func: (...args: unknown[]) => void;
delayMs: number;
timerId: NodeJS.Timeout;
args: unknown[];
constructor(target: unknown, func: (...args: unknown[]) => void, delayMs: number);
normalCall(...args: unknown[]): void;
immediateCall(...args: unknown[]): void;
import type { InputPolicy } from "../inputPolicies";
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
import type { AnyVoidFunction } from "../utils/extraTypes";
declare class Debouncer<X extends AnyVoidFunction> implements InputRatePolicy<X> {
target: InputPolicy;
func: X;
delayMs: number | undefined;
timerId: ReturnType<typeof setTimeout> | null;
args: Parameters<X> | null;
constructor(target: InputPolicy, func: X, delayMs: number | undefined);
normalCall(...args: Parameters<X>): void;
immediateCall(...args: Parameters<X>): void;
isPending(): boolean;
$clearTimer(): void;
$invoke(): void;
}
declare function debounce<T>(threshold: number, func: (...args: T[]) => void): (...args: T[]) => void;
declare function debounce<T extends (...args: unknown[]) => void>(threshold: number | undefined, func: T): (...args: Parameters<T>) => void;
export { Debouncer, debounce };

View File

@@ -1,4 +1,4 @@
import { Debouncer, debounce } from "./debounce";
import { Invoker } from "./invoke";
import { Throttler, throttle } from "./throttle";
export { Debouncer, debounce, Invoker, Throttler, throttle };
import { Throttler } from "./throttle";
export { Debouncer, debounce, Invoker, Throttler };

View File

@@ -1,9 +1,11 @@
import type { InputPolicy } from "../inputPolicies";
declare class Invoker<T> {
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
import type { AnyVoidFunction } from "../utils/extraTypes";
declare class Invoker<X extends AnyVoidFunction> implements InputRatePolicy<X> {
target: InputPolicy;
func: () => void;
constructor(target: InputPolicy, func: (...args: T[]) => void);
normalCall(...args: T[]): void;
immediateCall(...args: T[]): void;
func: X;
constructor(target: InputPolicy, func: X);
normalCall(...args: Parameters<X>): void;
immediateCall(...args: Parameters<X>): void;
}
export { Invoker };

View File

@@ -1,16 +1,17 @@
/// <reference types="node" />
declare class Throttler<T = unknown> {
target: unknown;
func: (...args: T[]) => void;
delayMs: number;
timerId: NodeJS.Timeout;
args: T[];
constructor(target: unknown, func: (...args: T[]) => void, delayMs: number);
normalCall(...args: T[]): void;
immediateCall(...args: T[]): void;
import type { InputPolicy } from "../inputPolicies";
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
import type { AnyVoidFunction } from "../utils/extraTypes";
declare class Throttler<X extends AnyVoidFunction> implements InputRatePolicy<X> {
target: InputPolicy;
func: X;
delayMs: number | undefined;
timerId: ReturnType<typeof setTimeout> | null;
args: Parameters<X> | null;
constructor(target: InputPolicy, func: X, delayMs: number | undefined);
normalCall(...args: Parameters<X>): void;
immediateCall(...args: Parameters<X>): void;
isPending(): boolean;
$clearTimer(): void;
$invoke(): void;
}
declare function throttle<T>(threshold: number, func: (...args: T[]) => void): (...args: T[]) => void;
export { Throttler, throttle };
export { Throttler, };

3
srcts/types/src/utils/extraTypes.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
declare type AnyFunction = (...args: any[]) => any;
declare type AnyVoidFunction = (...args: any[]) => void;
export type { AnyFunction, AnyVoidFunction };

View File

@@ -129,13 +129,11 @@ test_that("integration tests", {
df <- causeError(full = FALSE)
# dumpTests(df)
expect_equal(df$num, c(56L, 55L, 54L, 38L, 37L, 36L, 35L,
34L, 33L, 32L, 31L, 30L))
expect_equal(df$num, c(56L, 55L, 54L, 38L, 37L, 36L, 35L, 34L, 33L))
expect_equal(df$call, c("A", "B", "<reactive:C>", "C", "renderTable",
"func", "force", "withVisible", "withCallingHandlers", "domain$wrapSync",
"promises::with_promise_domain", "captureStackTraces"))
"func", "force", "withVisible", "withCallingHandlers"))
expect_equal(nzchar(df$loc), c(TRUE, TRUE, TRUE, FALSE, TRUE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE))
FALSE, FALSE, FALSE, FALSE))
df <- causeError(full = TRUE)
# dumpTests(df)

View File

@@ -173,6 +173,30 @@ test_that("sortByName works as expected", {
expect_identical(sortByName(c(b=1, a=2, b=3)), c(a=2, b=1, b=3))
})
test_that("sortByName gives expected sort order using `radix` method", {
skip_on_cran()
# without UTF-8
items <- list("aa"=1, "bb"=2, "AA"=5, "BB"=6, "a_"=7, "b_"=8, "_A"=9, "_B"=10)
items_expected <- list(AA=5, BB=6, "_A"=9, "_B"=10, a_=7, aa=1, b_=8, bb=2)
# sort(names(items), method = "radix")
# #> [1] "AA" "BB" "_A" "_B" "a_" "aa" "b_" "bb"
# sort(names(items), method = "shell")
# #> [1] "_A" "_B" "a_" "aa" "AA" "b_" "bb" "BB"
expect_identical(sortByName(items, method = "radix"), items_expected)
skip_on_os("windows") # windows can't handle UTF-8
# with UTF-8
items <- list("aa"=1, "bb"=2, "åå"=3, "∫∫"=4, "AA"=5, "BB"=6, "a_"=7, "b_"=8, "_A"=9, "_B"=10)
items_expected <- list(AA=5, BB=6, "_A"=9, "_B"=10, a_=7, aa=1, b_=8, bb=2, "åå"=3, "∫∫"=4)
# sort(name(items), method = "radix")
# #> [1] "AA" "BB" "_A" "_B" "a_" "aa" "b_" "bb" "åå" "∫∫"
# sort(items, method = "shell")
# #> [1] "_A" "_B" "∫∫" "a_" "aa" "AA" "åå" "b_" "bb" "BB"
expect_identical(sortByName(items, method = "radix"), items_expected)
})
test_that("Callbacks fire in predictable order", {
cb <- Callbacks$new()

View File

@@ -9,111 +9,108 @@ template:
# NOTE: These templates live in shiny-dev-center
path: _pkgdown_templates
reference:
- title: Page containers
desc: Create a user interface page container.
- title: UI Layout
desc: Functions for laying out the user interface for your application.
contents:
- absolutePanel
- bootstrapPage
- navbarPage
- fillPage
- htmlTemplate
- title: UI layout
desc: Control the layout of multiple UI components.
contents:
- column
- conditionalPanel
- fillPage
- fillRow
- fixedPage
- fluidPage
- helpText
- icon
- navbarPage
- navlistPanel
- sidebarLayout
- tabPanel
- tabsetPanel
- titlePanel
- inputPanel
- flowLayout
- splitLayout
- verticalLayout
- wellPanel
- withMathJax
- title: UI Inputs
desc: Create UI that prompts the user for input values or interaction.
desc: Functions for creating user interface elements that prompt the user for input values or interaction.
contents:
- actionButton
- checkboxGroupInput
- checkboxInput
- dateInput
- dateRangeInput
- fileInput
- numericInput
- radioButtons
- selectInput
- varSelectInput
- sliderInput
- dateInput
- dateRangeInput
- checkboxInput
- checkboxGroupInput
- radioButtons
- numericInput
- submitButton
- textInput
- textAreaInput
- passwordInput
- actionButton
- getQueryString
- submitButton
- title: Update inputs
desc: Programmatically update input values
contents:
- updateSelectInput
- updateSliderInput
- updateActionButton
- updateCheckboxGroupInput
- updateCheckboxInput
- updateDateInput
- updateDateRangeInput
- updateCheckboxInput
- updateCheckboxGroupInput
- updateRadioButtons
- updateNumericInput
- updateTextInput
- updateTextAreaInput
- updateActionButton
- updateQueryString
- title: Navigation (tab) panels
desc: Create segments of UI content.
contents:
- navbarPage
- tabPanel
- tabsetPanel
- navlistPanel
- updateRadioButtons
- updateSelectInput
- updateSliderInput
- updateTabsetPanel
- insertTab
- showTab
- title: UI panels
desc: Visually group together a section of UI components.
- updateTextInput
- updateTextAreaInput
- updateQueryString
- getQueryString
- title: UI Outputs
desc: Functions for creating user interface elements that, in conjunction with rendering functions, display different kinds of output from your application.
contents:
- absolutePanel
- conditionalPanel
- titlePanel
- inputPanel
- wellPanel
- title: Uploads & downloads
desc: Allows users to upload and download files.
contents:
- fileInput
- htmlOutput
- plotOutput
- outputOptions
- textOutput
- downloadButton
- downloadHandler
- title: Custom UI
desc: Lower-level UI functions for creating custom HTML/CSS/JS.
- Progress
- withProgress
- modalDialog
- urlModal
- showModal
- showNotification
- title: Interface builder functions
desc: A sub-library for writing HTML using R functions. These functions form the foundation on which the higher level user interface functions are built, and can also be used in your Shiny UI to provide custom HTML, CSS, and JavaScript.
contents:
- icon
- markdown
- helpText
- withMathJax
- builder
- HTML
- tagList
- insertUI
- include
- singleton
- tagList
- tagAppendAttributes
- tagAppendChild
- validateCssUnit
- withTags
- htmlTemplate
- bootstrapLib
- suppressDependencies
- singleton
- title: Rendering outputs
desc: UI (`*Output()`) and server (`render*()`) functions for generating content server-side.
- insertUI
- markdown
- title: Rendering functions
desc: Functions that you use in your application's server side code, assigning them to outputs that appear in your user interface.
contents:
- plotOutput
- renderPlot
- renderImage
- textOutput
- renderCachedPlot
- renderPrint
- htmlOutput
- renderUI
- renderDataTable
- renderImage
- renderTable
- outputOptions
- renderUI
- downloadHandler
- createRenderFunction
- title: Reactive programming
desc: A sub-library that provides reactive programming facilities for R.
contents:
@@ -135,101 +132,87 @@ reference:
- reactiveTimer
- domains
- freezeReactiveValue
- title: Caching
desc: Make apps more responsive by setting up a persistent cache.
- title: Running
desc: Functions that are used to run or stop Shiny applications.
contents:
- bindCache
- renderCachedPlot
- sizeGrowthRatio
- title: Create and run applications
desc: Create, run, stop, and hook into the lifecycle of Shiny applications.
contents:
- shinyApp
- runApp
- runGadget
- runExample
- runGadget
- runUrl
- stopApp
- onStop
- onFlush
- viewer
- isRunning
- loadSupport
- title: Display messages
desc: Display messages to the user.
contents:
- helpText
- showNotification
- Progress
- withProgress
- modalDialog
- showModal
- urlModal
- title: Modules
desc: Control application complexity by namespacing UI and server code.
contents:
- moduleServer
- NS
- callModule
- title: Error validation
desc: Control how errors are shown to the user.
contents:
- req
- isTruthy
- validate
- safeError
- title: Bookmarking
desc: Bookmark and restore application state.
- title: Bookmarking state
desc: Functions that are used for bookmarking and restoring state.
contents:
- bookmarkButton
- enableBookmarking
- setBookmarkExclude
- showBookmarkUrlModal
- onBookmark
- setSerializer
- restoreInput
- title: Static plot interaction
desc: Control the experience of interacting with static plots.
contents:
- brushedPoints
- brushOpts
- clickOpts
- title: Testing
desc: Test apps with and/or without a headless browser (shinytest).
contents:
- runTests
- testServer
- MockShinySession
- snapshotExclude
- snapshotPreprocessInput
- snapshotPreprocessOutput
- exportTestValues
- applyInputHandlers
- title: Utility functions
desc: Various utilities for advanced users.
contents:
- session
- shinyOptions
- serverInfo
- getCurrentOutputInfo
- httpResponse
- devmode
- shinyAppTemplate
- parseQueryString
- plotPNG
- repeatable
- key_missing
- maskReactiveContext
- title: Extending Shiny
desc: Various utilities for 3rd party packages that extend Shiny.
desc: Functions that are intended to be called by third-party packages that extend Shiny.
contents:
- createWebDependency
- resourcePaths
- registerInputHandler
- removeInputHandler
- createRenderFunction
- markRenderFunction
- title: Utility functions
desc: Miscellaneous utilities that may be useful to advanced users or when extending Shiny.
contents:
- devmode
- shinyAppTemplate
- req
- isTruthy
- validate
- session
- shinyOptions
- safeError
- onFlush
- restoreInput
- applyInputHandlers
- parseQueryString
- getCurrentOutputInfo
- plotPNG
- sizeGrowthRatio
- exportTestValues
- setSerializer
- snapshotExclude
- snapshotPreprocessInput
- snapshotPreprocessOutput
- repeatable
- serverInfo
- onStop
- httpResponse
- key_missing
- title: Plot interaction
desc: Functions related to interactive plots
contents:
- brushedPoints
- brushOpts
- clickOpts
- title: Modules
desc: Functions for modularizing Shiny apps
contents:
- NS
- moduleServer
- callModule
- title: Embedding
desc: Functions that are intended for third-party packages that embed Shiny applications.
contents:
- shinyApp
- maskReactiveContext
- title: Testing
desc: Functions intended for testing of Shiny components
contents:
- runTests
- testServer
- MockShinySession
- title: Superseded
desc: Functions that have been `r lifecycle::badge("superseded")`.
desc: Functions that have been `r lifecycle::badge("superseded")`
contents:
- markRenderFunction
- shinyUI

View File

@@ -6,7 +6,11 @@
"esModuleInterop": true,
"declaration": true,
"declarationDir": "./srcts/types",
"emitDeclarationOnly": true
"emitDeclarationOnly": true,
// Can not use `types: []` to disable injecting NodeJS types. More types are
// needed than just the DOM's `window.setTimeout`
// "types": [],
"strict": false
},
"include": [
"srcts/src/index.ts",

View File

@@ -1964,7 +1964,8 @@ __metadata:
"@typescript-eslint/parser": ^4.25.0
autoprefixer: ^10.2.6
bootstrap-datepicker: 1.9.0
browserslist: ^4.16.6
browserslist: ^4.19.1
caniuse-lite: ^1.0.30001312
core-js: ^3.13.0
esbuild: ^0.12.4
esbuild-plugin-babel: "https://github.com/schloerke/esbuild-plugin-babel#patch-2"
@@ -2776,6 +2777,21 @@ __metadata:
languageName: node
linkType: hard
"browserslist@npm:^4.19.1":
version: 4.19.1
resolution: "browserslist@npm:4.19.1"
dependencies:
caniuse-lite: ^1.0.30001286
electron-to-chromium: ^1.4.17
escalade: ^3.1.1
node-releases: ^2.0.1
picocolors: ^1.0.0
bin:
browserslist: cli.js
checksum: 340af7f0527f903445bf6dd3231d2031666db6c262cc56211f8ec2895a6f570152ed17f239331de400d54f823312d9f8e64f186132e0a310e2bcbd94cf7b354b
languageName: node
linkType: hard
"bs-logger@npm:0.x":
version: 0.2.6
resolution: "bs-logger@npm:0.2.6"
@@ -2898,10 +2914,10 @@ __metadata:
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001219, caniuse-lite@npm:^1.0.30001230":
version: 1.0.30001237
resolution: "caniuse-lite@npm:1.0.30001237"
checksum: 8b56e2fff5856adbc3abde2ee85defeba6f6df6cf4e1c195bb0fd863c9d09ee318721d5c228a74beaac812e2c79009bc8ef998d6e85f44153dc6c26cc8bae7ce
"caniuse-lite@npm:^1.0.30001219, caniuse-lite@npm:^1.0.30001230, caniuse-lite@npm:^1.0.30001286, caniuse-lite@npm:^1.0.30001312":
version: 1.0.30001312
resolution: "caniuse-lite@npm:1.0.30001312"
checksum: 2700039fd59dc26fba69ff25cbe25f16c9b17ee4e13de4a1514421fc82b24b2b183d6972d6f65aded8e737702ba0cc0f4f2520ae357226cf6c386af6d3282ca6
languageName: node
linkType: hard
@@ -3704,6 +3720,13 @@ __metadata:
languageName: node
linkType: hard
"electron-to-chromium@npm:^1.4.17":
version: 1.4.68
resolution: "electron-to-chromium@npm:1.4.68"
checksum: ca284d85670e9d46c8320a4363f23aaf6a150699095274770216eba64d786c6d9653630acb3987e59d1f878d8c89e6a61a3c0cb58338915560454940a3b4b060
languageName: node
linkType: hard
"emittery@npm:^0.7.1":
version: 0.7.2
resolution: "emittery@npm:0.7.2"
@@ -6699,6 +6722,13 @@ __metadata:
languageName: node
linkType: hard
"node-releases@npm:^2.0.1":
version: 2.0.2
resolution: "node-releases@npm:2.0.2"
checksum: c01de6705e73b5d0aea8a303d3f96c4e3c72ac857b8940f70a61babb45ac4e8c7cf1e449a4667111dcda17a1b3b75d389ede6b6993e0b88595b9358b55eb0dc4
languageName: node
linkType: hard
"node-source-walk@npm:^4.0.0, node-source-walk@npm:^4.2.0":
version: 4.2.0
resolution: "node-source-walk@npm:4.2.0"
@@ -7098,6 +7128,13 @@ __metadata:
languageName: node
linkType: hard
"picocolors@npm:^1.0.0":
version: 1.0.0
resolution: "picocolors@npm:1.0.0"
checksum: 6616d34dd03bde8881c63402dea34f0b5972845b04b791b234446d4a408bc3d7f932acea3970a6b671d8f5c5aae1b1ce9fc1f89b0ed9a363469cf9da8e916b71
languageName: node
linkType: hard
"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3":
version: 2.3.0
resolution: "picomatch@npm:2.3.0"