Compare commits
2 Commits
webr-next
...
async-remo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbca8071f4 | ||
|
|
090872f4f2 |
1
.github/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*.html
|
||||
1
.github/shiny-workflows/routine.sh
vendored
@@ -5,7 +5,6 @@ echo "Updating package.json version to match DESCRIPTION Version"
|
||||
Rscript ./tools/updatePackageJsonVersion.R
|
||||
if [ -n "$(git status --porcelain package.json)" ]
|
||||
then
|
||||
echo "package.json has changed after running ./tools/updatePackageJsonVersion.R. Re-running 'yarn build'"
|
||||
yarn build
|
||||
git add ./inst package.json && git commit -m 'Sync package version (GitHub Actions)' || echo "No package version to commit"
|
||||
else
|
||||
|
||||
19
.github/workflows/release-file-system-image.yml
vendored
@@ -1,19 +0,0 @@
|
||||
# Workflow derived from https://github.com/r-wasm/actions/tree/v1/examples
|
||||
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
|
||||
on:
|
||||
release:
|
||||
# Must republish release to update assets
|
||||
types: [ published ]
|
||||
|
||||
name: Build and deploy wasm R package image
|
||||
|
||||
jobs:
|
||||
release-file-system-image:
|
||||
uses: r-wasm/actions/.github/workflows/release-file-system-image.yml@v1
|
||||
permissions:
|
||||
# For publishing artifact files to the release
|
||||
contents: write
|
||||
# To download GitHub Packages within action
|
||||
repository-projects: read
|
||||
with:
|
||||
strip: "demo, doc, examples, help, html, include, tests, vignette"
|
||||
6
.vscode/settings.json
vendored
@@ -15,10 +15,4 @@
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"files.insertFinalNewline": true,
|
||||
},
|
||||
"[json]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"files.insertFinalNewline": true,
|
||||
},
|
||||
}
|
||||
|
||||
37
DESCRIPTION
@@ -1,7 +1,7 @@
|
||||
Package: shiny
|
||||
Type: Package
|
||||
Title: Web Application Framework for R
|
||||
Version: 1.8.1.9991
|
||||
Version: 1.8.1.9000
|
||||
Authors@R: c(
|
||||
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@posit.co", comment = c(ORCID = "0000-0002-1576-2126")),
|
||||
person("Joe", "Cheng", role = "aut", email = "joe@posit.co"),
|
||||
@@ -128,8 +128,6 @@ Collate:
|
||||
'map.R'
|
||||
'utils.R'
|
||||
'bootstrap.R'
|
||||
'busy-indicators-spinners.R'
|
||||
'busy-indicators.R'
|
||||
'cache-utils.R'
|
||||
'deprecated.R'
|
||||
'devmode.R'
|
||||
@@ -213,36 +211,3 @@ RdMacros: lifecycle
|
||||
Config/testthat/edition: 3
|
||||
Config/Needs/check:
|
||||
shinytest2
|
||||
Config/Needs/wasm:
|
||||
R6,
|
||||
Rcpp,
|
||||
base64enc,
|
||||
bslib,
|
||||
cachem,
|
||||
cli,
|
||||
codetools,
|
||||
commonmark,
|
||||
crayon,
|
||||
digest,
|
||||
ellipsis,
|
||||
fastmap,
|
||||
fontawesome,
|
||||
fs,
|
||||
glue,
|
||||
htmltools,
|
||||
httpuv,
|
||||
jquerylib,
|
||||
jsonlite,
|
||||
later,
|
||||
lifecycle,
|
||||
magrittr,
|
||||
memoise,
|
||||
mime,
|
||||
promises,
|
||||
rappdirs,
|
||||
renv,
|
||||
rlang,
|
||||
sass,
|
||||
sourcetools,
|
||||
withr,
|
||||
xtable
|
||||
|
||||
@@ -78,7 +78,6 @@ export(br)
|
||||
export(browserViewer)
|
||||
export(brushOpts)
|
||||
export(brushedPoints)
|
||||
export(busyIndicatorOptions)
|
||||
export(callModule)
|
||||
export(captureStackTraces)
|
||||
export(checkboxGroupInput)
|
||||
@@ -318,7 +317,6 @@ export(updateTextInput)
|
||||
export(updateVarSelectInput)
|
||||
export(updateVarSelectizeInput)
|
||||
export(urlModal)
|
||||
export(useBusyIndicators)
|
||||
export(validate)
|
||||
export(validateCssUnit)
|
||||
export(varSelectInput)
|
||||
|
||||
7
NEWS.md
@@ -1,14 +1,7 @@
|
||||
# shiny (development version)
|
||||
|
||||
## New features and improvements
|
||||
|
||||
* Added new functions, `useBusyIndicators()` and `busyIndicatorOptions()`, for enabling and customizing busy indication. Busy indicators provide a visual cue to users when the server is busy calculating outputs or otherwise serving requests to the client. When enabled, a spinner is shown on each calculating/recalculating output, and a pulsing banner is shown at the top of the page when the app is otherwise busy. (#4040)
|
||||
* Output bindings now include the `.recalculating` CSS class when they are first bound, up until the first render. This makes it possible/easier to show progress indication when the output is calculating for the first time. (#4039)
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* `downloadButton()` and `downloadLink()` are now disabled up until they are fully initialized. This prevents the user from clicking the button/link before the download is ready. (#4041)
|
||||
* Output bindings that are removed, invalidated, then inserted again (while invalidated) now correctly include the `.recalculating` CSS class. (#4039)
|
||||
* Fixed a recent issue with `uiOutput()` and `conditionalPanel()` not properly lower opacity when recalculation (in a Bootstrap 5 context). (#4027)
|
||||
|
||||
# shiny 1.8.1.1
|
||||
|
||||
@@ -1276,13 +1276,10 @@ downloadButton <- function(outputId,
|
||||
...,
|
||||
icon = shiny::icon("download")) {
|
||||
tags$a(id=outputId,
|
||||
class='btn btn-default shiny-download-link disabled',
|
||||
class=class,
|
||||
class=paste('btn btn-default shiny-download-link', class),
|
||||
href='',
|
||||
target='_blank',
|
||||
download=NA,
|
||||
"aria-disabled"="true",
|
||||
tabindex="-1",
|
||||
validateIcon(icon),
|
||||
label, ...)
|
||||
}
|
||||
@@ -1291,13 +1288,10 @@ downloadButton <- function(outputId,
|
||||
#' @export
|
||||
downloadLink <- function(outputId, label="Download", class=NULL, ...) {
|
||||
tags$a(id=outputId,
|
||||
class='shiny-download-link disabled',
|
||||
class=class,
|
||||
class=paste(c('shiny-download-link', class), collapse=" "),
|
||||
href='',
|
||||
target='_blank',
|
||||
download=NA,
|
||||
"aria-disabled"="true",
|
||||
tabindex="-1",
|
||||
label, ...)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Generated by tools/updateSpinnerTypes.R: do not edit by hand
|
||||
.busySpinnerTypes <-
|
||||
c("ring", "ring2", "ring3", "bars", "bars2", "bars3", "pulse",
|
||||
"pulse2", "pulse3", "dots", "dots2", "dots3")
|
||||
@@ -1,249 +0,0 @@
|
||||
#' Enable/disable busy indication
|
||||
#'
|
||||
#' Busy indicators provide a visual cue to users when the server is busy
|
||||
#' calculating outputs or otherwise performing tasks (e.g., producing
|
||||
#' downloads). When enabled, a spinner is shown on each
|
||||
#' calculating/recalculating output, and a pulsing banner is shown at the top of
|
||||
#' the page when the app is otherwise busy. Busy indication is enabled by
|
||||
#' default for UI created with \pkg{bslib}, but must be enabled otherwise. To
|
||||
#' enable/disable, include the result of this function in anywhere in the app's
|
||||
#' UI.
|
||||
#'
|
||||
#' When both `spinners` and `pulse` are set to `TRUE`, the pulse is
|
||||
#' automatically disabled when spinner(s) are active. When both `spinners` and
|
||||
#' `pulse` are set to `FALSE`, no busy indication is shown (other than the
|
||||
#' graying out of recalculating outputs).
|
||||
#'
|
||||
#' @param ... Currently ignored.
|
||||
#' @param spinners Whether to show a spinner on each calculating/recalculating
|
||||
#' output.
|
||||
#' @param pulse Whether to show a pulsing banner at the top of the page when the
|
||||
#' app is busy.
|
||||
#'
|
||||
#' @export
|
||||
#' @seealso [busyIndicatorOptions()] for customizing the appearance of the busy
|
||||
#' indicators.
|
||||
#' @examplesIf rlang::is_interactive()
|
||||
#'
|
||||
#' library(bslib)
|
||||
#'
|
||||
#' ui <- page_fillable(
|
||||
#' useBusyIndicators(),
|
||||
#' card(
|
||||
#' card_header(
|
||||
#' "A plot",
|
||||
#' input_task_button("simulate", "Simulate"),
|
||||
#' class = "d-flex justify-content-between align-items-center"
|
||||
#' ),
|
||||
#' plotOutput("p"),
|
||||
#' )
|
||||
#' )
|
||||
#'
|
||||
#' server <- function(input, output) {
|
||||
#' output$p <- renderPlot({
|
||||
#' input$simulate
|
||||
#' Sys.sleep(4)
|
||||
#' plot(x = rnorm(100), y = rnorm(100))
|
||||
#' })
|
||||
#' }
|
||||
#'
|
||||
#' shinyApp(ui, server)
|
||||
useBusyIndicators <- function(..., spinners = TRUE, pulse = TRUE) {
|
||||
|
||||
rlang::check_dots_empty()
|
||||
|
||||
attrs <- list("shinyBusySpinners" = spinners, "shinyBusyPulse" = pulse)
|
||||
|
||||
js <- vapply(names(attrs), character(1), FUN = function(key) {
|
||||
if (attrs[[key]]) {
|
||||
sprintf("document.documentElement.dataset.%s = 'true';", key)
|
||||
} else {
|
||||
sprintf("delete document.documentElement.dataset.%s;", key)
|
||||
}
|
||||
})
|
||||
|
||||
js <- HTML(paste(js, collapse = "\n"))
|
||||
|
||||
# TODO: it'd be nice if htmltools had something like a page_attrs() that allowed us
|
||||
# to do this without needing to inject JS into the head.
|
||||
tags$script(js)
|
||||
}
|
||||
|
||||
#' Customize busy indicator options
|
||||
#'
|
||||
#' When busy indicators are enabled (see [useBusyIndicators()]), a spinner is
|
||||
#' shown on each calculating/recalculating output, and a pulsing banner is shown
|
||||
#' at the top of the page when the app is otherwise busy. This function allows
|
||||
#' you to customize the appearance of those busy indicators. To apply the
|
||||
#' customization, include the result of this function inside the app's UI.
|
||||
#'
|
||||
#' @param ... Currently ignored.
|
||||
#' @param spinner_type The type of spinner. Pre-bundled types include:
|
||||
#' '`r paste0(.busySpinnerTypes, collapse = "', '")`'.
|
||||
#'
|
||||
#' A path to a local SVG file can also be provided. The SVG should adhere to
|
||||
#' the following rules:
|
||||
#' * The SVG itself should contain the animation.
|
||||
#' * It should avoid absolute sizes (the spinner's containing DOM element
|
||||
#' size is set in CSS by `spinner_size`, so it should fill that container).
|
||||
#' * It should avoid setting absolute colors (the spinner's containing DOM element
|
||||
#' color is set in CSS by `spinner_color`, so it should inherit that color).
|
||||
#' @param spinner_color The color of the spinner. This can be any valid CSS
|
||||
#' color. Defaults to the app's "primary" color if Bootstrap is on the page.
|
||||
#' @param spinner_size The size of the spinner. This can be any valid CSS size.
|
||||
#' @param spinner_delay The amount of time to wait before showing the spinner.
|
||||
#' This can be any valid CSS time and can be useful for not showing the spinner
|
||||
#' if the computation finishes quickly.
|
||||
#' @param spinner_selector A character string containing a CSS selector for
|
||||
#' scoping the spinner customization. The default (`NULL`) will apply the
|
||||
#' spinner customization to the parent element of the spinner.
|
||||
#' @param pulse_background A CSS background definition for the pulse. The
|
||||
#' default uses a
|
||||
#' [linear-gradient](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient)
|
||||
#' of the theme's indigo, purple, and pink colors.
|
||||
#' @param pulse_height The height of the pulsing banner. This can be any valid
|
||||
#' CSS size.
|
||||
#' @param pulse_speed The speed of the pulsing banner. This can be any valid CSS
|
||||
#' time.
|
||||
#'
|
||||
#' @export
|
||||
#' @seealso [useBusyIndicators()] for enabling/disabling busy indicators.
|
||||
#' @examplesIf rlang::is_interactive()
|
||||
#'
|
||||
#' library(bslib)
|
||||
#'
|
||||
#' card_ui <- function(id, spinner_type = id) {
|
||||
#' card(
|
||||
#' busyIndicatorOptions(spinner_type = spinner_type),
|
||||
#' card_header(paste("Spinner:", spinner_type)),
|
||||
#' plotOutput(shiny::NS(id, "plot"))
|
||||
#' )
|
||||
#' }
|
||||
#'
|
||||
#' card_server <- function(id, simulate = reactive()) {
|
||||
#' moduleServer(
|
||||
#' id = id,
|
||||
#' function(input, output, session) {
|
||||
#' output$plot <- renderPlot({
|
||||
#' Sys.sleep(1)
|
||||
#' simulate()
|
||||
#' plot(x = rnorm(100), y = rnorm(100))
|
||||
#' })
|
||||
#' }
|
||||
#' )
|
||||
#' }
|
||||
#'
|
||||
#' ui <- page_fillable(
|
||||
#' useBusyIndicators(),
|
||||
#' input_task_button("simulate", "Simulate", icon = icon("refresh")),
|
||||
#' layout_columns(
|
||||
#' card_ui("ring"),
|
||||
#' card_ui("bars"),
|
||||
#' card_ui("dots"),
|
||||
#' card_ui("pulse"),
|
||||
#' col_widths = 6
|
||||
#' )
|
||||
#' )
|
||||
#'
|
||||
#' server <- function(input, output, session) {
|
||||
#' simulate <- reactive(input$simulate)
|
||||
#' card_server("ring", simulate)
|
||||
#' card_server("bars", simulate)
|
||||
#' card_server("dots", simulate)
|
||||
#' card_server("pulse", simulate)
|
||||
#' }
|
||||
#'
|
||||
#' shinyApp(ui, server)
|
||||
#'
|
||||
busyIndicatorOptions <- function(
|
||||
...,
|
||||
spinner_type = NULL,
|
||||
spinner_color = NULL,
|
||||
spinner_size = NULL,
|
||||
spinner_delay = NULL,
|
||||
spinner_selector = NULL,
|
||||
pulse_background = NULL,
|
||||
pulse_height = NULL,
|
||||
pulse_speed = NULL
|
||||
) {
|
||||
|
||||
rlang::check_dots_empty()
|
||||
|
||||
res <- tagList(
|
||||
spinnerOptions(
|
||||
type = spinner_type,
|
||||
color = spinner_color,
|
||||
size = spinner_size,
|
||||
delay = spinner_delay,
|
||||
selector = spinner_selector
|
||||
),
|
||||
pulseOptions(
|
||||
background = pulse_background,
|
||||
height = pulse_height,
|
||||
speed = pulse_speed
|
||||
)
|
||||
)
|
||||
|
||||
bslib::as.card_item(dropNulls(res))
|
||||
}
|
||||
|
||||
|
||||
spinnerOptions <- function(type = NULL, color = NULL, size = NULL, delay = NULL, selector = NULL) {
|
||||
if (is.null(type) && is.null(color) && is.null(size) && is.null(delay) && is.null(selector)) {
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
url <- NULL
|
||||
if (!is.null(type)) {
|
||||
stopifnot(is.character(type) && length(type) == 1)
|
||||
if (file.exists(type) && grepl("\\.svg$", type)) {
|
||||
typeRaw <- readBin(type, "raw", n = file.info(type)$size)
|
||||
url <- sprintf("url('data:image/svg+xml;base64,%s')", rawToBase64(typeRaw))
|
||||
} else {
|
||||
type <- rlang::arg_match(type, .busySpinnerTypes)
|
||||
url <- sprintf("url('spinners/%s.svg')", type)
|
||||
}
|
||||
}
|
||||
|
||||
# Options controlled via CSS variables.
|
||||
css_vars <- htmltools::css(
|
||||
"--shiny-spinner-url" = url,
|
||||
"--shiny-spinner-color" = htmltools::parseCssColors(color),
|
||||
"--shiny-spinner-size" = htmltools::validateCssUnit(size),
|
||||
"--shiny-spinner-delay" = delay
|
||||
)
|
||||
|
||||
id <- NULL
|
||||
if (is.null(selector)) {
|
||||
id <- paste0("spinner-options-", p_randomInt(100, 1000000))
|
||||
selector <- sprintf(":has(> #%s)", id)
|
||||
}
|
||||
|
||||
css <- HTML(paste0(selector, " {", css_vars, "}"))
|
||||
|
||||
tags$style(css, id = id)
|
||||
}
|
||||
|
||||
pulseOptions <- function(background = NULL, height = NULL, speed = NULL) {
|
||||
if (is.null(background) && is.null(height) && is.null(speed)) {
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
css_vars <- htmltools::css(
|
||||
"--shiny-pulse-background" = background,
|
||||
"--shiny-pulse-height" = htmltools::validateCssUnit(height),
|
||||
"--shiny-pulse-speed" = speed
|
||||
)
|
||||
|
||||
tags$style(HTML(paste0(":root {", css_vars, "}")))
|
||||
}
|
||||
|
||||
busyIndicatorDependency <- function() {
|
||||
htmlDependency(
|
||||
name = "shiny-busy-indicators",
|
||||
version = get_package_version("shiny"),
|
||||
src = "www/shared/busy-indicators",
|
||||
package = "shiny",
|
||||
stylesheet = "busy-indicators.css"
|
||||
)
|
||||
}
|
||||
@@ -114,7 +114,6 @@ jqueryDependency <- function() {
|
||||
shinyDependencies <- function() {
|
||||
list(
|
||||
bslib::bs_dependency_defer(shinyDependencyCSS),
|
||||
busyIndicatorDependency(),
|
||||
htmlDependency(
|
||||
name = "shiny-javascript",
|
||||
version = get_package_version("shiny"),
|
||||
|
||||
69
R/utils.R
@@ -1515,44 +1515,41 @@ hybrid_chain <- function(expr, ..., catch = NULL, finally = NULL,
|
||||
|
||||
do <- function() {
|
||||
runFinally <- TRUE
|
||||
on.exit({ if (runFinally && !is.null(finally)) finally() })
|
||||
|
||||
catch_e <- NULL
|
||||
delayedAssign("do_catch",
|
||||
if (!is.null(catch)) {
|
||||
catch(catch_e)
|
||||
return()
|
||||
} else {
|
||||
stop(catch_e)
|
||||
}
|
||||
)
|
||||
|
||||
handlers <- list(error = function(e) { catch_e <<- e; do_catch })
|
||||
classes <- names(handlers)
|
||||
.Internal(.addCondHands(classes, handlers, parent.frame(), NULL, TRUE))
|
||||
|
||||
result <- withVisible(force(expr))
|
||||
if (promises::is.promising(result$value)) {
|
||||
# Purposefully NOT including domain (nor replace), as we're already in
|
||||
# the domain at this point
|
||||
p <- promise_chain(valueWithVisible(result), ..., catch = catch, finally = finally)
|
||||
runFinally <- FALSE
|
||||
p
|
||||
} else {
|
||||
result <- Reduce(
|
||||
function(v, func) {
|
||||
if (v$visible) {
|
||||
withVisible(func(v$value))
|
||||
tryCatch(
|
||||
{
|
||||
captureStackTraces({
|
||||
result <- withVisible(force(expr))
|
||||
if (promises::is.promising(result$value)) {
|
||||
# Purposefully NOT including domain (nor replace), as we're already in
|
||||
# the domain at this point
|
||||
p <- promise_chain(valueWithVisible(result), ..., catch = catch, finally = finally)
|
||||
runFinally <- FALSE
|
||||
p
|
||||
} else {
|
||||
withVisible(func(invisible(v$value)))
|
||||
}
|
||||
},
|
||||
list(...),
|
||||
result
|
||||
)
|
||||
result <- Reduce(
|
||||
function(v, func) {
|
||||
if (v$visible) {
|
||||
withVisible(func(v$value))
|
||||
} else {
|
||||
withVisible(func(invisible(v$value)))
|
||||
}
|
||||
},
|
||||
list(...),
|
||||
result
|
||||
)
|
||||
|
||||
valueWithVisible(result)
|
||||
}
|
||||
valueWithVisible(result)
|
||||
}
|
||||
})
|
||||
},
|
||||
error = function(e) {
|
||||
if (!is.null(catch))
|
||||
catch(e)
|
||||
else
|
||||
stop(e)
|
||||
},
|
||||
finally = if (runFinally && !is.null(finally)) finally()
|
||||
)
|
||||
}
|
||||
|
||||
if (!is.null(domain)) {
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
<mxfile host="app.diagrams.net" modified="2024-05-07T22:40:15.581Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" etag="Zsitjb4PT-sW3A63SWd7" version="24.3.1" type="device">
|
||||
<diagram name="Page-1" id="zz6aoPEyabkTD7ESu8ts">
|
||||
<mxGraphModel dx="595" dy="889" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-1" value="Initial" style="ellipse;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="120" y="270" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-2" value="Running" style="ellipse;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="270" y="270" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-3" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-1" target="DS1AFzV_2DL1v2c9v1jZ-2" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="480" as="sourcePoint" />
|
||||
<mxPoint x="310" y="270" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-4" value="Recalculating" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="210" y="250" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-6" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-2" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="220" as="sourcePoint" />
|
||||
<mxPoint x="310" y="350" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-7" value="Idle" style="ellipse;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="270" y="350" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-8" value="Recalculated" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="330" y="310" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-9" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-7" target="DS1AFzV_2DL1v2c9v1jZ-10" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="320" as="sourcePoint" />
|
||||
<mxPoint x="310" y="440" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="320" y="410" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-10" value="Value" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="280" y="440" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-11" value="Error" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="370" y="440" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-12" value="Persistent" style="ellipse;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="90" y="440" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-13" value="Cancel" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="440" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-14" value="<span style="text-align: start; font-size: 10pt; font-family: Arial;" data-sheets-userformat="{&quot;2&quot;:513,&quot;3&quot;:{&quot;1&quot;:0},&quot;12&quot;:0}" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;{progress: {type: \&quot;binding\&quot;, message: {persistent: true}}}&quot;}" data-sheets-root="1">{progress: {type: "binding", message: {persistent: true}}}</span>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="45" y="340" width="170" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-15" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-10" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="400" as="sourcePoint" />
|
||||
<mxPoint x="310" y="550" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="320" y="520" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-16" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-11" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="490" as="sourcePoint" />
|
||||
<mxPoint x="320" y="550" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-17" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-12" target="DS1AFzV_2DL1v2c9v1jZ-18" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="330" y="500" as="sourcePoint" />
|
||||
<mxPoint x="290" y="540" as="targetPoint" />
|
||||
<Array as="points" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-18" value="Invalidated" style="ellipse;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="260" y="550" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-20" value="" style="curved=1;endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-18" target="DS1AFzV_2DL1v2c9v1jZ-2" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="480" as="sourcePoint" />
|
||||
<mxPoint x="310" y="430" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="420" y="610" />
|
||||
<mxPoint x="550" y="470" />
|
||||
<mxPoint x="440" y="320" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-23" value="Recalculating" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="450" y="340" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-24" value="" style="endArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-2" target="DS1AFzV_2DL1v2c9v1jZ-12" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="400" as="sourcePoint" />
|
||||
<mxPoint x="320" y="450" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-25" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0.395;entryY=-0.025;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-7" target="DS1AFzV_2DL1v2c9v1jZ-11" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="330" y="410" as="sourcePoint" />
|
||||
<mxPoint x="330" y="460" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="380" y="410" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-26" value="" style="endArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-7" target="DS1AFzV_2DL1v2c9v1jZ-13" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="340" y="420" as="sourcePoint" />
|
||||
<mxPoint x="340" y="470" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-27" value="Value" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="270" y="400" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-28" value="Error" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="330" y="400" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-29" value="No message" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="200" y="400" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-30" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-13" target="DS1AFzV_2DL1v2c9v1jZ-18" edge="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="230" y="490" as="sourcePoint" />
|
||||
<mxPoint x="300" y="558" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="240" y="520" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-31" value="<span style="font-family: Arial; font-size: 13px; text-align: left; white-space: pre-wrap; background-color: rgb(255, 255, 255);">{progress: {type: "binding"}}</span>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="190" y="490" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DS1AFzV_2DL1v2c9v1jZ-35" value="<h1 style="margin-top: 0px;">Shiny output progress states</h1><p>This diagram depicts a state machine of output binding progress state. Each node represents a possible state and each edge represents a server-&gt;client message that moves outputs from one state to another. <b>If a node is highlighted in blue</b>, then the output should be showing a busy state when visible (i.e., <font face="Courier New">binding.showProgress(true)</font>)</p>" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="85" y="120" width="465" height="120" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="J9lKobNiy15ndT9nfcn--1" value="" style="curved=1;endArrow=classic;html=1;rounded=0;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="DS1AFzV_2DL1v2c9v1jZ-7" target="DS1AFzV_2DL1v2c9v1jZ-18">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="280" y="480" as="sourcePoint" />
|
||||
<mxPoint x="220" y="510" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="610" y="420" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
Before Width: | Height: | Size: 312 KiB |
@@ -1,2 +0,0 @@
|
||||
/*! shiny 1.8.1.9001 | (c) 2012-2024 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
:where([data-shiny-busy-spinners] .recalculating){position:relative}[data-shiny-busy-spinners] .recalculating{opacity:1}[data-shiny-busy-spinners] .recalculating:after{position:absolute;content:"";--_shiny-spinner-url: var(--shiny-spinner-url, url(spinners/ring.svg));--_shiny-spinner-color: var(--shiny-spinner-color, var(--bs-primary, #007bc2));--_shiny-spinner-size: var(--shiny-spinner-size, 32px);--_shiny-spinner-delay: var(--shiny-spinner-delay, 1s);background:var(--_shiny-spinner-color);width:var(--_shiny-spinner-size);height:var(--_shiny-spinner-size);inset:calc(50% - var(--_shiny-spinner-size) / 2);mask-image:var(--_shiny-spinner-url);-webkit-mask-image:var(--_shiny-spinner-url);opacity:0;animation-delay:var(--_shiny-spinner-delay);animation-name:fade-in;animation-duration:.25s}[data-shiny-busy-spinners] .recalculating>*:not(.recalculating){opacity:.2;transition:opacity .25s ease var(--shiny-spinner-delay, 1s)}[data-shiny-busy-spinners] .recalculating.shiny-html-output:after{display:none}[data-shiny-busy-spinners][data-shiny-busy-pulse].shiny-busy:after{--_shiny-pulse-background: var( --shiny-pulse-background, linear-gradient( 120deg, var(--bs-body-bg, #fff), var(--bs-indigo, #4b00c1), var(--bs-purple, #74149c), var(--bs-pink, #bf007f), var(--bs-body-bg, #fff) ) );--_shiny-pulse-height: var(--shiny-pulse-height, 5px);--_shiny-pulse-speed: var(--shiny-pulse-speed, 1.85s);position:fixed;top:0;left:0;height:var(--_shiny-pulse-height);background:var(--_shiny-pulse-background);z-index:9999;animation-name:busy-page-pulse;animation-duration:var(--_shiny-pulse-speed);animation-iteration-count:infinite;animation-timing-function:ease-in-out;content:""}[data-shiny-busy-spinners][data-shiny-busy-pulse].shiny-busy:has(.recalculating):after{display:none}[data-shiny-busy-spinners][data-shiny-busy-pulse].shiny-busy:has(#shiny-disconnected-overlay):after{display:none}[data-shiny-busy-pulse]:not([data-shiny-busy-spinners]).shiny-busy:after{--_shiny-pulse-background: var( --shiny-pulse-background, linear-gradient( 120deg, var(--bs-body-bg, #fff), var(--bs-indigo, #4b00c1), var(--bs-purple, #74149c), var(--bs-pink, #bf007f), var(--bs-body-bg, #fff) ) );--_shiny-pulse-height: var(--shiny-pulse-height, 5px);--_shiny-pulse-speed: var(--shiny-pulse-speed, 1.85s);position:fixed;top:0;left:0;height:var(--_shiny-pulse-height);background:var(--_shiny-pulse-background);z-index:9999;animation-name:busy-page-pulse;animation-duration:var(--_shiny-pulse-speed);animation-iteration-count:infinite;animation-timing-function:ease-in-out;content:""}[data-shiny-busy-pulse]:not([data-shiny-busy-spinners]).shiny-busy:has(#shiny-disconnected-overlay):after{display:none}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes busy-page-pulse{0%{left:-75%;width:75%}50%{left:100%;width:75%}to{left:-75%;width:75%}}
|
||||
@@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Utkarsh Verma
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_hzlK{animation:spinner_vc4H .8s linear infinite;animation-delay:-.8s}.spinner_koGT{animation-delay:-.65s}.spinner_YF1u{animation-delay:-.5s}@keyframes spinner_vc4H{0%{y:1px;height:22px}93.75%{y:5px;height:14px;opacity:.2}}</style><rect class="spinner_hzlK" x="1" y="1" width="6" height="22"/><rect class="spinner_hzlK spinner_koGT" x="9" y="1" width="6" height="22"/><rect class="spinner_hzlK spinner_YF1u" x="17" y="1" width="6" height="22"/></svg>
|
||||
|
Before Width: | Height: | Size: 526 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_jCIR{animation:spinner_B8Vq .9s linear infinite;animation-delay:-.9s}.spinner_upm8{animation-delay:-.8s}.spinner_2eL5{animation-delay:-.7s}.spinner_Rp9l{animation-delay:-.6s}.spinner_dy3W{animation-delay:-.5s}@keyframes spinner_B8Vq{0%,66.66%{animation-timing-function:cubic-bezier(0.36,.61,.3,.98);y:6px;height:12px}33.33%{animation-timing-function:cubic-bezier(0.36,.61,.3,.98);y:1px;height:22px}}</style><rect class="spinner_jCIR" x="1" y="6" width="2.8" height="12"/><rect class="spinner_jCIR spinner_upm8" x="5.8" y="6" width="2.8" height="12"/><rect class="spinner_jCIR spinner_2eL5" x="10.6" y="6" width="2.8" height="12"/><rect class="spinner_jCIR spinner_Rp9l" x="15.4" y="6" width="2.8" height="12"/><rect class="spinner_jCIR spinner_dy3W" x="20.2" y="6" width="2.8" height="12"/></svg>
|
||||
|
Before Width: | Height: | Size: 873 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_OSmW{transform-origin:center;animation:spinner_T6mA .75s step-end infinite}@keyframes spinner_T6mA{8.3%{transform:rotate(30deg)}16.6%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.3%{transform:rotate(120deg)}41.6%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.3%{transform:rotate(210deg)}66.6%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.3%{transform:rotate(300deg)}91.6%{transform:rotate(330deg)}100%{transform:rotate(360deg)}}</style><g class="spinner_OSmW"><rect x="11" y="1" width="2" height="5" opacity=".14"/><rect x="11" y="1" width="2" height="5" transform="rotate(30 12 12)" opacity=".29"/><rect x="11" y="1" width="2" height="5" transform="rotate(60 12 12)" opacity=".43"/><rect x="11" y="1" width="2" height="5" transform="rotate(90 12 12)" opacity=".57"/><rect x="11" y="1" width="2" height="5" transform="rotate(120 12 12)" opacity=".71"/><rect x="11" y="1" width="2" height="5" transform="rotate(150 12 12)" opacity=".86"/><rect x="11" y="1" width="2" height="5" transform="rotate(180 12 12)"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_b2T7{animation:spinner_xe7Q .8s linear infinite}.spinner_YRVV{animation-delay:-.65s}.spinner_c9oY{animation-delay:-.5s}@keyframes spinner_xe7Q{93.75%,100%{r:3px}46.875%{r:.2px}}</style><circle class="spinner_b2T7" cx="4" cy="12" r="3"/><circle class="spinner_b2T7 spinner_YRVV" cx="12" cy="12" r="3"/><circle class="spinner_b2T7 spinner_c9oY" cx="20" cy="12" r="3"/></svg>
|
||||
|
Before Width: | Height: | Size: 449 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_Wezc{transform-origin:center;animation:spinner_Oiah .75s step-end infinite}@keyframes spinner_Oiah{8.3%{transform:rotate(30deg)}16.6%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.3%{transform:rotate(120deg)}41.6%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.3%{transform:rotate(210deg)}66.6%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.3%{transform:rotate(300deg)}91.6%{transform:rotate(330deg)}100%{transform:rotate(360deg)}}</style><g class="spinner_Wezc"><circle cx="12" cy="2.5" r="1.5" opacity=".14"/><circle cx="16.75" cy="3.77" r="1.5" opacity=".29"/><circle cx="20.23" cy="7.25" r="1.5" opacity=".43"/><circle cx="21.50" cy="12.00" r="1.5" opacity=".57"/><circle cx="20.23" cy="16.75" r="1.5" opacity=".71"/><circle cx="16.75" cy="20.23" r="1.5" opacity=".86"/><circle cx="12" cy="21.5" r="1.5"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 926 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_DupU{animation:spinner_sM3D 1.2s infinite}.spinner_GWtZ{animation-delay:.1s}.spinner_dwN6{animation-delay:.2s}.spinner_46QP{animation-delay:.3s}.spinner_PD82{animation-delay:.4s}.spinner_eUgh{animation-delay:.5s}.spinner_eUaP{animation-delay:.6s}.spinner_j38H{animation-delay:.7s}.spinner_tVmX{animation-delay:.8s}.spinner_DQhX{animation-delay:.9s}.spinner_GIL4{animation-delay:1s}.spinner_n0Yb{animation-delay:1.1s}@keyframes spinner_sM3D{0%,50%{animation-timing-function:cubic-bezier(0,1,0,1);r:0}10%{animation-timing-function:cubic-bezier(.53,0,.61,.73);r:2px}}</style><circle class="spinner_DupU" cx="12" cy="3" r="0"/><circle class="spinner_DupU spinner_GWtZ" cx="16.50" cy="4.21" r="0"/><circle class="spinner_DupU spinner_n0Yb" cx="7.50" cy="4.21" r="0"/><circle class="spinner_DupU spinner_dwN6" cx="19.79" cy="7.50" r="0"/><circle class="spinner_DupU spinner_GIL4" cx="4.21" cy="7.50" r="0"/><circle class="spinner_DupU spinner_46QP" cx="21.00" cy="12.00" r="0"/><circle class="spinner_DupU spinner_DQhX" cx="3.00" cy="12.00" r="0"/><circle class="spinner_DupU spinner_PD82" cx="19.79" cy="16.50" r="0"/><circle class="spinner_DupU spinner_tVmX" cx="4.21" cy="16.50" r="0"/><circle class="spinner_DupU spinner_eUgh" cx="16.50" cy="19.79" r="0"/><circle class="spinner_DupU spinner_j38H" cx="7.50" cy="19.79" r="0"/><circle class="spinner_DupU spinner_eUaP" cx="12" cy="21" r="0"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_ZCsl{animation:spinner_qV4G 1.2s cubic-bezier(0.52,.6,.25,.99) infinite}.spinner_gaIW{animation-delay:.6s}@keyframes spinner_qV4G{0%{r:0;opacity:1}100%{r:11px;opacity:0}}</style><circle class="spinner_ZCsl" cx="12" cy="12" r="0"/><circle class="spinner_ZCsl spinner_gaIW" cx="12" cy="12" r="0"/></svg>
|
||||
|
Before Width: | Height: | Size: 378 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_ngNb{animation:spinner_ZRWK 1.2s cubic-bezier(0.52,.6,.25,.99) infinite}.spinner_6TBP{animation-delay:.6s}@keyframes spinner_ZRWK{0%{transform:translate(12px,12px) scale(0);opacity:1}100%{transform:translate(0,0) scale(1);opacity:0}}</style><path class="spinner_ngNb" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z" transform="translate(12, 12) scale(0)"/><path class="spinner_ngNb spinner_6TBP" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z" transform="translate(12, 12) scale(0)"/></svg>
|
||||
|
Before Width: | Height: | Size: 635 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_Uvk8{animation:spinner_otJF 1.6s cubic-bezier(.52,.6,.25,.99) infinite}.spinner_ypeD{animation-delay:.2s}.spinner_y0Rj{animation-delay:.4s}@keyframes spinner_otJF{0%{transform:translate(12px,12px) scale(0);opacity:1}75%,100%{transform:translate(0,0) scale(1);opacity:0}}</style><path class="spinner_Uvk8" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z" transform="translate(12, 12) scale(0)"/><path class="spinner_Uvk8 spinner_ypeD" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z" transform="translate(12, 12) scale(0)"/><path class="spinner_Uvk8 spinner_y0Rj" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z" transform="translate(12, 12) scale(0)"/></svg>
|
||||
|
Before Width: | Height: | Size: 834 B |
@@ -1 +0,0 @@
|
||||
<svg stroke="#000" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_V8m1{transform-origin:center;animation:spinner_zKoa 2s linear infinite}.spinner_V8m1 circle{stroke-linecap:round;animation:spinner_YpZS 1.5s ease-in-out infinite}@keyframes spinner_zKoa{100%{transform:rotate(360deg)}}@keyframes spinner_YpZS{0%{stroke-dasharray:0 150;stroke-dashoffset:0}47.5%{stroke-dasharray:42 150;stroke-dashoffset:-16}95%,100%{stroke-dasharray:42 150;stroke-dashoffset:-59}}</style><g class="spinner_V8m1"><circle cx="12" cy="12" r="9.5" fill="none" stroke-width="3"></circle></g></svg>
|
||||
|
Before Width: | Height: | Size: 598 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_ajPY{transform-origin:center;animation:spinner_AtaB .75s infinite linear}@keyframes spinner_AtaB{100%{transform:rotate(360deg)}}</style><path d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z" opacity=".25"/><path d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z" class="spinner_ajPY"/></svg>
|
||||
|
Before Width: | Height: | Size: 509 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_aj0A{transform-origin:center;animation:spinner_KYSC .75s infinite linear}@keyframes spinner_KYSC{100%{transform:rotate(360deg)}}</style><path d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z" class="spinner_aj0A"/></svg>
|
||||
|
Before Width: | Height: | Size: 412 B |
@@ -1,2 +1,2 @@
|
||||
/*! shiny 1.8.1.9001 | (c) 2012-2024 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
/*! shiny 1.8.1.9000 | (c) 2012-2024 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:400}.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,#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}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
/*! shiny 1.8.1.9001 | (c) 2012-2024 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
/*! shiny 1.8.1.9000 | (c) 2012-2024 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
"use strict";(function(){var a=eval;window.addEventListener("message",function(i){var e=i.data;e.code&&a(e.code)});})();
|
||||
//# sourceMappingURL=shiny-testmode.js.map
|
||||
|
||||
18965
inst/www/shared/shiny.js
2
inst/www/shared/shiny.min.css
vendored
4
inst/www/shared/shiny.min.js
vendored
@@ -1,117 +0,0 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/busy-indicators.R
|
||||
\name{busyIndicatorOptions}
|
||||
\alias{busyIndicatorOptions}
|
||||
\title{Customize busy indicator options}
|
||||
\usage{
|
||||
busyIndicatorOptions(
|
||||
...,
|
||||
spinner_type = NULL,
|
||||
spinner_color = NULL,
|
||||
spinner_size = NULL,
|
||||
spinner_delay = NULL,
|
||||
spinner_selector = NULL,
|
||||
pulse_background = NULL,
|
||||
pulse_height = NULL,
|
||||
pulse_speed = NULL
|
||||
)
|
||||
}
|
||||
\arguments{
|
||||
\item{...}{Currently ignored.}
|
||||
|
||||
\item{spinner_type}{The type of spinner. Pre-bundled types include:
|
||||
'ring', 'ring2', 'ring3', 'bars', 'bars2', 'bars3', 'pulse', 'pulse2', 'pulse3', 'dots', 'dots2', 'dots3'.
|
||||
|
||||
A path to a local SVG file can also be provided. The SVG should adhere to
|
||||
the following rules:
|
||||
\itemize{
|
||||
\item The SVG itself should contain the animation.
|
||||
\item It should avoid absolute sizes (the spinner's containing DOM element
|
||||
size is set in CSS by \code{spinner_size}, so it should fill that container).
|
||||
\item It should avoid setting absolute colors (the spinner's containing DOM element
|
||||
color is set in CSS by \code{spinner_color}, so it should inherit that color).
|
||||
}}
|
||||
|
||||
\item{spinner_color}{The color of the spinner. This can be any valid CSS
|
||||
color. Defaults to the app's "primary" color if Bootstrap is on the page.}
|
||||
|
||||
\item{spinner_size}{The size of the spinner. This can be any valid CSS size.}
|
||||
|
||||
\item{spinner_delay}{The amount of time to wait before showing the spinner.
|
||||
This can be any valid CSS time and can be useful for not showing the spinner
|
||||
if the computation finishes quickly.}
|
||||
|
||||
\item{spinner_selector}{A character string containing a CSS selector for
|
||||
scoping the spinner customization. The default (\code{NULL}) will apply the
|
||||
spinner customization to the parent element of the spinner.}
|
||||
|
||||
\item{pulse_background}{A CSS background definition for the pulse. The
|
||||
default uses a
|
||||
\href{https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient}{linear-gradient}
|
||||
of the theme's indigo, purple, and pink colors.}
|
||||
|
||||
\item{pulse_height}{The height of the pulsing banner. This can be any valid
|
||||
CSS size.}
|
||||
|
||||
\item{pulse_speed}{The speed of the pulsing banner. This can be any valid CSS
|
||||
time.}
|
||||
}
|
||||
\description{
|
||||
When busy indicators are enabled (see \code{\link[=useBusyIndicators]{useBusyIndicators()}}), a spinner is
|
||||
shown on each calculating/recalculating output, and a pulsing banner is shown
|
||||
at the top of the page when the app is otherwise busy. This function allows
|
||||
you to customize the appearance of those busy indicators. To apply the
|
||||
customization, include the result of this function inside the app's UI.
|
||||
}
|
||||
\examples{
|
||||
\dontshow{if (rlang::is_interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
|
||||
|
||||
library(bslib)
|
||||
|
||||
card_ui <- function(id, spinner_type = id) {
|
||||
card(
|
||||
busyIndicatorOptions(spinner_type = spinner_type),
|
||||
card_header(paste("Spinner:", spinner_type)),
|
||||
plotOutput(shiny::NS(id, "plot"))
|
||||
)
|
||||
}
|
||||
|
||||
card_server <- function(id, simulate = reactive()) {
|
||||
moduleServer(
|
||||
id = id,
|
||||
function(input, output, session) {
|
||||
output$plot <- renderPlot({
|
||||
Sys.sleep(1)
|
||||
simulate()
|
||||
plot(x = rnorm(100), y = rnorm(100))
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ui <- page_fillable(
|
||||
useBusyIndicators(),
|
||||
input_task_button("simulate", "Simulate", icon = icon("refresh")),
|
||||
layout_columns(
|
||||
card_ui("ring"),
|
||||
card_ui("bars"),
|
||||
card_ui("dots"),
|
||||
card_ui("pulse"),
|
||||
col_widths = 6
|
||||
)
|
||||
)
|
||||
|
||||
server <- function(input, output, session) {
|
||||
simulate <- reactive(input$simulate)
|
||||
card_server("ring", simulate)
|
||||
card_server("bars", simulate)
|
||||
card_server("dots", simulate)
|
||||
card_server("pulse", simulate)
|
||||
}
|
||||
|
||||
shinyApp(ui, server)
|
||||
\dontshow{\}) # examplesIf}
|
||||
}
|
||||
\seealso{
|
||||
\code{\link[=useBusyIndicators]{useBusyIndicators()}} for enabling/disabling busy indicators.
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/busy-indicators.R
|
||||
\name{useBusyIndicators}
|
||||
\alias{useBusyIndicators}
|
||||
\title{Enable/disable busy indication}
|
||||
\usage{
|
||||
useBusyIndicators(..., spinners = TRUE, pulse = TRUE)
|
||||
}
|
||||
\arguments{
|
||||
\item{...}{Currently ignored.}
|
||||
|
||||
\item{spinners}{Whether to show a spinner on each calculating/recalculating
|
||||
output.}
|
||||
|
||||
\item{pulse}{Whether to show a pulsing banner at the top of the page when the
|
||||
app is busy.}
|
||||
}
|
||||
\description{
|
||||
Busy indicators provide a visual cue to users when the server is busy
|
||||
calculating outputs or otherwise performing tasks (e.g., producing
|
||||
downloads). When enabled, a spinner is shown on each
|
||||
calculating/recalculating output, and a pulsing banner is shown at the top of
|
||||
the page when the app is otherwise busy. Busy indication is enabled by
|
||||
default for UI created with \pkg{bslib}, but must be enabled otherwise. To
|
||||
enable/disable, include the result of this function in anywhere in the app's
|
||||
UI.
|
||||
}
|
||||
\details{
|
||||
When both \code{spinners} and \code{pulse} are set to \code{TRUE}, the pulse is
|
||||
automatically disabled when spinner(s) are active. When both \code{spinners} and
|
||||
\code{pulse} are set to \code{FALSE}, no busy indication is shown (other than the
|
||||
graying out of recalculating outputs).
|
||||
}
|
||||
\examples{
|
||||
\dontshow{if (rlang::is_interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
|
||||
|
||||
library(bslib)
|
||||
|
||||
ui <- page_fillable(
|
||||
useBusyIndicators(),
|
||||
card(
|
||||
card_header(
|
||||
"A plot",
|
||||
input_task_button("simulate", "Simulate"),
|
||||
class = "d-flex justify-content-between align-items-center"
|
||||
),
|
||||
plotOutput("p"),
|
||||
)
|
||||
)
|
||||
|
||||
server <- function(input, output) {
|
||||
output$p <- renderPlot({
|
||||
input$simulate
|
||||
Sys.sleep(4)
|
||||
plot(x = rnorm(100), y = rnorm(100))
|
||||
})
|
||||
}
|
||||
|
||||
shinyApp(ui, server)
|
||||
\dontshow{\}) # examplesIf}
|
||||
}
|
||||
\seealso{
|
||||
\code{\link[=busyIndicatorOptions]{busyIndicatorOptions()}} for customizing the appearance of the busy
|
||||
indicators.
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"homepage": "https://shiny.rstudio.com",
|
||||
"repository": "github:rstudio/shiny",
|
||||
"name": "@types/rstudio-shiny",
|
||||
"version": "1.8.1-alpha.9001",
|
||||
"version": "1.8.1-alpha.9000",
|
||||
"license": "GPL-3.0-only",
|
||||
"main": "",
|
||||
"browser": "",
|
||||
@@ -69,7 +69,6 @@
|
||||
"phantomjs-prebuilt": "^2.1.16",
|
||||
"postcss": "^8.3.5",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"readcontrol": "^1.0.0",
|
||||
"replace": "^1.2.1",
|
||||
"ts-jest": "^26",
|
||||
@@ -95,11 +94,5 @@
|
||||
"coverage": "type-coverage -p tsconfig.json --at-least 90",
|
||||
"circular": "madge --circular --extensions ts srcts/src",
|
||||
"circular_image": "madge --circular --extensions ts --image madge.svg srcts/src"
|
||||
},
|
||||
"prettier": {
|
||||
"plugins": [
|
||||
"prettier-plugin-organize-imports"
|
||||
],
|
||||
"organizeImportsSkipDestructiveCodeActions": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,11 +53,3 @@ build({
|
||||
],
|
||||
outfile: outDir + "shiny.min.css",
|
||||
});
|
||||
build({
|
||||
...sassOpts,
|
||||
entryPoints: ["srcts/extras/busy-indicators/busy-indicators.scss"],
|
||||
outfile: outDir + "busy-indicators/busy-indicators.css",
|
||||
plugins: [sassPlugin()],
|
||||
bundle: false,
|
||||
metafile: true,
|
||||
});
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
:where([data-shiny-busy-spinners] .recalculating) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* This data atttribute is set by ui.busy_indicators.use() */
|
||||
[data-shiny-busy-spinners] {
|
||||
|
||||
.recalculating {
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
|
||||
/* ui.busy_indicators.spinner_options() */
|
||||
--_shiny-spinner-url: var(--shiny-spinner-url, url(spinners/ring.svg));
|
||||
--_shiny-spinner-color: var(--shiny-spinner-color, var(--bs-primary, #007bc2));
|
||||
--_shiny-spinner-size: var(--shiny-spinner-size, 32px);
|
||||
--_shiny-spinner-delay: var(--shiny-spinner-delay, 1s);
|
||||
|
||||
background: var(--_shiny-spinner-color);
|
||||
width: var(--_shiny-spinner-size);
|
||||
height: var(--_shiny-spinner-size);
|
||||
inset: calc(50% - var(--_shiny-spinner-size) / 2);
|
||||
|
||||
mask-image: var(--_shiny-spinner-url);
|
||||
-webkit-mask-image: var(--_shiny-spinner-url);
|
||||
|
||||
opacity: 0;
|
||||
animation-delay: var(--_shiny-spinner-delay);
|
||||
animation-name: fade-in;
|
||||
animation-duration: 250ms;
|
||||
}
|
||||
|
||||
/*
|
||||
shiny.css puts `opacity: 0.3` on .recalculating, which unfortunately applies to
|
||||
the spinner. Undo that, but still apply (smaller) opacity to immediate children
|
||||
that aren't recalculating.
|
||||
*/
|
||||
opacity: 1;
|
||||
> *:not(.recalculating) {
|
||||
opacity: 0.2;
|
||||
transition: opacity 250ms ease var(--shiny-spinner-delay, 1s);
|
||||
}
|
||||
|
||||
/*
|
||||
Disable spinner on uiOutput() mainly because (for other reasons) it has
|
||||
`display:contents`, which breaks the ::after positioning.
|
||||
Note that, even if we could position it, we'd probably want to disable it
|
||||
if it has recalculating children.
|
||||
*/
|
||||
&.shiny-html-output::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Styles for the page-level pulse banner */
|
||||
@mixin shiny-page-busy {
|
||||
/* ui.busy_indicators.pulse_options() */
|
||||
--_shiny-pulse-background: var(
|
||||
--shiny-pulse-background,
|
||||
linear-gradient(
|
||||
120deg,
|
||||
var(--bs-body-bg, #fff),
|
||||
var(--bs-indigo, #4b00c1),
|
||||
var(--bs-purple, #74149c),
|
||||
var(--bs-pink, #bf007f),
|
||||
var(--bs-body-bg, #fff)
|
||||
)
|
||||
);
|
||||
--_shiny-pulse-height: var(--shiny-pulse-height, 5px);
|
||||
--_shiny-pulse-speed: var(--shiny-pulse-speed, 1.85s);
|
||||
|
||||
/* Color, sizing, & positioning */
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: var(--_shiny-pulse-height);
|
||||
background: var(--_shiny-pulse-background);
|
||||
z-index: 9999;
|
||||
|
||||
/* Animation */
|
||||
animation-name: busy-page-pulse;
|
||||
animation-duration: var(--_shiny-pulse-speed);
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: ease-in-out;
|
||||
|
||||
content: ""; /* Used in a ::after context */
|
||||
}
|
||||
|
||||
/*
|
||||
In spinners+pulse mode (the recommended default), show a page-level banner if the
|
||||
page is busy, but there are no recalculating elements.
|
||||
*/
|
||||
[data-shiny-busy-spinners][data-shiny-busy-pulse] {
|
||||
&.shiny-busy::after {
|
||||
@include shiny-page-busy;
|
||||
}
|
||||
&.shiny-busy:has(.recalculating)::after {
|
||||
display: none;
|
||||
}
|
||||
&.shiny-busy:has(#shiny-disconnected-overlay)::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* In pulse _only_ mode, show a page-level banner whenever shiny is busy. */
|
||||
[data-shiny-busy-pulse]:not([data-shiny-busy-spinners]) {
|
||||
&.shiny-busy::after {
|
||||
@include shiny-page-busy;
|
||||
}
|
||||
&.shiny-busy:has(#shiny-disconnected-overlay)::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframes for the fading spinner */
|
||||
@keyframes fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframes for the pulsing banner */
|
||||
@keyframes busy-page-pulse {
|
||||
0% {
|
||||
left: -75%;
|
||||
width: 75%;
|
||||
}
|
||||
50% {
|
||||
left: 100%;
|
||||
width: 75%;
|
||||
}
|
||||
/* Go back */
|
||||
100% {
|
||||
left: -75%;
|
||||
width: 75%;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from "jquery";
|
||||
import { hasDefinedProperty } from "../../utils";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import { hasDefinedProperty } from "../../utils";
|
||||
|
||||
type CheckedHTMLElement = HTMLInputElement;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import $ from "jquery";
|
||||
|
||||
import { $escape, hasDefinedProperty, updateLabel } from "../../utils";
|
||||
import type { CheckedHTMLElement } from "./checkbox";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import { $escape, updateLabel, hasDefinedProperty } from "../../utils";
|
||||
import type { CheckedHTMLElement } from "./checkbox";
|
||||
|
||||
type CheckboxGroupHTMLElement = CheckedHTMLElement;
|
||||
type ValueLabelObject = {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import $ from "jquery";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import {
|
||||
$escape,
|
||||
formatDateUTC,
|
||||
hasDefinedProperty,
|
||||
parseDate,
|
||||
updateLabel,
|
||||
$escape,
|
||||
parseDate,
|
||||
hasDefinedProperty,
|
||||
} from "../../utils";
|
||||
import type { NotUndefined } from "../../utils/extraTypes";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
|
||||
declare global {
|
||||
interface JQuery {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import $ from "jquery";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import { FileUploader } from "../../file/fileProcessor";
|
||||
import { shinyShinyApp } from "../../shiny/initedMethods";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
|
||||
const zoneActive = "shiny-file-input-active";
|
||||
const zoneOver = "shiny-file-input-over";
|
||||
|
||||
@@ -2,20 +2,20 @@ import { BindingRegistry } from "../registry";
|
||||
|
||||
import { InputBinding } from "./inputBinding";
|
||||
|
||||
import { ActionButtonInputBinding } from "./actionbutton";
|
||||
import { CheckboxInputBinding } from "./checkbox";
|
||||
import { CheckboxGroupInputBinding } from "./checkboxgroup";
|
||||
import { DateInputBinding } from "./date";
|
||||
import { DateRangeInputBinding } from "./daterange";
|
||||
import { FileInputBinding } from "./fileinput";
|
||||
import { NumberInputBinding } from "./number";
|
||||
import { PasswordInputBinding } from "./password";
|
||||
import { RadioInputBinding } from "./radio";
|
||||
import { SelectInputBinding } from "./selectInput";
|
||||
import { SliderInputBinding } from "./slider";
|
||||
import { BootstrapTabInputBinding } from "./tabinput";
|
||||
import { TextInputBinding } from "./text";
|
||||
import { TextareaInputBinding } from "./textarea";
|
||||
import { RadioInputBinding } from "./radio";
|
||||
import { DateInputBinding } from "./date";
|
||||
import { SliderInputBinding } from "./slider";
|
||||
import { DateRangeInputBinding } from "./daterange";
|
||||
import { SelectInputBinding } from "./selectInput";
|
||||
import { ActionButtonInputBinding } from "./actionbutton";
|
||||
import { BootstrapTabInputBinding } from "./tabinput";
|
||||
import { FileInputBinding } from "./fileinput";
|
||||
|
||||
// TODO-barret make this an init method
|
||||
type InitInputBindings = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from "jquery";
|
||||
import { $escape, hasDefinedProperty, updateLabel } from "../../utils";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import { $escape, hasDefinedProperty, updateLabel } from "../../utils";
|
||||
|
||||
type RadioHTMLElement = HTMLInputElement;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import $ from "jquery";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import { $escape, hasDefinedProperty, updateLabel } from "../../utils";
|
||||
import { indirectEval } from "../../utils/eval";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
|
||||
type SelectHTMLElement = HTMLSelectElement & { nonempty: boolean };
|
||||
|
||||
@@ -154,7 +154,7 @@ class SelectInputBinding extends InputBinding {
|
||||
selectize.settings.load = function (query: string, callback: CallbackFn) {
|
||||
const settings = selectize.settings;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
$.ajax({
|
||||
url: data.url,
|
||||
data: {
|
||||
|
||||
@@ -5,10 +5,10 @@ import type {
|
||||
import $ from "jquery";
|
||||
// import { NameValueHTMLElement } from ".";
|
||||
import {
|
||||
$escape,
|
||||
formatDateUTC,
|
||||
hasDefinedProperty,
|
||||
updateLabel,
|
||||
$escape,
|
||||
hasDefinedProperty,
|
||||
} from "../../utils";
|
||||
|
||||
import type { TextHTMLElement } from "./text";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from "jquery";
|
||||
import { hasDefinedProperty, isBS3 } from "../../utils";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import { hasDefinedProperty, isBS3 } from "../../utils";
|
||||
|
||||
type TabInputReceiveMessageData = { value?: string };
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import $ from "jquery";
|
||||
import { $escape, hasDefinedProperty, updateLabel } from "../../utils";
|
||||
import { $escape, updateLabel, hasDefinedProperty } from "../../utils";
|
||||
|
||||
import { InputBinding } from "./inputBinding";
|
||||
|
||||
@@ -122,4 +122,5 @@ class TextInputBinding extends TextInputBindingBase {
|
||||
}
|
||||
|
||||
export { TextInputBinding, TextInputBindingBase };
|
||||
|
||||
export type { TextHTMLElement, TextReceiveMessageData };
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import $ from "jquery";
|
||||
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
import { shinyUnbindAll } from "../../shiny/initedMethods";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import { debounce } from "../../time";
|
||||
import { escapeHTML } from "../../utils";
|
||||
import { indirectEval } from "../../utils/eval";
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
|
||||
class DatatableOutputBinding extends OutputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement> {
|
||||
|
||||
@@ -7,17 +7,7 @@ class DownloadLinkOutputBinding extends OutputBinding {
|
||||
return $(scope).find("a.shiny-download-link");
|
||||
}
|
||||
renderValue(el: HTMLElement, data: string): void {
|
||||
el.setAttribute("href", data);
|
||||
el.classList.remove("disabled");
|
||||
el.removeAttribute("aria-disabled");
|
||||
el.removeAttribute("tabindex");
|
||||
}
|
||||
// Progress shouldn't be shown on the download button
|
||||
// (progress will be shown as a page level pulse instead)
|
||||
showProgress(el: HTMLElement, show: boolean): void {
|
||||
return;
|
||||
el;
|
||||
show;
|
||||
$(el).attr("href", data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import $ from "jquery";
|
||||
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
import { shinyUnbindAll } from "../../shiny/initedMethods";
|
||||
import { renderContentAsync } from "../../shiny/render";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
|
||||
class HtmlOutputBinding extends OutputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement> {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import $ from "jquery";
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
import {
|
||||
createBrushHandler,
|
||||
createClickHandler,
|
||||
@@ -7,17 +8,16 @@ import {
|
||||
disableDrag,
|
||||
initCoordmap,
|
||||
} from "../../imageutils";
|
||||
import type { CoordmapInit } from "../../imageutils/initCoordmap";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import {
|
||||
strToBool,
|
||||
getComputedLinkColor,
|
||||
getStyle,
|
||||
hasOwnProperty,
|
||||
strToBool,
|
||||
} from "../../utils";
|
||||
import { IEVersion, isIE } from "../../utils/browser";
|
||||
import { isIE, IEVersion } from "../../utils/browser";
|
||||
import type { CoordmapInit } from "../../imageutils/initCoordmap";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import { ifUndefined } from "../../utils/object";
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
|
||||
class ImageOutputBinding extends OutputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement> {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { TextOutputBinding } from "./text";
|
||||
import { BindingRegistry } from "../registry";
|
||||
import { DatatableOutputBinding } from "./datatable";
|
||||
import { DownloadLinkOutputBinding } from "./downloadlink";
|
||||
import { DatatableOutputBinding } from "./datatable";
|
||||
import { HtmlOutputBinding } from "./html";
|
||||
import { imageOutputBinding } from "./image";
|
||||
import { TextOutputBinding } from "./text";
|
||||
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from "jquery";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import { asArray } from "../../utils";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
|
||||
class OutputBinding {
|
||||
name!: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { ShinyClientError } from "../shiny/error";
|
||||
|
||||
const buttonStyles = css`
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import $ from "jquery";
|
||||
import { triggerFileInputChanged } from "../events/inputChanged";
|
||||
import { getFileInputBinding } from "../shiny/initedMethods";
|
||||
import type { ShinyApp } from "../shiny/shinyapp";
|
||||
import { $escape } from "../utils";
|
||||
import type { ShinyApp } from "../shiny/shinyapp";
|
||||
import { getFileInputBinding } from "../shiny/initedMethods";
|
||||
|
||||
type JobId = string;
|
||||
type UploadUrl = string;
|
||||
@@ -180,7 +180,7 @@ class FileUploader extends FileProcessor {
|
||||
onFile(file: File, cont: () => void): void {
|
||||
this.onProgress(file, 0);
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
$.ajax(this.uploadUrl, {
|
||||
type: "POST",
|
||||
cache: false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import $ from "jquery";
|
||||
import { equal, isnan, mapValues, roundSignif } from "../utils";
|
||||
import type { Coordmap } from "./initCoordmap";
|
||||
import { findOrigin } from "./initCoordmap";
|
||||
import { equal, isnan, mapValues, roundSignif } from "../utils";
|
||||
import type { Panel } from "./initPanelScales";
|
||||
|
||||
import type { Offset } from "./findbox";
|
||||
@@ -656,4 +656,5 @@ function createBrush(
|
||||
}
|
||||
|
||||
export { createBrush };
|
||||
|
||||
export type { Bounds, BrushOpts, BoundsCss };
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import $ from "jquery";
|
||||
import { imageOutputBinding } from "../bindings/output/image";
|
||||
import type { InputRatePolicy } from "../inputPolicies";
|
||||
import { shinySetInputValue } from "../shiny/initedMethods";
|
||||
import { Debouncer, Throttler } from "../time";
|
||||
import type { Bounds, BoundsCss, BrushOpts } from "./createBrush";
|
||||
import { createBrush } from "./createBrush";
|
||||
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.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { createBrush } from "./createBrush";
|
||||
import { createClickInfo } from "./createClickInfo";
|
||||
import {
|
||||
createBrushHandler,
|
||||
createClickHandler,
|
||||
createHoverHandler,
|
||||
createBrushHandler,
|
||||
} from "./createHandlers";
|
||||
import { disableDrag } from "./disableDrag";
|
||||
import { findBox } from "./findbox";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import $ from "jquery";
|
||||
import { shinySetInputValue } from "../shiny/initedMethods";
|
||||
import { mapValues } from "../utils";
|
||||
import type { Bounds } from "./createBrush";
|
||||
import type { Offset } from "./findbox";
|
||||
import type { Bounds } from "./createBrush";
|
||||
import type { Panel, PanelInit } from "./initPanelScales";
|
||||
import { initPanelScales } from "./initPanelScales";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Map a value x from a domain to a range. If clip is true, clip it to the
|
||||
|
||||
import type { Offset } from "./findbox";
|
||||
import { mapValues } from "../utils";
|
||||
import type { Bounds } from "./createBrush";
|
||||
import type { Offset } from "./findbox";
|
||||
|
||||
// range.
|
||||
function mapLinear(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from "jquery";
|
||||
|
||||
import { isIE, setIEVersion, setIsIE, setIsQt } from "../utils/browser";
|
||||
import { isIE, setIsQt, setIsIE, setIEVersion } from "../utils/browser";
|
||||
import { userAgent } from "../utils/userAgent";
|
||||
|
||||
function getIEVersion() {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { determineBrowserInfo } from "./browser";
|
||||
import { disableFormSubmission } from "./disableForm";
|
||||
import { trackHistory } from "./history";
|
||||
import { determineBrowserInfo } from "./browser";
|
||||
|
||||
import { windowShiny } from "../window/libraries";
|
||||
import { setShiny } from "../shiny";
|
||||
import { setUserAgent } from "../utils/userAgent";
|
||||
import { windowShiny } from "../window/libraries";
|
||||
import { windowUserAgent } from "../window/userAgent";
|
||||
|
||||
import { initReactlog } from "../shiny/reactlog";
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { InputBatchSender } from "./inputBatchSender";
|
||||
import { InputDeferDecorator } from "./inputDeferDecorator";
|
||||
import { InputEventDecorator } from "./inputEventDecorator";
|
||||
import { InputNoResendDecorator } from "./inputNoResendDecorator";
|
||||
import { InputEventDecorator } from "./inputEventDecorator";
|
||||
import { InputRateDecorator } from "./inputRateDecorator";
|
||||
import { InputDeferDecorator } from "./inputDeferDecorator";
|
||||
import { InputValidateDecorator } from "./inputValidateDecorator";
|
||||
|
||||
import type { EventPriority, InputPolicy } from "./inputPolicy";
|
||||
import type { InputPolicy } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import type { InputRatePolicy } from "./inputRatePolicy";
|
||||
|
||||
export {
|
||||
@@ -16,4 +17,5 @@ export {
|
||||
InputDeferDecorator,
|
||||
InputValidateDecorator,
|
||||
};
|
||||
|
||||
export type { InputPolicy, EventPriority, InputRatePolicy };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ShinyApp } from "../shiny/shinyapp";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { ShinyApp } from "../shiny/shinyapp";
|
||||
|
||||
// Schedules data to be sent to shinyapp at the next setTimeout(0).
|
||||
// Batches multiple input calls into one websocket message.
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import { hasDefinedProperty } from "../utils";
|
||||
import type {
|
||||
EventPriority,
|
||||
InputPolicy,
|
||||
InputPolicyOpts,
|
||||
} from "./inputPolicy";
|
||||
|
||||
class InputDeferDecorator implements InputPolicy {
|
||||
pendingInput: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from "jquery";
|
||||
import type { ShinyEventInputChanged } from "../events/shinyEvents";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { ShinyEventInputChanged } from "../events/shinyEvents";
|
||||
import { splitInputNameType } from "./splitInputNameType";
|
||||
|
||||
class InputEventDecorator implements InputPolicy {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { hasDefinedProperty } from "../utils";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import { hasDefinedProperty } from "../utils";
|
||||
import { splitInputNameType } from "./splitInputNameType";
|
||||
|
||||
type LastSentValues = { [key: string]: { [key: string]: string } };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Debouncer, Invoker, Throttler } from "../time";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { InputRatePolicy } from "./inputRatePolicy";
|
||||
import { Debouncer, Invoker, Throttler } from "../time";
|
||||
import { splitInputNameType } from "./splitInputNameType";
|
||||
import type { InputRatePolicy } from "./inputRatePolicy";
|
||||
|
||||
type RatePolicyModes = "debounce" | "direct" | "throttle";
|
||||
|
||||
@@ -66,4 +66,5 @@ class InputRateDecorator implements InputPolicy {
|
||||
}
|
||||
|
||||
export { InputRateDecorator };
|
||||
|
||||
export type { RatePolicyModes };
|
||||
|
||||
@@ -6,9 +6,9 @@ import type {
|
||||
InputRateDecorator,
|
||||
InputValidateDecorator,
|
||||
} from "../inputPolicies";
|
||||
import { ShinyClientError } from "./error";
|
||||
import { shinyAppBindOutput, shinyAppUnbindOutput } from "./initedMethods";
|
||||
import { sendImageSizeFns } from "./sendImageSize";
|
||||
import { ShinyClientError } from "./error";
|
||||
|
||||
type BindScope = HTMLElement | JQuery<HTMLElement>;
|
||||
|
||||
@@ -320,10 +320,6 @@ async function bindOutputs(
|
||||
$el.addClass("shiny-bound-output");
|
||||
if (!$el.attr("aria-live")) $el.attr("aria-live", "polite");
|
||||
|
||||
if (Shiny.shinyapp?.$outputProgress.isRecalculating(id)) {
|
||||
bindingAdapter.showProgress(true);
|
||||
}
|
||||
|
||||
bindingsRegistry.addBinding(id, "output");
|
||||
$el.trigger({
|
||||
type: "shiny:bound",
|
||||
@@ -464,4 +460,5 @@ async function bindAll(
|
||||
}
|
||||
|
||||
export { unbindAll, bindAll, _bindAll };
|
||||
|
||||
export type { BindScope, BindInputsCtx };
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
import $ from "jquery";
|
||||
|
||||
import { InputBinding, OutputBinding } from "../bindings";
|
||||
import { initInputBindings } from "../bindings/input";
|
||||
import { initOutputBindings } from "../bindings/output";
|
||||
import { showErrorInClientConsole } from "../components/errorConsole";
|
||||
import { resetBrush } from "../imageutils/resetBrush";
|
||||
import { $escape, compareVersion } from "../utils";
|
||||
import { showNotification, removeNotification } from "./notifications";
|
||||
import { showModal, removeModal } from "./modal";
|
||||
import { showReconnectDialog, hideReconnectDialog } from "./reconnectDialog";
|
||||
import {
|
||||
renderContentAsync,
|
||||
renderContent,
|
||||
renderDependenciesAsync,
|
||||
renderDependencies,
|
||||
renderHtmlAsync,
|
||||
renderHtml,
|
||||
} from "./render";
|
||||
import { initShiny } from "./init";
|
||||
import type {
|
||||
shinyBindAll,
|
||||
shinyForgetLastInputValue,
|
||||
shinyInitializeInputs,
|
||||
shinySetInputValue,
|
||||
shinyInitializeInputs,
|
||||
shinyUnbindAll,
|
||||
} from "./initedMethods";
|
||||
import { setFileInputBinding } from "./initedMethods";
|
||||
import { removeModal, showModal } from "./modal";
|
||||
import { removeNotification, showNotification } from "./notifications";
|
||||
import { hideReconnectDialog, showReconnectDialog } from "./reconnectDialog";
|
||||
import {
|
||||
renderContent,
|
||||
renderContentAsync,
|
||||
renderDependencies,
|
||||
renderDependenciesAsync,
|
||||
renderHtml,
|
||||
renderHtmlAsync,
|
||||
} from "./render";
|
||||
import type { Handler, ShinyApp } from "./shinyapp";
|
||||
import { addCustomMessageHandler } from "./shinyapp";
|
||||
import { initInputBindings } from "../bindings/input";
|
||||
import { initOutputBindings } from "../bindings/output";
|
||||
import { showErrorInClientConsole } from "../components/errorConsole";
|
||||
|
||||
interface Shiny {
|
||||
version: string;
|
||||
@@ -138,4 +138,5 @@ function setShiny(windowShiny_: Shiny): void {
|
||||
}
|
||||
|
||||
export { windowShiny, setShiny };
|
||||
|
||||
export type { Shiny };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import $ from "jquery";
|
||||
import type { Shiny } from ".";
|
||||
import type { InputPolicy } from "../inputPolicies";
|
||||
import {
|
||||
InputBatchSender,
|
||||
InputDeferDecorator,
|
||||
@@ -9,7 +8,7 @@ import {
|
||||
InputRateDecorator,
|
||||
InputValidateDecorator,
|
||||
} from "../inputPolicies";
|
||||
import type { InputPolicyOpts } from "../inputPolicies/inputPolicy";
|
||||
import type { InputPolicy } from "../inputPolicies";
|
||||
import { addDefaultInputOpts } from "../inputPolicies/inputValidateDecorator";
|
||||
import { debounce, Debouncer } from "../time";
|
||||
import {
|
||||
@@ -19,13 +18,14 @@ import {
|
||||
mapValues,
|
||||
pixelRatio,
|
||||
} from "../utils";
|
||||
import type { BindInputsCtx, BindScope } from "./bind";
|
||||
import { bindAll, unbindAll, _bindAll } from "./bind";
|
||||
import type { BindInputsCtx, BindScope } from "./bind";
|
||||
import { setShinyObj } from "./initedMethods";
|
||||
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"
|
||||
async function initShiny(windowShiny: Shiny): Promise<void> {
|
||||
|
||||
@@ -3,7 +3,8 @@ import $ from "jquery";
|
||||
import { $escape, randomId } from "../utils";
|
||||
import { shinyUnbindAll } from "./initedMethods";
|
||||
import type { HtmlDep } from "./render";
|
||||
import { renderContentAsync, renderDependenciesAsync } from "./render";
|
||||
import { renderDependenciesAsync } from "./render";
|
||||
import { renderContentAsync } from "./render";
|
||||
|
||||
// Milliseconds to fade in or out
|
||||
const fadeDuration = 250;
|
||||
|
||||
@@ -1,280 +0,0 @@
|
||||
/*
|
||||
* A state machine for tracking Shiny output progress.
|
||||
*
|
||||
* Although there are a handful of possible states, the ultimate goal here is to
|
||||
* be able to say whether a given output `isRecalculating()` or not (and thus,
|
||||
* whether we should show progress indication or not).
|
||||
*
|
||||
* The diagram below depicts the state machine. Each node represents a possible
|
||||
* state and each edge represents a server-->client message that moves outputs
|
||||
* from one state to another. If a node name is all caps, then the output should
|
||||
* be showing a busy state when visible (i.e., `binding.showProgress(true)`).
|
||||
*
|
||||
* A more polished SVG version of this diagram can be found here:
|
||||
* https://github.com/rstudio/shiny/blob/main/inst/diagrams/outputProgressStateMachine.svg
|
||||
*
|
||||
* +---------+ recalculating +---------+
|
||||
* | INITIAL +--------------->| RUNNING |<----------------+
|
||||
* +---------+ +---+-----+ |
|
||||
* +-----------/ | |
|
||||
* | recalculated |
|
||||
* | | |
|
||||
* | +--v---+---------------+ |
|
||||
* | +--+ IDLE +--+-------+ | |
|
||||
* | | +------+ | | | |
|
||||
* 1 | 2| 3| 4| | |
|
||||
* v v v v | |
|
||||
* +------------+ +------+ +-----+ +-----+ | |
|
||||
* | PERSISTENT | |cancel| |value| |error| | |
|
||||
* +-------+----+ +---+--+ +-+---+ +-+---+ | |
|
||||
* | 5| 5| | | |
|
||||
* 5| v v 5| | |
|
||||
* | +-------------+ | | |
|
||||
* +------>| INVALIDATED |<-----+ | |
|
||||
* +-----+-------+<-----------+ |
|
||||
* | |
|
||||
* | recalculating |
|
||||
* +-----------------------+
|
||||
*
|
||||
* 1. {progress: {type: "binding", message: {persistent: true}}}
|
||||
* 2. No message
|
||||
* 3. Value
|
||||
* 4. Error
|
||||
* 5. {progress: {type: "binding"}}
|
||||
*/
|
||||
|
||||
// The possible states of a given output.
|
||||
enum OutputStates {
|
||||
Initial = "initial",
|
||||
Running = "running",
|
||||
Idle = "idle",
|
||||
Value = "value",
|
||||
Error = "error",
|
||||
Cancel = "cancel",
|
||||
Persistent = "persistent",
|
||||
Invalidated = "invalidated",
|
||||
}
|
||||
|
||||
// Server->client messages that have an impact on output progress state.
|
||||
// These derive from the Session's defineOutput() method.
|
||||
type RecalculatingMessage = {
|
||||
recalculating: {
|
||||
name: string;
|
||||
status: "recalculated" | "recalculating";
|
||||
};
|
||||
};
|
||||
|
||||
type FlushMessage = {
|
||||
errors: { [key: string]: unknown };
|
||||
values: { [key: string]: unknown };
|
||||
inputMessages: [];
|
||||
};
|
||||
|
||||
type ProgressMessage = {
|
||||
progress: {
|
||||
type: "binding";
|
||||
message: {
|
||||
id: string;
|
||||
persistent: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// A generic server->client message type.
|
||||
type Message = { [key: string]: unknown };
|
||||
|
||||
// The state machine that tracks the progress of outputs in a Shiny app.
|
||||
class OutputProgressReporter {
|
||||
private outputStates: Map<string, OutputStates> = new Map();
|
||||
// A map of outputs that have changed their progress status since the last call to takeChanges().
|
||||
// The value is true if the output is recalculating, and false otherwise.
|
||||
private changedOutputs: Map<string, boolean> = new Map();
|
||||
|
||||
takeChanges(): Map<string, boolean> {
|
||||
const result = this.changedOutputs;
|
||||
this.changedOutputs = new Map();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns whether the output is recalculating or not.
|
||||
isRecalculating(name: string): boolean {
|
||||
const state = this.#getState(name);
|
||||
|
||||
// The blue nodes in the state machine diagram
|
||||
const recalculatingStates = [
|
||||
OutputStates.Initial,
|
||||
OutputStates.Running,
|
||||
OutputStates.Idle,
|
||||
OutputStates.Persistent,
|
||||
OutputStates.Invalidated,
|
||||
];
|
||||
|
||||
return recalculatingStates.includes(state);
|
||||
}
|
||||
|
||||
// Update output state based on the message received from the server.
|
||||
// Note that any message can be passed to this method, but only the
|
||||
// messages that are relevant to output progress do anything to the state.
|
||||
updateStateFromMessage(message: Message): void {
|
||||
if (isRecalculatingMessage(message)) {
|
||||
// The "1st level" of the state machine diagram
|
||||
this.#updateStateFromRecalculating(message);
|
||||
}
|
||||
|
||||
if (isFlushMessage(message)) {
|
||||
// The "2nd level" of the state machine diagram
|
||||
this.#updateStateFromFlush(message);
|
||||
}
|
||||
|
||||
if (isProgressMessage(message)) {
|
||||
// The "3rd level" of the state machine diagram
|
||||
this.#updateStateFromProgress(message);
|
||||
}
|
||||
}
|
||||
|
||||
#updateStateFromRecalculating(message: RecalculatingMessage): void {
|
||||
const { name, status } = message.recalculating;
|
||||
|
||||
const state = this.#getState(name);
|
||||
|
||||
if (status === "recalculating") {
|
||||
switch (state) {
|
||||
case OutputStates.Initial:
|
||||
case OutputStates.Invalidated:
|
||||
this.#setState(name, OutputStates.Running);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Shiny server sent a message that the output '${name}' is recalculating,
|
||||
but the output is in an unexpected state of: '${state}'.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (status === "recalculated") {
|
||||
switch (state) {
|
||||
case OutputStates.Running:
|
||||
this.#setState(name, OutputStates.Idle);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Shiny server sent a message that the output '${name}' has been recalculated,
|
||||
but the output is in an unexpected state of: '${state}'.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#updateStateFromFlush(message: FlushMessage): void {
|
||||
for (const name in message.values) {
|
||||
this.#updateStateFromValueOrError(name, OutputStates.Value);
|
||||
}
|
||||
|
||||
for (const name in message.errors) {
|
||||
this.#updateStateFromValueOrError(name, OutputStates.Error);
|
||||
}
|
||||
|
||||
// Since req(F, cancelOutput = TRUE) doesn't send a message, we need to identify
|
||||
// the situation by looking for outputs that are still idle and move them to cancel.
|
||||
for (const [name, state] of this.outputStates) {
|
||||
switch (state) {
|
||||
case OutputStates.Idle:
|
||||
this.#setState(name, OutputStates.Cancel);
|
||||
break;
|
||||
case OutputStates.Value:
|
||||
case OutputStates.Error:
|
||||
case OutputStates.Cancel:
|
||||
case OutputStates.Persistent:
|
||||
case OutputStates.Invalidated: // If the output is suspended
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Shiny server sent a flush message, and after processing the values and errors,
|
||||
the output '${name}' has an unexpected ending state of: '${state}'.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#updateStateFromProgress(message: ProgressMessage): void {
|
||||
const { id, persistent } = message.progress.message;
|
||||
const state = this.#getState(id);
|
||||
if (persistent) {
|
||||
switch (state) {
|
||||
case OutputStates.Running:
|
||||
this.#setState(id, OutputStates.Persistent);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Shiny server has sent a 'persistent progress' message for ${id},
|
||||
but the output is in an unexpected state of: ${state}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
switch (state) {
|
||||
case OutputStates.Value:
|
||||
case OutputStates.Error:
|
||||
case OutputStates.Cancel:
|
||||
case OutputStates.Persistent:
|
||||
case OutputStates.Idle:
|
||||
this.#setState(id, OutputStates.Invalidated);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Shiny server has sent a progress message for ${id},
|
||||
but the output is in an unexpected state of: ${state}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When receiving values/errors as part of a flush message, outputs should generally
|
||||
// be moving from Idle to Value/Error state.
|
||||
#updateStateFromValueOrError(
|
||||
name: string,
|
||||
type: OutputStates.Error | OutputStates.Value
|
||||
): void {
|
||||
const state = this.#getState(name);
|
||||
switch (state) {
|
||||
case OutputStates.Idle:
|
||||
this.#setState(name, type);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Shiny server has sent a ${type} for the output '${name}',
|
||||
but the output is in an unexpected state of: '${state}'.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#getState(name: string): OutputStates {
|
||||
return this.outputStates.get(name) ?? OutputStates.Initial;
|
||||
}
|
||||
|
||||
#setState(name: string, state: OutputStates): void {
|
||||
const oldRecalc = this.isRecalculating(name);
|
||||
this.outputStates.set(name, state);
|
||||
const newRecalc = this.isRecalculating(name);
|
||||
if (oldRecalc !== newRecalc) {
|
||||
this.changedOutputs.set(name, newRecalc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Type guards
|
||||
function isRecalculatingMessage(x: Message): x is RecalculatingMessage {
|
||||
const m = x as RecalculatingMessage;
|
||||
return m.recalculating !== undefined;
|
||||
}
|
||||
|
||||
function isFlushMessage(x: Message): x is FlushMessage {
|
||||
const m = x as FlushMessage;
|
||||
return m.values !== undefined && m.errors !== undefined;
|
||||
}
|
||||
|
||||
function isProgressMessage(x: Message): x is ProgressMessage {
|
||||
const m = x as ProgressMessage;
|
||||
return m.progress !== undefined && m.progress.type === "binding";
|
||||
}
|
||||
|
||||
export { OutputProgressReporter };
|
||||
@@ -50,14 +50,13 @@ function initReactlog(): void {
|
||||
window.escape(shinyAppConfig().sessionId);
|
||||
|
||||
// send notification
|
||||
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
$.get(url, function (result: "marked" | void) {
|
||||
if (result !== "marked") return;
|
||||
|
||||
const html =
|
||||
'<span id="shiny-reactlog-mark-text">Marked time point in reactlog</span>';
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
||||
showNotification({
|
||||
html: html,
|
||||
closeButton: true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from "jquery";
|
||||
|
||||
import { removeNotification, showNotification } from "./notifications";
|
||||
import { showNotification, removeNotification } from "./notifications";
|
||||
|
||||
function updateTime(reconnectTime: number): void {
|
||||
const $time = $("#shiny-reconnect-time");
|
||||
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
} from "./initedMethods";
|
||||
import { sendImageSizeFns } from "./sendImageSize";
|
||||
|
||||
import type { WherePosition } from "./singletons";
|
||||
import { renderHtml as singletonsRenderHtml } from "./singletons";
|
||||
import type { WherePosition } from "./singletons";
|
||||
|
||||
// There are synchronous and asynchronous versions of the exported functions
|
||||
// renderContent(), renderHtml(), and renderDependencies(). This is because they
|
||||
|
||||
@@ -1,19 +1,5 @@
|
||||
import $ from "jquery";
|
||||
import type { InputBinding } from "../bindings";
|
||||
import type { OutputBindingAdapter } from "../bindings/outputAdapter";
|
||||
import { showErrorInClientConsole } from "../components/errorConsole";
|
||||
import type {
|
||||
ShinyEventError,
|
||||
ShinyEventMessage,
|
||||
ShinyEventUpdateInput,
|
||||
ShinyEventValue,
|
||||
} from "../events/shinyEvents";
|
||||
import type { UploadEndValue, UploadInitValue } from "../file/fileProcessor";
|
||||
import { resetBrush } from "../imageutils/resetBrush";
|
||||
import { $escape, hasOwnProperty, randomId, scopeExprToFunc } from "../utils";
|
||||
import { AsyncQueue } from "../utils/asyncQueue";
|
||||
import { isQt } from "../utils/browser";
|
||||
import { indirectEval } from "../utils/eval";
|
||||
import {
|
||||
getShinyCreateWebsocket,
|
||||
getShinyOnCustomMessage,
|
||||
@@ -21,14 +7,26 @@ import {
|
||||
shinyForgetLastInputValue,
|
||||
shinyUnbindAll,
|
||||
} from "./initedMethods";
|
||||
import { removeModal, showModal } from "./modal";
|
||||
import { removeNotification, showNotification } from "./notifications";
|
||||
import { hideReconnectDialog, showReconnectDialog } from "./reconnectDialog";
|
||||
import type { HtmlDep } from "./render";
|
||||
import { isQt } from "../utils/browser";
|
||||
import { showNotification, removeNotification } from "./notifications";
|
||||
import { showModal, removeModal } from "./modal";
|
||||
import { renderContentAsync, renderHtmlAsync } from "./render";
|
||||
import type { HtmlDep } from "./render";
|
||||
import { hideReconnectDialog, showReconnectDialog } from "./reconnectDialog";
|
||||
import { resetBrush } from "../imageutils/resetBrush";
|
||||
import type { OutputBindingAdapter } from "../bindings/outputAdapter";
|
||||
import type {
|
||||
ShinyEventError,
|
||||
ShinyEventMessage,
|
||||
ShinyEventValue,
|
||||
ShinyEventUpdateInput,
|
||||
} from "../events/shinyEvents";
|
||||
import type { InputBinding } from "../bindings";
|
||||
import { indirectEval } from "../utils/eval";
|
||||
import type { WherePosition } from "./singletons";
|
||||
|
||||
import { OutputProgressReporter } from "./outputProgress";
|
||||
import type { UploadInitValue, UploadEndValue } from "../file/fileProcessor";
|
||||
import { AsyncQueue } from "../utils/asyncQueue";
|
||||
import { showErrorInClientConsole } from "../components/errorConsole";
|
||||
|
||||
type ResponseValue = UploadEndValue | UploadInitValue;
|
||||
type Handler = (message: any) => Promise<void> | void;
|
||||
@@ -132,9 +130,7 @@ class ShinyApp {
|
||||
|
||||
// Output bindings
|
||||
$bindings: { [key: string]: OutputBindingAdapter } = {};
|
||||
|
||||
// Output progress states
|
||||
$outputProgress = new OutputProgressReporter();
|
||||
$persistentProgress: Set<string> = new Set();
|
||||
|
||||
// Cached values/errors
|
||||
$values: { [key: string]: any } = {};
|
||||
@@ -245,7 +241,7 @@ class ShinyApp {
|
||||
|
||||
// This launches the action queue loop, which just runs in the background,
|
||||
// so we don't need to await it.
|
||||
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
this.startActionQueueLoop();
|
||||
};
|
||||
socket.onmessage = (e) => {
|
||||
@@ -363,7 +359,6 @@ class ShinyApp {
|
||||
) {
|
||||
const delay = this.reconnectDelay.next();
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
||||
showReconnectDialog(delay);
|
||||
this.$scheduleReconnect(delay);
|
||||
}
|
||||
@@ -661,9 +656,6 @@ class ShinyApp {
|
||||
$(document).trigger(evt);
|
||||
if (evt.isDefaultPrevented()) return;
|
||||
|
||||
// Before passing the message to handlers, use it to update output progress state
|
||||
this.$outputProgress.updateStateFromMessage(evt.message);
|
||||
|
||||
// Send msgObj.foo and msgObj.bar to appropriate handlers
|
||||
await this._sendMessagesToHandlers(
|
||||
evt.message,
|
||||
@@ -695,17 +687,13 @@ class ShinyApp {
|
||||
}
|
||||
}
|
||||
|
||||
// Call showProgress() on any output bindings that have changed their
|
||||
// recalculating status since the last call to takeChanges().
|
||||
// Note that we only need to call this function when a "flush" (i.e. "values")
|
||||
// message or a "progress" message is received since these are the only
|
||||
// two types of messages that can change the recalculating status. For more,
|
||||
// see the state machine diagram in outputProgress.ts.
|
||||
private _updateProgress() {
|
||||
const changed = this.$outputProgress.takeChanges();
|
||||
for (const [name, recalculating] of changed.entries()) {
|
||||
if (hasOwnProperty(this.$bindings, name)) {
|
||||
this.$bindings[name].showProgress(recalculating);
|
||||
private _clearProgress() {
|
||||
for (const name in this.$bindings) {
|
||||
if (
|
||||
hasOwnProperty(this.$bindings, name) &&
|
||||
!this.$persistentProgress.has(name)
|
||||
) {
|
||||
this.$bindings[name].showProgress(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,10 +704,11 @@ class ShinyApp {
|
||||
// * However, `_sendMessagesToHandlers()` will adjust the `this` context to the same _`this`_.
|
||||
|
||||
addMessageHandler("values", async (message: { [key: string]: any }) => {
|
||||
this._updateProgress();
|
||||
this._clearProgress();
|
||||
|
||||
for (const key in message) {
|
||||
if (hasOwnProperty(message, key)) {
|
||||
this.$persistentProgress.delete(key);
|
||||
await this.receiveOutput(key, message[key]);
|
||||
}
|
||||
}
|
||||
@@ -730,6 +719,7 @@ class ShinyApp {
|
||||
(message: { [key: string]: ErrorsMessageValue }) => {
|
||||
for (const key in message) {
|
||||
if (hasOwnProperty(message, key)) {
|
||||
this.$persistentProgress.delete(key);
|
||||
this.receiveError(key, message[key]);
|
||||
}
|
||||
}
|
||||
@@ -799,9 +789,13 @@ class ShinyApp {
|
||||
| { type: "show"; message: Parameters<typeof showNotification>[0] }
|
||||
| { type: void }
|
||||
) => {
|
||||
if (message.type === "show") await showNotification(message.message);
|
||||
else if (message.type === "remove") removeNotification(message.message);
|
||||
else throw "Unkown notification type: " + message.type;
|
||||
if (message.type === "show") {
|
||||
await showNotification(message.message);
|
||||
} else if (message.type === "remove") {
|
||||
await Promise.resolve(() => removeNotification(message.message));
|
||||
} else {
|
||||
throw "Unknown notification type: " + message.type;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -813,10 +807,14 @@ class ShinyApp {
|
||||
| { type: "show"; message: Parameters<typeof showModal>[0] }
|
||||
| { type: void }
|
||||
) => {
|
||||
if (message.type === "show") await showModal(message.message);
|
||||
// For 'remove', message content isn't used
|
||||
else if (message.type === "remove") removeModal();
|
||||
else throw "Unkown modal type: " + message.type;
|
||||
if (message.type === "show") {
|
||||
await showModal(message.message);
|
||||
} else if (message.type === "remove") {
|
||||
// For 'remove', message content isn't used
|
||||
await Promise.resolve(() => removeModal());
|
||||
} else {
|
||||
throw "Unknown modal type: " + message.type;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1435,9 +1433,13 @@ class ShinyApp {
|
||||
binding: binding,
|
||||
name: key,
|
||||
});
|
||||
if (binding.showProgress) binding.showProgress(true);
|
||||
if (message.persistent) {
|
||||
this.$persistentProgress.add(key);
|
||||
} else {
|
||||
this.$persistentProgress.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
this._updateProgress();
|
||||
},
|
||||
|
||||
// Open a page-level progress bar
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { debounce, Debouncer } from "./debounce";
|
||||
import { Debouncer, debounce } from "./debounce";
|
||||
import { Invoker } from "./invoke";
|
||||
import { Throttler } from "./throttle";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import $ from "jquery";
|
||||
import { windowDevicePixelRatio } from "../window/pixelRatio";
|
||||
import type { MapValuesUnion, MapWithResult } from "./extraTypes";
|
||||
import { hasDefinedProperty, hasOwnProperty } from "./object";
|
||||
import { hasOwnProperty, hasDefinedProperty } from "./object";
|
||||
|
||||
function escapeHTML(str: string): string {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
@@ -14,7 +14,6 @@ function escapeHTML(str: string): string {
|
||||
"'": "'",
|
||||
"/": "/",
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
|
||||
return str.replace(/[&<>'"/]/g, function (m) {
|
||||
return escaped[m] as string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { CheckedHTMLElement } from "./checkbox";
|
||||
import { InputBinding } from "./inputBinding";
|
||||
import type { CheckedHTMLElement } from "./checkbox";
|
||||
type CheckboxGroupHTMLElement = CheckedHTMLElement;
|
||||
type ValueLabelObject = {
|
||||
value: HTMLInputElement["value"];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
declare class DatatableOutputBinding extends OutputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement>;
|
||||
onValueError(el: HTMLElement, err: ErrorsMessageValue): void;
|
||||
|
||||
@@ -2,6 +2,5 @@ import { OutputBinding } from "./outputBinding";
|
||||
declare class DownloadLinkOutputBinding extends OutputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement>;
|
||||
renderValue(el: HTMLElement, data: string): void;
|
||||
showProgress(el: HTMLElement, show: boolean): void;
|
||||
}
|
||||
export { DownloadLinkOutputBinding };
|
||||
|
||||
2
srcts/types/src/bindings/output/html.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
import { renderContentAsync } from "../../shiny/render";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
declare class HtmlOutputBinding extends OutputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement>;
|
||||
onValueError(el: HTMLElement, err: ErrorsMessageValue): void;
|
||||
|
||||
2
srcts/types/src/bindings/output/image.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
import type { CoordmapInit } from "../../imageutils/initCoordmap";
|
||||
import type { ErrorsMessageValue } from "../../shiny/shinyapp";
|
||||
import { OutputBinding } from "./outputBinding";
|
||||
declare class ImageOutputBinding extends OutputBinding {
|
||||
find(scope: HTMLElement): JQuery<HTMLElement>;
|
||||
renderValue(el: HTMLElement, data: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/// <reference types="jquery" />
|
||||
import type { Bounds, BoundsCss, BrushOpts } from "./createBrush";
|
||||
import type { BoundsCss, Bounds, BrushOpts } from "./createBrush";
|
||||
import type { Offset } from "./findbox";
|
||||
import type { Coordmap } from "./initCoordmap";
|
||||
import type { Panel } from "./initPanelScales";
|
||||
|
||||
2
srcts/types/src/imageutils/index.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
import { createBrush } from "./createBrush";
|
||||
import { createClickInfo } from "./createClickInfo";
|
||||
import { createBrushHandler, createClickHandler, createHoverHandler } from "./createHandlers";
|
||||
import { createClickHandler, createHoverHandler, createBrushHandler } from "./createHandlers";
|
||||
import { disableDrag } from "./disableDrag";
|
||||
import { findBox } from "./findbox";
|
||||
import { initCoordmap } from "./initCoordmap";
|
||||
|
||||
2
srcts/types/src/imageutils/initCoordmap.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
/// <reference types="jquery" />
|
||||
import type { Bounds } from "./createBrush";
|
||||
import type { Offset } from "./findbox";
|
||||
import type { Bounds } from "./createBrush";
|
||||
import type { Panel, PanelInit } from "./initPanelScales";
|
||||
declare function findOrigin($el: JQuery<HTMLElement>): Offset;
|
||||
type OffsetCss = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Bounds } from "./createBrush";
|
||||
import type { Offset } from "./findbox";
|
||||
import type { Bounds } from "./createBrush";
|
||||
type PanelInit = {
|
||||
domain: {
|
||||
top: number;
|
||||
|
||||
7
srcts/types/src/inputPolicies/index.d.ts
vendored
@@ -1,10 +1,11 @@
|
||||
import { InputBatchSender } from "./inputBatchSender";
|
||||
import { InputDeferDecorator } from "./inputDeferDecorator";
|
||||
import { InputEventDecorator } from "./inputEventDecorator";
|
||||
import { InputNoResendDecorator } from "./inputNoResendDecorator";
|
||||
import { InputEventDecorator } from "./inputEventDecorator";
|
||||
import { InputRateDecorator } from "./inputRateDecorator";
|
||||
import { InputDeferDecorator } from "./inputDeferDecorator";
|
||||
import { InputValidateDecorator } from "./inputValidateDecorator";
|
||||
import type { EventPriority, InputPolicy } from "./inputPolicy";
|
||||
import type { 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 };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ShinyApp } from "../shiny/shinyapp";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { ShinyApp } from "../shiny/shinyapp";
|
||||
declare class InputBatchSender implements InputPolicy {
|
||||
target: InputPolicy;
|
||||
shinyapp: ShinyApp;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { EventPriority, InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
import type { EventPriority } from "./inputPolicy";
|
||||
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
|
||||
declare class InputDeferDecorator implements InputPolicy {
|
||||
pendingInput: {
|
||||
[key: string]: {
|
||||
|
||||
14
srcts/types/src/shiny/index.d.ts
vendored
@@ -1,15 +1,15 @@
|
||||
import { InputBinding, OutputBinding } from "../bindings";
|
||||
import { initInputBindings } from "../bindings/input";
|
||||
import { initOutputBindings } from "../bindings/output";
|
||||
import { resetBrush } from "../imageutils/resetBrush";
|
||||
import { $escape, compareVersion } from "../utils";
|
||||
import type { shinyBindAll, shinyForgetLastInputValue, shinyInitializeInputs, shinySetInputValue, shinyUnbindAll } from "./initedMethods";
|
||||
import { removeModal, showModal } from "./modal";
|
||||
import { removeNotification, showNotification } from "./notifications";
|
||||
import { hideReconnectDialog, showReconnectDialog } from "./reconnectDialog";
|
||||
import { renderContent, renderContentAsync, renderDependencies, renderDependenciesAsync, renderHtml, renderHtmlAsync } from "./render";
|
||||
import { showNotification, removeNotification } from "./notifications";
|
||||
import { showModal, removeModal } from "./modal";
|
||||
import { showReconnectDialog, hideReconnectDialog } from "./reconnectDialog";
|
||||
import { renderContentAsync, renderContent, renderDependenciesAsync, renderDependencies, renderHtmlAsync, renderHtml } from "./render";
|
||||
import type { shinyBindAll, shinyForgetLastInputValue, shinySetInputValue, shinyInitializeInputs, shinyUnbindAll } from "./initedMethods";
|
||||
import type { Handler, ShinyApp } from "./shinyapp";
|
||||
import { addCustomMessageHandler } from "./shinyapp";
|
||||
import { initInputBindings } from "../bindings/input";
|
||||
import { initOutputBindings } from "../bindings/output";
|
||||
interface Shiny {
|
||||
version: string;
|
||||
$escape: typeof $escape;
|
||||
|
||||
12
srcts/types/src/shiny/outputProgress.d.ts
vendored
@@ -1,12 +0,0 @@
|
||||
type Message = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
declare class OutputProgressReporter {
|
||||
#private;
|
||||
private outputStates;
|
||||
private changedOutputs;
|
||||
takeChanges(): Map<string, boolean>;
|
||||
isRecalculating(name: string): boolean;
|
||||
updateStateFromMessage(message: Message): void;
|
||||
}
|
||||
export { OutputProgressReporter };
|
||||
2
srcts/types/src/shiny/render.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
import type { BindScope } from "./bind";
|
||||
import type { WherePosition } from "./singletons";
|
||||
import { renderHtml as singletonsRenderHtml } from "./singletons";
|
||||
import type { WherePosition } from "./singletons";
|
||||
declare function renderContentAsync(el: BindScope, content: string | {
|
||||
html: string;
|
||||
deps?: HtmlDep[];
|
||||
|
||||
7
srcts/types/src/shiny/shinyapp.d.ts
vendored
@@ -1,7 +1,6 @@
|
||||
import type { OutputBindingAdapter } from "../bindings/outputAdapter";
|
||||
import type { UploadEndValue, UploadInitValue } from "../file/fileProcessor";
|
||||
import type { UploadInitValue, UploadEndValue } from "../file/fileProcessor";
|
||||
import { AsyncQueue } from "../utils/asyncQueue";
|
||||
import { OutputProgressReporter } from "./outputProgress";
|
||||
type ResponseValue = UploadEndValue | UploadInitValue;
|
||||
type Handler = (message: any) => Promise<void> | void;
|
||||
type ShinyWebSocket = WebSocket & {
|
||||
@@ -31,7 +30,7 @@ declare class ShinyApp {
|
||||
$bindings: {
|
||||
[key: string]: OutputBindingAdapter;
|
||||
};
|
||||
$outputProgress: OutputProgressReporter;
|
||||
$persistentProgress: Set<string>;
|
||||
$values: {
|
||||
[key: string]: any;
|
||||
};
|
||||
@@ -76,7 +75,7 @@ declare class ShinyApp {
|
||||
$updateConditionals(): void;
|
||||
dispatchMessage(data: ArrayBufferLike | string): Promise<void>;
|
||||
private _sendMessagesToHandlers;
|
||||
private _updateProgress;
|
||||
private _clearProgress;
|
||||
private _init;
|
||||
progressHandlers: {
|
||||
binding: (this: ShinyApp, message: {
|
||||
|
||||