Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fill arguments to shinyWidgetOutput() and sizingPolicy() #442

Merged
merged 6 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 23 additions & 71 deletions .github/workflows/R-CMD-check.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
# NOTE: This workflow is overkill for most R packages
# check-standard.yaml is likely a better choice
# usethis::use_github_action("check-standard") will install it.
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
#
# For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag.
# https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions
# NOTE: This workflow is overkill for most R packages and
# check-standard.yaml is likely a better choice.
# usethis::use_github_action("check-standard") will install it.
on:
push:
branches:
- master
branches: [main, master]
pull_request:
branches:
- master
branches: [main, master]

name: R-CMD-check

Expand All @@ -26,79 +24,33 @@ jobs:
config:
- {os: macOS-latest, r: 'release'}
- {os: windows-latest, r: 'release'}
- {os: windows-latest, r: '3.6'}
- {os: ubuntu-16.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest", http-user-agent: "R/4.0.0 (ubuntu-16.04) R (4.0.0 x86_64-pc-linux-gnu x86_64 linux-gnu) on GitHub Actions" }
- {os: ubuntu-16.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.5', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.4', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.3', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
- {os: ubuntu-latest, r: 'release'}
- {os: ubuntu-latest, r: 'oldrel-1'}
- {os: ubuntu-latest, r: 'oldrel-2'}
- {os: ubuntu-latest, r: 'oldrel-3'}
- {os: ubuntu-latest, r: 'oldrel-4'}

env:
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
RSPM: ${{ matrix.config.rspm }}
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes

steps:
- uses: actions/checkout@v2

- uses: r-lib/actions/setup-r@master
- uses: r-lib/actions/setup-pandoc@v2

- uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ matrix.config.r }}
http-user-agent: ${{ matrix.config.http-user-agent }}
use-public-rspm: true

- uses: r-lib/actions/setup-pandoc@master

- name: Query dependencies
run: |
install.packages('remotes')
saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
shell: Rscript {0}

- name: Cache R packages
if: runner.os != 'Windows'
uses: actions/cache@v2
- uses: r-lib/actions/setup-r-dependencies@v2
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-

- name: Install system dependencies
if: runner.os == 'Linux'
run: |
while read -r cmd
do
eval sudo $cmd
done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "16.04"))')

- name: Install dependencies
run: |
remotes::install_deps(dependencies = TRUE)
remotes::install_cran("rcmdcheck")
shell: Rscript {0}

- name: Session info
run: |
options(width = 100)
pkgs <- installed.packages()[, "Package"]
sessioninfo::session_info(pkgs, include_base = TRUE)
shell: Rscript {0}

- name: Check
env:
_R_CHECK_CRAN_INCOMING_: false
run: rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
shell: Rscript {0}

- name: Show testthat output
if: always()
run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true
shell: bash
extra-packages: any::rcmdcheck
needs: check

