Compare commits

..

2 Commits

Author SHA1 Message Date
cpsievert
0dade0c553 Document (GitHub Actions) 2021-03-22 17:45:21 +00:00
Carson
ad6c1a4660 Revert "remove card argument (at least for now)"
This reverts commit b5b0ba1774.
2021-03-22 12:39:38 -05:00
35 changed files with 91 additions and 200 deletions

View File

@@ -156,7 +156,6 @@ Collate:
'input-select.R'
'input-slider.R'
'input-submit.R'
'input-switch.R'
'input-text.R'
'input-textarea.R'
'input-utils.R'

View File

@@ -280,7 +280,6 @@ export(stopApp)
export(strong)
export(submitButton)
export(suppressDependencies)
export(switchInput)
export(tabPanel)
export(tabPanelBody)
export(tableOutput)
@@ -315,7 +314,6 @@ export(updateRadioButtons)
export(updateSelectInput)
export(updateSelectizeInput)
export(updateSliderInput)
export(updateSwitchInput)
export(updateTabsetPanel)
export(updateTextAreaInput)
export(updateTextInput)

13
NEWS.md
View File

@@ -7,18 +7,7 @@ shiny 1.6.0.9000
* The `format` and `locale` arguments to `sliderInput()` have been removed. They have been deprecated since 0.10.2.2 (released on 2014-12-08).
### New features and improvements
* All uses of `list(...)` have been replaced with `rlang::list2(...)`. This means that you can use trailing `,` without error and use rlang's `!!!` operator to "splice" a list of argument values into `...`. We think this'll be particularly useful for passing a list of `tabPanel()` to their consumers (i.e., `tabsetPanel()`, `navbarPage()`, etc). For example, `tabs <- list(tabPanel("A", "a"), tabPanel("B", "b")); navbarPage(!!!tabs)`. (#3315 and #3328)
* Numerous improvements tabset panels (i.e., `tabPanel()`, `navbarMenu()`, `tabsetPanel()`, `navbarPage()`, etc) (#3315):
* Closed #3322: `tabsetPanel()` and `navlistPanel()` gain `header`/`footer` arguments (inspired by `navbarPage()`'s already existing `header`/`footer`), making it easier to include content that should appear on every tab.
* Closed #3313 and #1823: More informative error when non-`tabPanel()`/`shiny.tag` objects are supplied to `...`.
* Closed #3321: New informative warning when `shiny.tag` object(s) are supplied to `...`. In this case we will continue to create an "empty" nav item and include the content on every tab, but the warning will mention the (new) `header`/`footer` args, which is likely what the user wants.
* Closed #3320: The HTML markup that `tabPanel()` et. al generate (for Bootstrap nav) is now Bootstrap 4+ compliant when used with `theme = bslib::bs_theme()`.
* Closed #1928: `NULL` values are now dropped instead of producing an empty nav item.
### Other improvements
### Minor new features and improvements
* Shiny's core JavaScript code was converted to TypeScript. For the latest development information, please see the [README.md in `./srcts`](https://github.com/rstudio/shiny/tree/master/srcts). (#3296)

View File

@@ -396,7 +396,7 @@ mainPanel <- function(..., width = 8) {
#' }
#' @export
verticalLayout <- function(..., fluid = TRUE) {
lapply(list2(...), function(row) {
lapply(list(...), function(row) {
col <- column(12, row)
if (fluid)
fluidRow(col)
@@ -433,7 +433,7 @@ verticalLayout <- function(..., fluid = TRUE) {
#' @export
flowLayout <- function(..., cellArgs = list()) {
children <- list2(...)
children <- list(...)
childIdx <- !nzchar(names(children) %||% character(length(children)))
attribs <- children[!childIdx]
children <- children[childIdx]
@@ -516,7 +516,7 @@ inputPanel <- function(...) {
#' @export
splitLayout <- function(..., cellWidths = NULL, cellArgs = list()) {
children <- list2(...)
children <- list(...)
childIdx <- !nzchar(names(children) %||% character(length(children)))
attribs <- children[!childIdx]
children <- children[childIdx]
@@ -614,7 +614,7 @@ fillCol <- function(..., flex = 1, width = "100%", height = "100%") {
}
flexfill <- function(..., direction, flex, width = width, height = height) {
children <- list2(...)
children <- list(...)
attrs <- list()
if (!is.null(names(children))) {

View File

@@ -49,7 +49,7 @@ bootstrapPage <- function(..., title = NULL, responsive = deprecated(), theme =
tags$head(tags$link(rel="stylesheet", type="text/css", href=theme))
},
# remainder of tags passed to the function
list2(...)
list(...)
)
# If theme is a bslib::bs_theme() object, bootstrapLib() needs to come first
@@ -707,6 +707,7 @@ tabPanelBody <- function(value, ..., icon = NULL) {
#' conjunction with [tabPanelBody()] and [updateTabsetPanel()] to control the
#' active tab via other input controls. (See example below)}
#' }
#' @param card whether to wrap the navigation controls and content into an 'output card'. This functionality currently requires a [bslib::bs_theme()] in the page layout with `version = 4` or higher.
#' @param position This argument is deprecated; it has been discontinued in
#' Bootstrap 3.
#' @inheritParams navbarPage
@@ -761,6 +762,7 @@ tabsetPanel <- function(...,
type = c("tabs", "pills", "hidden"),
header = NULL,
footer = NULL,
card = FALSE,
position = deprecated()) {
if (lifecycle::is_present(position)) {
shinyDeprecated(
@@ -775,15 +777,34 @@ tabsetPanel <- function(...,
type <- match.arg(type)
tabset <- buildTabset(..., ulClass = paste0("nav nav-", type), id = id, selected = selected)
tags$div(
class = "tabbable",
!!!dropNulls(list(
tabset$navList,
header,
tabset$content,
footer
))
)
nav <- tabset$navList
if (card) {
nav <- tags$div(
class = "card-header",
tagFunction(function() {
if (getCurrentVersion() >= 4) {
return(NULL)
}
stop(
"`tabsetPanel(card = TRUE)` requires Bootstrap 4 or higher. ",
"Please supply `bslib::bs_theme()` to the UI's page layout function ",
"(e.g., `fluidPage(theme = bslib::bs_theme())`).",
call. = FALSE
)
}),
tagAppendAttributes(
nav, class = paste0("card-header-", type)
)
)
}
tabs <- tags$div(class = "tabbable", class = if (card) "card", nav)
content <- dropNulls(list(header, tabset$content, footer))
if (card) {
tagAppendChild(tabs, tags$div(class = "card-body", !!!content))
} else {
tagAppendChildren(tabs, content)
}
}
#' Create a navigation list panel

View File

@@ -1,65 +0,0 @@
#' Switch Input Control
#'
#' Create a switch for toggling a logical value.
#'
#' @inheritParams checkboxInput
#' @return A switch control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [checkboxInput()], [updateSwitchInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#' ui <- fluidPage(
#' switchInput("somevalue", "Some value", FALSE),
#' verbatimTextOutput("value")
#' )
#' server <- function(input, output) {
#' output$value <- renderText({ input$somevalue })
#' }
#' shinyApp(ui, server)
#' }
#'
#' @section Server value:
#' `TRUE` if checked, `FALSE` otherwise.
#'
#' @export
switchInput <- function(inputId, label, value = FALSE, width = NULL) {
value <- restoreInput(id = inputId, default = value)
inputTag <- tags$input(
id = inputId, type = "checkbox",
checked = if (isTRUE(value)) "checked"
)
# TODO: checkboxInput() should do this too (for accessibility)?
labelTag <- shinyInputLabel(inputId, label)
tagFunction(function() {
if (getCurrentVersion() < 4) {
stop(
"switchInput() requires Bootstrap 4 or higher. ",
"Please supply `bslib::bs_theme()` to the UI's page layout function ",
"(e.g., `fluidPage(theme = bslib::bs_theme())`).",
call. = FALSE
)
}
isBS4 <- getCurrentVersion() == 4
div(
class = "shiny-input-container",
style = css(width = validateCssUnit(width)),
div(
class = if (isBS4) "custom-control custom-switch" else "form-check form-switch",
tagAppendAttributes(
inputTag, class = if (isBS4) "custom-control-input" else "form-check-input"
),
tagAppendAttributes(
labelTag, class = if (isBS4) "custom-control-label" else "form-check-label"
)
)
)
})
}

View File

@@ -568,7 +568,7 @@ ReactiveValues <- R6Class(
#' @seealso [isolate()] and [is.reactivevalues()].
#' @export
reactiveValues <- function(...) {
args <- list2(...)
args <- list(...)
if ((length(args) > 0) && (is.null(names(args)) || any(names(args) == "")))
rlang::abort("All arguments passed to reactiveValues() must be named.")
@@ -1915,7 +1915,7 @@ reactivePoll <- function(intervalMillis, session, checkFunc, valueFunc) {
#' @export
reactiveFileReader <- function(intervalMillis, session, filePath, readFunc, ...) {
filePath <- coerceToFunc(filePath)
extraArgs <- list2(...)
extraArgs <- list(...)
reactivePoll(
intervalMillis, session,

View File

@@ -178,7 +178,7 @@ getShinyOption <- function(name, default = NULL) {
#' @aliases shiny-options
#' @export
shinyOptions <- function(...) {
newOpts <- list2(...)
newOpts <- list(...)
if (length(newOpts) > 0) {
# If we're within a session, modify at the session level.

View File

@@ -115,12 +115,6 @@ updateCheckboxInput <- function(session = getDefaultReactiveDomain(), inputId, l
session$sendInputMessage(inputId, message)
}
#' @rdname updateCheckboxInput
#' @export
updateSwitchInput <- function(session = getDefaultReactiveDomain(), inputId, label = NULL, value = NULL) {
updateCheckboxInput(session = session, inputId = inputId, label = label, value = value)
}
#' Change the label or icon of an action button on the client
#'

View File

@@ -1176,7 +1176,7 @@ reactiveStop <- function(message = "", class = NULL) {
#'
#' }
validate <- function(..., errorClass = character(0)) {
results <- sapply(list2(...), function(x) {
results <- sapply(list(...), function(x) {
# Detect NULL or NA
if (is.null(x))
return(NA_character_)

View File

@@ -5163,7 +5163,7 @@
},
getState: function getState(el) {
return {
label: import_jquery6.default(el).parent().find("span, label").text(),
label: import_jquery6.default(el).parent().find("span").text(),
value: el.checked
};
},
@@ -5171,7 +5171,7 @@
if (data.hasOwnProperty("value"))
el.checked = data.value;
if (data.hasOwnProperty("label"))
import_jquery6.default(el).parent().find("span, label").text(data.label);
import_jquery6.default(el).parent().find("span").text(data.label);
import_jquery6.default(el).trigger("change");
}
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -83,7 +83,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -112,7 +112,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -57,7 +57,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -143,7 +143,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -147,7 +147,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -113,7 +113,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -71,7 +71,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -65,7 +65,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -128,7 +128,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -148,7 +148,6 @@ Other input elements:
\code{\link{radioButtons}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -151,7 +151,6 @@ Other input elements:
\code{\link{radioButtons}()},
\code{\link{selectInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -76,7 +76,6 @@ Other input elements:
\code{\link{radioButtons}()},
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}

View File

@@ -1,64 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/input-switch.R
\name{switchInput}
\alias{switchInput}
\title{Switch Input Control}
\usage{
switchInput(inputId, label, value = FALSE, width = NULL)
}
\arguments{
\item{inputId}{The \code{input} slot that will be used to access the value.}
\item{label}{Display label for the control, or \code{NULL} for no label.}
\item{value}{Initial value (\code{TRUE} or \code{FALSE}).}
\item{width}{The width of the input, e.g. \code{'400px'}, or \code{'100\%'};
see \code{\link[=validateCssUnit]{validateCssUnit()}}.}
}
\value{
A switch control that can be added to a UI definition.
}
\description{
Create a switch for toggling a logical value.
}
\section{Server value}{
\code{TRUE} if checked, \code{FALSE} otherwise.
}
\examples{
## Only run examples in interactive R sessions
if (interactive()) {
ui <- fluidPage(
switchInput("somevalue", "Some value", FALSE),
verbatimTextOutput("value")
)
server <- function(input, output) {
output$value <- renderText({ input$somevalue })
}
shinyApp(ui, server)
}
}
\seealso{
\code{\link[=checkboxInput]{checkboxInput()}}, \code{\link[=updateSwitchInput]{updateSwitchInput()}}
Other input elements:
\code{\link{actionButton}()},
\code{\link{checkboxGroupInput}()},
\code{\link{checkboxInput}()},
\code{\link{dateInput}()},
\code{\link{dateRangeInput}()},
\code{\link{fileInput}()},
\code{\link{numericInput}()},
\code{\link{passwordInput}()},
\code{\link{radioButtons}()},
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}
}
\concept{input elements}

View File

@@ -11,6 +11,7 @@ tabsetPanel(
type = c("tabs", "pills", "hidden"),
header = NULL,
footer = NULL,
card = FALSE,
position = deprecated()
)
}
@@ -40,6 +41,8 @@ tabPanels.}
\item{footer}{Tag or list of tags to display as a common footer below all
tabPanels}
\item{card}{whether to wrap the navigation controls and content into an 'output card'. This functionality currently requires a \code{\link[bslib:bs_theme]{bslib::bs_theme()}} in the page layout with \code{version = 4} or higher.}
\item{position}{This argument is deprecated; it has been discontinued in
Bootstrap 3.}
}

View File

@@ -91,7 +91,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textInput}()},
\code{\link{varSelectInput}()}
}

View File

@@ -63,7 +63,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{varSelectInput}()}
}

View File

@@ -2,7 +2,6 @@
% Please edit documentation in R/update-input.R
\name{updateCheckboxInput}
\alias{updateCheckboxInput}
\alias{updateSwitchInput}
\title{Change the value of a checkbox input on the client}
\usage{
updateCheckboxInput(
@@ -11,13 +10,6 @@ updateCheckboxInput(
label = NULL,
value = NULL
)
updateSwitchInput(
session = getDefaultReactiveDomain(),
inputId,
label = NULL,
value = NULL
)
}
\arguments{
\item{session}{The \code{session} object passed to function given to

View File

@@ -140,7 +140,6 @@ Other input elements:
\code{\link{selectInput}()},
\code{\link{sliderInput}()},
\code{\link{submitButton}()},
\code{\link{switchInput}()},
\code{\link{textAreaInput}()},
\code{\link{textInput}()}
}

View File

@@ -4627,7 +4627,7 @@ function main(): void {
},
getState: function (el) {
return {
label: $(el).parent().find("span, label").text(),
label: $(el).parent().find("span").text(),
value: el.checked,
};
},
@@ -4637,7 +4637,7 @@ function main(): void {
// checkboxInput()'s label works different from other
// input labels...the label container should always exist
if (data.hasOwnProperty("label"))
$(el).parent().find("span, label").text(data.label);
$(el).parent().find("span").text(data.label);
$(el).trigger("change");
},

View File

@@ -138,6 +138,43 @@
<div class="content-footer"></div>
</div>
---
Code
bslib_tags(x)
Output
<div class="tabbable card">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs" data-tabsetid="4785">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" data-value="A" href="#tab-4785-1">A</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#tab-4785-2" data-toggle="tab" data-value="B">
<i class=" fab fa-github fa-fw" role="presentation" aria-label=" icon"></i>
B
</a>
</li>
<li class="dropdown nav-item">
<a class="dropdown-toggle nav-link" data-toggle="dropdown" data-value="Menu" href="#">
Menu
<b class="caret"></b>
</a>
<ul class="dropdown-menu" data-tabsetid="1502">
<a class="dropdown-item" href="#tab-1502-1" data-toggle="tab" data-value="C">C</a>
</ul>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content" data-tabsetid="4785">
<div class="tab-pane active" data-value="A" id="tab-4785-1">a</div>
<div class="tab-pane" data-value="B" data-icon-class="fab fa-github" id="tab-4785-2">b</div>
<div class="tab-pane" data-value="C" id="tab-1502-1">c</div>
</div>
</div>
</div>
# navbarPage() markup is correct
Code

View File

@@ -54,6 +54,8 @@ test_that("tabsetPanel() markup is correct", {
# BS4
expect_snapshot_bslib(default)
expect_snapshot_bslib(pills)
card <- tabset_panel(!!!panels, card = TRUE)
expect_snapshot_bslib(card)
})
test_that("navbarPage() markup is correct", {