mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-11 16:08:19 -05:00
Compare commits
8 Commits
dynamicJsx
...
ui-docs-re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4671eccd84 | ||
|
|
6c0cf4f7e5 | ||
|
|
dc7d4b46d8 | ||
|
|
509acb62b0 | ||
|
|
d05b2c305e | ||
|
|
a562e286d0 | ||
|
|
a40903c7e3 | ||
|
|
1faefe66fa |
@@ -1,7 +1,7 @@
|
||||
Package: shiny
|
||||
Type: Package
|
||||
Title: Web Application Framework for R
|
||||
Version: 1.7.1.9003
|
||||
Version: 1.7.1.9002
|
||||
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
10
NEWS.md
@@ -1,20 +1,14 @@
|
||||
shiny development
|
||||
shiny 1.7.1.9001
|
||||
================
|
||||
|
||||
## 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.
|
||||
@@ -23,8 +17,6 @@ shiny development
|
||||
|
||||
* 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
|
||||
===========
|
||||
|
||||
|
||||
@@ -1,87 +1,4 @@
|
||||
|
||||
#' 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
|
||||
#' @rdname bootstrapPage
|
||||
#' @export
|
||||
fluidPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
|
||||
bootstrapPage(div(class = "container-fluid", ...),
|
||||
@@ -91,62 +8,13 @@ fluidPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
|
||||
}
|
||||
|
||||
|
||||
#' @rdname fluidPage
|
||||
#' @rdname column
|
||||
#' @export
|
||||
fluidRow <- function(...) {
|
||||
div(class = "row", ...)
|
||||
}
|
||||
|
||||
#' 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
|
||||
#' @rdname bootstrapPage
|
||||
#' @export
|
||||
fixedPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
|
||||
bootstrapPage(div(class = "container", ...),
|
||||
@@ -155,28 +23,39 @@ fixedPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
|
||||
lang = lang)
|
||||
}
|
||||
|
||||
#' @rdname fixedPage
|
||||
#' @rdname column
|
||||
#' @export
|
||||
fixedRow <- function(...) {
|
||||
div(class = "row", ...)
|
||||
}
|
||||
|
||||
|
||||
#' Create a column within a UI definition
|
||||
#' Responsive row-column based layout
|
||||
#'
|
||||
#' Create a column for use within a [fluidRow()] or
|
||||
#' [fixedRow()]
|
||||
#' 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.
|
||||
#'
|
||||
#' @param width The grid width of the column (must be between 1 and 12)
|
||||
#' @param ... Elements to include within the column
|
||||
#' 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 offset The number of columns to offset this column from the end of the
|
||||
#' previous column.
|
||||
#'
|
||||
#' @return A column that can be included within a
|
||||
#' [fluidRow()] or [fixedRow()].
|
||||
#' @return A UI element (i.e., [tags]).
|
||||
#'
|
||||
#'
|
||||
#' @seealso [fluidRow()], [fixedRow()].
|
||||
#' @seealso [fluidPage()]
|
||||
#'
|
||||
#' @examples
|
||||
#' ## Only run examples in interactive R sessions
|
||||
@@ -202,16 +81,10 @@ 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) { })
|
||||
|
||||
@@ -1,36 +1,84 @@
|
||||
#' @include utils.R
|
||||
NULL
|
||||
|
||||
#' Create a Bootstrap page
|
||||
#' Create a Bootstrap UI page container
|
||||
#'
|
||||
#' 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).
|
||||
#' @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()`).
|
||||
#'
|
||||
#' 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()].
|
||||
#' 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].
|
||||
#'
|
||||
#' @param ... The contents of the document body.
|
||||
#' @param title The browser window title (defaults to the host URL of the page)
|
||||
#' @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 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 \code{<html>} tag, as in \code{<html lang="en">}.
|
||||
#' This will be used as the lang in the `<html>` tag, as in `<html lang="en">`.
|
||||
#' The default (NULL) results in an empty string.
|
||||
#'
|
||||
#' @return A UI defintion that can be passed to the [shinyUI] function.
|
||||
#' @return A UI definition (i.e., a [tags] object) that can be passed to [shinyApp()].
|
||||
#'
|
||||
#' @note The `basicPage` function is deprecated, you should use the
|
||||
#' [fluidPage()] function instead.
|
||||
#'
|
||||
#' @seealso [fluidPage()], [fixedPage()]
|
||||
#' @seealso [navbarPage()], [fillPage()], [column()], [tabPanel()]
|
||||
#' @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(
|
||||
@@ -234,14 +282,12 @@ 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
|
||||
|
||||
@@ -121,8 +121,7 @@ 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 `"HEAD"`, which means the default branch on GitHub, typically
|
||||
#' `"main"` or `"master"`.
|
||||
#' Defaults to `"master"`.
|
||||
#' @export
|
||||
#' @examples
|
||||
#' ## Only run this example in interactive R sessions
|
||||
@@ -134,7 +133,7 @@ runGist <- function(gist, destdir = NULL, ...) {
|
||||
#' runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
|
||||
#' }
|
||||
runGitHub <- function(repo, username = getOption("github.user"),
|
||||
ref = "HEAD", subdir = NULL, destdir = NULL, ...) {
|
||||
ref = "master", subdir = NULL, destdir = NULL, ...) {
|
||||
|
||||
if (grepl('/', repo)) {
|
||||
res <- strsplit(repo, '/')[[1]]
|
||||
|
||||
@@ -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. The value of this parameter can also be a
|
||||
#' interactive sessions only. This 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
|
||||
|
||||
@@ -125,9 +125,6 @@ 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),
|
||||
|
||||
38
R/shiny.R
38
R/shiny.R
@@ -478,35 +478,6 @@ 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()
|
||||
|
||||
@@ -549,7 +520,7 @@ ShinySession <- R6Class(
|
||||
}
|
||||
)
|
||||
|
||||
values$input <- sortByName(values$input, method = sortMethod)
|
||||
values$input <- sortByName(values$input)
|
||||
}
|
||||
|
||||
if (!is.null(params$output)) {
|
||||
@@ -577,7 +548,7 @@ ShinySession <- R6Class(
|
||||
}
|
||||
)
|
||||
|
||||
values$output <- sortByName(values$output, method = sortMethod)
|
||||
values$output <- sortByName(values$output)
|
||||
}
|
||||
|
||||
if (!is.null(params$export)) {
|
||||
@@ -598,7 +569,7 @@ ShinySession <- R6Class(
|
||||
)
|
||||
}
|
||||
|
||||
values$export <- sortByName(values$export, method = sortMethod)
|
||||
values$export <- sortByName(values$export)
|
||||
}
|
||||
|
||||
# Make sure input, output, and export are all named lists (at this
|
||||
@@ -1748,7 +1719,7 @@ ShinySession <- R6Class(
|
||||
},
|
||||
|
||||
getTestSnapshotUrl = function(input = TRUE, output = TRUE, export = TRUE,
|
||||
format = "json", sortC = FALSE) {
|
||||
format = "json") {
|
||||
reqString <- function(group, value) {
|
||||
if (isTRUE(value))
|
||||
paste0(group, "=1")
|
||||
@@ -1762,7 +1733,6 @@ ShinySession <- R6Class(
|
||||
reqString("input", input),
|
||||
reqString("output", output),
|
||||
reqString("export", export),
|
||||
reqString("sortC", sortC),
|
||||
paste0("format=", format),
|
||||
sep = "&"
|
||||
)
|
||||
|
||||
16
R/utils.R
16
R/utils.R
@@ -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, method = "auto") {
|
||||
sortByName <- function(x) {
|
||||
if (any_unnamed(x))
|
||||
stop("All items must be named")
|
||||
|
||||
@@ -170,19 +170,7 @@ sortByName <- function(x, method = "auto") {
|
||||
if (length(x) == 0)
|
||||
return(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)]
|
||||
x[order(names(x))]
|
||||
}
|
||||
|
||||
# Sort a vector. If a character vector, sort using C locale, which is consistent
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
/*! shiny 1.7.1.9002 | (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==
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
/*! shiny 1.7.1.9002 | (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
@@ -1,3 +1,3 @@
|
||||
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
/*! shiny 1.7.1.9002 | (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
2
inst/www/shared/shiny.min.css
vendored
2
inst/www/shared/shiny.min.css
vendored
File diff suppressed because one or more lines are too long
4
inst/www/shared/shiny.min.js
vendored
4
inst/www/shared/shiny.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,6 +14,7 @@ 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{
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/bootstrap.R
|
||||
\name{bootstrapPage}
|
||||
% Please edit documentation in R/bootstrap-layout.R, R/bootstrap.R
|
||||
\name{fluidPage}
|
||||
\alias{fluidPage}
|
||||
\alias{fixedPage}
|
||||
\alias{bootstrapPage}
|
||||
\alias{basicPage}
|
||||
\title{Create a Bootstrap page}
|
||||
\title{Create a Bootstrap UI page container}
|
||||
\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{...}{The contents of the document body.}
|
||||
\item{...}{UI elements (i.e., \link{tags}).}
|
||||
|
||||
\item{title}{The browser window title (defaults to the host URL of 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{
|
||||
@@ -21,30 +28,74 @@ basicPage(...)
|
||||
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 \code{<html>} tag, as in \code{<html lang="en">}.
|
||||
This will be used as the lang in the \verb{<html>} tag, as in \verb{<html lang="en">}.
|
||||
The default (NULL) results in an empty string.}
|
||||
}
|
||||
\value{
|
||||
A UI defintion that can be passed to the \link{shinyUI} function.
|
||||
A UI definition (i.e., a \link{tags} object) that can be passed to \code{\link[=shinyApp]{shinyApp()}}.
|
||||
}
|
||||
\description{
|
||||
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).
|
||||
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}.
|
||||
}
|
||||
\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()}}.
|
||||
\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)))
|
||||
}
|
||||
\note{
|
||||
The \code{basicPage} function is deprecated, you should use the
|
||||
\code{\link[=fluidPage]{fluidPage()}} function instead.
|
||||
|
||||
# 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
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
\seealso{
|
||||
\code{\link[=fluidPage]{fluidPage()}}, \code{\link[=fixedPage]{fixedPage()}}
|
||||
\code{\link[=navbarPage]{navbarPage()}}, \code{\link[=fillPage]{fillPage()}}, \code{\link[=column]{column()}}, \code{\link[=tabPanel]{tabPanel()}}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,45 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/bootstrap-layout.R
|
||||
\name{column}
|
||||
\name{fluidRow}
|
||||
\alias{fluidRow}
|
||||
\alias{fixedRow}
|
||||
\alias{column}
|
||||
\title{Create a column within a UI definition}
|
||||
\title{Responsive row-column based layout}
|
||||
\usage{
|
||||
fluidRow(...)
|
||||
|
||||
fixedRow(...)
|
||||
|
||||
column(width, ..., offset = 0)
|
||||
}
|
||||
\arguments{
|
||||
\item{width}{The grid width of the column (must be between 1 and 12)}
|
||||
\item{...}{UI elements (i.e., \link{tags}). For \code{fluidRow()}, \code{...} should be a set of \code{column()}s.}
|
||||
|
||||
\item{...}{Elements to include within the column}
|
||||
\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{offset}{The number of columns to offset this column from the end of the
|
||||
previous column.}
|
||||
}
|
||||
\value{
|
||||
A column that can be included within a
|
||||
\code{\link[=fluidRow]{fluidRow()}} or \code{\link[=fixedRow]{fixedRow()}}.
|
||||
A UI element (i.e., \link{tags}).
|
||||
}
|
||||
\description{
|
||||
Create a column for use within a \code{\link[=fluidRow]{fluidRow()}} or
|
||||
\code{\link[=fixedRow]{fixedRow()}}
|
||||
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.
|
||||
}
|
||||
\examples{
|
||||
## Only run examples in interactive R sessions
|
||||
@@ -46,21 +65,15 @@ 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[=fluidRow]{fluidRow()}}, \code{\link[=fixedRow]{fixedRow()}}.
|
||||
\code{\link[=fluidPage]{fluidPage()}}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ 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 \code{<html>} tag, as in \code{<html lang="en">}.
|
||||
This will be used as the lang in the \verb{<html>} tag, as in \verb{<html lang="en">}.
|
||||
The default (NULL) results in an empty string.}
|
||||
}
|
||||
\description{
|
||||
@@ -101,9 +102,7 @@ fillPage(
|
||||
}
|
||||
\seealso{
|
||||
Other layout functions:
|
||||
\code{\link{fixedPage}()},
|
||||
\code{\link{flowLayout}()},
|
||||
\code{\link{fluidPage}()},
|
||||
\code{\link{navbarPage}()},
|
||||
\code{\link{sidebarLayout}()},
|
||||
\code{\link{splitLayout}()},
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
% 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}
|
||||
@@ -34,8 +34,6 @@ 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
119
man/fluidPage.Rd
@@ -1,119 +0,0 @@
|
||||
% 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}
|
||||
@@ -71,6 +71,7 @@ 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
|
||||
@@ -79,7 +80,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 \code{<html>} tag, as in \code{<html lang="en">}.
|
||||
This will be used as the lang in the \verb{<html>} tag, as in \verb{<html lang="en">}.
|
||||
The default (NULL) results in an empty string.}
|
||||
|
||||
\item{menuName}{A name that identifies this \code{navbarMenu}. This
|
||||
@@ -124,9 +125,7 @@ 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}()}
|
||||
|
||||
@@ -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. The value of this parameter can also be a
|
||||
interactive sessions only. This 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
|
||||
|
||||
@@ -13,7 +13,7 @@ runGist(gist, destdir = NULL, ...)
|
||||
runGitHub(
|
||||
repo,
|
||||
username = getOption("github.user"),
|
||||
ref = "HEAD",
|
||||
ref = "master",
|
||||
subdir = NULL,
|
||||
destdir = NULL,
|
||||
...
|
||||
@@ -47,8 +47,7 @@ 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{"HEAD"}, which means the default branch on GitHub, typically
|
||||
\code{"main"} or \code{"master"}.}
|
||||
Defaults to \code{"master"}.}
|
||||
}
|
||||
\description{
|
||||
\code{runUrl()} downloads and launches a Shiny application that is hosted at
|
||||
|
||||
@@ -104,9 +104,6 @@ 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),
|
||||
|
||||
@@ -83,9 +83,7 @@ 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}()}
|
||||
|
||||
@@ -64,9 +64,7 @@ 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}()}
|
||||
|
||||
@@ -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:injection-operator]{rlang::!!()}}. For example,
|
||||
used with rlang's \code{\link[rlang:nse-force]{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:splice-operator]{rlang::!!!()}} to expand
|
||||
should be used with rlang's \code{\link[rlang:nse-force]{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)]])}.
|
||||
|
||||
@@ -33,9 +33,7 @@ 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}()}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"homepage": "https://shiny.rstudio.com",
|
||||
"repository": "github:rstudio/shiny",
|
||||
"name": "@types/rstudio-shiny",
|
||||
"version": "1.7.1-alpha.9003",
|
||||
"version": "1.7.1-alpha.9002",
|
||||
"license": "GPL-3.0-only",
|
||||
"main": "",
|
||||
"browser": "",
|
||||
@@ -46,8 +46,7 @@
|
||||
"@typescript-eslint/parser": "^4.25.0",
|
||||
"autoprefixer": "^10.2.6",
|
||||
"bootstrap-datepicker": "1.9.0",
|
||||
"browserslist": "^4.19.1",
|
||||
"caniuse-lite": "^1.0.30001312",
|
||||
"browserslist": "^4.16.6",
|
||||
"core-js": "^3.13.0",
|
||||
"esbuild": "^0.12.4",
|
||||
"esbuild-plugin-babel": "https://github.com/schloerke/esbuild-plugin-babel#patch-2",
|
||||
|
||||
@@ -22,7 +22,7 @@ class InputBinding {
|
||||
return false;
|
||||
el;
|
||||
}
|
||||
getValue(el: HTMLElement): any {
|
||||
getValue(el: HTMLElement): unknown {
|
||||
throw "Not implemented";
|
||||
el; // unused var
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ import type { ErrorsMessageValue } from "../shiny/shinyapp";
|
||||
interface ShinyEventCommon extends JQuery.Event {
|
||||
name: string;
|
||||
value: unknown;
|
||||
el: HTMLElement | null;
|
||||
el: HTMLElement;
|
||||
}
|
||||
interface ShinyEventInputChanged extends ShinyEventCommon {
|
||||
value: unknown;
|
||||
binding: InputBinding | null;
|
||||
binding: InputBinding;
|
||||
inputType: string;
|
||||
priority: EventPriority;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ function createClickInfo(
|
||||
mousedown: (e: JQuery.MouseDownEvent) => void;
|
||||
dblclickIE8: (e: JQuery.DoubleClickEvent) => void;
|
||||
} {
|
||||
let clickTimer: ReturnType<typeof setTimeout> = null;
|
||||
let clickTimer = null;
|
||||
let pendingE: JQuery.MouseDownEvent = null; // A pending mousedown2 event
|
||||
|
||||
// Create a new event of type eventType (like 'mousedown2'), and trigger
|
||||
|
||||
@@ -7,7 +7,6 @@ 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.
|
||||
@@ -84,7 +83,7 @@ function createHoverHandler(
|
||||
nullOutside
|
||||
);
|
||||
|
||||
let hoverInfoSender: InputRatePolicy<typeof sendHoverInfo>;
|
||||
let hoverInfoSender: Debouncer | Throttler;
|
||||
|
||||
if (delayType === "throttle")
|
||||
hoverInfoSender = new Throttler(null, sendHoverInfo, delay);
|
||||
|
||||
@@ -118,7 +118,7 @@ type Coordmap = {
|
||||
inputId: string,
|
||||
clip?: boolean,
|
||||
nullOutside?: boolean
|
||||
) => (e: JQuery.MouseDownEvent | JQuery.MouseMoveEvent) => void;
|
||||
) => (e: JQuery.MouseDownEvent) => void;
|
||||
};
|
||||
|
||||
// This adds functions to the coordmap object to handle various
|
||||
|
||||
@@ -5,9 +5,8 @@ import { InputRateDecorator } from "./inputRateDecorator";
|
||||
import { InputDeferDecorator } from "./inputDeferDecorator";
|
||||
import { InputValidateDecorator } from "./inputValidateDecorator";
|
||||
|
||||
import type { InputPolicy } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import type { InputRatePolicy } from "./inputRatePolicy";
|
||||
|
||||
export {
|
||||
InputBatchSender,
|
||||
@@ -16,6 +15,7 @@ export {
|
||||
InputRateDecorator,
|
||||
InputDeferDecorator,
|
||||
InputValidateDecorator,
|
||||
InputPolicy,
|
||||
};
|
||||
|
||||
export type { InputPolicy, EventPriority, InputRatePolicy };
|
||||
export type { EventPriority };
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import $ from "jquery";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } 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 implements InputPolicy {
|
||||
target!: InputPolicy; // We need this field to satisfy the InputPolicy interface
|
||||
class InputBatchSender extends InputPolicy {
|
||||
shinyapp: ShinyApp;
|
||||
timerId: ReturnType<typeof setTimeout> | null = null;
|
||||
timerId: NodeJS.Timeout = null;
|
||||
pendingData: { [key: string]: unknown } = {};
|
||||
reentrant = false;
|
||||
lastChanceCallback: Array<() => void> = [];
|
||||
|
||||
constructor(shinyapp: ShinyApp) {
|
||||
super();
|
||||
this.shinyapp = shinyapp;
|
||||
}
|
||||
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
|
||||
setInput(
|
||||
nameType: string,
|
||||
value: unknown,
|
||||
opts: { priority: EventPriority }
|
||||
): void {
|
||||
this.pendingData[nameType] = value;
|
||||
|
||||
if (!this.reentrant) {
|
||||
@@ -35,7 +41,9 @@ class InputBatchSender implements InputPolicy {
|
||||
this.reentrant = true;
|
||||
try {
|
||||
this.timerId = null;
|
||||
this.lastChanceCallback.forEach((callback) => callback());
|
||||
$.each(this.lastChanceCallback, (i, callback) => {
|
||||
callback();
|
||||
});
|
||||
const currentData = this.pendingData;
|
||||
|
||||
this.pendingData = {};
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import { hasOwnProperty } from "../utils";
|
||||
|
||||
class InputDeferDecorator implements InputPolicy {
|
||||
class InputDeferDecorator extends InputPolicy {
|
||||
pendingInput: {
|
||||
[key: string]: { value: unknown; opts: { priority: EventPriority } };
|
||||
} = {};
|
||||
target: InputPolicy;
|
||||
|
||||
constructor(target: InputPolicy) {
|
||||
super();
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
|
||||
setInput(
|
||||
nameType: string,
|
||||
value: unknown,
|
||||
opts: { priority: EventPriority }
|
||||
): void {
|
||||
if (/^\./.test(nameType)) this.target.setInput(nameType, value, opts);
|
||||
else this.pendingInput[nameType] = { value, opts };
|
||||
}
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
import $ from "jquery";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import type { InputBinding } from "../bindings";
|
||||
import type { ShinyEventInputChanged } from "../events/shinyEvents";
|
||||
import { splitInputNameType } from "./splitInputNameType";
|
||||
|
||||
class InputEventDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
|
||||
class InputEventDecorator extends InputPolicy {
|
||||
constructor(target: InputPolicy) {
|
||||
super();
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
|
||||
setInput(
|
||||
nameType: string,
|
||||
value: unknown,
|
||||
opts: {
|
||||
el: HTMLElement;
|
||||
priority: EventPriority;
|
||||
binding: InputBinding;
|
||||
}
|
||||
): void {
|
||||
const evt = jQuery.Event("shiny:inputchanged") as ShinyEventInputChanged;
|
||||
|
||||
const input = splitInputNameType(nameType);
|
||||
@@ -18,15 +27,11 @@ class InputEventDecorator implements InputPolicy {
|
||||
evt.name = input.name;
|
||||
evt.inputType = input.inputType;
|
||||
evt.value = value;
|
||||
evt.binding = opts.binding || null;
|
||||
evt.el = opts.el || null;
|
||||
evt.binding = opts.binding;
|
||||
evt.el = opts.el;
|
||||
evt.priority = opts.priority;
|
||||
|
||||
// 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);
|
||||
$(opts.el).trigger(evt);
|
||||
|
||||
if (!evt.isDefaultPrevented()) {
|
||||
let name = evt.name;
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import { hasOwnProperty } from "../utils";
|
||||
import { splitInputNameType } from "./splitInputNameType";
|
||||
|
||||
type LastSentValues = { [key: string]: { [key: string]: string } };
|
||||
|
||||
class InputNoResendDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
lastSentValues: LastSentValues = {};
|
||||
class InputNoResendDecorator extends InputPolicy {
|
||||
lastSentValues: LastSentValues;
|
||||
|
||||
constructor(target: InputPolicy, initialValues: LastSentValues = {}) {
|
||||
super();
|
||||
this.target = target;
|
||||
this.reset(initialValues);
|
||||
}
|
||||
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void {
|
||||
setInput(
|
||||
nameType: string,
|
||||
value: unknown,
|
||||
opts: { priority: EventPriority }
|
||||
): void {
|
||||
const { name: inputName, inputType: inputType } =
|
||||
splitInputNameType(nameType);
|
||||
const jsonValue = JSON.stringify(value);
|
||||
@@ -29,15 +34,13 @@ class InputNoResendDecorator implements InputPolicy {
|
||||
this.lastSentValues[inputName] = { jsonValue, inputType };
|
||||
this.target.setInput(nameType, value, opts);
|
||||
}
|
||||
reset(values: LastSentValues = {}): void {
|
||||
reset(values = {}): 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: {
|
||||
[key: string]: { jsonValue: string; inputType: string };
|
||||
} = {};
|
||||
const cacheValues = {};
|
||||
|
||||
for (const inputName in values) {
|
||||
if (hasOwnProperty(values, inputName)) {
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
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.
|
||||
interface InputPolicy {
|
||||
class InputPolicy {
|
||||
target: InputPolicy;
|
||||
|
||||
setInput(name: string, value: unknown, opts: InputPolicyOpts): void;
|
||||
setInput(
|
||||
name: string,
|
||||
value: unknown,
|
||||
opts: { priority: EventPriority }
|
||||
): void {
|
||||
throw "not implemented";
|
||||
name;
|
||||
value;
|
||||
opts;
|
||||
}
|
||||
}
|
||||
|
||||
export type { InputPolicy, EventPriority, InputPolicyOpts };
|
||||
export { InputPolicy };
|
||||
export type { EventPriority };
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import { Debouncer, Invoker, Throttler } from "../time";
|
||||
import { splitInputNameType } from "./splitInputNameType";
|
||||
import type { InputRatePolicy } from "./inputRatePolicy";
|
||||
|
||||
type RatePolicyModes = "debounce" | "direct" | "throttle";
|
||||
|
||||
class InputRateDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
inputRatePolicies: {
|
||||
[key: string]: InputRatePolicy<InputRateDecorator["_doSetInput"]>;
|
||||
} = {};
|
||||
class InputRateDecorator extends InputPolicy {
|
||||
inputRatePolicies = {};
|
||||
|
||||
constructor(target: InputPolicy) {
|
||||
super();
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@@ -21,7 +18,11 @@ class InputRateDecorator implements 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: InputPolicyOpts): void {
|
||||
setInput(
|
||||
nameType: string,
|
||||
value: unknown,
|
||||
opts: { priority: EventPriority }
|
||||
): void {
|
||||
const { name: inputName } = splitInputNameType(nameType);
|
||||
|
||||
this._ensureInit(inputName);
|
||||
@@ -59,7 +60,7 @@ class InputRateDecorator implements InputPolicy {
|
||||
private _doSetInput(
|
||||
nameType: string,
|
||||
value: unknown,
|
||||
opts: InputPolicyOpts
|
||||
opts: { priority: EventPriority }
|
||||
): void {
|
||||
this.target.setInput(nameType, value, opts);
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
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 };
|
||||
@@ -1,43 +1,61 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import $ from "jquery";
|
||||
import type { EventPriority, InputPolicy } from "./inputPolicy";
|
||||
|
||||
type MaybeInputOpts = {
|
||||
priority?: EventPriority;
|
||||
binding?: unknown;
|
||||
el?: HTMLElement;
|
||||
};
|
||||
|
||||
// Merge opts with defaults, and return a new object.
|
||||
function addDefaultInputOpts(opts: Partial<InputPolicyOpts>): InputPolicyOpts {
|
||||
const newOpts: InputPolicyOpts = {
|
||||
priority: "immediate",
|
||||
...opts,
|
||||
};
|
||||
function addDefaultInputOpts<T>(opts?: MaybeInputOpts & T): T & {
|
||||
priority: EventPriority;
|
||||
binding: unknown;
|
||||
el?: HTMLElement;
|
||||
} {
|
||||
const newOpts = $.extend(
|
||||
{
|
||||
priority: "immediate",
|
||||
binding: null,
|
||||
el: null,
|
||||
},
|
||||
opts
|
||||
);
|
||||
|
||||
switch (newOpts.priority) {
|
||||
case "deferred":
|
||||
case "immediate":
|
||||
case "event":
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
"Unexpected input value mode: '" + newOpts.priority + "'"
|
||||
);
|
||||
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 + "'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return newOpts;
|
||||
}
|
||||
|
||||
class InputValidateDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
class InputValidateDecorator {
|
||||
target;
|
||||
|
||||
constructor(target: InputPolicy) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
setInput(
|
||||
setInput = function <T>(
|
||||
nameType: string,
|
||||
value: unknown,
|
||||
opts: Partial<InputPolicyOpts> = {}
|
||||
opts?: MaybeInputOpts & T
|
||||
): void {
|
||||
if (!nameType) throw "Can't set input with empty name.";
|
||||
|
||||
const newOpts = addDefaultInputOpts(opts);
|
||||
|
||||
this.target.setInput(nameType, value, newOpts);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export { InputValidateDecorator, addDefaultInputOpts };
|
||||
|
||||
@@ -47,7 +47,7 @@ function bindInputs(
|
||||
scope: BindScope = document.documentElement
|
||||
): {
|
||||
[key: string]: {
|
||||
value: ReturnType<InputBinding["getValue"]>;
|
||||
value: unknown;
|
||||
opts: { immediate: boolean; binding: InputBinding; el: HTMLElement };
|
||||
};
|
||||
} {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
InputRateDecorator,
|
||||
InputValidateDecorator,
|
||||
} from "../inputPolicies";
|
||||
import type { InputPolicy } from "../inputPolicies";
|
||||
import type { EventPriority } from "../inputPolicies";
|
||||
import { addDefaultInputOpts } from "../inputPolicies/inputValidateDecorator";
|
||||
import { debounce, Debouncer } from "../time";
|
||||
import {
|
||||
@@ -25,7 +25,6 @@ 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 {
|
||||
@@ -40,7 +39,7 @@ function initShiny(windowShiny: Shiny): void {
|
||||
const inputsRate = new InputRateDecorator(inputsEvent);
|
||||
const inputsDefer = new InputDeferDecorator(inputsEvent);
|
||||
|
||||
let target: InputPolicy;
|
||||
let target;
|
||||
|
||||
if ($('input[type="submit"], button[type="submit"]').length > 0) {
|
||||
// If there is a submit button on the page, use defer decorator
|
||||
@@ -62,7 +61,7 @@ function initShiny(windowShiny: Shiny): void {
|
||||
windowShiny.setInputValue = windowShiny.onInputChange = function (
|
||||
name: string,
|
||||
value: unknown,
|
||||
opts: Partial<InputPolicyOpts> = {}
|
||||
opts?: { priority?: EventPriority }
|
||||
): void {
|
||||
const newOpts = addDefaultInputOpts(opts);
|
||||
|
||||
|
||||
@@ -155,8 +155,7 @@ function addRemovalCallback(id, delay) {
|
||||
// Clear a removal callback from a notification, if present.
|
||||
function clearRemovalCallback(id) {
|
||||
const $notification = get(id);
|
||||
const oldRemovalCallback: ReturnType<typeof setTimeout> =
|
||||
$notification.data("removalCallback");
|
||||
const oldRemovalCallback = $notification.data("removalCallback");
|
||||
|
||||
if (oldRemovalCallback) {
|
||||
clearTimeout(oldRemovalCallback);
|
||||
|
||||
@@ -10,7 +10,7 @@ class SendImageSize {
|
||||
setImageSend(
|
||||
inputBatchSender: InputBatchSender,
|
||||
doSendImageSize: () => void
|
||||
): Debouncer<typeof doSendImageSize> {
|
||||
): Debouncer {
|
||||
const sendImageSizeDebouncer = new Debouncer(null, doSendImageSize, 0);
|
||||
|
||||
this.regular = function () {
|
||||
|
||||
@@ -160,7 +160,7 @@ class ShinyApp {
|
||||
return !!this.$socket;
|
||||
}
|
||||
|
||||
private scheduledReconnect: ReturnType<typeof setTimeout> = null;
|
||||
private scheduledReconnect = null;
|
||||
|
||||
reconnect(): void {
|
||||
// This function can be invoked directly even if there's a scheduled
|
||||
@@ -971,37 +971,7 @@ 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);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import type { InputPolicy } from "../inputPolicies";
|
||||
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
|
||||
import type { AnyVoidFunction } from "../utils/extraTypes";
|
||||
class Debouncer {
|
||||
target: unknown;
|
||||
func: (...args: unknown[]) => void;
|
||||
delayMs: number;
|
||||
timerId: NodeJS.Timeout;
|
||||
args: unknown[];
|
||||
|
||||
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) {
|
||||
constructor(
|
||||
target: unknown,
|
||||
func: (...args: unknown[]) => void,
|
||||
delayMs: number
|
||||
) {
|
||||
this.target = target;
|
||||
this.func = func;
|
||||
this.delayMs = delayMs;
|
||||
@@ -18,7 +18,7 @@ class Debouncer<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
this.args = null;
|
||||
}
|
||||
|
||||
normalCall(...args: Parameters<X>): void {
|
||||
normalCall(...args: unknown[]): void {
|
||||
this.$clearTimer();
|
||||
this.args = args;
|
||||
|
||||
@@ -30,7 +30,7 @@ class Debouncer<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
this.$invoke();
|
||||
}, this.delayMs);
|
||||
}
|
||||
immediateCall(...args: Parameters<X>): void {
|
||||
immediateCall(...args: unknown[]): void {
|
||||
this.$clearTimer();
|
||||
this.args = args;
|
||||
this.$invoke();
|
||||
@@ -45,11 +45,7 @@ class Debouncer<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
}
|
||||
}
|
||||
$invoke(): void {
|
||||
if (this.args && this.args.length > 0) {
|
||||
this.func.apply(this.target, this.args);
|
||||
} else {
|
||||
this.func.apply(this.target);
|
||||
}
|
||||
this.func.apply(this.target, this.args);
|
||||
this.args = null;
|
||||
}
|
||||
}
|
||||
@@ -66,15 +62,13 @@ class Debouncer<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
// 900ms intervals will result in a single execution
|
||||
// of the underlying function, 1000ms after the 17th
|
||||
// call.
|
||||
function debounce<T extends (...args: unknown[]) => void>(
|
||||
threshold: number | undefined,
|
||||
func: T
|
||||
): (...args: Parameters<T>) => void {
|
||||
let timerId: ReturnType<typeof setTimeout> | null = null;
|
||||
function debounce<T>(
|
||||
threshold: number,
|
||||
func: (...args: T[]) => void
|
||||
): (...args: T[]) => void {
|
||||
let timerId = null;
|
||||
|
||||
// Do not alter `function()` into an arrow function.
|
||||
// The `this` context needs to be dynamically bound
|
||||
return function thisFunc(...args: Parameters<T>) {
|
||||
return function (...args) {
|
||||
if (timerId !== null) {
|
||||
clearTimeout(timerId);
|
||||
timerId = null;
|
||||
@@ -84,8 +78,7 @@ function debounce<T extends (...args: unknown[]) => void>(
|
||||
// check is needed
|
||||
if (timerId === null) return;
|
||||
timerId = null;
|
||||
// Applying on `thisFunc` passes through the `this` context
|
||||
func.apply(thisFunc, args);
|
||||
func.apply(this, args);
|
||||
}, threshold);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Debouncer, debounce } from "./debounce";
|
||||
import { Invoker } from "./invoke";
|
||||
import { Throttler } from "./throttle";
|
||||
import { Throttler, throttle } from "./throttle";
|
||||
|
||||
export { Debouncer, debounce, Invoker, Throttler };
|
||||
export { Debouncer, debounce, Invoker, Throttler, throttle };
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import type { InputPolicy } from "../inputPolicies";
|
||||
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
|
||||
import type { AnyVoidFunction } from "../utils/extraTypes";
|
||||
|
||||
class Invoker<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
class Invoker<T> {
|
||||
target: InputPolicy;
|
||||
func: X;
|
||||
func: () => void;
|
||||
|
||||
constructor(target: InputPolicy, func: X) {
|
||||
constructor(target: InputPolicy, func: (...args: T[]) => void) {
|
||||
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: Parameters<X>): void {
|
||||
normalCall(...args: T[]): void {
|
||||
this.func.apply(this.target, args);
|
||||
}
|
||||
immediateCall(...args: Parameters<X>): void {
|
||||
immediateCall(...args: T[]): void {
|
||||
this.func.apply(this.target, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
/* eslint-disable indent */
|
||||
import type { InputPolicy } from "../inputPolicies";
|
||||
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
|
||||
import type { AnyVoidFunction } from "../utils/extraTypes";
|
||||
class Throttler<T = unknown> {
|
||||
target: unknown;
|
||||
func: (...args: T[]) => void;
|
||||
delayMs: number;
|
||||
timerId: NodeJS.Timeout;
|
||||
args: T[];
|
||||
|
||||
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) {
|
||||
constructor(target: unknown, func: (...args: T[]) => void, delayMs: number) {
|
||||
this.target = target;
|
||||
this.func = func;
|
||||
this.delayMs = delayMs;
|
||||
@@ -19,7 +14,7 @@ class Throttler<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
this.args = null;
|
||||
}
|
||||
|
||||
normalCall(...args: Parameters<X>): void {
|
||||
normalCall(...args: T[]): void {
|
||||
this.args = args;
|
||||
if (this.timerId === null) {
|
||||
this.$invoke();
|
||||
@@ -28,11 +23,11 @@ class Throttler<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
// check is needed
|
||||
if (this.timerId === null) return;
|
||||
this.$clearTimer();
|
||||
if (args.length > 0) this.normalCall(...args);
|
||||
if (args.length > 0) this.normalCall.apply(this, ...args);
|
||||
}, this.delayMs);
|
||||
}
|
||||
}
|
||||
immediateCall(...args: Parameters<X>): void {
|
||||
immediateCall(...args: T[]): void {
|
||||
this.$clearTimer();
|
||||
this.args = args;
|
||||
this.$invoke();
|
||||
@@ -47,61 +42,54 @@ class Throttler<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
}
|
||||
}
|
||||
$invoke(): void {
|
||||
if (this.args && this.args.length > 0) {
|
||||
this.func.apply(this.target, this.args);
|
||||
} else {
|
||||
this.func.apply(this.target);
|
||||
}
|
||||
this.func.apply(this.target, this.args);
|
||||
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: number | null = null;
|
||||
// let self: unknown, args: T[] | 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[];
|
||||
|
||||
// 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;
|
||||
// }
|
||||
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;
|
||||
}
|
||||
|
||||
export {
|
||||
Throttler,
|
||||
// throttle
|
||||
};
|
||||
export { Throttler, throttle };
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
type AnyFunction = (...args: any[]) => any;
|
||||
type AnyVoidFunction = (...args: any[]) => void;
|
||||
|
||||
export type { AnyFunction, AnyVoidFunction };
|
||||
@@ -5,7 +5,7 @@ declare class InputBinding {
|
||||
find(scope: BindScope): JQuery<HTMLElement>;
|
||||
getId(el: HTMLElement): string;
|
||||
getType(el: HTMLElement): string | false;
|
||||
getValue(el: HTMLElement): any;
|
||||
getValue(el: HTMLElement): unknown;
|
||||
subscribe(el: HTMLElement, callback: (value: boolean) => void): void;
|
||||
unsubscribe(el: HTMLElement): void;
|
||||
receiveMessage(el: HTMLElement, data: unknown): void;
|
||||
|
||||
4
srcts/types/src/events/shinyEvents.d.ts
vendored
4
srcts/types/src/events/shinyEvents.d.ts
vendored
@@ -6,11 +6,11 @@ import type { ErrorsMessageValue } from "../shiny/shinyapp";
|
||||
interface ShinyEventCommon extends JQuery.Event {
|
||||
name: string;
|
||||
value: unknown;
|
||||
el: HTMLElement | null;
|
||||
el: HTMLElement;
|
||||
}
|
||||
interface ShinyEventInputChanged extends ShinyEventCommon {
|
||||
value: unknown;
|
||||
binding: InputBinding | null;
|
||||
binding: InputBinding;
|
||||
inputType: string;
|
||||
priority: EventPriority;
|
||||
}
|
||||
|
||||
2
srcts/types/src/imageutils/initCoordmap.d.ts
vendored
2
srcts/types/src/imageutils/initCoordmap.d.ts
vendored
@@ -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 | JQuery.MouseMoveEvent) => void;
|
||||
mouseCoordinateSender: (inputId: string, clip?: boolean, nullOutside?: boolean) => (e: JQuery.MouseDownEvent) => void;
|
||||
};
|
||||
declare function initCoordmap($el: JQuery<HTMLElement>, coordmap_: CoordmapInit): Coordmap;
|
||||
export type { Coordmap, CoordmapInit };
|
||||
|
||||
7
srcts/types/src/inputPolicies/index.d.ts
vendored
7
srcts/types/src/inputPolicies/index.d.ts
vendored
@@ -4,8 +4,7 @@ import { InputEventDecorator } from "./inputEventDecorator";
|
||||
import { InputRateDecorator } from "./inputRateDecorator";
|
||||
import { InputDeferDecorator } from "./inputDeferDecorator";
|
||||
import { InputValidateDecorator } from "./inputValidateDecorator";
|
||||
import type { InputPolicy } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import type { InputRatePolicy } from "./inputRatePolicy";
|
||||
export { InputBatchSender, InputEventDecorator, InputNoResendDecorator, InputRateDecorator, InputDeferDecorator, InputValidateDecorator, };
|
||||
export type { InputPolicy, EventPriority, InputRatePolicy };
|
||||
export { InputBatchSender, InputEventDecorator, InputNoResendDecorator, InputRateDecorator, InputDeferDecorator, InputValidateDecorator, InputPolicy, };
|
||||
export type { EventPriority };
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
/// <reference types="node" />
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import type { ShinyApp } from "../shiny/shinyapp";
|
||||
declare class InputBatchSender implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
declare class InputBatchSender extends InputPolicy {
|
||||
shinyapp: ShinyApp;
|
||||
timerId: ReturnType<typeof setTimeout> | null;
|
||||
timerId: NodeJS.Timeout;
|
||||
pendingData: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
reentrant: boolean;
|
||||
lastChanceCallback: Array<() => void>;
|
||||
constructor(shinyapp: ShinyApp);
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
|
||||
setInput(nameType: string, value: unknown, opts: {
|
||||
priority: EventPriority;
|
||||
}): void;
|
||||
private _sendNow;
|
||||
}
|
||||
export { InputBatchSender };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
declare class InputDeferDecorator implements InputPolicy {
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
declare class InputDeferDecorator extends InputPolicy {
|
||||
pendingInput: {
|
||||
[key: string]: {
|
||||
value: unknown;
|
||||
@@ -9,9 +9,10 @@ declare class InputDeferDecorator implements InputPolicy {
|
||||
};
|
||||
};
|
||||
};
|
||||
target: InputPolicy;
|
||||
constructor(target: InputPolicy);
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
|
||||
setInput(nameType: string, value: unknown, opts: {
|
||||
priority: EventPriority;
|
||||
}): void;
|
||||
submit(): void;
|
||||
}
|
||||
export { InputDeferDecorator };
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
declare class InputEventDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
import type { InputBinding } from "../bindings";
|
||||
declare class InputEventDecorator extends InputPolicy {
|
||||
constructor(target: InputPolicy);
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
|
||||
setInput(nameType: string, value: unknown, opts: {
|
||||
el: HTMLElement;
|
||||
priority: EventPriority;
|
||||
binding: InputBinding;
|
||||
}): void;
|
||||
}
|
||||
export { InputEventDecorator };
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
declare type LastSentValues = {
|
||||
[key: string]: {
|
||||
[key: string]: string;
|
||||
};
|
||||
};
|
||||
declare class InputNoResendDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
declare class InputNoResendDecorator extends InputPolicy {
|
||||
lastSentValues: LastSentValues;
|
||||
constructor(target: InputPolicy, initialValues?: LastSentValues);
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
|
||||
reset(values?: LastSentValues): void;
|
||||
setInput(nameType: string, value: unknown, opts: {
|
||||
priority: EventPriority;
|
||||
}): void;
|
||||
reset(values?: {}): void;
|
||||
forget(name: string): void;
|
||||
}
|
||||
export { InputNoResendDecorator };
|
||||
|
||||
15
srcts/types/src/inputPolicies/inputPolicy.d.ts
vendored
15
srcts/types/src/inputPolicies/inputPolicy.d.ts
vendored
@@ -1,12 +1,9 @@
|
||||
import type { InputBinding } from "../bindings";
|
||||
declare type EventPriority = "deferred" | "event" | "immediate";
|
||||
declare type InputPolicyOpts = {
|
||||
priority: EventPriority;
|
||||
el?: HTMLElement;
|
||||
binding?: InputBinding;
|
||||
};
|
||||
interface InputPolicy {
|
||||
declare class InputPolicy {
|
||||
target: InputPolicy;
|
||||
setInput(name: string, value: unknown, opts: InputPolicyOpts): void;
|
||||
setInput(name: string, value: unknown, opts: {
|
||||
priority: EventPriority;
|
||||
}): void;
|
||||
}
|
||||
export type { InputPolicy, EventPriority, InputPolicyOpts };
|
||||
export { InputPolicy };
|
||||
export type { EventPriority };
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { InputRatePolicy } from "./inputRatePolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import { InputPolicy } from "./inputPolicy";
|
||||
declare type RatePolicyModes = "debounce" | "direct" | "throttle";
|
||||
declare class InputRateDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
inputRatePolicies: {
|
||||
[key: string]: InputRatePolicy<InputRateDecorator["_doSetInput"]>;
|
||||
};
|
||||
declare class InputRateDecorator extends InputPolicy {
|
||||
inputRatePolicies: {};
|
||||
constructor(target: InputPolicy);
|
||||
setInput(nameType: string, value: unknown, opts: InputPolicyOpts): void;
|
||||
setInput(nameType: string, value: unknown, opts: {
|
||||
priority: EventPriority;
|
||||
}): void;
|
||||
setRatePolicy(nameType: string, mode: RatePolicyModes, millis?: number): void;
|
||||
private _ensureInit;
|
||||
private _doSetInput;
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
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 };
|
||||
@@ -1,8 +1,17 @@
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
declare function addDefaultInputOpts(opts: Partial<InputPolicyOpts>): InputPolicyOpts;
|
||||
declare class InputValidateDecorator implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
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;
|
||||
constructor(target: InputPolicy);
|
||||
setInput(nameType: string, value: unknown, opts?: Partial<InputPolicyOpts>): void;
|
||||
setInput: <T>(nameType: string, value: unknown, opts?: MaybeInputOpts & T) => void;
|
||||
}
|
||||
export { InputValidateDecorator, addDefaultInputOpts };
|
||||
|
||||
2
srcts/types/src/shiny/bind.d.ts
vendored
2
srcts/types/src/shiny/bind.d.ts
vendored
@@ -13,7 +13,7 @@ declare type BindInputsCtx = {
|
||||
};
|
||||
declare function bindInputs(shinyCtx: BindInputsCtx, scope?: BindScope): {
|
||||
[key: string]: {
|
||||
value: ReturnType<InputBinding["getValue"]>;
|
||||
value: unknown;
|
||||
opts: {
|
||||
immediate: boolean;
|
||||
binding: InputBinding;
|
||||
|
||||
2
srcts/types/src/shiny/sendImageSize.d.ts
vendored
2
srcts/types/src/shiny/sendImageSize.d.ts
vendored
@@ -3,7 +3,7 @@ import { Debouncer } from "../time";
|
||||
declare class SendImageSize {
|
||||
regular: () => void;
|
||||
transitioned: () => void;
|
||||
setImageSend(inputBatchSender: InputBatchSender, doSendImageSize: () => void): Debouncer<typeof doSendImageSize>;
|
||||
setImageSend(inputBatchSender: InputBatchSender, doSendImageSize: () => void): Debouncer;
|
||||
}
|
||||
declare const sendImageSizeFns: SendImageSize;
|
||||
export { sendImageSizeFns };
|
||||
|
||||
24
srcts/types/src/time/debounce.d.ts
vendored
24
srcts/types/src/time/debounce.d.ts
vendored
@@ -1,18 +1,16 @@
|
||||
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;
|
||||
/// <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;
|
||||
isPending(): boolean;
|
||||
$clearTimer(): void;
|
||||
$invoke(): void;
|
||||
}
|
||||
declare function debounce<T extends (...args: unknown[]) => void>(threshold: number | undefined, func: T): (...args: Parameters<T>) => void;
|
||||
declare function debounce<T>(threshold: number, func: (...args: T[]) => void): (...args: T[]) => void;
|
||||
export { Debouncer, debounce };
|
||||
|
||||
4
srcts/types/src/time/index.d.ts
vendored
4
srcts/types/src/time/index.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
import { Debouncer, debounce } from "./debounce";
|
||||
import { Invoker } from "./invoke";
|
||||
import { Throttler } from "./throttle";
|
||||
export { Debouncer, debounce, Invoker, Throttler };
|
||||
import { Throttler, throttle } from "./throttle";
|
||||
export { Debouncer, debounce, Invoker, Throttler, throttle };
|
||||
|
||||
12
srcts/types/src/time/invoke.d.ts
vendored
12
srcts/types/src/time/invoke.d.ts
vendored
@@ -1,11 +1,9 @@
|
||||
import type { InputPolicy } from "../inputPolicies";
|
||||
import type { InputRatePolicy } from "../inputPolicies/inputRatePolicy";
|
||||
import type { AnyVoidFunction } from "../utils/extraTypes";
|
||||
declare class Invoker<X extends AnyVoidFunction> implements InputRatePolicy<X> {
|
||||
declare class Invoker<T> {
|
||||
target: InputPolicy;
|
||||
func: X;
|
||||
constructor(target: InputPolicy, func: X);
|
||||
normalCall(...args: Parameters<X>): void;
|
||||
immediateCall(...args: Parameters<X>): void;
|
||||
func: () => void;
|
||||
constructor(target: InputPolicy, func: (...args: T[]) => void);
|
||||
normalCall(...args: T[]): void;
|
||||
immediateCall(...args: T[]): void;
|
||||
}
|
||||
export { Invoker };
|
||||
|
||||
25
srcts/types/src/time/throttle.d.ts
vendored
25
srcts/types/src/time/throttle.d.ts
vendored
@@ -1,17 +1,16 @@
|
||||
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;
|
||||
/// <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;
|
||||
isPending(): boolean;
|
||||
$clearTimer(): void;
|
||||
$invoke(): void;
|
||||
}
|
||||
export { Throttler, };
|
||||
declare function throttle<T>(threshold: number, func: (...args: T[]) => void): (...args: T[]) => void;
|
||||
export { Throttler, throttle };
|
||||
|
||||
3
srcts/types/src/utils/extraTypes.d.ts
vendored
3
srcts/types/src/utils/extraTypes.d.ts
vendored
@@ -1,3 +0,0 @@
|
||||
declare type AnyFunction = (...args: any[]) => any;
|
||||
declare type AnyVoidFunction = (...args: any[]) => void;
|
||||
export type { AnyFunction, AnyVoidFunction };
|
||||
@@ -129,11 +129,13 @@ test_that("integration tests", {
|
||||
df <- causeError(full = FALSE)
|
||||
# dumpTests(df)
|
||||
|
||||
expect_equal(df$num, c(56L, 55L, 54L, 38L, 37L, 36L, 35L, 34L, 33L))
|
||||
expect_equal(df$num, c(56L, 55L, 54L, 38L, 37L, 36L, 35L,
|
||||
34L, 33L, 32L, 31L, 30L))
|
||||
expect_equal(df$call, c("A", "B", "<reactive:C>", "C", "renderTable",
|
||||
"func", "force", "withVisible", "withCallingHandlers"))
|
||||
"func", "force", "withVisible", "withCallingHandlers", "domain$wrapSync",
|
||||
"promises::with_promise_domain", "captureStackTraces"))
|
||||
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)
|
||||
|
||||
@@ -173,30 +173,6 @@ 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()
|
||||
|
||||
|
||||
@@ -9,108 +9,111 @@ template:
|
||||
# NOTE: These templates live in shiny-dev-center
|
||||
path: _pkgdown_templates
|
||||
reference:
|
||||
- title: UI Layout
|
||||
desc: Functions for laying out the user interface for your application.
|
||||
- title: Page containers
|
||||
desc: Create a user interface page container.
|
||||
contents:
|
||||
- absolutePanel
|
||||
- bootstrapPage
|
||||
- column
|
||||
- conditionalPanel
|
||||
- fillPage
|
||||
- fillRow
|
||||
- fixedPage
|
||||
- fluidPage
|
||||
- helpText
|
||||
- icon
|
||||
- navbarPage
|
||||
- navlistPanel
|
||||
- fillPage
|
||||
- htmlTemplate
|
||||
- title: UI layout
|
||||
desc: Control the layout of multiple UI components.
|
||||
contents:
|
||||
- column
|
||||
- fillRow
|
||||
- sidebarLayout
|
||||
- tabPanel
|
||||
- tabsetPanel
|
||||
- titlePanel
|
||||
- inputPanel
|
||||
- flowLayout
|
||||
- splitLayout
|
||||
- verticalLayout
|
||||
- wellPanel
|
||||
- withMathJax
|
||||
- title: UI Inputs
|
||||
desc: Functions for creating user interface elements that prompt the user for input values or interaction.
|
||||
desc: Create UI that prompts the user for input values or interaction.
|
||||
contents:
|
||||
- actionButton
|
||||
- checkboxGroupInput
|
||||
- checkboxInput
|
||||
- dateInput
|
||||
- dateRangeInput
|
||||
- fileInput
|
||||
- numericInput
|
||||
- radioButtons
|
||||
- selectInput
|
||||
- varSelectInput
|
||||
- sliderInput
|
||||
- submitButton
|
||||
- dateInput
|
||||
- dateRangeInput
|
||||
- checkboxInput
|
||||
- checkboxGroupInput
|
||||
- radioButtons
|
||||
- numericInput
|
||||
- textInput
|
||||
- textAreaInput
|
||||
- passwordInput
|
||||
- updateActionButton
|
||||
- updateCheckboxGroupInput
|
||||
- updateCheckboxInput
|
||||
- updateDateInput
|
||||
- updateDateRangeInput
|
||||
- updateNumericInput
|
||||
- updateRadioButtons
|
||||
- actionButton
|
||||
- getQueryString
|
||||
- submitButton
|
||||
- title: Update inputs
|
||||
desc: Programmatically update input values
|
||||
contents:
|
||||
- updateSelectInput
|
||||
- updateSliderInput
|
||||
- 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
|
||||
- updateTabsetPanel
|
||||
- insertTab
|
||||
- showTab
|
||||
- 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.
|
||||
- title: UI panels
|
||||
desc: Visually group together a section of UI components.
|
||||
contents:
|
||||
- htmlOutput
|
||||
- plotOutput
|
||||
- outputOptions
|
||||
- textOutput
|
||||
- absolutePanel
|
||||
- conditionalPanel
|
||||
- titlePanel
|
||||
- inputPanel
|
||||
- wellPanel
|
||||
- title: Uploads & downloads
|
||||
desc: Allows users to upload and download files.
|
||||
contents:
|
||||
- fileInput
|
||||
- downloadButton
|
||||
- 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.
|
||||
- downloadHandler
|
||||
- title: Custom UI
|
||||
desc: Lower-level UI functions for creating custom HTML/CSS/JS.
|
||||
contents:
|
||||
- icon
|
||||
- markdown
|
||||
- helpText
|
||||
- withMathJax
|
||||
- builder
|
||||
- HTML
|
||||
- include
|
||||
- singleton
|
||||
- tagList
|
||||
- insertUI
|
||||
- include
|
||||
- tagAppendAttributes
|
||||
- tagAppendChild
|
||||
- validateCssUnit
|
||||
- withTags
|
||||
- htmlTemplate
|
||||
- bootstrapLib
|
||||
- suppressDependencies
|
||||
- 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.
|
||||
- singleton
|
||||
- title: Rendering outputs
|
||||
desc: UI (`*Output()`) and server (`render*()`) functions for generating content server-side.
|
||||
contents:
|
||||
- plotOutput
|
||||
- renderPlot
|
||||
- renderCachedPlot
|
||||
- renderPrint
|
||||
- renderDataTable
|
||||
- renderImage
|
||||
- renderTable
|
||||
- textOutput
|
||||
- renderPrint
|
||||
- htmlOutput
|
||||
- renderUI
|
||||
- downloadHandler
|
||||
- createRenderFunction
|
||||
- renderDataTable
|
||||
- renderTable
|
||||
- outputOptions
|
||||
- title: Reactive programming
|
||||
desc: A sub-library that provides reactive programming facilities for R.
|
||||
contents:
|
||||
@@ -132,87 +135,101 @@ reference:
|
||||
- reactiveTimer
|
||||
- domains
|
||||
- freezeReactiveValue
|
||||
- title: Running
|
||||
desc: Functions that are used to run or stop Shiny applications.
|
||||
- title: Caching
|
||||
desc: Make apps more responsive by setting up a persistent cache.
|
||||
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: Bookmarking state
|
||||
desc: Functions that are used for bookmarking and restoring state.
|
||||
- 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.
|
||||
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: Functions that are intended to be called by third-party packages that extend Shiny.
|
||||
desc: Various utilities for 3rd party packages that extend Shiny.
|
||||
contents:
|
||||
- createWebDependency
|
||||
- resourcePaths
|
||||
- registerInputHandler
|
||||
- removeInputHandler
|
||||
- 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
|
||||
- createRenderFunction
|
||||
- title: Superseded
|
||||
desc: Functions that have been `r lifecycle::badge("superseded")`
|
||||
desc: Functions that have been `r lifecycle::badge("superseded")`.
|
||||
contents:
|
||||
- markRenderFunction
|
||||
- shinyUI
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
"esModuleInterop": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "./srcts/types",
|
||||
"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
|
||||
"emitDeclarationOnly": true
|
||||
},
|
||||
"include": [
|
||||
"srcts/src/index.ts",
|
||||
|
||||
47
yarn.lock
47
yarn.lock
@@ -1964,8 +1964,7 @@ __metadata:
|
||||
"@typescript-eslint/parser": ^4.25.0
|
||||
autoprefixer: ^10.2.6
|
||||
bootstrap-datepicker: 1.9.0
|
||||
browserslist: ^4.19.1
|
||||
caniuse-lite: ^1.0.30001312
|
||||
browserslist: ^4.16.6
|
||||
core-js: ^3.13.0
|
||||
esbuild: ^0.12.4
|
||||
esbuild-plugin-babel: "https://github.com/schloerke/esbuild-plugin-babel#patch-2"
|
||||
@@ -2777,21 +2776,6 @@ __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"
|
||||
@@ -2914,10 +2898,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"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
|
||||
"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
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -3720,13 +3704,6 @@ __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"
|
||||
@@ -6722,13 +6699,6 @@ __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"
|
||||
@@ -7128,13 +7098,6 @@ __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"
|
||||
|
||||
Reference in New Issue
Block a user