- name: Upload check results
if: failure()
uses: actions/upload-artifact@main
- uses: r-lib/actions/check-r-package@v2
with:
name: ${{ runner.os }}-r${{ matrix.config.r }}-results
path: check
upload-snapshots: true
7 changes: 5 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: htmlwidgets
Type: Package
Title: HTML Widgets for R
Version: 1.5.4.9000
Version: 1.5.4.9001
Authors@R: c(
person("Ramnath", "Vaidyanathan", role = c("aut", "cph")),
person("Yihui", "Xie", role = c("aut")),
Expand All @@ -19,7 +19,7 @@ License: MIT + file LICENSE
VignetteBuilder: knitr
Imports:
grDevices,
htmltools (>= 0.3),
htmltools (>= 0.5.3.9001),
jsonlite (>= 0.9.16),
yaml
Suggests:
Expand All @@ -30,3 +30,6 @@ Enhances: shiny (>= 1.1)
URL: https://github.com/ramnathv/htmlwidgets
BugReports: https://github.com/ramnathv/htmlwidgets/issues
RoxygenNote: 7.2.1
Encoding: UTF-8
Remotes:
rstudio/htmltools
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ htmlwidgets 1.5.4.9000

### Breaking change

* `shinyWidgetOutput()`'s `reportSize` argument now defaults to `TRUE`. This way, calling `shiny::getCurrentOutputInfo()` inside a `shinyRenderWidget()` context will report the current height and width of the widget.
* `shinyWidgetOutput()`'s `reportSize` argument now defaults to `TRUE`. This way, calling `shiny::getCurrentOutputInfo()` inside a `shinyRenderWidget()` context will report the current height and width of the widget.

### Improvements

* `shinyWidgetOutput()` and `sizingPolicy()` both gain a new `fill` parameter. When `TRUE`, the widget is allowed to grow/shrink to fit it's parent container so long as that parent has a defined height and has been marked with `htmltools::asFillContainer()` (https://github.com/rstudio/htmltools/pull/343). The primary motivation for this is to allow widgets to grow and shrink (by default) when used [inside `bslib::card_body_fill()`](https://rstudio.github.io/bslib/articles/cards.html#responsive-sizing) (#442)
cpsievert marked this conversation as resolved.
Show resolved Hide resolved
* Closed #433: `saveWidget()` no longer throw deprecation warning when pandoc 2.19 or higher is used.

htmlwidgets 1.5.4
Expand Down
139 changes: 70 additions & 69 deletions R/htmlwidgets.R
Original file line number Diff line number Diff line change
Expand Up @@ -170,62 +170,51 @@ addHook <- function(x, hookName, jsCode, data = NULL) {

toHTML <- function(x, standalone = FALSE, knitrOptions = NULL) {

x$id <- x$elementId %||% paste("htmlwidget", createWidgetId(), sep = "-")

sizeInfo <- resolveSizing(x, x$sizingPolicy, standalone = standalone, knitrOptions = knitrOptions)

if (!is.null(x$elementId))
id <- x$elementId
else
id <- paste("htmlwidget", createWidgetId(), sep="-")
name <- class(x)[1]
package <- attr(x, "package")

w <- validateCssUnit(sizeInfo$width)
h <- validateCssUnit(sizeInfo$height)
html <- widget_html(
name, package, id = x$id,
style = css(
width = validateCssUnit(sizeInfo$width),
height = validateCssUnit(sizeInfo$height)
),
class = paste(name, "html-widget"),
width = sizeInfo$width,
height = sizeInfo$height
)

# create a style attribute for the width and height
style <- paste(
"width:", w, ";",
"height:", h, ";",
sep = "")
if (sizeInfo$fill) {
html <- asFillItem(html)
}

x$id <- id
html <- tagList(x$append, html, x$prepend)

container <- if (isTRUE(standalone)) {
function(x) {
div(id="htmlwidget_container", x)
}
} else {
identity
if (isTRUE(standalone)) {
html <- div(id = "htmlwidget_container", html)
}

html <- htmltools::tagList(
container(
htmltools::tagList(
x$prepend,
widget_html(
name = class(x)[1],
package = attr(x, "package"),
id = id,
style = style,
class = paste(class(x)[1], "html-widget"),
width = sizeInfo$width,
height = sizeInfo$height
),
x$append
)
),
widget_data(x, id),
html <- tagList(
html, widget_data(x, x$id),
if (!is.null(sizeInfo$runtime)) {
tags$script(type="application/htmlwidget-sizing", `data-for` = id,
tags$script(
type = "application/htmlwidget-sizing",
`data-for` = x$id,
toJSON(sizeInfo$runtime)
)
}
)
html <- htmltools::attachDependencies(html,
c(widget_dependencies(class(x)[1], attr(x, 'package')),
x$dependencies)
)

htmltools::browsable(html)
deps <- c(
widget_dependencies(name, package),
x$dependencies
)

browsable(attachDependencies(html, deps, append = TRUE))
}

lookup_func <- function(name, package) {
Expand Down Expand Up @@ -263,7 +252,7 @@ lookup_widget_html_method <- function(name, package) {
list(fn = widget_html.default, name = "widget_html.default", legacy = FALSE)
}

widget_html <- function (name, package, id, style, class, inline = FALSE, ...) {
widget_html <- function(name, package, id, style, class, inline = FALSE, ...) {

fn_info <- lookup_widget_html_method(name, package)

Expand Down Expand Up @@ -432,11 +421,11 @@ createWidget <- function(name,
#'
#' @param outputId output variable to read from
#' @param name Name of widget to create output binding for
#' @param width,height Must be a valid CSS unit (like \code{"100\%"},
#' \code{"400px"}, \code{"auto"}) or a number, which will be coerced to a
#' string and have \code{"px"} appended.
#' @param package Package containing widget (defaults to \code{name})
#' @param inline use an inline (\code{span()}) or block container (\code{div()})
#' @param width,height Must be a valid CSS unit (like `"100%"`,
#' `"400px"`, `"auto"`) or a number, which will be coerced to a
#' string and have `"px"` appended.
#' @param package Package containing widget (defaults to `name`)
#' @param inline use an inline (`span()`) or block container (`div()`)
#' for the output
#' @param outputFunction Shiny output function corresponding to this render
#' function.
Expand All @@ -445,12 +434,17 @@ createWidget <- function(name,
#' @param reportTheme Should the widget's container styles (e.g., colors and fonts)
#' be reported in the shiny session's client data?
#' @param expr An expression that generates an HTML widget (or a
#' \href{https://rstudio.github.io/promises/}{promise} of an HTML widget).
#' @param env The environment in which to evaluate \code{expr}.
#' @param quoted Is \code{expr} a quoted expression (with \code{quote()})? This
#' [promise](https://rstudio.github.io/promises/) of an HTML widget).
#' @param env The environment in which to evaluate `expr`.
#' @param quoted Is `expr` a quoted expression (with `quote()`)? This
#' is useful if you want to save an expression in a variable.
#' @param cacheHint Extra information to use for optional caching using
#' \code{shiny::bindCache()}.
#' `shiny::bindCache()`.
#' @param fill whether or not the returned tag should be treated as a fill item
#' ([htmltools::asFillItem()]), meaning that its `height` is allowed to
#' grow/shrink inside a fill container ([htmltools::asFillContainer()]) with
#' an opinionated height. Examples of fill containers include `bslib::card()`
#' and `bslib::card_body_fill()`.
#'
#' @return An output or render function that enables the use of the widget
#' within Shiny applications.
Expand All @@ -473,35 +467,42 @@ createWidget <- function(name,
#' @name htmlwidgets-shiny
#'
#' @export
#' @md
shinyWidgetOutput <- function(outputId, name, width, height, package = name,
inline = FALSE, reportSize = TRUE, reportTheme = FALSE) {
inline = FALSE, reportSize = TRUE, reportTheme = FALSE,
fill = !inline) {

# Theme reporting requires this shiny feature
# https://github.com/rstudio/shiny/pull/2740/files
if (reportTheme && !is_installed("shiny", "1.4.0.9003")) {
message("`reportTheme = TRUE` requires shiny v.1.4.0.9003 or higher. Consider upgrading shiny.")
}

# generate html
html <- htmltools::tagList(
widget_html(
name, package, id = outputId,
class = paste0(
name, " html-widget html-widget-output",
if (reportSize) " shiny-report-size",
if (reportTheme) " shiny-report-theme"
),
style = sprintf("width:%s; height:%s; %s",
htmltools::validateCssUnit(width),
htmltools::validateCssUnit(height),
if (inline) "display: inline-block;" else ""
), width = width, height = height
tag <- widget_html(
name, package, id = outputId,
class = paste0(
name, " html-widget html-widget-output",
if (reportSize) " shiny-report-size",
if (reportTheme) " shiny-report-theme"
),
style = css(
width = validateCssUnit(width),
height = validateCssUnit(height),
display = if (inline) "inline-block"
)
)

# attach dependencies
dependencies = widget_dependencies(name, package)
htmltools::attachDependencies(html, dependencies)
if (fill) {
tag <- asFillItem(tag)
}

# Adds an additional and unnecessary tagList() container to the return value...
# I'd love remove it, but lets keep it for backwards-compatibility
tag <- tagList(tag)

attachDependencies(
tag, widget_dependencies(name, package), append = TRUE
)
}


Expand Down
Loading