Compare commits
62 Commits
py-shiny
...
more-spinn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f4bd63dbf | ||
|
|
62250b751d | ||
|
|
65a3536102 | ||
|
|
f6ef2e39d1 | ||
|
|
0f99fba328 | ||
|
|
9fb9004fa1 | ||
|
|
a693096684 | ||
|
|
c4fa6a74a1 | ||
|
|
439f48ea4b | ||
|
|
9b78f7b706 | ||
|
|
f7ab2be2a3 | ||
|
|
4348aaf717 | ||
|
|
f7ec5acda5 | ||
|
|
2872c87e32 | ||
|
|
53edf198ae | ||
|
|
5c73e0195c | ||
|
|
8238b299af | ||
|
|
5c3430d96f | ||
|
|
ecb591f2e1 | ||
|
|
4e2e373f07 | ||
|
|
0e5baf01eb | ||
|
|
9c84bff757 | ||
|
|
3d444d3ec3 | ||
|
|
397fc6eff7 | ||
|
|
6167c1dfd7 | ||
|
|
c40f9f1de8 | ||
|
|
a0f3629bad | ||
|
|
7144e5cf74 | ||
|
|
4cc31df40d | ||
|
|
8e37d45948 | ||
|
|
c11f120bb9 | ||
|
|
950c63049b | ||
|
|
3edf9bfad8 | ||
|
|
420a2c054c | ||
|
|
5e566a057d | ||
|
|
edd1db78e3 | ||
|
|
47526a769a | ||
|
|
0474eeeead | ||
|
|
e8cdc78f0f | ||
|
|
7742b652ba | ||
|
|
7ed68ed927 | ||
|
|
ac06350e08 | ||
|
|
43698f0860 | ||
|
|
c73e1a21b8 | ||
|
|
d855468398 | ||
|
|
b8efd88448 | ||
|
|
a8c6065b9f | ||
|
|
12a8b228d9 | ||
|
|
47fb562151 | ||
|
|
f0059b71e5 | ||
|
|
89aaa977e8 | ||
|
|
ae308e03ad | ||
|
|
c1a1542cfe | ||
|
|
3c4a908773 | ||
|
|
e2b7f91138 | ||
|
|
c73978cdd5 | ||
|
|
6760c31818 | ||
|
|
781ceaaa5c | ||
|
|
fff283648b | ||
|
|
f71f1256b8 | ||
|
|
f26b1335d8 | ||
|
|
370ba1f288 |
@@ -1,7 +1,7 @@
|
||||
Package: shiny
|
||||
Type: Package
|
||||
Title: Web Application Framework for R
|
||||
Version: 1.8.0.9000
|
||||
Version: 1.8.1.9001
|
||||
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"),
|
||||
@@ -93,10 +93,10 @@ Imports:
|
||||
glue (>= 1.3.2),
|
||||
bslib (>= 0.3.0),
|
||||
cachem,
|
||||
ellipsis,
|
||||
lifecycle (>= 0.2.0)
|
||||
Suggests:
|
||||
datasets,
|
||||
DT,
|
||||
Cairo (>= 1.5-5),
|
||||
testthat (>= 3.0.0),
|
||||
knitr (>= 1.6),
|
||||
@@ -128,6 +128,8 @@ Collate:
|
||||
'map.R'
|
||||
'utils.R'
|
||||
'bootstrap.R'
|
||||
'busy-indicators-spinners.R'
|
||||
'busy-indicators.R'
|
||||
'cache-utils.R'
|
||||
'deprecated.R'
|
||||
'devmode.R'
|
||||
@@ -204,7 +206,7 @@ Collate:
|
||||
'version_selectize.R'
|
||||
'version_strftime.R'
|
||||
'viewer.R'
|
||||
RoxygenNote: 7.2.3
|
||||
RoxygenNote: 7.3.1
|
||||
Encoding: UTF-8
|
||||
Roxygen: list(markdown = TRUE)
|
||||
RdMacros: lifecycle
|
||||
|
||||
@@ -19,6 +19,7 @@ S3method("[[",shinyoutput)
|
||||
S3method("[[<-",reactivevalues)
|
||||
S3method("[[<-",shinyoutput)
|
||||
S3method("names<-",reactivevalues)
|
||||
S3method(as.list,Map)
|
||||
S3method(as.list,reactivevalues)
|
||||
S3method(as.shiny.appobj,character)
|
||||
S3method(as.shiny.appobj,list)
|
||||
@@ -43,6 +44,7 @@ S3method(bindEvent,reactiveExpr)
|
||||
S3method(bindEvent,shiny.render.function)
|
||||
S3method(format,reactiveExpr)
|
||||
S3method(format,reactiveVal)
|
||||
S3method(length,Map)
|
||||
S3method(names,reactivevalues)
|
||||
S3method(print,reactive)
|
||||
S3method(print,reactivevalues)
|
||||
@@ -76,6 +78,7 @@ export(br)
|
||||
export(browserViewer)
|
||||
export(brushOpts)
|
||||
export(brushedPoints)
|
||||
export(busyIndicatorOptions)
|
||||
export(callModule)
|
||||
export(captureStackTraces)
|
||||
export(checkboxGroupInput)
|
||||
@@ -189,6 +192,7 @@ export(onRestore)
|
||||
export(onRestored)
|
||||
export(onSessionEnded)
|
||||
export(onStop)
|
||||
export(onUnhandledError)
|
||||
export(outputOptions)
|
||||
export(p)
|
||||
export(pageWithSidebar)
|
||||
@@ -314,6 +318,7 @@ export(updateTextInput)
|
||||
export(updateVarSelectInput)
|
||||
export(updateVarSelectizeInput)
|
||||
export(urlModal)
|
||||
export(useBusyIndicators)
|
||||
export(validate)
|
||||
export(validateCssUnit)
|
||||
export(varSelectInput)
|
||||
@@ -333,8 +338,6 @@ import(httpuv)
|
||||
import(methods)
|
||||
import(mime)
|
||||
import(xtable)
|
||||
importFrom(ellipsis,check_dots_empty)
|
||||
importFrom(ellipsis,check_dots_unnamed)
|
||||
importFrom(fastmap,fastmap)
|
||||
importFrom(fastmap,is.key_missing)
|
||||
importFrom(fastmap,key_missing)
|
||||
@@ -392,6 +395,8 @@ importFrom(rlang,"fn_body<-")
|
||||
importFrom(rlang,"fn_fmls<-")
|
||||
importFrom(rlang,as_function)
|
||||
importFrom(rlang,as_quosure)
|
||||
importFrom(rlang,check_dots_empty)
|
||||
importFrom(rlang,check_dots_unnamed)
|
||||
importFrom(rlang,enexpr)
|
||||
importFrom(rlang,enquo)
|
||||
importFrom(rlang,enquo0)
|
||||
|
||||
40
NEWS.md
@@ -1,19 +1,47 @@
|
||||
# shiny (development version)
|
||||
|
||||
## Breaking changes
|
||||
|
||||
* Both `conditionalPanel()` and `uiOutput()` are now styled with `display: contents` by default in Shiny apps that use Bootstrap 5. This means that the elements they contain are positioned as if they were direct children of the parent container holding the `conditionalPanel()` or `uiOutput()`. This is probably what most users intend when they use these functions, but it may break apps that applied styles directly to the container elements created by these two functions. In that case, you may include CSS rules to set `display: block` for the `.shiny-panel-conditional` or `.shiny-html-output` classes. (#3957, #3960)
|
||||
|
||||
## New features and improvements
|
||||
|
||||
* Added an console that shows some errors in the browser. Also provide better error messages for duplicate input and output bindings. (#3931)
|
||||
* 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)
|
||||
|
||||
* Added a new `ExtendedTask` abstraction, for long-running asynchronous tasks that you don't want to block the rest of the app, or even the rest of the session. Designed to be used with new `bslib::input_task_button()` and `bslib::bind_task_button()` functions that help give user feedback and prevent extra button clicks. (#3958)
|
||||
## 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
|
||||
|
||||
* In v1.8.1, shiny.js starting throwing an error when input/output bindings have duplicate IDs. This error is now only thrown when `shiny::devmode(TRUE)` is enabled, so the issue is still made discoverable through the JS error console, but avoids unnecessarily breaking apps that happen to work with duplicate IDs. (#4019)
|
||||
|
||||
# shiny 1.8.1
|
||||
|
||||
## New features and improvements
|
||||
|
||||
* Added `ExtendedTask`, a new simple way to launch long-running asynchronous tasks that are truly non-blocking. That is, even _within_ a session, an `ExtendedTask` won't block the main thread from flushing the reactive graph (i.e., UI updates won't be blocked). `ExtendedTask` pairs nicely with new `bslib::input_task_button()` and `bslib::bind_task_button()` functions, which help give user feedback and prevent extra button clicks. (#3958)
|
||||
|
||||
* Added a JavaScript error dialog, reporting errors that previously were only discoverable by opening the browser's devtools open. Since this dialog is mainly useful for debugging and development, it must be enabled with `shiny::devmode()`. (#3931)
|
||||
|
||||
* `runExamples()` now uses the `{bslib}` package to generate a better looking result. It also gains a `package` argument so that other packages can leverage this same function to run Shiny app examples. For more, see `?runExamples`. (#3963, #4005)
|
||||
|
||||
* Added `onUnhandledError()` to register a function that will be called when an unhandled error occurs in a Shiny app. Note that this handler doesn't stop the error or prevent the session from closing, but it can be used to log the error or to clean up session-specific resources. (thanks @JohnCoene, #3993)
|
||||
|
||||
## Changes
|
||||
|
||||
* `renderDataTable()`/`dataTableOutput()` are officially deprecated in favor of [their `{DT}` equivalents](https://rstudio.github.io/DT/shiny.html). Migrating to `{DT}`, in most cases, just requires changing `renderDataTable()` to `DT::renderDT()` and `dataTableOutput()` to `DT::DTOutput()`. Also, to promote migration, when a recent version of `{DT}` is available, `renderDataTable()`/`dataTableOutput()` now automatically use their `{DT}` equivalent (and provide a message that they are doing so). If this happens to degrade an existing app, set `options(shiny.legacy.datatable = TRUE)` to get the old (i.e., non-`{DT}`) implementation. (#3998)
|
||||
|
||||
* Both `conditionalPanel()` and `uiOutput()` are now styled with `display: contents` by default in Shiny apps that use Bootstrap 5. This means that the elements they contain are positioned as if they were direct children of the parent container holding the `conditionalPanel()` or `uiOutput()`. This is probably what most users intend when they use these functions, but it may break apps that applied styles directly to the container elements created by these two functions. In that case, you may include CSS rules to set `display: block` for the `.shiny-panel-conditional` or `.shiny-html-output` classes. (#3957, #3960)
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* Notifications are now constrained to the width of the viewport for window widths smaller the default notification panel size. (#3949)
|
||||
|
||||
* Fixed #2392: `downloadButton()` now visibly returns its HTML tag so that it renders correctly in R Markdown and Quarto output. (Thanks to @fennovj, #2672)
|
||||
|
||||
* Calling `updateSelectizeInput()` with `choices` and `selected` now clears the current selection before updating the choices and selected value. (#3967)
|
||||
|
||||
* Loading a Shiny app in a package-like directory will no longer warn if autoloading is disabled by the presence of an `R/_disable_autoload.R` file. (Thanks to @krlmlr and @tanho63, #3513)
|
||||
|
||||
# shiny 1.8.0
|
||||
|
||||
## Breaking changes
|
||||
|
||||
@@ -453,7 +453,7 @@ utils::globalVariables(".GenericCallEnv", add = TRUE)
|
||||
#' bindEvent(input$go)
|
||||
#' # The cached, eventified reactive takes a reactive dependency on
|
||||
#' # input$go, but doesn't use it for the cache key. It uses input$x and
|
||||
#' # input$y for the cache key, but doesn't take a reactive depdency on
|
||||
#' # input$y for the cache key, but doesn't take a reactive dependency on
|
||||
#' # them, because the reactive dependency is superseded by addEvent().
|
||||
#'
|
||||
#' output$txt <- renderText(r())
|
||||
|
||||
@@ -551,7 +551,7 @@ restoreInput <- function(id, default) {
|
||||
#' `window.history.pushState(null, null, queryString)`.
|
||||
#'
|
||||
#' @param queryString The new query string to show in the location bar.
|
||||
#' @param mode When the query string is updated, should the the current history
|
||||
#' @param mode When the query string is updated, should the current history
|
||||
#' entry be replaced (default), or should a new history entry be pushed onto
|
||||
#' the history stack? The former should only be used in a live bookmarking
|
||||
#' context. The latter is useful if you want to navigate between states using
|
||||
|
||||
@@ -1118,17 +1118,17 @@ tableOutput <- function(outputId) {
|
||||
dataTableDependency <- list(
|
||||
htmlDependency(
|
||||
"datatables",
|
||||
"1.10.5",
|
||||
"1.10.22",
|
||||
src = "www/shared/datatables",
|
||||
package = "shiny",
|
||||
script = "js/jquery.dataTables.min.js"
|
||||
),
|
||||
htmlDependency(
|
||||
"datatables-bootstrap",
|
||||
"1.10.5",
|
||||
"1.10.22",
|
||||
src = "www/shared/datatables",
|
||||
package = "shiny",
|
||||
stylesheet = c("css/dataTables.bootstrap.css", "css/dataTables.extra.css"),
|
||||
stylesheet = "css/dataTables.bootstrap.css",
|
||||
script = "js/dataTables.bootstrap.js"
|
||||
)
|
||||
)
|
||||
@@ -1136,12 +1136,49 @@ dataTableDependency <- list(
|
||||
#' @rdname renderDataTable
|
||||
#' @export
|
||||
dataTableOutput <- function(outputId) {
|
||||
attachDependencies(
|
||||
div(id = outputId, class="shiny-datatable-output"),
|
||||
dataTableDependency
|
||||
)
|
||||
legacy <- useLegacyDataTable(from = "shiny::dataTableOutput()", to = "DT::DTOutput()")
|
||||
|
||||
if (legacy) {
|
||||
attachDependencies(
|
||||
div(id = outputId, class = "shiny-datatable-output"),
|
||||
dataTableDependency
|
||||
)
|
||||
} else {
|
||||
DT::DTOutput(outputId)
|
||||
}
|
||||
}
|
||||
|
||||
useLegacyDataTable <- function(from, to) {
|
||||
legacy <- getOption("shiny.legacy.datatable")
|
||||
|
||||
# If option has been set, user knows what they're doing
|
||||
if (!is.null(legacy)) {
|
||||
return(legacy)
|
||||
}
|
||||
|
||||
# If not set, use DT if a suitable version is available (and inform either way)
|
||||
hasDT <- is_installed("DT", "0.32.1")
|
||||
details <- NULL
|
||||
if (hasDT) {
|
||||
details <- paste0(c(
|
||||
"Since you have a suitable version of DT (>= v0.32.1), ",
|
||||
from,
|
||||
" will automatically use ",
|
||||
to,
|
||||
" under-the-hood.\n",
|
||||
"If this happens to break your app, set `options(shiny.legacy.datatable = TRUE)` ",
|
||||
"to get the legacy datatable implementation (or `FALSE` to squelch this message).\n"
|
||||
), collapse = "")
|
||||
}
|
||||
|
||||
details <- paste0(details, "See <https://rstudio.github.io/DT/shiny.html> for more information.")
|
||||
|
||||
shinyDeprecated("1.8.1", from, to, details)
|
||||
|
||||
!hasDT
|
||||
}
|
||||
|
||||
|
||||
#' Create an HTML output element
|
||||
#'
|
||||
#' Render a reactive output variable as HTML within an application page. The
|
||||
@@ -1238,23 +1275,29 @@ downloadButton <- function(outputId,
|
||||
class=NULL,
|
||||
...,
|
||||
icon = shiny::icon("download")) {
|
||||
aTag <- tags$a(id=outputId,
|
||||
class=paste('btn btn-default shiny-download-link', class),
|
||||
href='',
|
||||
target='_blank',
|
||||
download=NA,
|
||||
validateIcon(icon),
|
||||
label, ...)
|
||||
tags$a(id=outputId,
|
||||
class='btn btn-default shiny-download-link disabled',
|
||||
class=class,
|
||||
href='',
|
||||
target='_blank',
|
||||
download=NA,
|
||||
"aria-disabled"="true",
|
||||
tabindex="-1",
|
||||
validateIcon(icon),
|
||||
label, ...)
|
||||
}
|
||||
|
||||
#' @rdname downloadButton
|
||||
#' @export
|
||||
downloadLink <- function(outputId, label="Download", class=NULL, ...) {
|
||||
tags$a(id=outputId,
|
||||
class=paste(c('shiny-download-link', class), collapse=" "),
|
||||
class='shiny-download-link disabled',
|
||||
class=class,
|
||||
href='',
|
||||
target='_blank',
|
||||
download=NA,
|
||||
"aria-disabled"="true",
|
||||
tabindex="-1",
|
||||
label, ...)
|
||||
}
|
||||
|
||||
|
||||
13
R/busy-indicators-spinners.R
Normal file
@@ -0,0 +1,13 @@
|
||||
# Generated by tools/updateSpinners.R: do not edit by hand
|
||||
.spinner_types <-
|
||||
c("12-dots-scale-rotate", "180-ring-with-bg", "180-ring", "270-ring-with-bg",
|
||||
"270-ring", "3-dots-bounce", "3-dots-fade", "3-dots-move", "3-dots-rotate",
|
||||
"3-dots-scale-middle", "3-dots-scale", "6-dots-rotate", "6-dots-scale-middle",
|
||||
"6-dots-scale", "8-dots-rotate", "90-ring-with-bg", "90-ring",
|
||||
"bars-fade", "bars-rotate-fade", "bars-scale-fade", "bars-scale-middle",
|
||||
"bars-scale", "blocks-scale", "blocks-shuffle-2", "blocks-shuffle-3",
|
||||
"blocks-wave", "bouncing-ball", "clock", "dot-revolve", "eclipse-half",
|
||||
"eclipse", "gooey-balls-1", "gooey-balls-2", "pulse-2", "pulse-3",
|
||||
"pulse-multiple", "pulse-ring", "pulse-rings-2", "pulse-rings-3",
|
||||
"pulse-rings-multiple", "pulse", "ring-resize", "tadpole", "wifi-fade",
|
||||
"wifi", "wind-toy")
|
||||
231
R/busy-indicators.R
Normal file
@@ -0,0 +1,231 @@
|
||||
#' Enable/disable busy indication
|
||||
#'
|
||||
#' To enable/disable busy indicators, include the result of this function 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 (for future expansion).
|
||||
#' @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.
|
||||
#'
|
||||
#' To customize the appearance of the busy indicators, include the result of
|
||||
#' this function in the app's UI.
|
||||
#'
|
||||
#' @param ... Currently ignored (for future expansion).
|
||||
#' @param spinner_type The type of spinner to use for the busy indicator. This
|
||||
#' can be any of the spinner types from the `shiny` package.
|
||||
#'
|
||||
#' Available spinner types include:
|
||||
#' "`r paste0(.spinner_types, collapse = '", "')`".
|
||||
#'
|
||||
#' Alternatively, you can provide a path to a custom spinner SVG file. There
|
||||
#' are many free spinner SVGs available online, such as those from
|
||||
#' the [svg-spinners](https://github.com/n3r4zzurr0/svg-spinners) repository.
|
||||
#' @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 CSS selector for scoping the spinner customization.
|
||||
#' This can be useful if you want to have different spinners for different
|
||||
#' parts of the app. Defaults to the root document element. Use `NULL` to
|
||||
#' return inline styles for spinner customizations (note that you cannot
|
||||
#' customize both the pulse and the spinner without providing a selector).
|
||||
#' @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)
|
||||
#'
|
||||
#' ui <- page_fillable(
|
||||
#' useBusyIndicators(),
|
||||
#' busyIndicatorOptions(spinner_color = "orange"),
|
||||
#' 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)
|
||||
busyIndicatorOptions <- function(
|
||||
...,
|
||||
spinner_type = NULL,
|
||||
spinner_color = NULL,
|
||||
spinner_size = NULL,
|
||||
spinner_delay = NULL,
|
||||
spinner_selector = ":root",
|
||||
pulse_background = NULL,
|
||||
pulse_height = NULL,
|
||||
pulse_speed = NULL
|
||||
) {
|
||||
|
||||
rlang::check_dots_empty()
|
||||
|
||||
pulse_opts <- pulseOptions(
|
||||
background = pulse_background,
|
||||
height = pulse_height,
|
||||
speed = pulse_speed
|
||||
)
|
||||
|
||||
spinner_opts <- spinnerOptions(
|
||||
type = spinner_type,
|
||||
color = spinner_color,
|
||||
size = spinner_size,
|
||||
delay = spinner_delay,
|
||||
selector = spinner_selector
|
||||
)
|
||||
|
||||
if (!is.null(spinner_opts) && is.null(spinner_selector)) {
|
||||
if (!is.null(pulse_opts)) {
|
||||
abort(c(
|
||||
"`spinner_selector` must be provided when customizing both the pulse and the spinner.",
|
||||
"i" = "`spinner_selector = NULL` returns inline styles for spinner customizations."
|
||||
))
|
||||
}
|
||||
return(spinner_opts)
|
||||
}
|
||||
|
||||
dropNulls(tagList(spinner_opts, pulse_opts))
|
||||
}
|
||||
|
||||
spinnerOptions <- function(
|
||||
type = NULL,
|
||||
color = NULL,
|
||||
size = NULL,
|
||||
delay = NULL,
|
||||
selector = ":root"
|
||||
) {
|
||||
if (is.null(type) && is.null(color) && is.null(size) && is.null(delay)) {
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
type_is_file <- file.exists(type) && grepl("\\.svg$", type)
|
||||
if (!is.null(type)) {
|
||||
if (type_is_file) {
|
||||
stopifnot(file.exists(type) && grepl("\\.svg$", type))
|
||||
typeData <- readBin(type, "raw", n = file.info(type)$size)
|
||||
type_base64 <- rawToBase64(typeData)
|
||||
type <- sprintf("url('data:image/svg+xml;base64,%s')", type_base64)
|
||||
} else {
|
||||
type <- rlang::arg_match(type, .spinner_types)
|
||||
type <- sprintf("url('spinners/%s.svg')", type)
|
||||
}
|
||||
}
|
||||
|
||||
# Options controlled via CSS variables.
|
||||
css_vars <- htmltools::css(
|
||||
`--shiny-spinner-url` = type,
|
||||
`--shiny-spinner-color` = htmltools::parseCssColors(color),
|
||||
`--shiny-spinner-size` = htmltools::validateCssUnit(size),
|
||||
`--shiny-spinner-delay` = delay
|
||||
)
|
||||
|
||||
if (is.null(selector)) {
|
||||
return(css_vars)
|
||||
}
|
||||
|
||||
tags$style(HTML(paste0(selector, " {", css_vars, "}")))
|
||||
}
|
||||
|
||||
pulseOptions <- function(background = NULL, height = NULL, speed = NULL) {
|
||||
if (is.null(background) && is.null(height) && is.null(speed)) {
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
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",
|
||||
script = "busy-indicators.js"
|
||||
)
|
||||
}
|
||||
@@ -42,7 +42,7 @@
|
||||
#' session to immediately unblock and carry on with other user interactions.
|
||||
#'
|
||||
#' @export
|
||||
ExtendedTask <- R6Class("ExtendedTask", portable = TRUE,
|
||||
ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
|
||||
public = list(
|
||||
#' @description
|
||||
#' Creates a new `ExtendedTask` object. `ExtendedTask` should generally be
|
||||
|
||||
59
R/graph.R
@@ -1,31 +1,3 @@
|
||||
# Check that the version of an suggested package satisfies the requirements
|
||||
#
|
||||
# @param package The name of the suggested package
|
||||
# @param version The version of the package
|
||||
check_suggested <- function(package, version = NULL) {
|
||||
|
||||
if (is_installed(package, version)) {
|
||||
return()
|
||||
}
|
||||
|
||||
msg <- paste0(
|
||||
sQuote(package),
|
||||
if (is.na(version %||% NA)) "" else paste0("(>= ", version, ")"),
|
||||
" must be installed for this functionality."
|
||||
)
|
||||
|
||||
if (interactive()) {
|
||||
message(msg, "\nWould you like to install it?")
|
||||
if (utils::menu(c("Yes", "No")) == 1) {
|
||||
return(utils::install.packages(package))
|
||||
}
|
||||
}
|
||||
|
||||
stop(msg, call. = FALSE)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# domain is like session
|
||||
|
||||
@@ -110,34 +82,15 @@ renderReactlog <- function(sessionToken = NULL, time = TRUE) {
|
||||
time = time
|
||||
)
|
||||
}
|
||||
|
||||
check_reactlog <- function() {
|
||||
check_suggested("reactlog", reactlog_version())
|
||||
}
|
||||
# read reactlog version from description file
|
||||
# prevents version mismatch in code and description file
|
||||
reactlog_version <- local({
|
||||
version <- NULL
|
||||
function() {
|
||||
if (!is.null(version)) return(version)
|
||||
|
||||
desc <- read.dcf(system_file("DESCRIPTION", package = "shiny"))
|
||||
suggests <- desc[1,"Suggests"][[1]]
|
||||
suggests_pkgs <- strsplit(suggests, "\n")[[1]]
|
||||
|
||||
reactlog_info <- suggests_pkgs[grepl("reactlog", suggests_pkgs)]
|
||||
if (length(reactlog_info) == 0) {
|
||||
stop("reactlog can not be found in shiny DESCRIPTION file")
|
||||
}
|
||||
|
||||
reactlog_info <- sub("^[^\\(]*\\(", "", reactlog_info)
|
||||
reactlog_info <- sub("\\)[^\\)]*$", "", reactlog_info)
|
||||
reactlog_info <- sub("^[>= ]*", "", reactlog_info)
|
||||
|
||||
version <<- package_version(reactlog_info)
|
||||
version
|
||||
if (!is_installed("reactlog", reactlog_min_version)) {
|
||||
rlang::check_installed("reactlog", reactlog_min_version)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
# Should match the (suggested) version in DESCRIPTION file
|
||||
reactlog_min_version <- "1.0.0"
|
||||
|
||||
RLog <- R6Class(
|
||||
"RLog",
|
||||
|
||||
@@ -14,7 +14,7 @@ NULL
|
||||
#' depending on the values in the query string / hash (e.g. instead of basing
|
||||
#' the conditional on an input or a calculated reactive, you can base it on the
|
||||
#' query string). However, note that, if you're changing the query string / hash
|
||||
#' programatically from within the server code, you must use
|
||||
#' programmatically from within the server code, you must use
|
||||
#' `updateQueryString(_yourNewQueryString_, mode = "push")`. The default
|
||||
#' `mode` for `updateQueryString` is `"replace"`, which doesn't
|
||||
#' raise any events, so any observers or reactives that depend on it will
|
||||
|
||||
3
R/map.R
@@ -48,9 +48,12 @@ Map <- R6Class(
|
||||
)
|
||||
)
|
||||
|
||||
#' @export
|
||||
as.list.Map <- function(x, ...) {
|
||||
x$values()
|
||||
}
|
||||
|
||||
#' @export
|
||||
length.Map <- function(x) {
|
||||
x$size()
|
||||
}
|
||||
|
||||
@@ -457,6 +457,11 @@ MockShinySession <- R6Class(
|
||||
function(v){
|
||||
list(val = v, err = NULL)
|
||||
}, catch=function(e){
|
||||
if (
|
||||
!inherits(e, c("shiny.custom.error", "shiny.output.cancel", "shiny.output.progress", "shiny.silent.error"))
|
||||
) {
|
||||
self$unhandledError(e, close = FALSE)
|
||||
}
|
||||
list(val = NULL, err = e)
|
||||
})
|
||||
})
|
||||
@@ -560,10 +565,26 @@ MockShinySession <- R6Class(
|
||||
rootScope = function() {
|
||||
self
|
||||
},
|
||||
#' @description Add an unhandled error callback.
|
||||
#' @param callback The callback to add, which should accept an error object
|
||||
#' as its first argument.
|
||||
#' @return A deregistration function.
|
||||
onUnhandledError = function(callback) {
|
||||
private$unhandledErrorCallbacks$register(callback)
|
||||
},
|
||||
#' @description Called by observers when a reactive expression errors.
|
||||
#' @param e An error object.
|
||||
unhandledError = function(e) {
|
||||
self$close()
|
||||
#' @param close If `TRUE`, the session will be closed after the error is
|
||||
#' handled, defaults to `FALSE`.
|
||||
unhandledError = function(e, close = TRUE) {
|
||||
if (close) {
|
||||
class(e) <- c("shiny.error.fatal", class(e))
|
||||
}
|
||||
|
||||
private$unhandledErrorCallbacks$invoke(e, onError = printError)
|
||||
.globals$onUnhandledErrorCallbacks$invoke(e, onError = printError)
|
||||
|
||||
if (close) self$close()
|
||||
},
|
||||
#' @description Freeze a value until the flush cycle completes.
|
||||
#' @param x A `ReactiveValues` object.
|
||||
@@ -620,6 +641,9 @@ MockShinySession <- R6Class(
|
||||
flushedCBs = NULL,
|
||||
# @field endedCBs `Callbacks` called when session ends.
|
||||
endedCBs = NULL,
|
||||
# @field unhandledErrorCallbacks `Callbacks` called when an unhandled error
|
||||
# occurs.
|
||||
unhandledErrorCallbacks = Callbacks$new(),
|
||||
# @field timer `MockableTimerCallbacks` called at particular times.
|
||||
timer = NULL,
|
||||
# @field was_closed Set to `TRUE` once the session is closed.
|
||||
|
||||
@@ -1216,7 +1216,7 @@ Observer <- R6Class(
|
||||
|
||||
printError(e)
|
||||
if (!is.null(.domain)) {
|
||||
.domain$unhandledError(e)
|
||||
.domain$unhandledError(e, close = TRUE)
|
||||
}
|
||||
},
|
||||
finally = .domain$decrementBusyCount
|
||||
@@ -2396,7 +2396,7 @@ isNullEvent <- function(value) {
|
||||
#' reactive recently (within the time window) invalidated. New `r`
|
||||
#' invalidations do not reset the time window. This means that if invalidations
|
||||
#' continually come from `r` within the time window, the throttled reactive
|
||||
#' will invalidate regularly, at a rate equal to or slower than than the time
|
||||
#' will invalidate regularly, at a rate equal to or slower than the time
|
||||
#' window.
|
||||
#'
|
||||
#' `ooo-oo-oo---- => o--o--o--o---`
|
||||
|
||||
64
R/runapp.R
@@ -447,6 +447,16 @@ stopApp <- function(returnValue = invisible()) {
|
||||
#' @param display.mode The mode in which to display the example. Defaults to
|
||||
#' `showcase`, but may be set to `normal` to see the example without
|
||||
#' code or commentary.
|
||||
#' @param package The package in which to find the example (defaults to
|
||||
#' `"shiny"`).
|
||||
#'
|
||||
#' To provide examples in your package, store examples in the
|
||||
#' `inst/examples-shiny` directory of your package. Each example should be
|
||||
#' in its own subdirectory and should be runnable when [runApp()] is called
|
||||
#' on the subdirectory. Example apps can include a `DESCRIPTION` file and a
|
||||
#' `README.md` file to provide metadata and commentary about the example. See
|
||||
#' the article on [Display Modes](https://shiny.posit.co/r/articles/build/display-modes/)
|
||||
#' on the Shiny website for more information.
|
||||
#' @inheritParams runApp
|
||||
#'
|
||||
#' @examples
|
||||
@@ -462,32 +472,46 @@ stopApp <- function(returnValue = invisible()) {
|
||||
#' system.file("examples", package="shiny")
|
||||
#' }
|
||||
#' @export
|
||||
runExample <- function(example=NA,
|
||||
port=getOption("shiny.port"),
|
||||
launch.browser = getOption('shiny.launch.browser', interactive()),
|
||||
host=getOption('shiny.host', '127.0.0.1'),
|
||||
display.mode=c("auto", "normal", "showcase")) {
|
||||
examplesDir <- system_file('examples', package='shiny')
|
||||
runExample <- function(
|
||||
example = NA,
|
||||
port = getOption("shiny.port"),
|
||||
launch.browser = getOption("shiny.launch.browser", interactive()),
|
||||
host = getOption("shiny.host", "127.0.0.1"),
|
||||
display.mode = c("auto", "normal", "showcase"),
|
||||
package = "shiny"
|
||||
) {
|
||||
if (!identical(package, "shiny") && !is_installed(package)) {
|
||||
rlang::check_installed(package)
|
||||
}
|
||||
|
||||
use_legacy_shiny_examples <-
|
||||
identical(package, "shiny") &&
|
||||
isTRUE(getOption('shiny.legacy.examples', FALSE))
|
||||
|
||||
examplesDir <- system_file(
|
||||
if (use_legacy_shiny_examples) "examples" else "examples-shiny",
|
||||
package = package
|
||||
)
|
||||
|
||||
dir <- resolve(examplesDir, example)
|
||||
|
||||
if (is.null(dir)) {
|
||||
valid_examples <- sprintf(
|
||||
'Valid examples in {%s}: "%s"',
|
||||
package,
|
||||
paste(list.files(examplesDir), collapse = '", "')
|
||||
)
|
||||
|
||||
if (is.na(example)) {
|
||||
errFun <- message
|
||||
errMsg <- ''
|
||||
}
|
||||
else {
|
||||
errFun <- stop
|
||||
errMsg <- paste('Example', example, 'does not exist. ')
|
||||
message(valid_examples)
|
||||
return(invisible())
|
||||
}
|
||||
|
||||
errFun(errMsg,
|
||||
'Valid examples are "',
|
||||
paste(list.files(examplesDir), collapse='", "'),
|
||||
'"')
|
||||
}
|
||||
else {
|
||||
runApp(dir, port = port, host = host, launch.browser = launch.browser,
|
||||
display.mode = display.mode)
|
||||
stop("Example '", example, "' does not exist. ", valid_examples)
|
||||
}
|
||||
|
||||
runApp(dir, port = port, host = host, launch.browser = launch.browser,
|
||||
display.mode = display.mode)
|
||||
}
|
||||
|
||||
#' Run a gadget
|
||||
|
||||
@@ -113,7 +113,7 @@ getShinyOption <- function(name, default = NULL) {
|
||||
#' production.}
|
||||
#' \item{shiny.sanitize.errors (defaults to `FALSE`)}{If `TRUE`, then normal errors (i.e.
|
||||
#' errors not wrapped in `safeError`) won't show up in the app; a simple
|
||||
#' generic error message is printed instead (the error and strack trace printed
|
||||
#' generic error message is printed instead (the error and stack trace printed
|
||||
#' to the console remain unchanged). If you want to sanitize errors in general, but you DO want a
|
||||
#' particular error `e` to get displayed to the user, then set this option
|
||||
#' to `TRUE` and use `stop(safeError(e))` for errors you want the
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# See also R/reexports.R
|
||||
|
||||
## usethis namespace: start
|
||||
## usethis namespace: end
|
||||
#' @importFrom lifecycle deprecated is_present
|
||||
#' @importFrom grDevices dev.set dev.cur
|
||||
#' @importFrom fastmap fastmap
|
||||
@@ -18,13 +17,13 @@
|
||||
#' is_false list2
|
||||
#' missing_arg is_missing maybe_missing
|
||||
#' quo_is_missing fn_fmls<- fn_body fn_body<-
|
||||
#' @importFrom ellipsis
|
||||
#' check_dots_empty check_dots_unnamed
|
||||
#' @import htmltools
|
||||
#' @import httpuv
|
||||
#' @import xtable
|
||||
#' @import R6
|
||||
#' @import mime
|
||||
## usethis namespace: end
|
||||
NULL
|
||||
|
||||
# It's necessary to Depend on methods so Rscript doesn't fail. It's necessary
|
||||
|
||||
120
R/shiny.R
@@ -16,8 +16,7 @@ NULL
|
||||
#'
|
||||
#' @name shiny-package
|
||||
#' @aliases shiny
|
||||
#' @docType package
|
||||
NULL
|
||||
"_PACKAGE"
|
||||
|
||||
createUniqueId <- function(bytes, prefix = "", suffix = "") {
|
||||
withPrivateSeed({
|
||||
@@ -215,7 +214,7 @@ workerId <- local({
|
||||
#' Sends a custom message to the web page. `type` must be a
|
||||
#' single-element character vector giving the type of message, while
|
||||
#' `message` can be any jsonlite-encodable value. Custom messages
|
||||
#' have no meaning to Shiny itself; they are used soley to convey information
|
||||
#' have no meaning to Shiny itself; they are used solely to convey information
|
||||
#' to custom JavaScript logic in the browser. You can do this by adding
|
||||
#' JavaScript code to the browser that calls
|
||||
#' \code{Shiny.addCustomMessageHandler(type, function(message){...})}
|
||||
@@ -363,6 +362,7 @@ ShinySession <- R6Class(
|
||||
flushCallbacks = 'Callbacks',
|
||||
flushedCallbacks = 'Callbacks',
|
||||
inputReceivedCallbacks = 'Callbacks',
|
||||
unhandledErrorCallbacks = 'Callbacks',
|
||||
bookmarkCallbacks = 'Callbacks',
|
||||
bookmarkedCallbacks = 'Callbacks',
|
||||
restoreCallbacks = 'Callbacks',
|
||||
@@ -724,6 +724,7 @@ ShinySession <- R6Class(
|
||||
private$flushCallbacks <- Callbacks$new()
|
||||
private$flushedCallbacks <- Callbacks$new()
|
||||
private$inputReceivedCallbacks <- Callbacks$new()
|
||||
private$unhandledErrorCallbacks <- Callbacks$new()
|
||||
private$.input <- ReactiveValues$new(dedupe = FALSE, label = "input")
|
||||
private$.clientData <- ReactiveValues$new(dedupe = TRUE, label = "clientData")
|
||||
private$timingRecorder <- ShinyServerTimingRecorder$new()
|
||||
@@ -1044,8 +1045,21 @@ ShinySession <- R6Class(
|
||||
new data from the client."
|
||||
return(private$inputReceivedCallbacks$register(callback))
|
||||
},
|
||||
unhandledError = function(e) {
|
||||
self$close()
|
||||
onUnhandledError = function(callback) {
|
||||
"Registers the callback to be invoked when an unhandled error occurs."
|
||||
return(private$unhandledErrorCallbacks$register(callback))
|
||||
},
|
||||
unhandledError = function(e, close = TRUE) {
|
||||
"Call the global and session unhandled error handlers and then close the
|
||||
session if the error is fatal."
|
||||
if (close) {
|
||||
class(e) <- c("shiny.error.fatal", class(e))
|
||||
}
|
||||
|
||||
private$unhandledErrorCallbacks$invoke(e, onError = printError)
|
||||
.globals$onUnhandledErrorCallbacks$invoke(e, onError = printError)
|
||||
|
||||
if (close) self$close()
|
||||
},
|
||||
close = function() {
|
||||
if (!self$closed) {
|
||||
@@ -1169,6 +1183,7 @@ ShinySession <- R6Class(
|
||||
"logs or contact the app author for",
|
||||
"clarification."))
|
||||
}
|
||||
self$unhandledError(cond, close = FALSE)
|
||||
invisible(structure(list(), class = "try-error", condition = cond))
|
||||
}
|
||||
}
|
||||
@@ -2370,23 +2385,89 @@ getCurrentOutputInfo <- function(session = getDefaultReactiveDomain()) {
|
||||
|
||||
#' Add callbacks for Shiny session events
|
||||
#'
|
||||
#' @description
|
||||
#' These functions are for registering callbacks on Shiny session events.
|
||||
#' `onFlush` registers a function that will be called before Shiny flushes
|
||||
#' the reactive system. `onFlushed` registers a function that will be
|
||||
#' called after Shiny flushes the reactive system. `onSessionEnded`
|
||||
#' registers a function to be called after the client has disconnected.
|
||||
#' `onFlush` registers a function that will be called before Shiny flushes the
|
||||
#' reactive system. `onFlushed` registers a function that will be called after
|
||||
#' Shiny flushes the reactive system. `onUnhandledError` registers a function to
|
||||
#' be called when an unhandled error occurs before the session is closed.
|
||||
#' `onSessionEnded` registers a function to be called after the client has
|
||||
#' disconnected.
|
||||
#'
|
||||
#' These functions should be called within the application's server function.
|
||||
#'
|
||||
#' All of these functions return a function which can be called with no
|
||||
#' arguments to cancel the registration.
|
||||
#'
|
||||
#' @section Unhandled Errors:
|
||||
#' Unhandled errors are errors that aren't otherwise handled by Shiny or by the
|
||||
#' application logic. In other words, they are errors that will either cause the
|
||||
#' application to crash or will result in "Error" output in the UI.
|
||||
#'
|
||||
#' You can use `onUnhandledError()` to register a function that will be called
|
||||
#' when an unhandled error occurs. This function will be called with the error
|
||||
#' object as its first argument. If the error is fatal and will result in the
|
||||
#' session closing, the error condition will have the `shiny.error.fatal` class.
|
||||
#'
|
||||
#' Note that the `onUnhandledError()` callbacks cannot be used to prevent the
|
||||
#' app from closing or to modify the error condition. Instead, they are intended
|
||||
#' to give you an opportunity to log the error or perform other cleanup
|
||||
#' operations.
|
||||
#'
|
||||
#' @param fun A callback function.
|
||||
#' @param once Should the function be run once, and then cleared, or should it
|
||||
#' re-run each time the event occurs. (Only for `onFlush` and
|
||||
#' `onFlushed`.)
|
||||
#' @param session A shiny session object.
|
||||
#'
|
||||
#' @examplesIf interactive()
|
||||
#' library(shiny)
|
||||
#'
|
||||
#' ui <- fixedPage(
|
||||
#' markdown(c(
|
||||
#' "Set the number to 8 or higher to cause an error",
|
||||
#' "in the `renderText()` output."
|
||||
#' )),
|
||||
#' sliderInput("number", "Number", 0, 10, 4),
|
||||
#' textOutput("text"),
|
||||
#' hr(),
|
||||
#' markdown(c(
|
||||
#' "Click the button below to crash the app with an unhandled error",
|
||||
#' "in an `observe()` block."
|
||||
#' )),
|
||||
#' actionButton("crash", "Crash the app!")
|
||||
#' )
|
||||
#'
|
||||
#' log_event <- function(level, ...) {
|
||||
#' ts <- strftime(Sys.time(), " [%F %T] ")
|
||||
#' message(level, ts, ...)
|
||||
#' }
|
||||
#'
|
||||
#' server <- function(input, output, session) {
|
||||
#' log_event("INFO", "Session started")
|
||||
#'
|
||||
#' onUnhandledError(function(err) {
|
||||
#' # log the unhandled error
|
||||
#' level <- if (inherits(err, "shiny.error.fatal")) "FATAL" else "ERROR"
|
||||
#' log_event(level, conditionMessage(err))
|
||||
#' })
|
||||
#'
|
||||
#' onStop(function() {
|
||||
#' log_event("INFO", "Session ended")
|
||||
#' })
|
||||
#'
|
||||
#' observeEvent(input$crash, stop("Oops, an unhandled error happened!"))
|
||||
#'
|
||||
#' output$text <- renderText({
|
||||
#' if (input$number > 7) {
|
||||
#' stop("that's too high!")
|
||||
#' }
|
||||
#' sprintf("You picked number %d.", input$number)
|
||||
#' })
|
||||
#' }
|
||||
#'
|
||||
#' shinyApp(ui, server)
|
||||
#'
|
||||
#' @export
|
||||
onFlush <- function(fun, once = TRUE, session = getDefaultReactiveDomain()) {
|
||||
session$onFlush(fun, once = once)
|
||||
@@ -2407,6 +2488,27 @@ onSessionEnded <- function(fun, session = getDefaultReactiveDomain()) {
|
||||
session$onSessionEnded(fun)
|
||||
}
|
||||
|
||||
.globals$onUnhandledErrorCallbacks <- NULL
|
||||
on_load({
|
||||
.globals$onUnhandledErrorCallbacks <- Callbacks$new()
|
||||
})
|
||||
|
||||
#' @rdname onFlush
|
||||
#' @export
|
||||
onUnhandledError <- function(fun, session = getDefaultReactiveDomain()) {
|
||||
if (!is.function(fun) || length(formals(fun)) == 0) {
|
||||
rlang::abort(
|
||||
"The unhandled error callback must be a function that takes an error object as its first argument."
|
||||
)
|
||||
}
|
||||
|
||||
if (is.null(session)) {
|
||||
.globals$onUnhandledErrorCallbacks$register(fun)
|
||||
} else {
|
||||
session$onUnhandledError(fun)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
flushPendingSessions <- function() {
|
||||
lapply(appsNeedingFlush$values(), function(shinysession) {
|
||||
|
||||
36
R/shinyapp.R
@@ -351,17 +351,6 @@ loadSupport <- function(appDir=NULL, renv=new.env(parent=globalenv()), globalren
|
||||
appDir <- findEnclosingApp(".")
|
||||
}
|
||||
|
||||
descFile <- file.path.ci(appDir, "DESCRIPTION")
|
||||
if (file.exists(file.path.ci(appDir, "NAMESPACE")) ||
|
||||
(file.exists(descFile) &&
|
||||
identical(as.character(read.dcf(descFile, fields = "Type")), "Package")))
|
||||
{
|
||||
warning(
|
||||
"Loading R/ subdirectory for Shiny application, but this directory appears ",
|
||||
"to contain an R package. Sourcing files in R/ may cause unexpected behavior."
|
||||
)
|
||||
}
|
||||
|
||||
if (!is.null(globalrenv)){
|
||||
# Evaluate global.R, if it exists.
|
||||
globalPath <- file.path.ci(appDir, "global.R")
|
||||
@@ -376,10 +365,12 @@ loadSupport <- function(appDir=NULL, renv=new.env(parent=globalenv()), globalren
|
||||
helpersDir <- file.path(appDir, "R")
|
||||
|
||||
disabled <- list.files(helpersDir, pattern="^_disable_autoload\\.r$", recursive=FALSE, ignore.case=TRUE)
|
||||
if (length(disabled) > 0){
|
||||
if (length(disabled) > 0) {
|
||||
return(invisible(renv))
|
||||
}
|
||||
|
||||
warn_if_app_dir_is_package(appDir)
|
||||
|
||||
helpers <- list.files(helpersDir, pattern="\\.[rR]$", recursive=FALSE, full.names=TRUE)
|
||||
# Ensure files in R/ are sorted according to the 'C' locale before sourcing.
|
||||
# This convention is based on the default for packages. For details, see:
|
||||
@@ -394,6 +385,27 @@ loadSupport <- function(appDir=NULL, renv=new.env(parent=globalenv()), globalren
|
||||
invisible(renv)
|
||||
}
|
||||
|
||||
warn_if_app_dir_is_package <- function(appDir) {
|
||||
has_namespace <- file.exists(file.path.ci(appDir, "NAMESPACE"))
|
||||
has_desc_pkg <- FALSE
|
||||
|
||||
if (!has_namespace) {
|
||||
descFile <- file.path.ci(appDir, "DESCRIPTION")
|
||||
|
||||
has_desc_pkg <-
|
||||
file.exists(descFile) &&
|
||||
identical(as.character(read.dcf(descFile, fields = "Type")), "Package")
|
||||
}
|
||||
|
||||
if (has_namespace || has_desc_pkg) {
|
||||
warning(
|
||||
"Loading R/ subdirectory for Shiny application, but this directory appears ",
|
||||
"to contain an R package. Sourcing files in R/ may cause unexpected behavior. ",
|
||||
"See `?loadSupport` for more details."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
# This reads in an app dir for a single-file application (e.g. app.R), and
|
||||
# returns a shiny.appobj.
|
||||
# appDir must be a normalized (absolute) path, not a relative one
|
||||
|
||||
18
R/shinyui.R
@@ -69,6 +69,21 @@ renderPage <- function(ui, showcase=0, testMode=FALSE) {
|
||||
)
|
||||
}
|
||||
|
||||
if (in_devmode()) {
|
||||
# If we're in dev mode, add a simple script to the head that injects a
|
||||
# global variable for the client to use to detect dev mode.
|
||||
shiny_deps[[length(shiny_deps) + 1]] <-
|
||||
htmlDependency(
|
||||
"shiny-devmode",
|
||||
get_package_version("shiny"),
|
||||
src = "www/shared",
|
||||
package = "shiny",
|
||||
head="<script>window.__SHINY_DEV_MODE__ = true;</script>",
|
||||
all_files = FALSE
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
html <- renderDocument(ui, shiny_deps, processDep = createWebDependency)
|
||||
enc2utf8(paste(collapse = "\n", html))
|
||||
}
|
||||
@@ -99,6 +114,7 @@ jqueryDependency <- function() {
|
||||
shinyDependencies <- function() {
|
||||
list(
|
||||
bslib::bs_dependency_defer(shinyDependencyCSS),
|
||||
busyIndicatorDependency(),
|
||||
htmlDependency(
|
||||
name = "shiny-javascript",
|
||||
version = get_package_version("shiny"),
|
||||
@@ -159,7 +175,7 @@ shinyDependencyCSS <- function(theme) {
|
||||
#' This function is kept for backwards compatibility with older applications. It
|
||||
#' returns the value that is passed to it.
|
||||
#'
|
||||
#' @param ui A user interace definition
|
||||
#' @param ui A user interface definition
|
||||
#' @return The user interface definition, without modifications or side effects.
|
||||
#' @keywords internal
|
||||
#' @export
|
||||
|
||||
@@ -778,8 +778,8 @@ renderUI <- function(expr, env = parent.frame(), quoted = FALSE,
|
||||
#' function.)
|
||||
#' @param contentType A string of the download's
|
||||
#' [content type](https://en.wikipedia.org/wiki/Internet_media_type), for
|
||||
#' example `"text/csv"` or `"image/png"`. If `NULL`, the content type
|
||||
#' will be guessed based on the filename extension, or
|
||||
#' example `"text/csv"` or `"image/png"`. If `NULL`, the content type
|
||||
#' will be guessed based on the filename extension, or
|
||||
#' `application/octet-stream` if the extension is unknown.
|
||||
#' @param outputArgs A list of arguments to be passed through to the implicit
|
||||
#' call to [downloadButton()] when `downloadHandler` is used
|
||||
@@ -822,20 +822,12 @@ downloadHandler <- function(filename, content, contentType=NULL, outputArgs=list
|
||||
#' Table output with the JavaScript DataTables library
|
||||
#'
|
||||
#' @description
|
||||
#' `r lifecycle::badge("superseded")` Please use
|
||||
#' \href{https://rstudio.github.io/DT/shiny.html}{\code{DT::renderDataTable()}}.
|
||||
#' (Shiny 0.11.1)
|
||||
#' `r lifecycle::badge("deprecated")`
|
||||
#'
|
||||
#' Makes a reactive version of the given function that returns a data frame (or
|
||||
#' matrix), which will be rendered with the [DataTables](https://datatables.net)
|
||||
#' library. Paging, searching, filtering, and sorting can be done on the R side
|
||||
#' using Shiny as the server infrastructure.
|
||||
#'
|
||||
#' This function only provides the server-side version of DataTables (using R
|
||||
#' to process the data object on the server side). There is a separate
|
||||
#' [DT](https://github.com/rstudio/DT) that allows you to create both
|
||||
#' server-side and client-side DataTables, and supports additional features.
|
||||
#' Learn more at <https://rstudio.github.io/DT/shiny.html>.
|
||||
#' This function is deprecated, use
|
||||
#' [DT::renderDT()](https://rstudio.github.io/DT/shiny.html) instead. It
|
||||
#' provides a superset of functionality, better performance, and better user
|
||||
#' experience.
|
||||
#'
|
||||
#' @param expr An expression that returns a data frame or a matrix.
|
||||
#' @inheritParams renderTable
|
||||
@@ -887,18 +879,60 @@ downloadHandler <- function(filename, content, contentType=NULL, outputArgs=list
|
||||
#' }
|
||||
#' )
|
||||
#' }
|
||||
#' @keywords internal
|
||||
renderDataTable <- function(expr, options = NULL, searchDelay = 500,
|
||||
callback = 'function(oTable) {}', escape = TRUE,
|
||||
env = parent.frame(), quoted = FALSE,
|
||||
outputArgs=list())
|
||||
{
|
||||
outputArgs = list()) {
|
||||
|
||||
if (in_devmode()) {
|
||||
shinyDeprecated(
|
||||
"0.11.1", "shiny::renderDataTable()", "DT::renderDataTable()",
|
||||
details = "See <https://rstudio.github.io/DT/shiny.html> for more information"
|
||||
legacy <- useLegacyDataTable(
|
||||
from = "shiny::renderDataTable()",
|
||||
to = "DT::renderDT()"
|
||||
)
|
||||
|
||||
if (!quoted) {
|
||||
expr <- substitute(expr)
|
||||
quoted <- TRUE
|
||||
}
|
||||
|
||||
if (legacy) {
|
||||
|
||||
legacyRenderDataTable(
|
||||
expr, env = env, quoted = quoted,
|
||||
options = options,
|
||||
searchDelay = searchDelay,
|
||||
callback = callback,
|
||||
escape = escape,
|
||||
outputArgs = outputArgs
|
||||
)
|
||||
|
||||
} else {
|
||||
|
||||
if (!missing(searchDelay)) {
|
||||
warning("Ignoring renderDataTable()'s searchDelay value (since DT::renderDT() has no equivalent).")
|
||||
}
|
||||
|
||||
force(options)
|
||||
force(callback)
|
||||
force(escape)
|
||||
force(outputArgs)
|
||||
|
||||
DT::renderDataTable(
|
||||
expr, env = env, quoted = quoted,
|
||||
options = if (is.null(options)) list() else options,
|
||||
# Turn function into a statement
|
||||
callback = DT::JS(paste0("(", callback, ")(table)")),
|
||||
escape = escape,
|
||||
outputArgs = outputArgs
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
legacyRenderDataTable <- function(expr, options = NULL, searchDelay = 500,
|
||||
callback = 'function(oTable) {}', escape = TRUE,
|
||||
env = parent.frame(), quoted = FALSE,
|
||||
outputArgs=list()) {
|
||||
|
||||
func <- installExprFunction(expr, "func", env, quoted, label = "renderDataTable")
|
||||
|
||||
|
||||
@@ -150,13 +150,13 @@ updateCheckboxInput <- function(session = getDefaultReactiveDomain(), inputId, l
|
||||
#' label = "New label",
|
||||
#' icon = icon("calendar"))
|
||||
#'
|
||||
#' # Leaves goButton2's label unchaged and
|
||||
#' # Leaves goButton2's label unchanged and
|
||||
#' # removes its icon
|
||||
#' updateActionButton(session, "goButton2",
|
||||
#' icon = character(0))
|
||||
#'
|
||||
#' # Leaves goButton3's icon, if it exists,
|
||||
#' # unchaged and changes its label
|
||||
#' # unchanged and changes its label
|
||||
#' updateActionButton(session, "goButton3",
|
||||
#' label = "New label 3")
|
||||
#'
|
||||
|
||||
@@ -493,7 +493,6 @@ shinyCallingHandlers <- function(expr) {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
#' Register a function with the debugger (if one is active).
|
||||
#'
|
||||
#' Call this function after exprToFunction to give any active debugger a hook
|
||||
@@ -1093,7 +1092,7 @@ need <- function(expr, message = paste(label, "must be provided"), label) {
|
||||
#'
|
||||
#' You can use `req(FALSE)` (i.e. no condition) if you've already performed
|
||||
#' all the checks you needed to by that point and just want to stop the reactive
|
||||
#' chain now. There is no advantange to this, except perhaps ease of readibility
|
||||
#' chain now. There is no advantage to this, except perhaps ease of readability
|
||||
#' if you have a complicated condition to check for (or perhaps if you'd like to
|
||||
#' divide your condition into nested `if` statements).
|
||||
#'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- badges: start -->
|
||||
[](https://CRAN.R-project.org/package=shiny)
|
||||
[](https://github.com/rstudio/shiny/actions)
|
||||
[](https://community.rstudio.com/new-topic?category=shiny&tags=shiny)
|
||||
[](https://forum.posit.co/new-topic?category=shiny&tags=shiny)
|
||||
|
||||
<!-- badges: end -->
|
||||
|
||||
@@ -51,7 +51,7 @@ If you want to chat about Shiny, meet other developers, or help us decide what t
|
||||
|
||||
## Getting Help
|
||||
|
||||
To ask a question about Shiny, please use the [RStudio Community website](https://community.rstudio.com/new-topic?category=shiny&tags=shiny).
|
||||
To ask a question about Shiny, please use the [RStudio Community website](https://forum.posit.co/new-topic?category=shiny&tags=shiny).
|
||||
|
||||
For bug reports, please use the [issue tracker](https://github.com/rstudio/shiny/issues) and also keep in mind that by [writing a good bug report](https://github.com/rstudio/shiny/wiki/Writing-Good-Bug-Reports), you're more likely to get help with your problem.
|
||||
|
||||
|
||||
154
inst/diagrams/outputProgressStateMachine.drawio
Normal file
@@ -0,0 +1,154 @@
|
||||
<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>
|
||||
4
inst/diagrams/outputProgressStateMachine.svg
Normal file
|
After Width: | Height: | Size: 312 KiB |
6
inst/examples-shiny/01_hello/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Hello Shiny!
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
3
inst/examples-shiny/01_hello/Readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
This small Shiny application demonstrates Shiny's automatic UI updates.
|
||||
|
||||
Move the *Number of bins* slider and notice how the `renderPlot` expression is automatically re-evaluated when its dependant, `input$bins`, changes, causing a histogram with a new number of bins to be rendered.
|
||||
54
inst/examples-shiny/01_hello/app.R
Normal file
@@ -0,0 +1,54 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for app that draws a histogram ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Hello Shiny!",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Slider for the number of bins ----
|
||||
sliderInput(
|
||||
inputId = "bins",
|
||||
label = "Number of bins:",
|
||||
min = 1,
|
||||
max = 50,
|
||||
value = 30
|
||||
)
|
||||
),
|
||||
|
||||
# Output: Histogram ----
|
||||
plotOutput(outputId = "distPlot")
|
||||
)
|
||||
|
||||
# Define server logic required to draw a histogram ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Histogram of the Old Faithful Geyser Data ----
|
||||
# with requested number of bins
|
||||
# This expression that generates a histogram is wrapped in a call
|
||||
# to renderPlot to indicate that:
|
||||
#
|
||||
# 1. It is "reactive" and therefore should be automatically
|
||||
# re-executed when inputs (input$bins) change
|
||||
# 2. Its output type is a plot
|
||||
output$distPlot <- renderPlot({
|
||||
x <- faithful$waiting
|
||||
bins <- seq(min(x), max(x), length.out = input$bins + 1)
|
||||
|
||||
hist(
|
||||
x,
|
||||
breaks = bins,
|
||||
col = "#75AADB",
|
||||
border = "white",
|
||||
xlab = "Waiting time to next eruption (in mins)",
|
||||
main = "Histogram of waiting times"
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui = ui, server = server)
|
||||
6
inst/examples-shiny/02_text/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Shiny Text
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
1
inst/examples-shiny/02_text/Readme.md
Normal file
@@ -0,0 +1 @@
|
||||
This example demonstrates output of raw text from R using the `renderPrint` function in `server` and the `verbatimTextOutput` function in `ui`. In this case, a textual summary of the data is shown using R's built-in `summary` function.
|
||||
61
inst/examples-shiny/02_text/app.R
Normal file
@@ -0,0 +1,61 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for dataset viewer app ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Shiny Text",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Selector for choosing dataset ----
|
||||
selectInput(
|
||||
inputId = "dataset",
|
||||
label = "Choose a dataset:",
|
||||
choices = c("rock", "pressure", "cars")
|
||||
),
|
||||
|
||||
# Input: Numeric entry for number of obs to view ----
|
||||
numericInput(
|
||||
inputId = "obs",
|
||||
label = "Number of observations to view:",
|
||||
value = 10
|
||||
)
|
||||
),
|
||||
|
||||
# Output: Verbatim text for data summary ----
|
||||
verbatimTextOutput("summary"),
|
||||
|
||||
# Output: HTML table with requested number of observations ----
|
||||
tableOutput("view")
|
||||
)
|
||||
|
||||
# Define server logic to summarize and view selected dataset ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Return the requested dataset ----
|
||||
datasetInput <- reactive({
|
||||
switch(
|
||||
input$dataset,
|
||||
"rock" = rock,
|
||||
"pressure" = pressure,
|
||||
"cars" = cars
|
||||
)
|
||||
})
|
||||
|
||||
# Generate a summary of the dataset ----
|
||||
output$summary <- renderPrint({
|
||||
dataset <- datasetInput()
|
||||
summary(dataset)
|
||||
})
|
||||
|
||||
# Show the first "n" observations ----
|
||||
output$view <- renderTable({
|
||||
head(datasetInput(), n = input$obs)
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui = ui, server = server)
|
||||
6
inst/examples-shiny/03_reactivity/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Reactivity
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
5
inst/examples-shiny/03_reactivity/Readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
This example demonstrates a core feature of Shiny: **reactivity**. In the `server` function, a reactive called `datasetInput` is declared.
|
||||
|
||||
Notice that the reactive expression depends on the input expression `input$dataset`, and that it's used by two output expressions: `output$summary` and `output$view`. Try changing the dataset (using *Choose a dataset*) while looking at the reactive and then at the outputs; you will see first the reactive and then its dependencies flash.
|
||||
|
||||
Notice also that the reactive expression doesn't just update whenever anything changes--only the inputs it depends on will trigger an update. Change the "Caption" field and notice how only the `output$caption` expression is re-evaluated; the reactive and its dependents are left alone.
|
||||
100
inst/examples-shiny/03_reactivity/app.R
Normal file
@@ -0,0 +1,100 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for dataset viewer app ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Reactivity",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Text for providing a caption ----
|
||||
# Note: Changes made to the caption in the textInput control
|
||||
# are updated in the output area immediately as you type
|
||||
textInput(
|
||||
inputId = "caption",
|
||||
label = "Caption:",
|
||||
value = "Data Summary"
|
||||
),
|
||||
|
||||
# Input: Selector for choosing dataset ----
|
||||
selectInput(
|
||||
inputId = "dataset",
|
||||
label = "Choose a dataset:",
|
||||
choices = c("rock", "pressure", "cars")
|
||||
),
|
||||
|
||||
# Input: Numeric entry for number of obs to view ----
|
||||
numericInput(
|
||||
inputId = "obs",
|
||||
label = "Number of observations to view:",
|
||||
value = 10
|
||||
)
|
||||
),
|
||||
|
||||
# Output: Formatted text for caption ----
|
||||
h3(textOutput("caption", container = span)),
|
||||
|
||||
# Output: Verbatim text for data summary ----
|
||||
verbatimTextOutput("summary"),
|
||||
|
||||
# Output: HTML table with requested number of observations ----
|
||||
tableOutput("view")
|
||||
)
|
||||
|
||||
# Define server logic to summarize and view selected dataset ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Return the requested dataset ----
|
||||
# By declaring datasetInput as a reactive expression we ensure
|
||||
# that:
|
||||
#
|
||||
# 1. It is only called when the inputs it depends on changes
|
||||
# 2. The computation and result are shared by all the callers,
|
||||
# i.e. it only executes a single time
|
||||
datasetInput <- reactive({
|
||||
switch(
|
||||
input$dataset,
|
||||
"rock" = rock,
|
||||
"pressure" = pressure,
|
||||
"cars" = cars
|
||||
)
|
||||
})
|
||||
|
||||
# Create caption ----
|
||||
# The output$caption is computed based on a reactive expression
|
||||
# that returns input$caption. When the user changes the
|
||||
# "caption" field:
|
||||
#
|
||||
# 1. This function is automatically called to recompute the output
|
||||
# 2. New caption is pushed back to the browser for re-display
|
||||
#
|
||||
# Note that because the data-oriented reactive expressions
|
||||
# below don't depend on input$caption, those expressions are
|
||||
# NOT called when input$caption changes
|
||||
output$caption <- renderText({
|
||||
input$caption
|
||||
})
|
||||
|
||||
# Generate a summary of the dataset ----
|
||||
# The output$summary depends on the datasetInput reactive
|
||||
# expression, so will be re-executed whenever datasetInput is
|
||||
# invalidated, i.e. whenever the input$dataset changes
|
||||
output$summary <- renderPrint({
|
||||
dataset <- datasetInput()
|
||||
summary(dataset)
|
||||
})
|
||||
|
||||
# Show the first "n" observations ----
|
||||
# The output$view depends on both the databaseInput reactive
|
||||
# expression and input$obs, so it will be re-executed whenever
|
||||
# input$dataset or input$obs is changed
|
||||
output$view <- renderTable({
|
||||
head(datasetInput(), n = input$obs)
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
6
inst/examples-shiny/04_mpg/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Miles Per Gallon
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
4
inst/examples-shiny/04_mpg/Readme.md
Normal file
@@ -0,0 +1,4 @@
|
||||
This example demonstrates the following concepts:
|
||||
|
||||
- **Global variables**: The `mpgData` variable is declared outside of the `ui` and `server` function definitions. This makes it available anywhere inside `app.R`. The code in `app.R` outside of `ui` and `server` function definitions is only run once when the app starts up, so it can't contain user input.
|
||||
- **Reactive expressions**: `formulaText` is a reactive expression. Note how it re-evaluates when the Variable field is changed, but not when the Show Outliers box is unchecked.
|
||||
73
inst/examples-shiny/04_mpg/app.R
Normal file
@@ -0,0 +1,73 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
library(datasets)
|
||||
|
||||
# Data pre-processing ----
|
||||
# Tweak the "am" variable to have nicer factor labels -- since this
|
||||
# doesn't rely on any user inputs, we can do this once at startup
|
||||
# and then use the value throughout the lifetime of the app
|
||||
mpgData <- mtcars
|
||||
mpgData$am <- factor(mpgData$am, labels = c("Automatic", "Manual"))
|
||||
|
||||
|
||||
# Define UI for miles per gallon app ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Miles Per Gallon",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Selector for variable to plot against mpg ----
|
||||
selectInput(
|
||||
"variable",
|
||||
"Variable:",
|
||||
c(
|
||||
"Cylinders" = "cyl",
|
||||
"Transmission" = "am",
|
||||
"Gears" = "gear"
|
||||
)
|
||||
),
|
||||
|
||||
# Input: Checkbox for whether outliers should be included ----
|
||||
checkboxInput("outliers", "Show outliers", TRUE)
|
||||
),
|
||||
|
||||
# Output: Formatted text for caption ----
|
||||
h3(textOutput("caption")),
|
||||
|
||||
# Output: Plot of the requested variable against mpg ----
|
||||
plotOutput("mpgPlot")
|
||||
)
|
||||
|
||||
# Define server logic to plot various variables against mpg ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Compute the formula text ----
|
||||
# This is in a reactive expression since it is shared by the
|
||||
# output$caption and output$mpgPlot functions
|
||||
formulaText <- reactive({
|
||||
paste("mpg ~", input$variable)
|
||||
})
|
||||
|
||||
# Return the formula text for printing as a caption ----
|
||||
output$caption <- renderText({
|
||||
formulaText()
|
||||
})
|
||||
|
||||
# Generate a plot of the requested variable against mpg ----
|
||||
# and only exclude outliers if requested
|
||||
output$mpgPlot <- renderPlot({
|
||||
boxplot(
|
||||
as.formula(formulaText()),
|
||||
data = mpgData,
|
||||
outline = input$outliers,
|
||||
col = "#75AADB",
|
||||
pch = 19
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
6
inst/examples-shiny/05_sliders/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Sliders
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
3
inst/examples-shiny/05_sliders/Readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
This example demonstrates Shiny's versatile `sliderInput` widget.
|
||||
|
||||
Slider inputs can be used to select single values, to select a continuous range of values, and even to animate over a range.
|
||||
103
inst/examples-shiny/05_sliders/app.R
Normal file
@@ -0,0 +1,103 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for slider demo app ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Sliders",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Simple integer interval ----
|
||||
sliderInput(
|
||||
"integer",
|
||||
"Integer:",
|
||||
min = 0,
|
||||
max = 1000,
|
||||
value = 500
|
||||
),
|
||||
|
||||
# Input: Decimal interval with step value ----
|
||||
sliderInput(
|
||||
"decimal",
|
||||
"Decimal:",
|
||||
min = 0,
|
||||
max = 1,
|
||||
value = 0.5,
|
||||
step = 0.1
|
||||
),
|
||||
|
||||
# Input: Specification of range within an interval ----
|
||||
sliderInput(
|
||||
"range",
|
||||
"Range:",
|
||||
min = 1,
|
||||
max = 1000,
|
||||
value = c(200, 500)
|
||||
),
|
||||
|
||||
# Input: Custom currency format for with basic animation ----
|
||||
sliderInput(
|
||||
"format",
|
||||
"Custom Format:",
|
||||
min = 0,
|
||||
max = 10000,
|
||||
value = 0,
|
||||
step = 2500,
|
||||
pre = "$",
|
||||
sep = ",",
|
||||
animate = TRUE
|
||||
),
|
||||
|
||||
# Input: Animation with custom interval (in ms) ----
|
||||
# to control speed, plus looping
|
||||
sliderInput(
|
||||
"animation",
|
||||
"Looping Animation:",
|
||||
min = 1,
|
||||
max = 2000,
|
||||
value = 1,
|
||||
step = 10,
|
||||
animate =
|
||||
animationOptions(interval = 300, loop = TRUE)
|
||||
)
|
||||
),
|
||||
|
||||
# Output: Table summarizing the values entered ----
|
||||
tableOutput("values")
|
||||
)
|
||||
|
||||
# Define server logic for slider examples ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Reactive expression to create data frame of all input values ----
|
||||
sliderValues <- reactive({
|
||||
data.frame(
|
||||
Name = c(
|
||||
"Integer",
|
||||
"Decimal",
|
||||
"Range",
|
||||
"Custom Format",
|
||||
"Animation"
|
||||
),
|
||||
Value = as.character(c(
|
||||
input$integer,
|
||||
input$decimal,
|
||||
paste(input$range, collapse = " "),
|
||||
input$format,
|
||||
input$animation
|
||||
)),
|
||||
stringsAsFactors = FALSE
|
||||
)
|
||||
})
|
||||
|
||||
# Show the values in an HTML table ----
|
||||
output$values <- renderTable({
|
||||
sliderValues()
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
6
inst/examples-shiny/06_tabsets/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Tabsets
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
9
inst/examples-shiny/06_tabsets/Readme.md
Normal file
@@ -0,0 +1,9 @@
|
||||
This example demonstrates the `navset_*` and `nav_panel` widgets from the `bslib` package.
|
||||
|
||||
Notice that outputs that are not visible are not re-evaluated until they become visible. Try this:
|
||||
|
||||
1. Scroll to the bottom of the `server` function. You might need to use the *show with app* option so you can easily view the code and interact with the app at the same time.
|
||||
2. Change the number of observations, and observe that only `output$plot` is evaluated.
|
||||
3. Click the Summary tab, and observe that `output$summary` is evaluated.
|
||||
4. Change the number of observations again, and observe that now only `output$summary` is evaluated.
|
||||
|
||||
99
inst/examples-shiny/06_tabsets/app.R
Normal file
@@ -0,0 +1,99 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for random distribution app ----
|
||||
# Sidebar layout with input and output definitions ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Tabsets",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Select the random distribution type ----
|
||||
radioButtons(
|
||||
"dist",
|
||||
"Distribution type:",
|
||||
c(
|
||||
"Normal" = "norm",
|
||||
"Uniform" = "unif",
|
||||
"Log-normal" = "lnorm",
|
||||
"Exponential" = "exp"
|
||||
)
|
||||
),
|
||||
# br() element to introduce extra vertical spacing ----
|
||||
br(),
|
||||
# Input: Slider for the number of observations to generate ----
|
||||
sliderInput(
|
||||
"n",
|
||||
"Number of observations:",
|
||||
value = 500,
|
||||
min = 1,
|
||||
max = 1000
|
||||
)
|
||||
),
|
||||
|
||||
# Main panel for displaying outputs ----
|
||||
# Output: A tabset that combines three panels ----
|
||||
navset_card_underline(
|
||||
# Panel with plot ----
|
||||
nav_panel("Plot", plotOutput("plot")),
|
||||
|
||||
# Panel with summary ----
|
||||
nav_panel("Summary", verbatimTextOutput("summary")),
|
||||
|
||||
# Panel with table ----
|
||||
nav_panel("Table", tableOutput("table"))
|
||||
)
|
||||
)
|
||||
|
||||
# Define server logic for random distribution app ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Reactive expression to generate the requested distribution ----
|
||||
# This is called whenever the inputs change. The output functions
|
||||
# defined below then use the value computed from this expression
|
||||
d <- reactive({
|
||||
dist <- switch(
|
||||
input$dist,
|
||||
norm = rnorm,
|
||||
unif = runif,
|
||||
lnorm = rlnorm,
|
||||
exp = rexp,
|
||||
rnorm
|
||||
)
|
||||
|
||||
dist(input$n)
|
||||
})
|
||||
|
||||
# Generate a plot of the data ----
|
||||
# Also uses the inputs to build the plot label. Note that the
|
||||
# dependencies on the inputs and the data reactive expression are
|
||||
# both tracked, and all expressions are called in the sequence
|
||||
# implied by the dependency graph.
|
||||
output$plot <- renderPlot({
|
||||
dist <- input$dist
|
||||
n <- input$n
|
||||
|
||||
hist(
|
||||
d(),
|
||||
main = paste("r", dist, "(", n, ")", sep = ""),
|
||||
col = "#75AADB",
|
||||
border = "white"
|
||||
)
|
||||
})
|
||||
|
||||
# Generate a summary of the data ----
|
||||
output$summary <- renderPrint({
|
||||
summary(d())
|
||||
})
|
||||
|
||||
# Generate an HTML table view of the data ----
|
||||
output$table <- renderTable({
|
||||
d()
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
6
inst/examples-shiny/07_widgets/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Widgets
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
1
inst/examples-shiny/07_widgets/Readme.md
Normal file
@@ -0,0 +1 @@
|
||||
This example demonstrates some additional widgets included in Shiny, such as `helpText` and `actionButton`. The latter is used to delay rendering output until the user explicitly requests it (a construct which also introduces two important server functions, `eventReactive` and `isolate`).
|
||||
83
inst/examples-shiny/07_widgets/app.R
Normal file
@@ -0,0 +1,83 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for slider demo app ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "More Widgets",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Select a dataset ----
|
||||
selectInput(
|
||||
"dataset",
|
||||
"Choose a dataset:",
|
||||
choices = c("rock", "pressure", "cars")
|
||||
),
|
||||
|
||||
# Input: Specify the number of observations to view ----
|
||||
numericInput("obs", "Number of observations to view:", 10),
|
||||
|
||||
# Include clarifying text ----
|
||||
helpText(
|
||||
"Note: while the data view will show only the specified",
|
||||
"number of observations, the summary will still be based",
|
||||
"on the full dataset."
|
||||
),
|
||||
|
||||
# Input: actionButton() to defer the rendering of output ----
|
||||
# until the user explicitly clicks the button (rather than
|
||||
# doing it immediately when inputs change). This is useful if
|
||||
# the computations required to render output are inordinately
|
||||
# time-consuming.
|
||||
actionButton("update", "Update View")
|
||||
),
|
||||
|
||||
# Output: Header + summary of distribution ----
|
||||
h4("Summary"),
|
||||
verbatimTextOutput("summary"),
|
||||
|
||||
# Output: Header + table of distribution ----
|
||||
h4("Observations"),
|
||||
tableOutput("view")
|
||||
)
|
||||
|
||||
# Define server logic to summarize and view selected dataset ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Return the requested dataset ----
|
||||
# Note that we use eventReactive() here, which depends on
|
||||
# input$update (the action button), so that the output is only
|
||||
# updated when the user clicks the button
|
||||
datasetInput <- eventReactive(
|
||||
input$update,
|
||||
{
|
||||
switch(
|
||||
input$dataset,
|
||||
"rock" = rock,
|
||||
"pressure" = pressure,
|
||||
"cars" = cars
|
||||
)
|
||||
},
|
||||
ignoreNULL = FALSE
|
||||
)
|
||||
|
||||
# Generate a summary of the dataset ----
|
||||
output$summary <- renderPrint({
|
||||
dataset <- datasetInput()
|
||||
summary(dataset)
|
||||
})
|
||||
|
||||
# Show the first "n" observations ----
|
||||
# The use of isolate() is necessary because we don't want the table
|
||||
# to update whenever input$obs changes (only when the user clicks
|
||||
# the action button)
|
||||
output$view <- renderTable({
|
||||
head(datasetInput(), n = isolate(input$obs))
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
@@ -2,6 +2,5 @@ Title: Custom HTML UI
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
DisplayMode: Showcase
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
@@ -7,12 +7,14 @@ server <- function(input, output) {
|
||||
# This is called whenever the inputs change. The output functions
|
||||
# defined below then use the value computed from this expression
|
||||
d <- reactive({
|
||||
dist <- switch(input$dist,
|
||||
norm = rnorm,
|
||||
unif = runif,
|
||||
lnorm = rlnorm,
|
||||
exp = rexp,
|
||||
rnorm)
|
||||
dist <- switch(
|
||||
input$dist,
|
||||
norm = rnorm,
|
||||
unif = runif,
|
||||
lnorm = rlnorm,
|
||||
exp = rexp,
|
||||
rnorm
|
||||
)
|
||||
|
||||
dist(input$n)
|
||||
})
|
||||
@@ -26,9 +28,12 @@ server <- function(input, output) {
|
||||
dist <- input$dist
|
||||
n <- input$n
|
||||
|
||||
hist(d(),
|
||||
main = paste("r", dist, "(", n, ")", sep = ""),
|
||||
col = "#75AADB", border = "white")
|
||||
hist(
|
||||
d(),
|
||||
main = paste("r", dist, "(", n, ")", sep = ""),
|
||||
col = "#75AADB",
|
||||
border = "white"
|
||||
)
|
||||
})
|
||||
|
||||
# Generate a summary of the data ----
|
||||
@@ -40,7 +45,6 @@ server <- function(input, output) {
|
||||
output$table <- renderTable({
|
||||
head(data.frame(x = d()))
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
6
inst/examples-shiny/09_upload/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: File Upload
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
3
inst/examples-shiny/09_upload/Readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
We can add a file upload input in the UI using the function `fileInput()`,
|
||||
e.g. `fileInput('foo')`. In the `server` function, we can access the
|
||||
uploaded files via `input$foo`.
|
||||
99
inst/examples-shiny/09_upload/app.R
Normal file
@@ -0,0 +1,99 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for slider demo app ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Uploading Files",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Select a file ----
|
||||
fileInput(
|
||||
"file1",
|
||||
"Choose CSV File",
|
||||
multiple = TRUE,
|
||||
accept = c(
|
||||
"text/csv",
|
||||
"text/comma-separated-values,text/plain",
|
||||
".csv"
|
||||
)
|
||||
),
|
||||
|
||||
# Horizontal line ----
|
||||
tags$hr(),
|
||||
|
||||
# Input: Checkbox if file has header ----
|
||||
checkboxInput("header", "Header", TRUE),
|
||||
|
||||
# Input: Select separator ----
|
||||
radioButtons(
|
||||
"sep",
|
||||
"Separator",
|
||||
choices = c(
|
||||
Comma = ",",
|
||||
Semicolon = ";",
|
||||
Tab = "\t"
|
||||
),
|
||||
selected = ","
|
||||
),
|
||||
|
||||
# Input: Select quotes ----
|
||||
radioButtons(
|
||||
"quote",
|
||||
"Quote",
|
||||
choices = c(
|
||||
None = "",
|
||||
"Double Quote" = '"',
|
||||
"Single Quote" = "'"
|
||||
),
|
||||
selected = '"'
|
||||
),
|
||||
|
||||
# Horizontal line ----
|
||||
tags$hr(),
|
||||
|
||||
# Input: Select number of rows to display ----
|
||||
radioButtons(
|
||||
"disp",
|
||||
"Display",
|
||||
choices = c(
|
||||
Head = "head",
|
||||
All = "all"
|
||||
),
|
||||
selected = "head"
|
||||
)
|
||||
),
|
||||
|
||||
# Output: Data file ----
|
||||
tableOutput("contents")
|
||||
)
|
||||
|
||||
# Define server logic to read selected file ----
|
||||
server <- function(input, output) {
|
||||
output$contents <- renderTable({
|
||||
# input$file1 will be NULL initially. After the user selects
|
||||
# and uploads a file, head of that data file by default,
|
||||
# or all rows if selected, will be shown.
|
||||
|
||||
req(input$file1)
|
||||
|
||||
df <- read.csv(
|
||||
input$file1$datapath,
|
||||
header = input$header,
|
||||
sep = input$sep,
|
||||
quote = input$quote
|
||||
)
|
||||
|
||||
if (input$disp == "head") {
|
||||
return(head(df))
|
||||
} else {
|
||||
return(df)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
6
inst/examples-shiny/10_download/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: File Download
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
2
inst/examples-shiny/10_download/Readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
We can add a download button to the UI using `downloadButton()`, and write
|
||||
the content of the file in `downloadHandler()` in the `server` function.
|
||||
56
inst/examples-shiny/10_download/app.R
Normal file
@@ -0,0 +1,56 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for slider demo app ----
|
||||
ui <- page_sidebar(
|
||||
|
||||
# App title ----
|
||||
title = "Downloading Data",
|
||||
|
||||
# Sidebar panel for inputs ----
|
||||
sidebar = sidebar(
|
||||
|
||||
# Input: Choose dataset ----
|
||||
selectInput(
|
||||
"dataset",
|
||||
"Choose a dataset:",
|
||||
choices = c("rock", "pressure", "cars")
|
||||
),
|
||||
|
||||
# Button
|
||||
downloadButton("downloadData", "Download")
|
||||
),
|
||||
tableOutput("table")
|
||||
)
|
||||
|
||||
# Define server logic to display and download selected file ----
|
||||
server <- function(input, output) {
|
||||
|
||||
# Reactive value for selected dataset ----
|
||||
datasetInput <- reactive({
|
||||
switch(
|
||||
input$dataset,
|
||||
"rock" = rock,
|
||||
"pressure" = pressure,
|
||||
"cars" = cars
|
||||
)
|
||||
})
|
||||
|
||||
# Table of selected dataset ----
|
||||
output$table <- renderTable({
|
||||
datasetInput()
|
||||
})
|
||||
|
||||
# Downloadable csv of selected dataset ----
|
||||
output$downloadData <- downloadHandler(
|
||||
filename = function() {
|
||||
paste(input$dataset, ".csv", sep = "")
|
||||
},
|
||||
content = function(file) {
|
||||
write.csv(datasetInput(), file, row.names = FALSE)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
6
inst/examples-shiny/11_timer/DESCRIPTION
Normal file
@@ -0,0 +1,6 @@
|
||||
Title: Timer
|
||||
Author: RStudio, Inc.
|
||||
AuthorUrl: http://www.rstudio.com/
|
||||
License: MIT
|
||||
Tags: getting-started
|
||||
Type: Shiny
|
||||
4
inst/examples-shiny/11_timer/Readme.md
Normal file
@@ -0,0 +1,4 @@
|
||||
The function `invalidateLater()` can be used to invalidate an observer or
|
||||
reactive expression in a given number of milliseconds. In this example, the
|
||||
output `currentTime` is updated every second, so it shows the current time
|
||||
on a second basis.
|
||||
18
inst/examples-shiny/11_timer/app.R
Normal file
@@ -0,0 +1,18 @@
|
||||
library(shiny)
|
||||
library(bslib)
|
||||
|
||||
# Define UI for displaying current time ----
|
||||
ui <- page_fluid(
|
||||
h2(textOutput("currentTime"))
|
||||
)
|
||||
|
||||
# Define server logic to show current time, update every second ----
|
||||
server <- function(input, output, session) {
|
||||
output$currentTime <- renderText({
|
||||
invalidateLater(1000, session)
|
||||
paste("The current time is", Sys.time())
|
||||
})
|
||||
}
|
||||
|
||||
# Create Shiny app ----
|
||||
shinyApp(ui, server)
|
||||
2
inst/www/shared/busy-indicators/busy-indicators.css
Normal file
3
inst/www/shared/busy-indicators/busy-indicators.js
Normal file
@@ -0,0 +1,3 @@
|
||||
/*! shiny 1.8.1.9001 | (c) 2012-2024 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
"use strict";(function(){document.documentElement.classList.add("shiny-not-yet-idle");$(document).one("shiny:idle",function(){document.documentElement.classList.remove("shiny-not-yet-idle")});})();
|
||||
//# sourceMappingURL=busy-indicators.js.map
|
||||
7
inst/www/shared/busy-indicators/busy-indicators.js.map
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../../../srcts/extras/busy-indicators/busy-indicators.ts"],
|
||||
"sourcesContent": ["// Think of this like the .shiny-busy class that shiny.js puts on the root element,\n// except it's added before shiny.js is initialized, connected, etc.\ndocument.documentElement.classList.add(\"shiny-not-yet-idle\");\n$(document).one(\"shiny:idle\", function () {\n document.documentElement.classList.remove(\"shiny-not-yet-idle\");\n});"],
|
||||
"mappings": ";yBAEA,SAAS,gBAAgB,UAAU,IAAI,oBAAoB,EAC3D,EAAE,QAAQ,EAAE,IAAI,aAAc,UAAY,CACxC,SAAS,gBAAgB,UAAU,OAAO,oBAAoB,CAChE,CAAC",
|
||||
"names": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><circle cx="12" cy="3" r="1"><animate id="spinner_7Z73" begin="0;spinner_tKsu.end-0.5s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="16.50" cy="4.21" r="1"><animate id="spinner_Wd87" begin="spinner_7Z73.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="7.50" cy="4.21" r="1"><animate id="spinner_tKsu" begin="spinner_9Qlc.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="19.79" cy="7.50" r="1"><animate id="spinner_lMMO" begin="spinner_Wd87.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="4.21" cy="7.50" r="1"><animate id="spinner_9Qlc" begin="spinner_Khxv.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="21.00" cy="12.00" r="1"><animate id="spinner_5L9t" begin="spinner_lMMO.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="3.00" cy="12.00" r="1"><animate id="spinner_Khxv" begin="spinner_ld6P.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="19.79" cy="16.50" r="1"><animate id="spinner_BfTD" begin="spinner_5L9t.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="4.21" cy="16.50" r="1"><animate id="spinner_ld6P" begin="spinner_XyBs.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="16.50" cy="19.79" r="1"><animate id="spinner_7gAK" begin="spinner_BfTD.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="7.50" cy="19.79" r="1"><animate id="spinner_XyBs" begin="spinner_HiSl.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="12" cy="21" r="1"><animate id="spinner_HiSl" begin="spinner_7gAK.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="1;2;1" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><animateTransform attributeName="transform" type="rotate" dur="6s" values="360 12 12;0 12 12" repeatCount="indefinite"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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="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"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 471 B |
1
inst/www/shared/busy-indicators/spinners/180-ring.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 368 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 520 B |
1
inst/www/shared/busy-indicators/spinners/270-ring.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 417 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" r="3"><animate id="spinner_qFRN" begin="0;spinner_OcgL.end+0.25s" attributeName="cy" calcMode="spline" dur="0.6s" values="12;6;12" keySplines=".33,.66,.66,1;.33,0,.66,.33"/></circle><circle cx="12" cy="12" r="3"><animate begin="spinner_qFRN.begin+0.1s" attributeName="cy" calcMode="spline" dur="0.6s" values="12;6;12" keySplines=".33,.66,.66,1;.33,0,.66,.33"/></circle><circle cx="20" cy="12" r="3"><animate id="spinner_OcgL" begin="spinner_qFRN.begin+0.2s" attributeName="cy" calcMode="spline" dur="0.6s" values="12;6;12" keySplines=".33,.66,.66,1;.33,0,.66,.33"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 664 B |
1
inst/www/shared/busy-indicators/spinners/3-dots-fade.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" r="3" opacity="1"><animate id="spinner_qYjJ" begin="0;spinner_t4KZ.end-0.25s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></circle><circle cx="12" cy="12" r="3" opacity=".4"><animate begin="spinner_qYjJ.begin+0.15s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></circle><circle cx="20" cy="12" r="3" opacity=".3"><animate id="spinner_t4KZ" begin="spinner_qYjJ.begin+0.3s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 577 B |
1
inst/www/shared/busy-indicators/spinners/3-dots-move.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" r="0"><animate begin="0;spinner_z0Or.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="0;3" fill="freeze"/><animate begin="spinner_OLMs.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="4;12" fill="freeze"/><animate begin="spinner_UHR2.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="12;20" fill="freeze"/><animate id="spinner_lo66" begin="spinner_Aguh.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="3;0" fill="freeze"/><animate id="spinner_z0Or" begin="spinner_lo66.end" attributeName="cx" dur="0.001s" values="20;4" fill="freeze"/></circle><circle cx="4" cy="12" r="3"><animate begin="0;spinner_z0Or.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="4;12" fill="freeze"/><animate begin="spinner_OLMs.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="12;20" fill="freeze"/><animate id="spinner_JsnR" begin="spinner_UHR2.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="3;0" fill="freeze"/><animate id="spinner_Aguh" begin="spinner_JsnR.end" attributeName="cx" dur="0.001s" values="20;4" fill="freeze"/><animate begin="spinner_Aguh.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="0;3" fill="freeze"/></circle><circle cx="12" cy="12" r="3"><animate begin="0;spinner_z0Or.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="12;20" fill="freeze"/><animate id="spinner_hSjk" begin="spinner_OLMs.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="3;0" fill="freeze"/><animate id="spinner_UHR2" begin="spinner_hSjk.end" attributeName="cx" dur="0.001s" values="20;4" fill="freeze"/><animate begin="spinner_UHR2.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="0;3" fill="freeze"/><animate begin="spinner_Aguh.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="4;12" fill="freeze"/></circle><circle cx="20" cy="12" r="3"><animate id="spinner_4v5M" begin="0;spinner_z0Or.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="3;0" fill="freeze"/><animate id="spinner_OLMs" begin="spinner_4v5M.end" attributeName="cx" dur="0.001s" values="20;4" fill="freeze"/><animate begin="spinner_OLMs.end" attributeName="r" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="0;3" fill="freeze"/><animate begin="spinner_UHR2.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="4;12" fill="freeze"/><animate begin="spinner_Aguh.end" attributeName="cx" calcMode="spline" dur="0.5s" keySplines=".36,.6,.31,1" values="12;20" fill="freeze"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="3"/><g><circle cx="4" cy="12" r="3"/><circle cx="20" cy="12" r="3"/><animateTransform attributeName="transform" type="rotate" calcMode="spline" dur="1s" keySplines=".36,.6,.31,1;.36,.6,.31,1" values="0 12 12;180 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
|
||||
|
After Width: | Height: | Size: 353 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" r="1.5"><animate attributeName="r" dur="0.75s" values="1.5;3;1.5" repeatCount="indefinite"/></circle><circle cx="12" cy="12" r="3"><animate attributeName="r" dur="0.75s" values="3;1.5;3" repeatCount="indefinite"/></circle><circle cx="20" cy="12" r="1.5"><animate attributeName="r" dur="0.75s" values="1.5;3;1.5" repeatCount="indefinite"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 437 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" r="3"><animate id="spinner_jObz" begin="0;spinner_vwSQ.end-0.25s" attributeName="r" dur="0.75s" values="3;.2;3"/></circle><circle cx="12" cy="12" r="3"><animate begin="spinner_jObz.end-0.6s" attributeName="r" dur="0.75s" values="3;.2;3"/></circle><circle cx="20" cy="12" r="3"><animate id="spinner_vwSQ" begin="spinner_jObz.end-0.45s" attributeName="r" dur="0.75s" values="3;.2;3"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 481 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><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"/><animateTransform attributeName="transform" type="rotate" calcMode="discrete" dur="0.75s" values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
|
||||
|
After Width: | Height: | Size: 670 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="3" r="0"><animate id="spinner_6RAU" begin="0;spinner_GErc.end-0.5s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="16.50" cy="4.21" r="0"><animate id="spinner_khXL" begin="spinner_6RAU.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="7.50" cy="4.21" r="0"><animate id="spinner_GErc" begin="spinner_JEaM.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="19.79" cy="7.50" r="0"><animate id="spinner_9orP" begin="spinner_khXL.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="4.21" cy="7.50" r="0"><animate id="spinner_JEaM" begin="spinner_RwRf.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="21.00" cy="12.00" r="0"><animate id="spinner_W8J5" begin="spinner_9orP.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="3.00" cy="12.00" r="0"><animate id="spinner_RwRf" begin="spinner_tByH.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="19.79" cy="16.50" r="0"><animate id="spinner_tedm" begin="spinner_W8J5.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="4.21" cy="16.50" r="0"><animate id="spinner_tByH" begin="spinner_c3Lr.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="16.50" cy="19.79" r="0"><animate id="spinner_QxRo" begin="spinner_tedm.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="7.50" cy="19.79" r="0"><animate id="spinner_c3Lr" begin="spinner_PW3C.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle><circle cx="12" cy="21" r="0"><animate id="spinner_PW3C" begin="spinner_QxRo.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keySplines=".27,.42,.37,.99;.53,0,.61,.73"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="3" r="0"><animate id="spinner_318l" begin="0;spinner_cvkU.end-0.5s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="16.50" cy="4.21" r="0"><animate id="spinner_g5Gj" begin="spinner_318l.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="7.50" cy="4.21" r="0"><animate id="spinner_cvkU" begin="spinner_Uuk0.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="19.79" cy="7.50" r="0"><animate id="spinner_e8rM" begin="spinner_g5Gj.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="4.21" cy="7.50" r="0"><animate id="spinner_Uuk0" begin="spinner_z7ol.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="21.00" cy="12.00" r="0"><animate id="spinner_MooL" begin="spinner_e8rM.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="3.00" cy="12.00" r="0"><animate id="spinner_z7ol" begin="spinner_KEoo.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="19.79" cy="16.50" r="0"><animate id="spinner_btyV" begin="spinner_MooL.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="4.21" cy="16.50" r="0"><animate id="spinner_KEoo" begin="spinner_1IYD.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="16.50" cy="19.79" r="0"><animate id="spinner_1sIS" begin="spinner_btyV.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="7.50" cy="19.79" r="0"><animate id="spinner_1IYD" begin="spinner_NWhh.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle><circle cx="12" cy="21" r="0"><animate id="spinner_NWhh" begin="spinner_1sIS.begin+0.1s" attributeName="r" calcMode="spline" dur="0.6s" values="0;2;0" keyTimes="0;.2;1" keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><circle cx="3" cy="12" r="2"/><circle cx="21" cy="12" r="2"/><circle cx="12" cy="21" r="2"/><circle cx="12" cy="3" r="2"/><circle cx="5.64" cy="5.64" r="2"/><circle cx="18.36" cy="18.36" r="2"/><circle cx="5.64" cy="18.36" r="2"/><circle cx="18.36" cy="5.64" r="2"/><animateTransform attributeName="transform" type="rotate" dur="1.5s" values="0 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
|
||||
|
After Width: | Height: | Size: 462 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 465 B |
1
inst/www/shared/busy-indicators/spinners/90-ring.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 362 B |
20
inst/www/shared/busy-indicators/spinners/LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
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
inst/www/shared/busy-indicators/spinners/bars-fade.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="4" width="6" height="14" opacity="1"><animate id="spinner_rQ7m" begin="0;spinner_2dMV.end-0.25s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></rect><rect x="9" y="4" width="6" height="14" opacity=".4"><animate begin="spinner_rQ7m.begin+0.15s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></rect><rect x="17" y="4" width="6" height="14" opacity=".3"><animate id="spinner_2dMV" begin="spinner_rQ7m.begin+0.3s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 603 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><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)"/><animateTransform attributeName="transform" type="rotate" calcMode="discrete" dur="0.75s" values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
|
||||
|
After Width: | Height: | Size: 872 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="4" width="6" height="14" opacity="1"><animate id="spinner_aqiq" begin="0;spinner_xVBj.end-0.25s" attributeName="y" dur="0.75s" values="1;5" fill="freeze"/><animate begin="0;spinner_xVBj.end-0.25s" attributeName="height" dur="0.75s" values="22;14" fill="freeze"/><animate begin="0;spinner_xVBj.end-0.25s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></rect><rect x="9" y="4" width="6" height="14" opacity=".4"><animate begin="spinner_aqiq.begin+0.15s" attributeName="y" dur="0.75s" values="1;5" fill="freeze"/><animate begin="spinner_aqiq.begin+0.15s" attributeName="height" dur="0.75s" values="22;14" fill="freeze"/><animate begin="spinner_aqiq.begin+0.15s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></rect><rect x="17" y="4" width="6" height="14" opacity=".3"><animate id="spinner_xVBj" begin="spinner_aqiq.begin+0.3s" attributeName="y" dur="0.75s" values="1;5" fill="freeze"/><animate begin="spinner_aqiq.begin+0.3s" attributeName="height" dur="0.75s" values="22;14" fill="freeze"/><animate begin="spinner_aqiq.begin+0.3s" attributeName="opacity" dur="0.75s" values="1;.2" fill="freeze"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="6" width="2.8" height="12"><animate begin="spinner_Diec.begin+0.4s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/><animate begin="spinner_Diec.begin+0.4s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/></rect><rect x="5.8" y="6" width="2.8" height="12"><animate begin="spinner_Diec.begin+0.2s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/><animate begin="spinner_Diec.begin+0.2s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/></rect><rect x="10.6" y="6" width="2.8" height="12"><animate id="spinner_Diec" begin="0;spinner_dm8s.end-0.1s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/><animate begin="0;spinner_dm8s.end-0.1s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/></rect><rect x="15.4" y="6" width="2.8" height="12"><animate begin="spinner_Diec.begin+0.2s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/><animate begin="spinner_Diec.begin+0.2s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/></rect><rect x="20.2" y="6" width="2.8" height="12"><animate id="spinner_dm8s" begin="spinner_Diec.begin+0.4s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/><animate begin="spinner_Diec.begin+0.4s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".14,.73,.34,1;.65,.26,.82,.45"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
inst/www/shared/busy-indicators/spinners/bars-scale.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="6" width="2.8" height="12"><animate id="spinner_CcmT" begin="0;spinner_IzZB.end-0.1s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/><animate begin="0;spinner_IzZB.end-0.1s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/></rect><rect x="5.8" y="6" width="2.8" height="12"><animate begin="spinner_CcmT.begin+0.1s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/><animate begin="spinner_CcmT.begin+0.1s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/></rect><rect x="10.6" y="6" width="2.8" height="12"><animate begin="spinner_CcmT.begin+0.2s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/><animate begin="spinner_CcmT.begin+0.2s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/></rect><rect x="15.4" y="6" width="2.8" height="12"><animate begin="spinner_CcmT.begin+0.3s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/><animate begin="spinner_CcmT.begin+0.3s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/></rect><rect x="20.2" y="6" width="2.8" height="12"><animate id="spinner_IzZB" begin="spinner_CcmT.begin+0.4s" attributeName="y" calcMode="spline" dur="0.6s" values="6;1;6" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/><animate begin="spinner_CcmT.begin+0.4s" attributeName="height" calcMode="spline" dur="0.6s" values="12;22;12" keySplines=".36,.61,.3,.98;.36,.61,.3,.98"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1.5" y="1.5" rx="1" width="9" height="9"><animate id="spinner_M16P" begin="0;spinner_wNI2.end+0.15s" attributeName="x" dur="0.6s" values="1.5;.5;1.5" keyTimes="0;.2;1"/><animate begin="0;spinner_wNI2.end+0.15s" attributeName="y" dur="0.6s" values="1.5;.5;1.5" keyTimes="0;.2;1"/><animate begin="0;spinner_wNI2.end+0.15s" attributeName="width" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/><animate begin="0;spinner_wNI2.end+0.15s" attributeName="height" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/></rect><rect x="13.5" y="1.5" rx="1" width="9" height="9"><animate begin="spinner_M16P.begin+0.15s" attributeName="x" dur="0.6s" values="13.5;12.5;13.5" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.15s" attributeName="y" dur="0.6s" values="1.5;.5;1.5" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.15s" attributeName="width" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.15s" attributeName="height" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/></rect><rect x="13.5" y="13.5" rx="1" width="9" height="9"><animate begin="spinner_M16P.begin+0.3s" attributeName="x" dur="0.6s" values="13.5;12.5;13.5" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.3s" attributeName="y" dur="0.6s" values="13.5;12.5;13.5" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.3s" attributeName="width" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.3s" attributeName="height" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/></rect><rect x="1.5" y="13.5" rx="1" width="9" height="9"><animate id="spinner_wNI2" begin="spinner_M16P.begin+0.45s" attributeName="x" dur="0.6s" values="1.5;.5;1.5" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.45s" attributeName="y" dur="0.6s" values="13.5;12.5;13.5" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.45s" attributeName="width" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/><animate begin="spinner_M16P.begin+0.45s" attributeName="height" dur="0.6s" values="9;11;9" keyTimes="0;.2;1"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" rx="1" width="10" height="10"><animate id="spinner_FFyM" begin="0;spinner_HDCY.end" attributeName="x" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_AIvE" begin="spinner_1FwE.end" attributeName="y" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_wWCL" begin="spinner_gH4o.end" attributeName="x" dur="0.2s" values="13;1" fill="freeze"/><animate id="spinner_S3Gg" begin="spinner_Q0bx.end" attributeName="y" dur="0.2s" values="13;1" fill="freeze"/></rect><rect x="1" y="13" rx="1" width="10" height="10"><animate id="spinner_1FwE" begin="spinner_FFyM.end" attributeName="y" dur="0.2s" values="13;1" fill="freeze"/><animate id="spinner_gH4o" begin="spinner_AIvE.end" attributeName="x" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_Q0bx" begin="spinner_wWCL.end" attributeName="y" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_HDCY" begin="spinner_S3Gg.end" attributeName="x" dur="0.2s" values="13;1" fill="freeze"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" rx="1" width="10" height="10"><animate id="spinner_c7A9" begin="0;spinner_23zP.end" attributeName="x" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_Acnw" begin="spinner_ZmWi.end" attributeName="y" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_iIcm" begin="spinner_zfQN.end" attributeName="x" dur="0.2s" values="13;1" fill="freeze"/><animate id="spinner_WX4U" begin="spinner_rRAc.end" attributeName="y" dur="0.2s" values="13;1" fill="freeze"/></rect><rect x="1" y="13" rx="1" width="10" height="10"><animate id="spinner_YLx7" begin="spinner_c7A9.end" attributeName="y" dur="0.2s" values="13;1" fill="freeze"/><animate id="spinner_vwnJ" begin="spinner_Acnw.end" attributeName="x" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_KQuy" begin="spinner_iIcm.end" attributeName="y" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_arKy" begin="spinner_WX4U.end" attributeName="x" dur="0.2s" values="13;1" fill="freeze"/></rect><rect x="13" y="13" rx="1" width="10" height="10"><animate id="spinner_ZmWi" begin="spinner_YLx7.end" attributeName="x" dur="0.2s" values="13;1" fill="freeze"/><animate id="spinner_zfQN" begin="spinner_vwnJ.end" attributeName="y" dur="0.2s" values="13;1" fill="freeze"/><animate id="spinner_rRAc" begin="spinner_KQuy.end" attributeName="x" dur="0.2s" values="1;13" fill="freeze"/><animate id="spinner_23zP" begin="spinner_arKy.end" attributeName="y" dur="0.2s" values="1;13" fill="freeze"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
inst/www/shared/busy-indicators/spinners/blocks-wave.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="7.33" height="7.33"><animate id="spinner_oJFS" begin="0;spinner_5T1J.end+0.2s" attributeName="x" dur="0.6s" values="1;4;1"/><animate begin="0;spinner_5T1J.end+0.2s" attributeName="y" dur="0.6s" values="1;4;1"/><animate begin="0;spinner_5T1J.end+0.2s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="0;spinner_5T1J.end+0.2s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="8.33" y="1" width="7.33" height="7.33"><animate begin="spinner_oJFS.begin+0.1s" attributeName="x" dur="0.6s" values="8.33;11.33;8.33"/><animate begin="spinner_oJFS.begin+0.1s" attributeName="y" dur="0.6s" values="1;4;1"/><animate begin="spinner_oJFS.begin+0.1s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.1s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="1" y="8.33" width="7.33" height="7.33"><animate begin="spinner_oJFS.begin+0.1s" attributeName="x" dur="0.6s" values="1;4;1"/><animate begin="spinner_oJFS.begin+0.1s" attributeName="y" dur="0.6s" values="8.33;11.33;8.33"/><animate begin="spinner_oJFS.begin+0.1s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.1s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="15.66" y="1" width="7.33" height="7.33"><animate begin="spinner_oJFS.begin+0.2s" attributeName="x" dur="0.6s" values="15.66;18.66;15.66"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="y" dur="0.6s" values="1;4;1"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="8.33" y="8.33" width="7.33" height="7.33"><animate begin="spinner_oJFS.begin+0.2s" attributeName="x" dur="0.6s" values="8.33;11.33;8.33"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="y" dur="0.6s" values="8.33;11.33;8.33"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="1" y="15.66" width="7.33" height="7.33"><animate begin="spinner_oJFS.begin+0.2s" attributeName="x" dur="0.6s" values="1;4;1"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="y" dur="0.6s" values="15.66;18.66;15.66"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.2s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="15.66" y="8.33" width="7.33" height="7.33"><animate begin="spinner_oJFS.begin+0.3s" attributeName="x" dur="0.6s" values="15.66;18.66;15.66"/><animate begin="spinner_oJFS.begin+0.3s" attributeName="y" dur="0.6s" values="8.33;11.33;8.33"/><animate begin="spinner_oJFS.begin+0.3s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.3s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="8.33" y="15.66" width="7.33" height="7.33"><animate begin="spinner_oJFS.begin+0.3s" attributeName="x" dur="0.6s" values="8.33;11.33;8.33"/><animate begin="spinner_oJFS.begin+0.3s" attributeName="y" dur="0.6s" values="15.66;18.66;15.66"/><animate begin="spinner_oJFS.begin+0.3s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.3s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect><rect x="15.66" y="15.66" width="7.33" height="7.33"><animate id="spinner_5T1J" begin="spinner_oJFS.begin+0.4s" attributeName="x" dur="0.6s" values="15.66;18.66;15.66"/><animate begin="spinner_oJFS.begin+0.4s" attributeName="y" dur="0.6s" values="15.66;18.66;15.66"/><animate begin="spinner_oJFS.begin+0.4s" attributeName="width" dur="0.6s" values="7.33;1.33;7.33"/><animate begin="spinner_oJFS.begin+0.4s" attributeName="height" dur="0.6s" values="7.33;1.33;7.33"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><ellipse cx="12" cy="5" rx="4" ry="4"><animate id="spinner_jbYs" begin="0;spinner_JZdr.end" attributeName="cy" calcMode="spline" dur="0.375s" values="5;20" keySplines=".33,0,.66,.33" fill="freeze"/><animate begin="spinner_jbYs.end" attributeName="rx" calcMode="spline" dur="0.05s" values="4;4.8;4" keySplines=".33,0,.66,.33;.33,.66,.66,1"/><animate begin="spinner_jbYs.end" attributeName="ry" calcMode="spline" dur="0.05s" values="4;3;4" keySplines=".33,0,.66,.33;.33,.66,.66,1"/><animate id="spinner_ADF4" begin="spinner_jbYs.end" attributeName="cy" calcMode="spline" dur="0.025s" values="20;20.5" keySplines=".33,0,.66,.33"/><animate id="spinner_JZdr" begin="spinner_ADF4.end" attributeName="cy" calcMode="spline" dur="0.4s" values="20.5;5" keySplines=".33,.66,.66,1"/></ellipse></svg>
|
||||
|
After Width: | Height: | Size: 848 B |
1
inst/www/shared/busy-indicators/spinners/clock.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path 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"/><rect x="11" y="6" rx="1" width="2" height="7"><animateTransform attributeName="transform" type="rotate" dur="9s" values="0 12 12;360 12 12" repeatCount="indefinite"/></rect><rect x="11" y="11" rx="1" width="2" height="9"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></rect></svg>
|
||||
|
After Width: | Height: | Size: 508 B |
1
inst/www/shared/busy-indicators/spinners/dot-revolve.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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"/><circle cx="12" cy="2.5" r="1.5"><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 335 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2,12A10.94,10.94,0,0,1,5,4.65c-.21-.19-.42-.36-.62-.55h0A11,11,0,0,0,12,23c.34,0,.67,0,1-.05C6,23,2,17.74,2,12Z"><animateTransform attributeName="transform" type="rotate" dur="0.6s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 319 B |
1
inst/www/shared/busy-indicators/spinners/eclipse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2,12A11.2,11.2,0,0,1,13,1.05C12.67,1,12.34,1,12,1a11,11,0,0,0,0,22c.34,0,.67,0,1-.05C6,23,2,17.74,2,12Z"><animateTransform attributeName="transform" type="rotate" dur="0.6s" values="0 12 12;360 12 12" repeatCount="indefinite"/></path></svg>
|
||||
|
After Width: | Height: | Size: 311 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><defs><filter id="spinner-gF00"><feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="y"/><feColorMatrix in="y" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" result="z"/><feBlend in="SourceGraphic" in2="z"/></filter></defs><g filter="url(#spinner-gF00)"><circle cx="4" cy="12" r="3"><animate attributeName="cx" calcMode="spline" dur="0.75s" values="4;9;4" keySplines=".56,.52,.17,.98;.56,.52,.17,.98" repeatCount="indefinite"/><animate attributeName="r" calcMode="spline" dur="0.75s" values="3;8;3" keySplines=".56,.52,.17,.98;.56,.52,.17,.98" repeatCount="indefinite"/></circle><circle cx="15" cy="12" r="8"><animate attributeName="cx" calcMode="spline" dur="0.75s" values="15;20;15" keySplines=".56,.52,.17,.98;.56,.52,.17,.98" repeatCount="indefinite"/><animate attributeName="r" calcMode="spline" dur="0.75s" values="8;3;8" keySplines=".56,.52,.17,.98;.56,.52,.17,.98" repeatCount="indefinite"/></circle></g></svg>
|
||||
|
After Width: | Height: | Size: 1006 B |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><defs><filter id="spinner-gF01"><feGaussianBlur in="SourceGraphic" stdDeviation="1" result="y"/><feColorMatrix in="y" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" result="z"/><feBlend in="SourceGraphic" in2="z"/></filter></defs><g filter="url(#spinner-gF01)"><circle cx="5" cy="12" r="4"><animate attributeName="cx" calcMode="spline" dur="2s" values="5;8;5" keySplines=".36,.62,.43,.99;.79,0,.58,.57" repeatCount="indefinite"/></circle><circle cx="19" cy="12" r="4"><animate attributeName="cx" calcMode="spline" dur="2s" values="19;16;19" keySplines=".36,.62,.43,.99;.79,0,.58,.57" repeatCount="indefinite"/></circle><animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
|
||||
|
After Width: | Height: | Size: 831 B |
1
inst/www/shared/busy-indicators/spinners/pulse-2.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="0"><animate id="spinner_lNK6" begin="0;spinner_NDtD.begin+0.6s" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="0;spinner_NDtD.begin+0.6s" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle><circle cx="12" cy="12" r="0"><animate id="spinner_NDtD" begin="spinner_lNK6.begin+0.6s" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="spinner_lNK6.begin+0.6s" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 775 B |
1
inst/www/shared/busy-indicators/spinners/pulse-3.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="0"><animate id="spinner_0Nme" begin="0;spinner_ITag.begin+0.4s" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="0;spinner_ITag.begin+0.4s" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle><circle cx="12" cy="12" r="0"><animate id="spinner_f83A" begin="spinner_0Nme.begin+0.4s" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="spinner_0Nme.begin+0.4s" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle><circle cx="12" cy="12" r="0"><animate id="spinner_ITag" begin="spinner_0Nme.begin+0.8s" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="spinner_0Nme.begin+0.8s" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="0"><animate id="spinner_kIfO" begin="0;spinner_xBIM.end" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="0;spinner_xBIM.end" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle><circle cx="12" cy="12" r="0"><animate id="spinner_Pbsh" begin="spinner_kIfO.begin+0.2s" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="spinner_kIfO.begin+0.2s" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle><circle cx="12" cy="12" r="0"><animate id="spinner_xBIM" begin="spinner_kIfO.begin+0.4s" attributeName="r" calcMode="spline" dur="1.2s" values="0;11" keySplines=".52,.6,.25,.99" fill="freeze"/><animate begin="spinner_kIfO.begin+0.4s" attributeName="opacity" calcMode="spline" dur="1.2s" values="1;0" keySplines=".52,.6,.25,.99" fill="freeze"/></circle></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |