diff --git a/.Rbuildignore b/.Rbuildignore
index 50b376b4..4917606f 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -21,4 +21,3 @@
^CODE_OF_CONDUCT.md$
^doc/*
^Meta$
-^vignettes$
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 698c2855..be04eba0 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -12,20 +12,23 @@ jobs:
fail-fast: false
matrix:
config:
- - { os: windows-latest, r: '3.6'}
- - { os: macOS-latest, r: '3.6'}
- - { os: ubuntu-18.04, r: '3.6', cran: "https://demo.rstudiopm.com/all/__linux__/bionic/latest"}
+ - {os: macOS-latest, r: 'release'}
+ - {os: windows-latest, r: 'release'}
+ - {os: ubuntu-18.04, r: 'devel', http-user-agent: 'release', cran: "https://demo.rstudiopm.com/all/__linux__/bionic/latest"}
+ - {os: ubuntu-18.04, r: 'release', cran: "https://demo.rstudiopm.com/all/__linux__/bionic/latest"}
+ - {os: ubuntu-18.04, r: 'oldrel', cran: "https://demo.rstudiopm.com/all/__linux__/bionic/latest"}
env:
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
CRAN: ${{ matrix.config.cran }}
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v2
- uses: r-lib/actions/setup-r@master
with:
r-version: ${{ matrix.config.r }}
+ http-user-agent: ${{ matrix.config.http-user-agent }}
- uses: r-lib/actions/setup-pandoc@master
@@ -42,12 +45,9 @@ jobs:
- name: Install system dependencies
if: runner.os == 'Linux'
- env:
- RHUB_PLATFORM: linux-x86_64-ubuntu-gcc
- run: |
- Rscript -e "remotes::install_github('r-hub/sysreqs')"
- sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))")
- sudo -s eval "$sysreqs"
+ uses: r-lib/actions/setup-r-dependencies@v1
+ with:
+ extra-packages: rcmdcheck
- name: Install vctrs
if: runner.os == 'Windows'
@@ -56,7 +56,7 @@ jobs:
- name: Install vctrs
if: runner.os == 'macos'
run: Rscript -e "remotes::install_cran('Rcpp')"
-
+
- name: Install dependencies
run: Rscript -e "library(remotes)" -e "update(readRDS('depends.Rds'))" -e "remotes::install_cran('rcmdcheck')"
@@ -71,6 +71,6 @@ jobs:
path: check
- name: Test coverage
- if: matrix.config.os == 'macOS-latest' && matrix.config.r == '3.6'
+ if: matrix.config.os == 'ubuntu-18.04' && matrix.config.r == 'release'
run: |
Rscript -e 'covr::codecov(token = "${{secrets.CODECOV_TOKEN}}")'
diff --git a/DESCRIPTION b/DESCRIPTION
index babadccc..06eec92b 100755
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -3,7 +3,7 @@ Type: Package
Title: Semantic UI Support for Shiny
Version: 0.4.3
Authors@R: c(person("Filip", "Stachura", email = "filip@appsilon.com", role = "aut"),
- person("Dominik", "Krzeminski", email = "dominik@appsilon.com", role = "cre"),
+ person("Dominik", "Krzeminski", email = "dominik@appsilon.com", role = "aut"),
person("Krystian", "Igras", email = "krystian@appsilon.com", role = "aut"),
person("Adam", "Forys", email = "adam@appsilon.com", role = "aut"),
person("Paweł", "Przytuła", email = "pawel@appsilon.com", role = "aut"),
@@ -16,12 +16,13 @@ Authors@R: c(person("Filip", "Stachura", email = "filip@appsilon.com", role = "a
person("Paweł", "Przytuła", email = "pawel@appsilon.com", role = "ctb"),
person("Kamil", "Żyła", email = "kamil@appsilon.com", role = "ctb"),
person("Rabii", "Bouhestine", email = "rabii@appsilon.com", role = "ctb"),
+ person("Developers", "Appsilon", email = "support+opensource@appsilon.com", role = "cre"),
person(family = "Appsilon Sp. z o.o.", role = c("cph")))
Description: Creating a great user interface for your Shiny apps
can be a hassle, especially if you want to work purely in R
and don't want to use, for instance HTML templates. This
package adds support for a powerful UI library Fomantic UI -
- (before Semantic). It also supports
+ (before Semantic). It also supports
universal UI input binding that works with various DOM elements.
BugReports: https://github.com/Appsilon/shiny.semantic/issues
Encoding: UTF-8
@@ -48,5 +49,7 @@ Suggests:
DT,
covr,
leaflet,
- plotly
-RoxygenNote: 7.1.1
+ plotly,
+ rmarkdown,
+ markdown
+RoxygenNote: 7.1.2
diff --git a/NAMESPACE b/NAMESPACE
index ef8b9543..04287eb1 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -77,10 +77,12 @@ export(showNotification)
export(show_modal)
export(sidebar_layout)
export(sidebar_panel)
+export(single_step)
export(sliderInput)
export(slider_input)
export(splitLayout)
export(split_layout)
+export(steps)
export(tabset)
export(textAreaInput)
export(textInput)
@@ -88,6 +90,7 @@ export(text_input)
export(theme_selector)
export(toast)
export(toggle)
+export(toggle_step_state)
export(uiinput)
export(uirender)
export(updateActionButton)
@@ -97,6 +100,8 @@ export(updateSliderInput)
export(update_action_button)
export(update_calendar)
export(update_dropdown_input)
+export(update_multiple_checkbox)
+export(update_multiple_radio)
export(update_numeric_input)
export(update_progress)
export(update_range_input)
diff --git a/R/checkbox.R b/R/checkbox.R
index 3f824825..fce96aaf 100644
--- a/R/checkbox.R
+++ b/R/checkbox.R
@@ -103,12 +103,12 @@ toggle <- function(input_id, label = "", is_marked = TRUE, style = NULL) {
#' semanticPage(
#' title = "Checkbox example",
#' h1("Checkboxes"),
-#' multiple_checkbox("checkboxes", "Select Letters", LETTERS[1:6], value = "A"),
+#' multiple_checkbox("checkboxes", "Select Letters", LETTERS[1:6], selected = "A"),
#' p("Selected letters:"),
#' textOutput("selected_letters"),
#' tags$br(),
#' h1("Radioboxes"),
-#' multiple_radio("radioboxes", "Select Letter", LETTERS[1:6], value = "A"),
+#' multiple_radio("radioboxes", "Select Letter", LETTERS[1:6], selected = "A"),
#' p("Selected letter:"),
#' textOutput("selected_letter")
#' )
@@ -140,14 +140,76 @@ multiple_checkbox <- function(input_id, label, choices, choices_value = choices,
)
}))
- shiny::div(
- id = input_id, class = paste(position, "fields shiny-input-checkboxgroup"),
+ shiny::div(class="ui form",
+ id = input_id, class = paste(position, "fields ss-checkbox-input"),
tags$label(`for` = input_id, label),
choices_html,
...
)
}
+#' Update checkbox Semantic UI component
+#'
+#' Change the value of a \code{\link{multiple_checkbox}} input on the client.
+#'
+#' @param session The \code{session} object passed to function given to \code{shinyServer}.
+#' @param input_id The id of the input object
+#' @param choices All available options one can select from. If no need to update then leave as \code{NULL}
+#' @param choices_value What reactive value should be used for corresponding choice.
+#' @param selected The initially selected value.
+#' @param label The label linked to the input
+#'
+#' @examples
+#' if (interactive()) {
+#'
+#' library(shiny)
+#' library(shiny.semantic)
+#'
+#' ui <- function() {
+#' shinyUI(
+#' semanticPage(
+#' title = "Checkbox example",
+#' form(
+#' multiple_checkbox(
+#' "simple_checkbox", "Letters:", LETTERS[1:5], selected = c("A", "C"), type = "slider"
+#' )
+#' ),
+#' p("Selected letter:"),
+#' textOutput("selected_letter"),
+#' shiny.semantic::actionButton("simple_button", "Update input to D")
+#' )
+#' )
+#' }
+#'
+#' server <- shinyServer(function(input, output, session) {
+#' output$selected_letter <- renderText(paste(input[["simple_checkbox"]], collapse = ", "))
+#'
+#' observeEvent(input$simple_button, {
+#' update_multiple_checkbox(session, "simple_checkbox", selected = "D")
+#' })
+#' })
+#'
+#' shinyApp(ui = ui(), server = server)
+#'
+#' }
+#'
+#' @export
+update_multiple_checkbox <- function(session = getDefaultReactiveDomain(),
+ input_id, choices = NULL, choices_value = choices,
+ selected = NULL, label = NULL) {
+ if (!is.null(selected)) value <- jsonlite::toJSON(selected) else value <- NULL
+ if (!is.null(choices)) {
+ options <- jsonlite::toJSON(data.frame(name = choices, value = choices_value))
+ } else {
+ options <- NULL
+ }
+
+ message <- list(choices = options, value = value, label = label)
+ message <- message[!vapply(message, is.null, FUN.VALUE = logical(1))]
+
+ session$sendInputMessage(input_id, message)
+}
+
#' @rdname multiple_checkbox
#'
#' @export
@@ -168,10 +230,23 @@ multiple_radio <- function(input_id, label, choices, choices_value = choices,
)
}))
- shiny::div(
- id = input_id, class = paste(position, "fields shiny-input-radiogroup"),
+ shiny::div(class="ui form",
+ id = input_id, class = paste(position, "fields ss-checkbox-input"),
tags$label(`for` = input_id, label),
choices_html,
...
)
}
+
+#' @rdname update_multiple_checkbox
+#' @export
+update_multiple_radio <- function(session = getDefaultReactiveDomain(),
+ input_id, choices = NULL, choices_value = choices,
+ selected = NULL, label = NULL) {
+ if (length(selected) > 1) {
+ warning("More than one radio box has been selected, only first will be used")
+ selected <- selected[1]
+ }
+
+ update_multiple_checkbox(session, input_id, choices, choices_value, selected, label)
+}
diff --git a/R/input.R b/R/input.R
index bc88b756..3b345152 100644
--- a/R/input.R
+++ b/R/input.R
@@ -80,7 +80,7 @@ text_input <- function(input_id, label = NULL, value = "", type = "text",
}
if (type == "textarea") {
- input <- tags$textarea(id = input_id, value = value, placeholder = placeholder)
+ input <- tags$textarea(id = input_id, value, placeholder = placeholder)
} else {
input <- tags$input(id = input_id, value = value, type = type, placeholder = placeholder)
}
@@ -110,7 +110,7 @@ text_input <- function(input_id, label = NULL, value = "", type = "text",
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#' ui <- semanticPage(
-#' textAreaInput("a", "Area:", width = "200px"),
+#' textAreaInput("a", "Area:", value = "200", width = "200px"),
#' verbatimTextOutput("value")
#' )
#' server <- function(input, output, session) {
@@ -125,7 +125,7 @@ textAreaInput <- function(inputId, label, value = "", width = NULL, placeholder
style = if (!is.null(width)) glue::glue("width: {shiny::validateCssUnit(width)};"),
shiny::div(class = "field",
if (!is.null(label)) tags$label(label, `for` = inputId),
- text_input(inputId, value,
+ text_input(inputId, value = value,
placeholder = placeholder, type = "textarea")
)
)
diff --git a/R/layouts.R b/R/layouts.R
index 61a75a70..d52aa0e7 100644
--- a/R/layouts.R
+++ b/R/layouts.R
@@ -128,8 +128,8 @@ sidebar_layout <- function(sidebar_panel,
grid(
grid_template = layout,
- container_style,
- area_styles,
+ container_style = container_style,
+ area_styles = area_styles,
sidebar_panel = sidebar_children,
main_panel = main_children
)
diff --git a/R/modal.R b/R/modal.R
index 8cf7be8b..e73a96ef 100644
--- a/R/modal.R
+++ b/R/modal.R
@@ -96,6 +96,7 @@
#' })
#' shinyApp(ui, server)
#' }
+#'
#' ## Changing attributes of header and content.
#' if (interactive()) {
#' library(shiny)
@@ -123,24 +124,36 @@
#' }
#' shinyApp(ui, server)
#' }
+#'
+#' ## Modal that closes automatically after specific time
#' if (interactive()) {
#' library(shiny)
#' library(shiny.semantic)
-#' shinyApp(
-#' ui = semanticPage(
-#' actionButton("show", "Show modal dialog")
-#' ),
-#' server = function(input, output) {
-#' observeEvent(input$show, {
-#' showModal(modalDialog(
+#' ui <- function() {
+#' shinyUI(
+#' semanticPage(
+#' actionButton("show", "Show modal dialog")
+#' )
+#' )
+#' }
+#'
+#' server <- shinyServer(function(input, output, session) {
+#' observeEvent(input$show, {
+#' create_modal(
+#' modal(
+#' id = "simple-modal",
#' title = "Important message",
-#' "This modal will close after 3 sec.", easyClose = FALSE
-#' ))
-#' Sys.sleep(3)
-#' removeModal()
-#' })
-#' }
-#' )
+#' header = "Example modal",
+#' content = "This modal will close after 3 sec.",
+#' footer = NULL,
+#' )
+#' )
+#' Sys.sleep(3)
+#' hide_modal(id = "simple-modal")
+#' })
+#' })
+#'
+#' shinyApp(ui = ui(), server = server)
#' }
#'
#' @rdname modal
@@ -263,12 +276,16 @@ attach_rule <- function(id, behavior, target, value) {
#' @param id ID of the modal that will be displayed.
#' @param session The \code{session} object passed to function given to
#' \code{shinyServer}.
+#' @param asis A boolean indicating if the id must be handled as is (TRUE) or
+#' will be it must be namespaced (FALSE)
#' @seealso modal
#'
#' @rdname show_modal
#'
#' @export
-show_modal <- function(id, session = shiny::getDefaultReactiveDomain()) {
+show_modal <- function(id, session = shiny::getDefaultReactiveDomain(),
+ asis = TRUE) {
+ id <- ifelse(inherits(session, "session_proxy"), session$ns(id), id)
session$sendCustomMessage("showSemanticModal", list(id = id, action = "show")) # nolint
}
@@ -279,7 +296,9 @@ showModal <- function(ui, session = shiny::getDefaultReactiveDomain()) {
#' @rdname show_modal
#' @export
-remove_modal <- function(id, session = shiny::getDefaultReactiveDomain()) {
+remove_modal <- function(id, session = shiny::getDefaultReactiveDomain(),
+ asis = TRUE) {
+ id <- ifelse(inherits(session, "session_proxy"), session$ns(id), id)
shiny::removeUI(paste0("#", id))
}
@@ -298,6 +317,8 @@ removeModal <- function(session = shiny::getDefaultReactiveDomain()) {
#' @rdname show_modal
#' @export
-hide_modal <- function(id, session = shiny::getDefaultReactiveDomain()) {
+hide_modal <- function(id, session = shiny::getDefaultReactiveDomain(),
+ asis = TRUE) {
+ id <- ifelse(inherits(session, "session_proxy"), session$ns(id), id)
session$sendCustomMessage("showSemanticModal", list(id = id, action = "hide")) # nolint
}
diff --git a/R/progress.R b/R/progress.R
index 6cce97de..d31b067b 100644
--- a/R/progress.R
+++ b/R/progress.R
@@ -73,9 +73,9 @@ progress <- function(input_id, value = NULL, total = NULL, percent = NULL, progr
#' @export
update_progress <- function(session, input_id, type = c("increment", "decrement", "label", "value"), value = 1) {
type <- match.arg(type)
- message <- structure(list(value), names = type)
+ message <- list(id = input_id, type = type, value = value)
- session$sendInputMessage(input_id, message)
+ session$sendCustomMessage("ssprogress", list(type = "change", message = message))
}
#' Reporting progress (object-oriented API)
diff --git a/R/semanticPage.R b/R/semanticPage.R
index c00352ec..8500cdb2 100644
--- a/R/semanticPage.R
+++ b/R/semanticPage.R
@@ -162,6 +162,7 @@ semanticPage <- function(..., title = "", theme = NULL, suppress_bootstrap = TRU
shiny::tags$link(rel = "stylesheet", type = "text/css",
href = "shiny.semantic/shiny-semantic-DT.css"),
shiny::tags$script(src = "shiny.semantic/shiny-semantic-modal.js"),
+ shiny::tags$script(src = "shiny.semantic/shiny-semantic-checkbox.js"),
shiny::tags$script(src = "shiny.semantic/shiny-semantic-dropdown.js"),
shiny::tags$script(src = "shiny.semantic/shiny-semantic-button.js"),
shiny::tags$script(src = "shiny.semantic/shiny-semantic-slider.js"),
@@ -171,7 +172,8 @@ semanticPage <- function(..., title = "", theme = NULL, suppress_bootstrap = TRU
shiny::tags$script(src = "shiny.semantic/shiny-semantic-rating.js"),
shiny::tags$script(src = "shiny.semantic/shiny-semantic-tabset.js"),
shiny::tags$script(src = "shiny.semantic/shiny-semantic-progress.js"),
- shiny::tags$script(src = "shiny.semantic/shiny-semantic-toast.js")
+ shiny::tags$script(src = "shiny.semantic/shiny-semantic-toast.js"),
+ shiny::tags$script(src = "shiny.semantic/shiny-semantic-step.js")
),
shiny::tags$body(style = glue::glue("margin:{margin};"),
suppress_bootstrap,
diff --git a/R/step.R b/R/step.R
new file mode 100644
index 00000000..ea5b9ae4
--- /dev/null
+++ b/R/step.R
@@ -0,0 +1,142 @@
+#' Show steps
+#'
+#' @param id ID of the Steps that will be displayed.
+#' @param steps_list A list of steps generated by single_steps.
+#' @param class (Optional) A character string with the semantic class to be
+#' added to the steps element.
+#' @seealso single_steps
+#' @examples
+#' if (interactive()) {
+#' library(shiny)
+#' library(shiny.semantic)
+#' ui <- semanticPage(
+#' title = "Steps Example",
+#' shiny::tagList(
+#' h2("Steps example"),
+#' shiny.semantic::steps(
+#' id = "steps",
+#' steps_list = list(
+#' single_step(
+#' id = "step_1",
+#' title = "Step 1",
+#' description = "It's night?",
+#' icon_class = "moon"
+#' ),
+#' single_step(
+#' id = "step_2",
+#' title = "Step 2",
+#' description = "Order some food",
+#' icon_class = "bug"
+#' ),
+#' single_step(id = "step_3",
+#' title = "Step 3",
+#' description = "Feed the Kiwi",
+#' icon_class = "kiwi bird"
+#' )
+#' )
+#' ),
+#' h3("Actions"),
+#' shiny.semantic::action_button("step_1_complete", "Make it night"),
+#' shiny.semantic::action_button("step_2_complete", "Call the insects"),
+#' shiny.semantic::action_button("step_3_complete", "Feed the Kiwi"),
+#' shiny.semantic::action_button("hungry_kiwi", "Kiwi is hungry again"),
+#' )
+#')
+#'
+#' server <- function(input, output, session) {
+#' observeEvent(input$step_1_complete, {
+#' toggle_step_state("step_1")
+#' })
+#'
+#' observeEvent(input$step_2_complete, {
+#' toggle_step_state("step_2")
+#' })
+#'
+#' observeEvent(input$step_3_complete, {
+#' toggle_step_state("step_3")
+#' })
+#'
+#' observeEvent(input$hungry_kiwi, {
+#' toggle_step_state("step_1", FALSE)
+#' toggle_step_state("step_2", FALSE)
+#' toggle_step_state("step_3", FALSE)
+#' })
+#'
+#' }
+#'
+#' shiny::shinyApp(ui, server)
+#' }
+#' @rdname steps
+#' @export
+steps <- function(id, steps_list, class = NULL) {
+ steps_class <- if (is.null(class)) "ui steps" else sprintf("ui %s steps", class) # nolint
+ shiny::div(
+ id = id,
+ class = steps_class,
+ steps_list
+ )
+}
+
+
+
+#' Creates a single step to be used inside of a list of steps by the steps
+#' function
+#'
+#' @param id The \code{input} slot that will be used to access the value.
+#' @param title A character that will be the title of the ste
+#' @param description A character that will fill the description of the step
+#' @param icon_class A character which will be correpond to a fomantic icon
+#' class to be used in the step
+#' @param step_class A character representing a class to be passed to the step
+#'
+#' @seealso steps
+#'
+#' @rdname single_step
+#' @export
+single_step <- function(id, title, description = NULL, icon_class = NULL,
+ step_class = NULL) {
+ step_icon <- if (is.null(icon_class)) NULL else tags$i(
+ class = paste(icon_class, "icon")
+ )
+ step_description <- if (is.null(description)) NULL else shiny::div(
+ class = "description",
+ description
+ )
+ step_title <- shiny::div(class = "title", title)
+ step_class <- if(is.null(step_class)) "step" else sprintf("%s step", step_class) # nolint
+
+ shiny::div(
+ id = id,
+ class = step_class,
+ step_icon,
+ shiny::div(
+ class = "content",
+ step_title,
+ step_description)
+ )
+}
+
+#' Toggle step state
+#'
+#' @param id ID of step to be toggled
+#' @param state State of the step, \code{TRUE} stands for enabled
+#' @param automatic_steps Whether to toggle focus of next step automatically
+#' @param asis When used inside of Shiny module, \code{TRUE} will disable adding
+#' the namespace to \code{id}
+#'
+#' @seealso steps
+#'
+#' @rdname toggle_step_state
+#' @export
+toggle_step_state <- function(id, state = TRUE, automatic_steps = TRUE,
+ asis = TRUE) {
+ session <- shiny::getDefaultReactiveDomain()
+ # Make sure set_attribute_by_id works with namespaces (shiny modules)
+ if (inherits(session, "session_proxy") && !asis) session$ns(id) else id
+ parameters <- list(
+ "step_id" = id,
+ "state" = state,
+ "automatic_steps" = automatic_steps
+ )
+ session$sendCustomMessage("toggle_step_state", parameters)
+}
diff --git a/R/utils.R b/R/utils.R
index 0a12ae3a..b7a1b423 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -73,6 +73,8 @@ warn_unsupported_args <- function(args) {
to_wrn <- paste0(as.character(names(args)), collapse = ',')
else if (class(args) == "character")
to_wrn <- paste0(args, collapse = ',')
+ else if (is.null(args))
+ return()
else
stop("Wrong input type!")
if (nchar(to_wrn) >= 1)
diff --git a/README.md b/README.md
index fb4f349e..89eaabf0 100644
--- a/README.md
+++ b/README.md
@@ -245,11 +245,11 @@ install.packages("shiny", version='0.14.2.9001')
- adding more semantic components
- new version release on CRAN
-## Appsilon Data Science
+## Appsilon
Appsilon is the **Full Service Certified RStudio Partner**. Learn more
at [appsilon.com](https://appsilon.com).
-Get in touch [dev@appsilon.com](dev@appsilon.com)
+Get in touch [support+opensource@appsilon.com](support+opensource@appsilon.com)
diff --git a/examples/app.R b/examples/app.R
index 58767a9d..9512e4ae 100644
--- a/examples/app.R
+++ b/examples/app.R
@@ -104,6 +104,36 @@ icon_demo <- function() {
)
}
+step_demo <- function() {
+ div(
+ h1(class = "ui header", id = "step", "Step"),
+ demo(steps(
+ id = "steps",
+ steps_list = list(
+ single_step(
+ id = "step_1",
+ title = "Step 1",
+ description = "It's night?",
+ icon_class = "moon"
+ ),
+ single_step(
+ id = "step_2",
+ title = "Step 2",
+ description = "Order some food",
+ icon_class = "bug"
+ ),
+ single_step(
+ id = "step_3",
+ title = "Step 3",
+ description = "Feed the Kiwi",
+ icon_class = "kiwi bird"
+ )
+ )
+ )
+ )
+ )
+}
+
toast_demo <- function(){
toast_code <- "toast(
\"This is a semantic toast. Cheers!\",
@@ -494,6 +524,7 @@ ui <- function() {
button(),
counter_button_demo(),
icon_demo(),
+ step_demo(),
divider(),
uiinput_demo(),
uilabel(),
diff --git a/examples/modal/app_6.R b/examples/modal/app_6.R
new file mode 100644
index 00000000..bde04d4d
--- /dev/null
+++ b/examples/modal/app_6.R
@@ -0,0 +1,28 @@
+library(shiny)
+library(shiny.semantic)
+
+ui <- function() {
+ shinyUI(
+ semanticPage(
+ actionButton("show", "Show modal dialog")
+ )
+ )
+}
+
+server <- shinyServer(function(input, output, session) {
+ observeEvent(input$show, {
+ create_modal(
+ modal(
+ id = "simple-modal",
+ title = "Important message",
+ header = "Example modal",
+ content = "This modal will close after 3 sec.",
+ footer = NULL,
+ )
+ )
+ Sys.sleep(3)
+ hide_modal(id = "simple-modal")
+ })
+})
+
+shinyApp(ui = ui(), server = server)
diff --git a/examples/multiple_checkbox/app.R b/examples/multiple_checkbox/app.R
index 623c5876..0f33a0fc 100644
--- a/examples/multiple_checkbox/app.R
+++ b/examples/multiple_checkbox/app.R
@@ -6,22 +6,54 @@ ui <- function() {
shinyUI(
semanticPage(
title = "Multiple checkbox example",
- uiOutput("sliders"),
- textOutput("result")
+ div(
+ class = "ui form",
+ multiple_checkbox(
+ "chcbx", "Select type:", c("Type one", "Type two"), c("first", "second"),
+ type = "slider", position = "inline"
+ ),
+ actionButton("chcbx_update", "Update Checkboxes"),
+ textOutput("chcbx_result"),
+
+ tags$br(),
+
+ multiple_radio(
+ "radio", "Select type:", c("Option one", "Option two"), c("first", "second"),
+ "first", position = "inline"
+ ),
+ actionButton("radio_update", "Update Checkboxes"),
+ textOutput("radio_result"),
+ )
)
)
}
-server <- shinyServer(function(input, output) {
-
- output$sliders <- renderUI({
- multiple_checkbox("chcbx", "Select type:", list("Type one" = "first", "Type two" = "second"), type = "slider",
- style = "margin: 1em;")
+server <- shinyServer(function(input, output, session) {
+ observeEvent(input$chcbx_update, {
+ update_multiple_checkbox(
+ session,
+ "chcbx",
+ choices = c("Type Three", "Type Four"),
+ c("third", "fourth"),
+ selected = c("third", "fourth"))
})
- output$result <- renderText({
+ output$chcbx_result <- renderText({
input$chcbx
})
+
+ observeEvent(input$radio_update, {
+ update_multiple_radio(
+ session,
+ "radio",
+ choices = c("Option Three", "Option Four"),
+ c("third", "fourth"),
+ selected = "third")
+ })
+
+ output$radio_result <- renderText({
+ input$radio
+ })
})
shinyApp(ui = ui(), server = server)
diff --git a/examples/progress/app.R b/examples/progress/app.R
index f20f8805..443b5590 100644
--- a/examples/progress/app.R
+++ b/examples/progress/app.R
@@ -15,7 +15,7 @@ ui <- semanticPage(
"percent_ex", percent = 35, progress_lab = TRUE, label = "{percent}% complete", label_complete = "All done!"
),
tags$br(),
- button("button2", "Increase b 5%"),
+ button("button2", "Increase by 5%"),
button("button3", "Decrease by 5%"),
textOutput("percent_ex")
)
diff --git a/examples/steps/app.R b/examples/steps/app.R
new file mode 100644
index 00000000..c834701f
--- /dev/null
+++ b/examples/steps/app.R
@@ -0,0 +1,56 @@
+library(shiny)
+library(shiny.semantic)
+
+ui <- semanticPage(
+ title = "Steps Example",
+ shiny::tagList(
+ h2("Steps example"),
+ steps(
+ id = "steps",
+ steps_list = list(
+ single_step(
+ id = "step_1",
+ title = "Step 1",
+ description = "It's night?",
+ icon_class = "moon"
+ ),
+ single_step(
+ id = "step_2",
+ title = "Step 2",
+ description = "Order some food",
+ icon_class = "bug"
+ ),
+ single_step(
+ id = "step_3",
+ title = "Step 3",
+ description = "Feed the Kiwi",
+ icon_class = "kiwi bird"
+ )
+ )
+ ),
+ h3("Actions"),
+ action_button("step_1_complete", "Make it night"),
+ action_button("step_2_complete", "Call the insects"),
+ action_button("step_3_complete", "Feed the Kiwi"),
+ action_button("hungry_kiwi", "Kiwi is hungry again"),
+ )
+)
+
+server <- function(input, output, session) {
+ observeEvent(input$step_1_complete, {
+ toggle_step_state("step_1")
+ })
+ observeEvent(input$step_2_complete, {
+ toggle_step_state("step_2")
+ })
+ observeEvent(input$step_3_complete, {
+ toggle_step_state("step_3")
+ })
+ observeEvent(input$hungry_kiwi, {
+ toggle_step_state("step_1", FALSE)
+ toggle_step_state("step_2", FALSE)
+ toggle_step_state("step_3", FALSE)
+ })
+}
+
+shinyApp(ui = ui, server = server)
diff --git a/inst/www/shiny-semantic-checkbox.js b/inst/www/shiny-semantic-checkbox.js
new file mode 100644
index 00000000..a008c3e4
--- /dev/null
+++ b/inst/www/shiny-semantic-checkbox.js
@@ -0,0 +1,91 @@
+var semanticCheckboxBinding = new Shiny.InputBinding();
+
+$.extend(semanticCheckboxBinding, {
+
+ // This initialize input element. It extracts data-value attribute and use that as value.
+ initialize: function(el) {
+ $(el).checkbox({
+ fireOnInit: true
+ });
+ },
+
+ // This returns a jQuery object with the DOM element.
+ find: function(scope) {
+ return $(scope).find('.ss-checkbox-input');
+ },
+
+ // Returns the ID of the DOM element.
+ getId: function(el) {
+ return el.id;
+ },
+
+ // Given the DOM element for the input, return the value as JSON.
+ getValue: function(el) {
+ var checkboxes = $(el).find('.ui.checkbox');
+ var checkboxCheck = checkboxes.checkbox('is checked');
+ var checkboxValues = $.map(checkboxes.find('input'), function(n) { return n.value; });
+ return checkboxValues.filter(x => checkboxCheck[checkboxValues.indexOf(x)]);
+ },
+
+ // Given the DOM element for the input, set the value.
+ setValue: function(el, value) {
+ var checkboxes = $(el).find('.ui.checkbox');
+ checkboxes.checkbox('uncheck');
+
+ for (i = 0; i < checkboxes.length; i++) {
+ if (value.includes($(checkboxes[i]).find('input').attr('value'))) {
+ $(checkboxes[i]).checkbox('check');
+ }
+ }
+
+ return null;
+ },
+
+ // Set up the event listeners so that interactions with the
+ // input will result in data being sent to server.
+ // callback is a function that queues data to be sent to
+ // the server.
+ subscribe: function(el, callback) {
+ $(el).checkbox({
+ onChange: function() {
+ callback();
+ }
+ });
+ },
+
+ // TODO: Remove the event listeners.
+ unsubscribe: function(el) {
+ $(el).off();
+ },
+
+ receiveMessage: function(el, data) {
+ if (data.hasOwnProperty('choices')) {
+ var checkboxClass = $(el).find('.field .checkbox').attr('class');
+ var checkboxType = $(el).find('.field .checkbox input').attr('type');
+
+ $(el).find(".field").remove();
+
+ data.choices.forEach(x => {
+ $(el).append(
+ $(`
`)
+ );
+ });
+
+ }
+
+ if (data.hasOwnProperty('value')) {
+ this.setValue(el, data.value);
+ }
+
+ if (data.hasOwnProperty('label')) {
+ $("label[for='" + el.id + "'").html(data.label);
+ }
+ }
+});
+
+Shiny.inputBindings.register(semanticCheckboxBinding, 'shiny.semanticCheckbox');
diff --git a/inst/www/shiny-semantic-progress.js b/inst/www/shiny-semantic-progress.js
index 210669a0..b0b4f760 100644
--- a/inst/www/shiny-semantic-progress.js
+++ b/inst/www/shiny-semantic-progress.js
@@ -1,97 +1,20 @@
// Shiny input for progress bars
-var semanticProgressBinding = new Shiny.InputBinding();
-
-$.extend(semanticProgressBinding, {
-
- // This initialize input element. It extracts data-value attribute and use that as value.
- initialize: function(el) {
- $(el).progress({
- text: {
- active: $(el).data('label'),
- success: $(el).data('label-complete')
- }
- });
- },
-
- // This returns a jQuery object with the DOM element.
- find: function(scope) {
- return $(scope).find('.ss-progress');
- },
-
- // Returns the ID of the DOM element.
- getId: function(el) {
- return el.id;
- },
-
- // Given the DOM element for the input, return the value as JSON.
- getValue: function(el) {
- if ($(el).data('value')) {
- return $(el).progress('get value');
- } else {
- return $(el).progress('get percent');
- }
- },
-
- // Given the DOM element for the input, set the value.
- setValue: function(el, value) {
- if ($(el).data('value')) {
- return $(el).progress('set progress', value);
- } else {
- return $(el).progress('set percent', value);
- }
- },
-
- // Set up the event listeners so that interactions with the
- // input will result in data being sent to server.
- // callback is a function that queues data to be sent to
- // the server.
- subscribe: function(el, callback) {
- $(el).on('keyup change', function () { callback(true); });
- },
-
- // TODO: Remove the event listeners.
- unsubscribe: function(el) {
- $(el).off('.semanticProgressBinding');
- },
-
- // This returns a full description of the input's state.
- getState: function(el) {
- return {
- value: this.getValue(el)
- };
- },
-
- // The input rate limiting policy.
- getRatePolicy: function() {
- return {
- // Can be 'debounce' or 'throttle':
- policy: 'debounce',
- delay: 50
- };
- },
-
- receiveMessage: function(el, data) {
- if (data.hasOwnProperty('value')) {
- this.setValue(el, data.value);
- }
-
- if (data.hasOwnProperty('label')) {
- $(el).progress('set label', data.label);
+renderProgressBars = function() {
+ $('.progress').progress({
+ text: {
+ active: $(this).data('label'),
+ success: $(this).data('label-complete')
+ },
+ onActive: function() {
+ Shiny.setInputValue(this.id, $(this).progress('get value'));
+ },
+ onChange: function() {
+ Shiny.setInputValue(this.id, $(this).progress('get value'));
}
+ });
+};
- if (data.hasOwnProperty('increment')) {
- $(el).progress('increment', Number(data.increment));
- }
-
- if (data.hasOwnProperty('decrement')) {
- $(el).progress('decrement', Number(data.decrement));
- }
-
- $(el).trigger('change');
- }
-});
-
-Shiny.inputBindings.register(semanticProgressBinding, 'shiny.semanticProgress');
+$(window).on('load', renderProgressBars);
// JS to handle the Progress object similar to shiny
Shiny.addCustomMessageHandler('ssprogress', function(message) {
@@ -125,6 +48,18 @@ var ssProgressHandlers = {
$(`#ss-progress-${message.id}`).progress();
},
+ change: function(message) {
+ var progress = $('#' + message.id);
+
+ if (message.type === 'label') {
+ progress.progress('set label', message.value);
+ } else if (message.type === 'value') {
+ progress.progress('set progress', message.value);
+ } else {
+ progress.progress(message.type, message.value);
+ }
+ },
+
// Update page-level progress bar
update: function(message) {
// For new-style (starting in Shiny 0.14) progress indicators that use
@@ -139,7 +74,7 @@ var ssProgressHandlers = {
}
if (typeof(message.value) !== 'undefined' && message.value !== null) {
progress.progress('set progress', message.value);
- }
+ }
},
diff --git a/inst/www/shiny-semantic-slider.js b/inst/www/shiny-semantic-slider.js
index 45aa58af..4376e42b 100644
--- a/inst/www/shiny-semantic-slider.js
+++ b/inst/www/shiny-semantic-slider.js
@@ -18,7 +18,7 @@ $.extend(semanticSliderBinding, {
}
sliderOptions.max = sliderData.ticks.length - 1;
} else {
- sliderOptions.interpretLabel = Number(sliderData.min);
+ sliderOptions.min = Number(sliderData.min);
sliderOptions.max = Number(sliderData.max);
sliderOptions.step = Number(sliderData.step);
sliderOptions.start = Number(sliderData.start);
diff --git a/inst/www/shiny-semantic-step.js b/inst/www/shiny-semantic-step.js
new file mode 100644
index 00000000..69b1987e
--- /dev/null
+++ b/inst/www/shiny-semantic-step.js
@@ -0,0 +1,66 @@
+const resetAllSteps = (stepperId) => {
+ $(`#${stepperId}`).children(".step").addClass("disabled");
+ $(`#${stepperId}`).children(".step").removeClass("completed");
+ // Activating first step
+ $(`#${stepperId}`).children(".step").first().addClass("active")
+ $(`#${stepperId}`).children(".step").first().removeClass("disabled");
+}
+
+const _toggleStepCompleteState = (stepId, state, automaticSteps) => {
+ state ? _addCompletedState(stepId) : _removeCompletedState(stepId);
+ _removeActiveState(stepId);
+ if (automaticSteps) {
+ _toggleNextStep(stepId, state);
+ }
+}
+
+const _toggleNextStep = (stepId, state) => {
+ let next_step = _getNextStep(stepId);
+ if (next_step) {
+ state ? _removeDisabledState(next_step.attr("id")) : _addDisabledState(next_step.attr("id"));
+ state ? _addActiveState(next_step.attr("id")) : _removeActiveState(next_step.attr("id"));
+ }
+}
+
+const _removeCompletedState = (stepId) => {
+ $(`#${stepId}`).removeClass("completed");
+}
+
+const _addCompletedState = (stepId, autodisable = true) => {
+ $(`#${stepId}`).addClass("completed");
+ autodisable ? _removeDisabledState(stepId) : null;
+}
+
+const _removeDisabledState = (stepId) => {
+ $(`#${stepId}`).removeClass("disabled");
+}
+
+const _addDisabledState = (stepId) => {
+ $(`#${stepId}`).addClass("disabled");
+}
+
+const _removeActiveState = (stepId) => {
+ $(`#${stepId}`).removeClass("active")
+}
+
+const _addActiveState = (stepId) => {
+ $(`#${stepId}`).addClass("active")
+}
+
+const _getNextStep = (stepId) => {
+ let siblingStep = $(`#${stepId}`).next(".step");
+ return siblingStep.length > 0 ? siblingStep : false
+}
+
+
+const toggleCompletedState = (message) => {
+ let stepId = message.step_id ? message.step_id : false;
+ let state = message.state;
+ let automaticSteps = message.automatic_steps ? true : false;
+ if (!stepId) {
+ return
+ }
+ _toggleStepCompleteState(stepId, state, automaticSteps)
+}
+
+Shiny.addCustomMessageHandler("toggle_step_state", toggleCompletedState)
\ No newline at end of file
diff --git a/inst/www/shiny-semantic-tabset.js b/inst/www/shiny-semantic-tabset.js
index 5a592444..2db2ee83 100644
--- a/inst/www/shiny-semantic-tabset.js
+++ b/inst/www/shiny-semantic-tabset.js
@@ -2,7 +2,7 @@ var semanticTabset = new Shiny.InputBinding();
$.extend(semanticTabset, {
find: function(scope) {
- return $(scope).find('.tabular.menu');
+ return $(scope).find('.ui.menu.sem');
},
initialize: function(el){
$(el).find('.item').tab();
diff --git a/man/modal.Rd b/man/modal.Rd
index fcebbf6d..ab0fdef1 100644
--- a/man/modal.Rd
+++ b/man/modal.Rd
@@ -125,6 +125,7 @@ server <- shinyServer(function(input, output) {
})
shinyApp(ui, server)
}
+
## Changing attributes of header and content.
if (interactive()) {
library(shiny)
@@ -152,24 +153,36 @@ server = function(input, output) {
}
shinyApp(ui, server)
}
+
+## Modal that closes automatically after specific time
if (interactive()) {
library(shiny)
library(shiny.semantic)
-shinyApp(
- ui = semanticPage(
- actionButton("show", "Show modal dialog")
- ),
- server = function(input, output) {
- observeEvent(input$show, {
- showModal(modalDialog(
+ui <- function() {
+ shinyUI(
+ semanticPage(
+ actionButton("show", "Show modal dialog")
+ )
+ )
+}
+
+server <- shinyServer(function(input, output, session) {
+ observeEvent(input$show, {
+ create_modal(
+ modal(
+ id = "simple-modal",
title = "Important message",
- "This modal will close after 3 sec.", easyClose = FALSE
- ))
- Sys.sleep(3)
- removeModal()
- })
- }
-)
+ header = "Example modal",
+ content = "This modal will close after 3 sec.",
+ footer = NULL,
+ )
+ )
+ Sys.sleep(3)
+ hide_modal(id = "simple-modal")
+ })
+})
+
+shinyApp(ui = ui(), server = server)
}
}
diff --git a/man/multiple_checkbox.Rd b/man/multiple_checkbox.Rd
index 29c8120b..7b14fe36 100644
--- a/man/multiple_checkbox.Rd
+++ b/man/multiple_checkbox.Rd
@@ -70,12 +70,12 @@ if (interactive()) {
semanticPage(
title = "Checkbox example",
h1("Checkboxes"),
- multiple_checkbox("checkboxes", "Select Letters", LETTERS[1:6], value = "A"),
+ multiple_checkbox("checkboxes", "Select Letters", LETTERS[1:6], selected = "A"),
p("Selected letters:"),
textOutput("selected_letters"),
tags$br(),
h1("Radioboxes"),
- multiple_radio("radioboxes", "Select Letter", LETTERS[1:6], value = "A"),
+ multiple_radio("radioboxes", "Select Letter", LETTERS[1:6], selected = "A"),
p("Selected letter:"),
textOutput("selected_letter")
)
diff --git a/man/show_modal.Rd b/man/show_modal.Rd
index e0961013..8bfa2cfa 100644
--- a/man/show_modal.Rd
+++ b/man/show_modal.Rd
@@ -8,21 +8,24 @@
\alias{hide_modal}
\title{Show, Hide or Remove Semantic UI modal}
\usage{
-show_modal(id, session = shiny::getDefaultReactiveDomain())
+show_modal(id, session = shiny::getDefaultReactiveDomain(), asis = TRUE)
-remove_modal(id, session = shiny::getDefaultReactiveDomain())
+remove_modal(id, session = shiny::getDefaultReactiveDomain(), asis = TRUE)
remove_all_modals(session = shiny::getDefaultReactiveDomain())
removeModal(session = shiny::getDefaultReactiveDomain())
-hide_modal(id, session = shiny::getDefaultReactiveDomain())
+hide_modal(id, session = shiny::getDefaultReactiveDomain(), asis = TRUE)
}
\arguments{
\item{id}{ID of the modal that will be displayed.}
\item{session}{The \code{session} object passed to function given to
\code{shinyServer}.}
+
+\item{asis}{A boolean indicating if the id must be handled as is (TRUE) or
+will be it must be namespaced (FALSE)}
}
\description{
This displays a hidden Semantic UI modal.
diff --git a/man/single_step.Rd b/man/single_step.Rd
new file mode 100644
index 00000000..17741df3
--- /dev/null
+++ b/man/single_step.Rd
@@ -0,0 +1,34 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/step.R
+\name{single_step}
+\alias{single_step}
+\title{Creates a single step to be used inside of a list of steps by the steps
+function}
+\usage{
+single_step(
+ id,
+ title,
+ description = NULL,
+ icon_class = NULL,
+ step_class = NULL
+)
+}
+\arguments{
+\item{id}{The \code{input} slot that will be used to access the value.}
+
+\item{title}{A character that will be the title of the ste}
+
+\item{description}{A character that will fill the description of the step}
+
+\item{icon_class}{A character which will be correpond to a fomantic icon
+class to be used in the step}
+
+\item{step_class}{A character representing a class to be passed to the step}
+}
+\description{
+Creates a single step to be used inside of a list of steps by the steps
+function
+}
+\seealso{
+steps
+}
diff --git a/man/steps.Rd b/man/steps.Rd
new file mode 100644
index 00000000..6dbe348c
--- /dev/null
+++ b/man/steps.Rd
@@ -0,0 +1,84 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/step.R
+\name{steps}
+\alias{steps}
+\title{Show steps}
+\usage{
+steps(id, steps_list, class = NULL)
+}
+\arguments{
+\item{id}{ID of the Steps that will be displayed.}
+
+\item{steps_list}{A list of steps generated by single_steps.}
+
+\item{class}{(Optional) A character string with the semantic class to be
+added to the steps element.}
+}
+\description{
+Show steps
+}
+\examples{
+if (interactive()) {
+ library(shiny)
+ library(shiny.semantic)
+ ui <- semanticPage(
+ title = "Steps Example",
+ shiny::tagList(
+ h2("Steps example"),
+ shiny.semantic::steps(
+ id = "steps",
+ steps_list = list(
+ single_step(
+ id = "step_1",
+ title = "Step 1",
+ description = "It's night?",
+ icon_class = "moon"
+ ),
+ single_step(
+ id = "step_2",
+ title = "Step 2",
+ description = "Order some food",
+ icon_class = "bug"
+ ),
+ single_step(id = "step_3",
+ title = "Step 3",
+ description = "Feed the Kiwi",
+ icon_class = "kiwi bird"
+ )
+ )
+ ),
+ h3("Actions"),
+ shiny.semantic::action_button("step_1_complete", "Make it night"),
+ shiny.semantic::action_button("step_2_complete", "Call the insects"),
+ shiny.semantic::action_button("step_3_complete", "Feed the Kiwi"),
+ shiny.semantic::action_button("hungry_kiwi", "Kiwi is hungry again"),
+ )
+)
+
+ server <- function(input, output, session) {
+ observeEvent(input$step_1_complete, {
+ toggle_step_state("step_1")
+ })
+
+ observeEvent(input$step_2_complete, {
+ toggle_step_state("step_2")
+ })
+
+ observeEvent(input$step_3_complete, {
+ toggle_step_state("step_3")
+ })
+
+ observeEvent(input$hungry_kiwi, {
+ toggle_step_state("step_1", FALSE)
+ toggle_step_state("step_2", FALSE)
+ toggle_step_state("step_3", FALSE)
+ })
+
+ }
+
+ shiny::shinyApp(ui, server)
+}
+}
+\seealso{
+single_steps
+}
diff --git a/man/textAreaInput.Rd b/man/textAreaInput.Rd
index 11c6691e..b835f469 100644
--- a/man/textAreaInput.Rd
+++ b/man/textAreaInput.Rd
@@ -24,7 +24,7 @@ Create a text area input control for entry of unstructured text values.
## Only run examples in interactive R sessions
if (interactive()) {
ui <- semanticPage(
- textAreaInput("a", "Area:", width = "200px"),
+ textAreaInput("a", "Area:", value = "200", width = "200px"),
verbatimTextOutput("value")
)
server <- function(input, output, session) {
diff --git a/man/toggle_step_state.Rd b/man/toggle_step_state.Rd
new file mode 100644
index 00000000..3aab200c
--- /dev/null
+++ b/man/toggle_step_state.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/step.R
+\name{toggle_step_state}
+\alias{toggle_step_state}
+\title{Toggle step state}
+\usage{
+toggle_step_state(id, state = TRUE, automatic_steps = TRUE, asis = TRUE)
+}
+\arguments{
+\item{id}{ID of step to be toggled}
+
+\item{state}{State of the step, \code{TRUE} stands for enabled}
+
+\item{automatic_steps}{Whether to toggle focus of next step automatically}
+
+\item{asis}{When used inside of Shiny module, \code{TRUE} will disable adding
+the namespace to \code{id}}
+}
+\description{
+Toggle step state
+}
+\seealso{
+steps
+}
diff --git a/man/update_multiple_checkbox.Rd b/man/update_multiple_checkbox.Rd
new file mode 100644
index 00000000..f35f67a7
--- /dev/null
+++ b/man/update_multiple_checkbox.Rd
@@ -0,0 +1,76 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/checkbox.R
+\name{update_multiple_checkbox}
+\alias{update_multiple_checkbox}
+\alias{update_multiple_radio}
+\title{Update checkbox Semantic UI component}
+\usage{
+update_multiple_checkbox(
+ session = getDefaultReactiveDomain(),
+ input_id,
+ choices = NULL,
+ choices_value = choices,
+ selected = NULL,
+ label = NULL
+)
+
+update_multiple_radio(
+ session = getDefaultReactiveDomain(),
+ input_id,
+ choices = NULL,
+ choices_value = choices,
+ selected = NULL,
+ label = NULL
+)
+}
+\arguments{
+\item{session}{The \code{session} object passed to function given to \code{shinyServer}.}
+
+\item{input_id}{The id of the input object}
+
+\item{choices}{All available options one can select from. If no need to update then leave as \code{NULL}}
+
+\item{choices_value}{What reactive value should be used for corresponding choice.}
+
+\item{selected}{The initially selected value.}
+
+\item{label}{The label linked to the input}
+}
+\description{
+Change the value of a \code{\link{multiple_checkbox}} input on the client.
+}
+\examples{
+if (interactive()) {
+
+library(shiny)
+library(shiny.semantic)
+
+ui <- function() {
+ shinyUI(
+ semanticPage(
+ title = "Checkbox example",
+ form(
+ multiple_checkbox(
+ "simple_checkbox", "Letters:", LETTERS[1:5], selected = c("A", "C"), type = "slider"
+ )
+ ),
+ p("Selected letter:"),
+ textOutput("selected_letter"),
+ shiny.semantic::actionButton("simple_button", "Update input to D")
+ )
+ )
+}
+
+server <- shinyServer(function(input, output, session) {
+ output$selected_letter <- renderText(paste(input[["simple_checkbox"]], collapse = ", "))
+
+ observeEvent(input$simple_button, {
+ update_multiple_checkbox(session, "simple_checkbox", selected = "D")
+ })
+})
+
+shinyApp(ui = ui(), server = server)
+
+}
+
+}
diff --git a/man/update_numeric_input.Rd b/man/update_numeric_input.Rd
index 1b2f4446..4e37fb64 100644
--- a/man/update_numeric_input.Rd
+++ b/man/update_numeric_input.Rd
@@ -16,7 +16,7 @@ update_numeric_input(
)
updateNumericInput(
- session,
+ session = getDefaultReactiveDomain(),
inputId,
label = NULL,
value = NULL,
diff --git a/tests/testthat/test_step.R b/tests/testthat/test_step.R
new file mode 100644
index 00000000..2081f17f
--- /dev/null
+++ b/tests/testthat/test_step.R
@@ -0,0 +1,29 @@
+context("steps")
+
+test_that("test steps", {
+ # type
+ expect_is(single_step("step_1", "Step 1"), "shiny.tag")
+ expect_is(
+ steps(
+ "steps",
+ list(
+ single_step("step_1", "Step 1"),
+ single_step("step_1", "Step 1"))
+ ),
+ "shiny.tag"
+ )
+ # empty input
+ expect_error(single_step())
+ expect_error(steps())
+ # Single step
+ single_step_str <- as.character(single_step("step_1", "Step 1"))
+ expect_true(grepl("", # nolint
+ single_step_str))
+
+ # Steps
+ steps_str <- steps("steps", list(single_step("step_1", "Step 1"),
+ single_step("step_1", "Step 1")))
+ expect_true(grepl("", # nolint
+ steps_str))
+
+})
diff --git a/tests/testthat/test_utils.R b/tests/testthat/test_utils.R
index 55f8c43b..aa30a4dd 100644
--- a/tests/testthat/test_utils.R
+++ b/tests/testthat/test_utils.R
@@ -14,6 +14,7 @@ test_that("test check_proper_color", {
})
test_that("test warn_unsupported_args", {
+ expect_null(warn_unsupported_args(NULL))
expect_error(warn_unsupported_args(1), "Wrong input type!")
expect_warning(warn_unsupported_args(c("a","b")), "arguments: `a,b` are not supported yet")
expect_warning(warn_unsupported_args(list(a=1,b=2)), "arguments: `a,b` are not supported yet")
diff --git a/vignettes/basics.Rmd b/vignettes/basics.Rmd
index 533b4eef..4d2dcd14 100644
--- a/vignettes/basics.Rmd
+++ b/vignettes/basics.Rmd
@@ -37,9 +37,9 @@ UI framework that works under the hood.
- **What `shiny.semantic` has to do with Fomantic UI?**
Similarly to `Shiny` attaching *Bootstrap* CSS and JS libraries, `shiny.semantic` relies on
-[Fomantic UI](fomantic-ui.com/). Historically, we built this package around *Semantic UI*
+[Fomantic UI](https://fomantic-ui.com/). Historically, we built this package around *Semantic UI*
library, but it got deprecated and now (since December 2019) we rely on the well-supported
-and maintained community fork called [Fomantic UI](fomantic-ui.com/).
+and maintained community fork called [Fomantic UI](https://fomantic-ui.com/).
- **Do I need to learn a new syntax to be able to use it?**
@@ -70,7 +70,7 @@ You can use `shiny.semantic` in two ways:
### (a) Using Fomantic CSS classes
If you know this and that about web development, you can create a number of components
-by extending standard `Shiny` objects with class definitions from [Fomantic UI](fomantic-ui.com/)
+by extending standard `Shiny` objects with class definitions from [Fomantic UI](https://fomantic-ui.com/)
documentation. For example:
```{r echo=T, include = T, eval = FALSE, screenshot.force = FALSE}
@@ -107,7 +107,7 @@ text_input("txt", type = "text", placeholder = "Enter Text")
date_input("date")
```
-For more components visit our [Components live demo website](https://demo.appsilon.ai/semantic/)
+For more components visit our [Components live demo website](https://demo.appsilon.com/apps/semantic)
or the `examples/` folder on our [repository](https://github.com/Appsilon/shiny.semantic/).
Little sneak-peak of what you can get is listed on the graphics below. Most of the components