diff --git a/.Rbuildignore b/.Rbuildignore index ab987bf..c5461df 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,3 +1,4 @@ +^CRAN-RELEASE$ ^node_modules$ ^js-tests$ ^srcjs$ @@ -7,13 +8,13 @@ ^CONDUCT\.md$ ^README\.Rmd$ ^\.Rproj\.user$ -^\.travis\.yml$ ^buildupdate$ ^docs$ ^cran-comments\.md$ -^karma\.conf\.js$ ^logo.svg$ ^package\.json$ -^webpack\.config\.js$ -^yarn\.lock$ +^vite\.config\.js$ +^package-lock\.json$ ^logo\.svg$ +^\.github$ +^CRAN-SUBMISSION$ diff --git a/.github/.gitignore b/.github/.gitignore new file mode 100644 index 0000000..2d19fc7 --- /dev/null +++ b/.github/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml new file mode 100644 index 0000000..a3ac618 --- /dev/null +++ b/.github/workflows/R-CMD-check.yaml @@ -0,0 +1,49 @@ +# 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 +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: R-CMD-check + +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - {os: macos-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v3 + + - 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-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 + with: + upload-snapshots: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 092d345..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -matrix: - include: - # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r - - language: r - r: - - release - sudo: required - cache: packages - before_install: - - sudo apt-get install -y libv8-dev - - language: node_js - node_js: - - "11.4.0" - addons: - - chrome: stable \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index 42609e5..13dd679 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,13 +1,18 @@ Package: reactR Type: Package Title: React Helpers -Version: 0.4.1 -Date: 2019-05-14 +Version: 0.6.1 +Date: 2024-09-14 Authors@R: c( person( "Facebook", "Inc" , role = c("aut", "cph") - , comment = "React library in lib, https://facebook.github.io/react; see AUTHORS for full list of contributors" + , comment = "React library in lib, https://reactjs.org/; see AUTHORS for full list of contributors" + ), + person( + "Michel","Weststrate", + , role = c("aut", "cph") + , comment = "mobx library in lib, https://github.com/mobxjs" ), person( "Kent", "Russell" @@ -20,6 +25,12 @@ Authors@R: c( , role = c("aut") , comment = "R interface" , email = "alan@rstudio.com" + ), + person( + "Greg", "Lin" + , role = c("aut") + , comment = "R interface" + , email = "glin@glin.io" ) ) Maintainer: Kent Russell @@ -34,12 +45,12 @@ Encoding: UTF-8 Imports: htmltools Suggests: - htmlwidgets (>= 0.6.0), + htmlwidgets (>= 1.5.3), rmarkdown, shiny, V8, knitr, usethis, jsonlite -RoxygenNote: 6.1.1 +RoxygenNote: 7.3.2 VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index a996be6..a0e2eeb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,6 +9,7 @@ export(babel_transform) export(component) export(createReactShinyInput) export(html_dependency_corejs) +export(html_dependency_mobx) export(html_dependency_react) export(html_dependency_reacttools) export(reactMarkup) diff --git a/NEWS.md b/NEWS.md index 06c2a42..f87f910 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,51 @@ -# master +# reactR 0.6.1 + +* Fix issue where the `react-tools.umd.cjs` script could be blocked by the browser in some cases, such as apps deployed on shinyapps.io [#86](https://github.com/react-R/reactR/issues/86) + +# reactR 0.6.0 + +* retain `list` in `reactR::component` classes [#82](https://github.com/react-R/reactR/issues/82) +* hydrate props/attribs that are tags assuming tag-like props/attribs should be slots[#67](https://github.com/react-R/reactR/issues/67) [#61](https://github.com/react-R/reactR/issues/61) +* update build tools to `vite` from `webpack` +* update js testing library from `karma` to `vitest` + + +# reactR 0.5.0 + +* Update react to `18.2.0` + +# reactR 0.4.4 + +* Update react to `16.12.0` + +* Add `style-loader` and `css-loader` to webpack config [pull 50](https://github.com/react-R/reactR/pull/50) + +* Update to `PACKAGE::widget_html.WIDGETNAME` for new `htmlwidgets` convention [pull 49](https://github.com/react-R/reactR/pull/49) + +* Clean up template [pull 45](https://github.com/react-R/reactR/pull/45) + +# reactR 0.4.3 + +* Add element to Shiny input [pull 41](https://github.com/react-R/reactR/pull/41) + +* Upgrade npm dependencies + +# reactR 0.4.2 + +* Update react to `16.12.0` + +* Update core-js to `2.6.11` + +# reactR 0.4.1 * Add support for `shiny::registerInputHandler` in Shiny inputs; [pull 28](https://github.com/react-R/reactR/pull/28) * Add support for Shiny rate limit [pull 29](https://github.com/react-R/reactR/pull/29) +* Update react to `16.8.6` + +* Add `mobx` dependencies available through `html_dependency_mobx()` + # reactR 0.4.0 * Add Shiny input scaffold and functionality; [tutorial](https://react-r.github.io/reactR/articles/intro_inputs.html) and [pull 22](https://github.com/react-R/reactR/pull/22) thanks @alandipert @@ -44,7 +86,7 @@ * Update to react `15.5.0` * Update to babel `6.24.0` -* Add [office-fabric-react](http://dev.office.com/fabric) example +* Add fluent-ui(fabric) example * Build doc site with `pkgdown` # reactR 0.1.1 diff --git a/R/dependencies.R b/R/dependencies.R index 5dc4870..cfc0397 100644 --- a/R/dependencies.R +++ b/R/dependencies.R @@ -80,8 +80,88 @@ html_dependency_reacttools <- function(){ htmltools::htmlDependency( name = "reactwidget", src = "www/react-tools", - version = "1.0.0", + version = "2.0.0", package = "reactR", script = c("react-tools.js") ) } + +#' Dependencies for 'mobx' +#' +#' Add JavaScript 'mobx' and 'mobx-react' dependency. When using with 'react', the order +#' of the dependencies is important, so please add \code{html_dependency_react()} before +#' \code{html_dependency_mobx()}. +#' +#' @param react \code{logical} to add react 'mobx' dependencies. +#' +#' @return \code{\link[htmltools]{htmlDependency}} +#' @importFrom htmltools htmlDependency +#' @export +#' +#' @examples +#' if(interactive()) { +#' +#' library(htmltools) +#' library(reactR) +#' +#' browsable( +#' tagList( +#' html_dependency_mobx(react = FALSE), +#' div(id="test"), +#' tags$script(HTML( +#' " +#' var obs = mobx.observable({val: null}) +#' mobx.autorun(function() { +#' document.querySelector('#test').innerText = obs.val +#' }) +#' setInterval( +#' function() {obs.val++}, +#' 1000 +#' ) +#' " +#' )) +#' ) +#' ) +#' } +#' +#' \dontrun{ +#' # use with react +#' library(htmltools) +#' library(reactR) +#' +#' browsable( +#' tagList( +#' html_dependency_react(), +#' html_dependency_mobx(), +#' div(id="test"), +#' tags$script(HTML(babel_transform( +#' " +#' var obs = mobx.observable({val: null}) +#' var App = mobxReact.observer((props) =>
{props.obs.val}
) +#' +#' ReactDOM.render(, document.querySelector('#test')) +#' +#' setInterval( +#' function() {obs.val++}, +#' 1000 +#' ) +#' " +#' ))) +#' ) +#' ) +#' } + +html_dependency_mobx <- function(react = TRUE){ + hd <- htmltools::htmlDependency( + name = "mobx", + version = "4.11.0", + src = system.file("www/mobx",package="reactR"), + script = c("mobx.umd.min.js") + ) + + if(react) { + hd$script <- c(hd$script,"mobx-react-lite.js", "mobx-react.umd.js") + } + + hd +} diff --git a/R/meta.R b/R/meta.R index 1ca680f..76c246d 100644 --- a/R/meta.R +++ b/R/meta.R @@ -1,3 +1,3 @@ #'@keywords internal -react_version <- function(){'16.8.1'} +react_version <- function(){'18.2.0'} babel_version <- function(){'6.26.0'} \ No newline at end of file diff --git a/R/reacttools.R b/R/reacttools.R index 4f65f6b..08999f1 100644 --- a/R/reacttools.R +++ b/R/reacttools.R @@ -32,7 +32,7 @@ component <- function(name, varArgs = list()) { stop("Component name must be specified and start with an upper case character") } component <- htmltools::tag(name, varArgs) - structure(component, class = c("reactR_component", oldClass(component))) + structure(component, class = c("reactR_component", oldClass(component), "list")) } #' React component builder. @@ -145,10 +145,10 @@ createReactShinyInput <- function(inputId, container(id = inputId, class = class), htmltools::tags$script(id = sprintf("%s_value", inputId), type = "application/json", - jsonlite::toJSON(value, auto_unbox = TRUE, null = "null")), + jsonlite::toJSON(value, auto_unbox = TRUE, null = "null", force = TRUE)), htmltools::tags$script(id = sprintf("%s_configuration", inputId), type = "application/json", - jsonlite::toJSON(configuration, auto_unbox = TRUE, null = "null")), + jsonlite::toJSON(configuration, auto_unbox = TRUE, null = "null", force = TRUE)), dependencies ) } diff --git a/R/scaffold_input.R b/R/scaffold_input.R index fc9df6a..fa86c3b 100644 --- a/R/scaffold_input.R +++ b/R/scaffold_input.R @@ -4,10 +4,10 @@ #' R package. #' #' @param name Name of input -#' @param npmPkgs Optional \href{https://npmjs.com/}{NPM} packages upon which +#' @param npmPkgs Optional \href{https://www.npmjs.com/}{NPM} packages upon which #' this input is based which will be used to populate \code{package.json}. #' Should be a named list of names to -#' \href{https://docs.npmjs.com/files/package.json#dependencies}{versions}. +#' \href{https://docs.npmjs.com/files/package.json/}{versions}. #' @param edit Automatically open the input's source files after creating the #' scaffolding. #' diff --git a/R/scaffold_widget.R b/R/scaffold_widget.R index 4240f1b..6022de9 100644 --- a/R/scaffold_widget.R +++ b/R/scaffold_widget.R @@ -4,10 +4,10 @@ #' R package. #' #' @param name Name of widget -#' @param npmPkgs Optional \href{https://npmjs.com/}{NPM} packages upon which +#' @param npmPkgs Optional \href{https://www.npmjs.com/}{NPM} packages upon which #' this widget is based which will be used to populate \code{package.json}. #' Should be a named list of names to -#' \href{https://docs.npmjs.com/files/package.json#dependencies}{versions}. +#' \href{https://docs.npmjs.com/files/package.json/}{versions}. #' @param edit Automatically open the widget's JavaScript source file after #' creating the scaffolding. #' diff --git a/README.Rmd b/README.Rmd index a9171ca..a2ff8fd 100644 --- a/README.Rmd +++ b/README.Rmd @@ -16,10 +16,9 @@ knitr::opts_chunk$set( ``` [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/reactR)](https://cran.r-project.org/package=reactR) -[![Travis-CI Build Status](https://travis-ci.org/react-R/reactR.svg?branch=master)](https://travis-ci.org/react-R/reactR) -[![Slack Status](https://reactr-slackin.herokuapp.com/badge.svg)](https://reactr-slackin.herokuapp.com/) +[![R-CMD-check](https://github.com/react-R/reactR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/react-R/reactR/actions/workflows/R-CMD-check.yaml) -`reactR` provides a set of convenience functions for using [`React`](https://facebook.github.io/react) in `R` with `htmlwidget` constructor templates and local JavaScript dependencies. The `React` ecosystem is rich with components that can enhance `R` web and Shiny apps. `scaffoldReactWidget()` helps build `htmlwidgets` to integrate these `React` components as `R` `htmlwidgets`. `scaffoldReactShinyInput()` does the same for `Shiny` inputs. The local dependency functions are modeled after the `html_dependency_*` functions from RStudio's [`rmarkdown`](https://github.com/rstudio/rmarkdown) package. +`reactR` provides a set of convenience functions for using [`React`](https://reactjs.org/) in `R` with `htmlwidget` constructor templates and local JavaScript dependencies. The `React` ecosystem is rich with components that can enhance `R` web and Shiny apps. `scaffoldReactWidget()` helps build `htmlwidgets` to integrate these `React` components as `R` `htmlwidgets`. `scaffoldReactShinyInput()` does the same for `Shiny` inputs. The local dependency functions are modeled after the `html_dependency_*` functions from RStudio's [`rmarkdown`](https://github.com/rstudio/rmarkdown) package. ## Installation @@ -34,6 +33,9 @@ devtools::install_github("react-R/reactR") To wrap a `React` component as an `htmlwidget`, please see the tutorial [htmlwidgets with reactR](https://react-r.github.io/reactR/articles/intro_htmlwidgets.html). Also, there are a variety of examples in the [react-R Github organization](https://github.com/react-R). + +[`reactable`](https://github.com/glin/reactable) is a very well-built `htmlwidget` leveraging this functionality. + ## Shiny Outputs and Inputs `htmlwidgets` built with `reactR` work well in Shiny as outputs. In version `0.4.0` Alan Dipert has added the ability to easily create React-based official `Shiny` inputs with helpers and scaffolds. Please see the [tutorial](https://react-r.github.io/reactR/articles/intro_inputs.html) for more details. @@ -78,8 +80,8 @@ browsable( tags$script( babel_transform('ReactDOM.render(

Powered By React/JSX

,document.getElementById("app"))') ), - # add core-js shim first for React in RStudio Viewer - html_dependency_corejs(), + # add core-js shim first for React in older versions of RStudio Viewer + #html_dependency_corejs(), html_dependency_react() ) ) @@ -87,4 +89,4 @@ browsable( ## Contributing and Code of Conduct -We welcome contributors and would love your participation. Please note that this project is released with a [Contributor Code of Conduct](CONDUCT.md). By participating in this project you agree to abide by the terms. +We welcome contributors and would love your participation. Please note that this project is released with a [Contributor Code of Conduct](https://github.com/react-R/reactR/blob/master/CONDUCT.md). By participating in this project you agree to abide by the terms. diff --git a/README.md b/README.md index 29e6dcd..d9e9178 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,18 @@ -[![CRAN\_Status\_Badge](https://www.r-pkg.org/badges/version/reactR)](https://cran.r-project.org/package=reactR) -[![Travis-CI Build -Status](https://travis-ci.org/react-R/reactR.svg?branch=master)](https://travis-ci.org/react-R/reactR) -[![Slack -Status](https://reactr-slackin.herokuapp.com/badge.svg)](https://reactr-slackin.herokuapp.com/) +[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/reactR)](https://cran.r-project.org/package=reactR) +[![R-CMD-check](https://github.com/react-R/reactR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/react-R/reactR/actions/workflows/R-CMD-check.yaml) `reactR` provides a set of convenience functions for using -[`React`](https://facebook.github.io/react) in `R` with `htmlwidget` -constructor templates and local JavaScript dependencies. The `React` -ecosystem is rich with components that can enhance `R` web and Shiny -apps. `scaffoldReactWidget()` helps build `htmlwidgets` to integrate -these `React` components as `R` `htmlwidgets`. -`scaffoldReactShinyInput()` does the same for `Shiny` inputs. The local -dependency functions are modeled after the `html_dependency_*` functions -from RStudio’s [`rmarkdown`](https://github.com/rstudio/rmarkdown) -package. +[`React`](https://reactjs.org/) in `R` with `htmlwidget` constructor +templates and local JavaScript dependencies. The `React` ecosystem is +rich with components that can enhance `R` web and Shiny apps. +`scaffoldReactWidget()` helps build `htmlwidgets` to integrate these +`React` components as `R` `htmlwidgets`. `scaffoldReactShinyInput()` +does the same for `Shiny` inputs. The local dependency functions are +modeled after the `html_dependency_*` functions from RStudio’s +[`rmarkdown`](https://github.com/rstudio/rmarkdown) package. ## Installation @@ -38,6 +34,9 @@ reactR](https://react-r.github.io/reactR/articles/intro_htmlwidgets.html). Also, there are a variety of examples in the [react-R Github organization](https://github.com/react-R). +[`reactable`](https://github.com/glin/reactable) is a very well-built +`htmlwidget` leveraging this functionality. + ## Shiny Outputs and Inputs `htmlwidgets` built with `reactR` work well in Shiny as outputs. In @@ -88,8 +87,8 @@ browsable( tags$script( babel_transform('ReactDOM.render(

Powered By React/JSX

,document.getElementById("app"))') ), - # add core-js shim first for React in RStudio Viewer - html_dependency_corejs(), + # add core-js shim first for React in older versions of RStudio Viewer + #html_dependency_corejs(), html_dependency_react() ) ) @@ -99,5 +98,5 @@ browsable( We welcome contributors and would love your participation. Please note that this project is released with a [Contributor Code of -Conduct](CONDUCT.md). By participating in this project you agree to -abide by the terms. +Conduct](https://github.com/react-R/reactR/blob/master/CONDUCT.md). By +participating in this project you agree to abide by the terms. diff --git a/cran-comments.md b/cran-comments.md index d8f5781..5922624 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,8 +1,8 @@ ## Test environments -* local Windows 10 install, R 3.4.0 +* local Windows 10 install, R 4.3.1 * rhub check_for_cran * winbuilder -* travis-ci +* github actions check for cran - ubuntu, mac, windows ## R CMD check results @@ -10,4 +10,4 @@ ## Reverse dependencies -There are no reverse dependencies. +reactable - consulted with author who has tested and approved the changes diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 0000000..d76465a --- /dev/null +++ b/docs/404.html @@ -0,0 +1,127 @@ + + + + + + + +Page not found (404) • reactR + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + +Content not found. Please use links in the navbar. + +
+ + + +
+ + + +
+ +
+

+

Site built with pkgdown 2.0.7.

+
+ +
+
+ + + + + + + + diff --git a/docs/CONDUCT.html b/docs/CONDUCT.html index c57d556..94a2ad9 100644 --- a/docs/CONDUCT.html +++ b/docs/CONDUCT.html @@ -1,62 +1,12 @@ - - - - - - - -Contributor Code of Conduct • reactR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Contributor Code of Conduct • reactR - + + - - -
-
- -
-
+
+ +
-
- + +
+ + + - - + diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index 87fa6e9..ad8a151 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -1,62 +1,12 @@ - - - - - - - -License • reactR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -License • reactR - + + - - -
-
- -
-
+
+ +
-
- + +
+ + + - - + diff --git a/docs/articles/index.html b/docs/articles/index.html index 1408e0f..8027daa 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -1,62 +1,12 @@ - - - - - - - -Articles • reactR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Articles • reactR - + + - - -
-
- -
- -
- + +
+ + + - - + diff --git a/docs/articles/intro_htmlwidgets.html b/docs/articles/intro_htmlwidgets.html index bdbbcdc..f388849 100644 --- a/docs/articles/intro_htmlwidgets.html +++ b/docs/articles/intro_htmlwidgets.html @@ -12,18 +12,21 @@ - - - + + + + + - - + - + + +
-

The htmlwidgets package provides a framework for creating R bindings to JavaScript libraries. Using the htmlwidgets package alone, it’s not necessarily straight-forward to create an R binding to a React-powered JavaScript library. The reactR package builds on the htmlwidgets framework to make it much easier to author htmlwidgets that are powered by React. This vignette will show you how to effectively leverage reactR to build an htmlwidgets package that interfaces with react-sparklines React JavaScript library.

-
-

-Software pre-requisites

-

In order to develop a reactR widget, you’ll need to install R and optionally RStudio. If you’re on Windows, you should also install Rtools.

+

The htmlwidgets package +provides a framework for creating R bindings to JavaScript libraries. +Using the htmlwidgets package alone, it’s not +necessarily straight-forward to create an R binding to a React-powered JavaScript library. The +reactR package builds on the +htmlwidgets framework to make it much easier to author +htmlwidgets that are powered by React. This vignette +will show you how to effectively leverage reactR to +build an htmlwidgets package that interfaces with react-sparklines +React JavaScript library.

+
+

Software pre-requisites +

+

In order to develop a reactR widget, you’ll need to +install R and optionally RStudio. If you’re on Windows, you should also +install Rtools.

-

For an excellent general introduction to R package concepts, check out the R packages online book.

+

For an excellent general introduction to R package concepts, check +out the R packages online book.

-

In addition, you’ll need to install the following JavaScript tools on your machine:

+

In addition, you’ll need to install the following JavaScript tools on +your machine:

  • -Node.js: JavaScript engine and runtime for development outside of browsers. Provides the node and npm commands.
  • +Node.js: JavaScript engine and +runtime for development outside of browsers. Provides the +node and npm commands.
  • -Yarn: Command-line dependency management tool, provides the yarn command.
  • +Yarn: Command-line +dependency management tool, provides the yarn command.
-

To follow along in this vignette, you’ll also need the following R packages:

-
install.packages(c("shiny", "devtools", "usethis", "htmlwidgets", "reactR"))
+

To follow along in this vignette, you’ll also need the following R +packages:

+
+install.packages(c("shiny", "devtools", "usethis", "htmlwidgets", "reactR"))
-
-

-Scaffolding

-

To create a new widget you can call scaffoldReactWidget to generate the basic structure and build configuration. This function will:

+
+

Scaffolding +

+

To create a new widget you can call scaffoldReactWidget +to generate the basic structure and build configuration. This function +will:

    -
  • Create the .R, .js, .yaml, and .json files required by your widget;
  • -
  • If provided, take an npm package name and version as a named list with name and version elements. For example, the npm package foo at version ^1.2.0 would be expressed as list(name = "foo", version = "^1.2.0"). The package, if provided, will be added to the new widget’s package.json as a build dependency.
  • +
  • Create the .R, .js, .yaml, and .json files required by your +widget;
  • +
  • If provided, take an npm +package name and version as a named list with name and +version elements. For example, the npm package +foo at version ^1.2.0 would be expressed as +list(name = "foo", version = "^1.2.0"). The package, if +provided, will be added to the new widget’s package.json as +a build dependency.
-

The following R code will create an R package named sparklines, then provide the templating for creating an htmlwidget powered by the react-sparklines npm package:

- +

The following R code will create an R package named +sparklines, then provide the templating for creating an +htmlwidget powered by the react-sparklines npm package:

+
+# Create the R package
+usethis::create_package("~/sparklines")
+# Inject the widget templating
+withr::with_dir(
+  "~/sparklines", 
+  reactR::scaffoldReactWidget("sparklines", list("react-sparklines" = "^1.7.0"), edit = FALSE)
+)
-
-

-Building and installing

-
-

-Building the JavaScript

-

The next step is to navigate to the newly-created sparklines project and run the following R commands:

-
system("yarn install")
-system("yarn run webpack")
+
+

Building and installing +

+
+

Building the JavaScript +

+

The next step is to navigate to the newly-created +sparklines project and run the following R commands:

+
+system("yarn install")
+system("yarn run webpack")
    -
  • yarn install downloads all of the dependencies listed in package.json and creates a new file, yarn.lock. You should add this file to revision control. It will be updated whenever you change dependencies and run yarn install. Note: you only need to run it after modifying package.json. For further documentation on yarn install, see the yarn documentation.

  • -
  • yarn run webpack compiles the ES2015 JavaScript source file at srcjs/sparklines.js into inst/htmlwidgets/sparklines.js. The later file is one actually used by the R package and includes all the relevant JavaScript dependencies in a version of JavaScript that most browsers understand. Note that, if you add --mode=development to the end of this command, it will include a source map is included with the compiled JavaScript, which makes JavaScript debugging much easier, but hopefully you won’t need to do much of any JavaScript debugging.

  • +
  • yarn install downloads all of the dependencies +listed in package.json and creates a new file, +yarn.lock. You should add this file to revision control. It +will be updated whenever you change dependencies and run +yarn install. Note: you only need to run it after +modifying package.json. For further documentation on +yarn install, see the yarn +documentation.

  • +
  • yarn run webpack compiles the ES2015 JavaScript source +file at srcjs/sparklines.js into +inst/htmlwidgets/sparklines.js. The later file is one +actually used by the R package and includes all the relevant JavaScript +dependencies in a version of JavaScript that most browsers understand. +Note that, if you add --mode=development to the end of this +command, it will include a source +map is included with the compiled JavaScript, which makes JavaScript +debugging much easier, but hopefully you won’t need to do much of any +JavaScript debugging.

-

yarn run webpack is not strictly a yarn command. In fact, yarn run simply delegates to the webpack program. Webpack’s configuration is generated by scaffoldReactWidget in the file webpack.config.js, but you can always change this configuration and/or modify the yarn run webpack command to suit your needs.

+

yarn run webpack is not strictly a yarn +command. In fact, yarn run simply delegates to the webpack program. Webpack’s +configuration is generated by scaffoldReactWidget in the +file webpack.config.js, but you can always change this +configuration and/or modify the yarn run webpack command to +suit your needs.

-
-

-Installing the R package

-

Now that the widget’s JavaScript is compiled, go ahead and install the R package:

- -

Alternatively, in RStudio, you can use the keyboard shortcuts Ctrl+Shift+D and Ctrl-Shift-B to document and build the package. (On macOS, the shortcuts are Cmd+Shift+D and Cmd+Shift+B)

+
+

Installing the R package +

+

Now that the widget’s JavaScript is compiled, go ahead and install +the R package:

+
+devtools::document()
+devtools::install(quick = TRUE)
+

Alternatively, in RStudio, you can use the keyboard shortcuts +Ctrl+Shift+D and Ctrl-Shift-B to document and +build the package. (On macOS, the shortcuts are Cmd+Shift+D +and Cmd+Shift+B)

-
-

-Run the included demo

-

Now that the widget’s JavaScript is compiled, and the R package is installed, run app.R to see a demo in action:

- -

Alternatively, in RStudio, you can open app.R and press Ctrl-Shift-Enter (Cmd-Shift-Enter on macOS). You should see something like the following appear in the Viewer pane:

+
+

Run the included demo +

+

Now that the widget’s JavaScript is compiled, and the R package is +installed, run app.R to see a demo in action:

+
+shiny::runApp()
+

Alternatively, in RStudio, you can open app.R and press +Ctrl-Shift-Enter (Cmd-Shift-Enter on macOS). +You should see something like the following appear in the Viewer +pane:

-
-

-Authoring a React binding

-

At this point, we’ve built some scaffolding for an htmlwidget powered by React. Let’s modify it to create an interface to the react-sparklines library. Authoring the interface requires some changes on both the JavaScript and R side, but most of the hard thinking will be in figuring how best to design your interface. To give you an example of how this could work, let’s build an interface to the Sparklines component of the react-sparklines library.

-
-

-First, outline an interface

+
+

Authoring a React binding +

+

At this point, we’ve built some scaffolding for an htmlwidget powered +by React. Let’s modify it to create an interface to the +react-sparklines library. Authoring the interface requires +some changes on both the JavaScript and R side, but most of the hard +thinking will be in figuring how best to design your interface. To give +you an example of how this could work, let’s build an interface to the +Sparklines component of the react-sparklines library.

+
+

First, outline an interface +

-

Note that the examples in this section are just to demonstrate API possibilities and need not be pasted into any file.

+

Note that the examples in this section are just to demonstrate API +possibilities and need not be pasted into any file.

-

Consider the following example taken from the react-sparklines documentation.

- -

You have some choice in terms of how to design an R interface to this sort of React library, but usually it makes sense to have one function per component and have the arguments to that function feed into the properties of that React component. In other words, our goal is to create an R function that allows users of our package to recreate this example with the following code:

- -

The following sections show how to implement this R interface from our scaffolded widget.

+

Consider the following example taken from the react-sparklines +documentation.

+
import React from 'react';
+import { Sparklines } from 'react-sparklines';
+
+<Sparklines data={sampleData}>
+  <SparklinesLine color="#56b45d" />
+  <SparklinesSpots style={{ fill: "#56b45d" }} />
+</Sparklines>
+

You have some choice in terms of how to design an R interface to this +sort of React library, but usually it makes sense to have one function +per component and have the arguments to that function feed into the +properties of that React component. In other words, our goal is to +create an R function that allows users of our package to recreate this +example with the following code:

+
+library(sparklines)
+sparklines(
+  data = sampleData,
+  sparklinesLine(color = "#56b45d"),
+  sparklinesSpots(style = list(fill = "#56b45d"))
+)
+

The following sections show how to implement this R interface from +our scaffolded widget.

-
-

-R implementation

-

Consider the template that reactR::scaffoldReactWidget() provided for us:

- -

This function is designed to simply display a message within an HTML div using reactR and htmlwidgets. The critical piece here that makes it all work is reactR::reactMarkup(). This function can prepare a payload containing a mix of HTML tags (constructed via htmltools::tag()), React components (constructed via reactR::component()), or character vectors in a such way that the reactR and htmlwidgets toolchain will understand and know how to render in the browser (assuming we’ve imported our React component appropriately, as we cover later). Thus, to send a <Sparklines> react component instead of an HTML <div>, we could simply change:

- +
+

R implementation +

+

Consider the template that reactR::scaffoldReactWidget() +provided for us:

+
+sparklines <- function(message, width = NULL, height = NULL, elementId = NULL) {
+  
+  # describe a React component to send to the browser for rendering.
+  content <- htmltools::tag("div", list(message))
+  
+  # create widget
+  htmlwidgets::createWidget(
+    name = 'sparklines',
+    reactR::reactMarkup(content),
+    width = width,
+    height = height,
+    package = 'sparklines',
+    elementId = elementId
+  )
+}
+

This function is designed to simply display a message within an HTML +div using reactR and htmlwidgets. The +critical piece here that makes it all work is +reactR::reactMarkup(). This function can prepare a payload +containing a mix of HTML tags (constructed via +htmltools::tag()), React components (constructed via +reactR::component()), or character vectors in a such way +that the reactR and htmlwidgets +toolchain will understand and know how to render in the browser +(assuming we’ve imported our React component appropriately, as we cover +later). Thus, to send a <Sparklines> react component +instead of an HTML <div>, we could simply change:

+
+content <- htmltools::tag("div", list(message))

to

-
reactR::component("Sparklines", list(message))
-

Remember, though, that we’d like <Sparklines> to consume a data property and also accept other valid components (e.g., <SparklinesLine>, <SparklinesSpot>, etc) from this library as children. So, we could change the body and signature of sparklines() in the following way:

- -

At this point, we define functions that make it easy for the user to create the other components by adding these to R/sparklines.R

- +
+reactR::component("Sparklines", list(message))
+

Remember, though, that we’d like <Sparklines> to +consume a data property and also accept other valid +components (e.g., <SparklinesLine>, +<SparklinesSpot>, etc) from this library as children. +So, we could change the body and signature of sparklines() +in the following way:

+
+sparklines <- function(data, ..., width = NULL, height = NULL) {
+  
+  # describe a React component to send to the browser for rendering.
+  content <- reactR::component(
+    "Sparklines",
+    list(data = data, ...)
+  )
+  
+  # create widget
+  htmlwidgets::createWidget(
+    name = 'sparklines',
+    reactR::reactMarkup(content),
+    width = width,
+    height = height,
+    package = 'sparklines'
+  )
+}
+

At this point, we define functions that make it easy for the user to +create the other components by adding these to +R/sparklines.R

+
+#' @export
+sparklinesLine <- function(...) {
+  reactR::React$SparklinesLine(...)
+}
+
+#' @export
+sparklinesSpots <- function(...) {
+  reactR::React$SparklinesSpots(...)
+}
-
-

-JavaScript changes

-

In order for the reactR toolchain to know how to render components from the ‘react-sparklines’ library, we need to register the React components on the JavaScript side. This can be done in the srcjs/sparklines.js file which currently looks like this:

- -

First, reactWidget is imported from the 'reactR' JavaScript module. This function will register the React components we want within the reactR and htmlwidgets toolchain. Note that the 'reactR' JavaScript is an html dependency, but webpack is configured in webpack.config.js to consider it a module, so it’s available to us here via import syntax.

-

Then, there’s a call to reactWidget, and we pass it three arguments:

+
+

JavaScript changes +

+

In order for the reactR toolchain to know how to +render components from the ‘react-sparklines’ library, we need to +register the React components on the JavaScript side. This can be done +in the srcjs/sparklines.js file which currently looks like +this:

+
import { reactWidget } from 'reactR';
+
+reactWidget('sparklines', 'output', {});
+

First, reactWidget is imported +from the 'reactR' JavaScript module. This function will +register the React components we want within the reactR +and htmlwidgets toolchain. Note that the +'reactR' JavaScript is an html dependency, but webpack is +configured in webpack.config.js to consider it a module, so +it’s available to us here via import syntax.

+

Then, there’s a call to reactWidget, and we pass it +three arguments:

  1. The name of the widget ('sparklines')
  2. The type of the widget ('output')
  3. -
  4. The React components that should be exposed to the widget. In this template, we didn’t have to include any because it’s just rendering an HTML div.
  5. +
  6. The React components that should be exposed to the widget. In this +template, we didn’t have to include any because it’s just rendering an +HTML div.
-

Instead of passing an empty object ({}) as the React components, we provide an object with all the components we need from the ‘react-sparklines’ module:

- +

Instead of passing an empty object ({}) as the React +components, we provide an object with all the components we need from +the ‘react-sparklines’ module:

+
import { Sparklines, SparklinesLine, SparklinesSpots } from 'react-sparklines';
+import { reactWidget } from 'reactR';
+
+reactWidget('sparklines', 'output', {
+  Sparklines: Sparklines,
+  SparklinesLine: SparklinesLine,
+  SparklinesSpots: SparklinesSpots
+});
-
-

-Go for a spin

-

Now that we’ve made the necessary changes to the JavaScript and R source code, it’s time to compile the JavaScript and install the R package:

-
system("yarn install")
-system("yarn run webpack")
-devtools::document()
-devtools::install()
-library(sparklines)
-sparklines(rnorm(10), sparklinesLine())
-

This should open up the sparklines() widget in your browser. If it does, congratulations, you created a React-based htmlwidget!

+
+

Go for a spin +

+

Now that we’ve made the necessary changes to the JavaScript and R +source code, it’s time to compile the JavaScript and install the R +package:

+
+system("yarn install")
+system("yarn run webpack")
+devtools::document()
+devtools::install()
+library(sparklines)
+sparklines(rnorm(10), sparklinesLine())
+

This should open up the sparklines() widget in your +browser. If it does, congratulations, you created a React-based +htmlwidget!

-
-

-Shiny integration

-

The scaffolding template already provides the glue you need to get your reactR widget to render in Shiny. The two relevant functions are renderSparklines() and sparklinesOutput(). You shouldn’t need to modify these functions — they should work out of the box. You will, however, want to modify the example Shiny app in the app.R file:

- -

Now, when you run shiny::runApp(), you should see your react-based htmlwidget rendering in shiny app!

+
+

Shiny integration +

+

The scaffolding template already provides the glue you need to get +your reactR widget to render in Shiny. +The two relevant functions are renderSparklines() and +sparklinesOutput(). You shouldn’t need to modify these +functions — they should work out of the box. You will, however, want to +modify the example Shiny app in the app.R +file:

+
+library(shiny)
+library(sparklines)
+
+ui <- fluidPage(
+  titlePanel("Sparklines library"),
+  sliderInput("n", label = "Number of samples", min = 2, max = 1000, value = 100),
+  sparklinesOutput("myWidget")
+)
+
+server <- function(input, output, session) {
+    output$myWidget <- renderSparklines({
+        sparklines(
+            rnorm(input$n),
+            sparklinesLine()
+        )
+    })
+}
+
+shinyApp(ui, server)
+

Now, when you run shiny::runApp(), you should see your +react-based htmlwidget rendering in shiny app!

-
-

-Further learning

-

This tutorial walked you through the steps taken you create an R interface to the react-sparklines library. The full example package is accessible at https://github.com/react-R/sparklines-example. Our intention is keep creating example packages under the https://github.com/react-R organization, so head there if you’d like to see other examples of interfacing with React.

+
+

Further learning +

+

This tutorial walked you through the steps taken you create an R +interface to the react-sparklines library. The full example package is +accessible at https://github.com/react-R/sparklines-example. Our +intention is keep creating example packages under the https://github.com/react-R organization, so head there +if you’d like to see other examples of interfacing with React.

- +
-

Site built with pkgdown 1.3.0.

+

+

Site built with pkgdown 2.0.7.

+
+ + + diff --git a/docs/articles/intro_htmlwidgets_files/accessible-code-block-0.0.1/empty-anchor.js b/docs/articles/intro_htmlwidgets_files/accessible-code-block-0.0.1/empty-anchor.js new file mode 100644 index 0000000..ca349fd --- /dev/null +++ b/docs/articles/intro_htmlwidgets_files/accessible-code-block-0.0.1/empty-anchor.js @@ -0,0 +1,15 @@ +// Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> +// v0.0.1 +// Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. + +document.addEventListener('DOMContentLoaded', function() { + const codeList = document.getElementsByClassName("sourceCode"); + for (var i = 0; i < codeList.length; i++) { + var linkList = codeList[i].getElementsByTagName('a'); + for (var j = 0; j < linkList.length; j++) { + if (linkList[j].innerHTML === "") { + linkList[j].setAttribute('aria-hidden', 'true'); + } + } + } +}); diff --git a/docs/articles/intro_inputs.html b/docs/articles/intro_inputs.html index 341f433..f968adb 100644 --- a/docs/articles/intro_inputs.html +++ b/docs/articles/intro_inputs.html @@ -12,18 +12,21 @@ - - - + + + + + - - + - + + +
-

Shiny comes with a large library of input widgets for collecting input from the user and conveying input data to R.

-

If you want a kind of input not provided by Shiny — like a color picker, or a different kind of slider — you’ve always been able to build your own. Shiny’s input system is extensible. All that’s required is an understanding of certain conventions and a little custom JavaScript.

-

reactR provides additional tools to ease the creation of new Shiny inputs implemented using React. In the following tutorial, we will demonstrate these tools by implementing a new Shiny color picker input that wraps the react-color library.

-
-

-Software pre-requisites

-

In order to develop a reactR Shiny input, you’ll need to install R and optionally RStudio. If you’re on Windows, you should also install Rtools.

+

Shiny comes with a large +library of input widgets +for collecting input from the user and conveying input data to R.

+

If you want a kind of input not provided by Shiny — like a +color picker, or a different kind of slider — you’ve always been able to +build your own. Shiny’s input system is extensible. +All that’s required is an understanding of certain conventions and a +little custom JavaScript.

+

reactR provides additional tools to ease the creation of new Shiny +inputs implemented using React. In the following tutorial, we will +demonstrate these tools by implementing a new Shiny color picker input +that wraps the react-color +library.

+
+

Software pre-requisites +

+

In order to develop a reactR Shiny input, you’ll +need to install R and optionally RStudio. If you’re on Windows, you +should also install Rtools.

-

For an excellent general introduction to R package concepts, check out the R packages online book.

+

For an excellent general introduction to R package concepts, check +out the R packages online book.

-

In addition, you’ll need to install the following JavaScript tools on your machine:

+

In addition, you’ll need to install the following JavaScript tools on +your machine:

  • -Node.js: JavaScript engine and runtime for development outside of browsers. Provides the node and npm commands.
  • +Node.js: JavaScript engine and +runtime for development outside of browsers. Provides the +node and npm commands.
  • -Yarn: Command-line dependency management tool, provides the yarn command.
  • +Yarn: Command-line +dependency management tool, provides the yarn command.
-

To follow along in this vignette, you’ll also need the following R packages:

-
install.packages(c("shiny", "devtools", "usethis", "reactR"))
+

To follow along in this vignette, you’ll also need the following R +packages:

+
+install.packages(c("shiny", "devtools", "usethis", "reactR"))
-
-

-Scaffolding

-

To create a new widget you can call scaffoldReactShinyInput to generate the basic structure and build configuration. This function will:

+
+

Scaffolding +

+

To create a new widget you can call +scaffoldReactShinyInput to generate the basic structure and +build configuration. This function will:

  • Create the .R, .js, and .json files required by your input;
  • -
  • If provided, take an npm package name and version as a named list with name and version elements. For example, the npm package foo at version ^1.2.0 would be expressed as list(name = "foo", version = "^1.2.0"). The package, if provided, will be added to the new widget’s package.json as a build dependency.
  • +
  • If provided, take an npm +package name and version as a named list with name and +version elements. For example, the npm package +foo at version ^1.2.0 would be expressed as +list(name = "foo", version = "^1.2.0"). The package, if +provided, will be added to the new widget’s package.json as +a build dependency.
-

The following R code will create an R package named colorpicker, then provide the templating for creating an input powered by the react-color library on npm:

- +

The following R code will create an R package named +colorpicker, then provide the templating for creating +an input powered by the react-color library on npm:

+
+# Create the R package (rstudio=TRUE is recommended if you're not already comfortable with your terminal)
+usethis::create_package("~/colorpicker", rstudio = TRUE)
+# Scaffold initial input implementation files
+withr::with_dir(
+  "~/colorpicker",
+  reactR::scaffoldReactShinyInput("colorpicker", list("react-color" = "^2.17.0"), edit = FALSE)
+)
-
-

-Building and installing

-
-

-Building the JavaScript

-

The next step is to navigate to the newly-created colorpicker project and run the following commands in the terminal. If you’re new the terminal, we recommend opening your newly created RStudio ~/colorpicker/colorpicker.Rproj project file, then running the following in the RStudio terminal tab:

+
+

Building and installing +

+
+

Building the JavaScript +

+

The next step is to navigate to the newly-created +colorpicker project and run the following commands in the +terminal. If you’re new the terminal, we recommend opening your newly +created RStudio ~/colorpicker/colorpicker.Rproj project +file, then running the following in the RStudio terminal tab:

yarn install
 yarn run webpack
    -
  • yarn install downloads all of the dependencies listed in package.json and creates a new file, yarn.lock. You should add this file to revision control. It will be updated whenever you change dependencies and run yarn install. Note: you only need to run it after modifying package.json. For further documentation on yarn install, see the yarn documentation.

  • -
  • yarn run webpack compiles the modern JavaScript with JSX source file at srcjs/colorpicker.jsx into www/colorpicker/colorpicker/colorpicker.js. The latter file is the one actually used by the R package and includes all the relevant JavaScript dependencies in a dialect of JavaScript that most browsers understand.

  • +
  • yarn install downloads all of the dependencies +listed in package.json and creates a new file, +yarn.lock. You should add this file to revision control. It +will be updated whenever you change dependencies and run +yarn install. Note: you only need to run it after +modifying package.json. For further documentation on +yarn install, see the yarn +documentation.

  • +
  • yarn run webpack compiles the modern JavaScript +with JSX +source file at srcjs/colorpicker.jsx into +www/colorpicker/colorpicker/colorpicker.js. The latter file +is the one actually used by the R package and includes all the relevant +JavaScript dependencies in a dialect of JavaScript that most browsers +understand.

-

yarn run webpack is not strictly a yarn command. In fact, yarn run simply delegates to the webpack program. Webpack’s configuration is generated by scaffoldReactShinyInput in the file webpack.config.js, but you can always change this configuration and/or modify the yarn run webpack command to suit your needs.

+

yarn run webpack is not strictly a yarn +command. In fact, yarn run simply delegates to the webpack program. Webpack’s +configuration is generated by scaffoldReactShinyInput in +the file webpack.config.js, but you can always change this +configuration and/or modify the yarn run webpack command to +suit your needs.

-
-

-Installing the R package

-

Now that the input’s JavaScript is compiled, go ahead and install the R package:

- -

In RStudio, you can use the keyboard shortcuts Ctrl-Shift-D and Ctrl-Shift-B to document and build the package. (On macOS, the shortcuts are Cmd-Shift-D and Cmd-Shift-B)

+
+

Installing the R package +

+

Now that the input’s JavaScript is compiled, go ahead and install the +R package:

+
+devtools::document()
+devtools::install(quick = TRUE)
+

In RStudio, you can use the keyboard shortcuts +Ctrl-Shift-D and Ctrl-Shift-B to document and +build the package. (On macOS, the shortcuts are Cmd-Shift-D +and Cmd-Shift-B)

-
-

-Run the included demo

-

Now that the input’s JavaScript is compiled, and the R package is installed, run app.R to see a demo in action:

- -

In RStudio, you can open app.R and press Ctrl-Shift-Enter (Cmd-Shift-Enter on macOS). You should see something like the following appear in the Viewer pane:

+
+

Run the included demo +

+

Now that the input’s JavaScript is compiled, and the R package is +installed, run app.R to see a demo in action:

+
+shiny::runApp()
+

In RStudio, you can open app.R and press +Ctrl-Shift-Enter (Cmd-Shift-Enter on macOS). +You should see something like the following appear in the Viewer +pane:

-
-

-Authoring a React input

-

At this point, we have a working (if simple) React-powered text input. Let’s modify it to create an interface to the react-color library.

-
-

-Connecting Shiny with React

-

Consider the following example taken from the react-color documentation.

- -

That JavaScript code produces a SketchPicker-type interface that looks like this:

+
+

Authoring a React input +

+

At this point, we have a working (if simple) React-powered text +input. Let’s modify it to create an interface to the +react-color library.

+
+

Connecting Shiny with React +

+

Consider the following example taken from the react-color +documentation.

+
import React from 'react';
+import { SketchPicker } from 'react-color';
+
+class Component extends React.Component {
+
+  render() {
+    return <SketchPicker />;
+  }
+}
+

That JavaScript code produces a SketchPicker-type +interface that looks like this:

-

However, that example doesn’t demonstrate a way to default to a particular color, or a way to cause something to happen when the color changes. To accomplish these, react-color components can optionally take the following props:

+

However, that example doesn’t demonstrate a way to default to a +particular color, or a way to cause something to happen when the color +changes. To accomplish these, react-color components can optionally +take the following props:

  • -color: accepts a string of a hex color like '#333' +color: +accepts a string of a hex color like '#333'
  • -onChangeComplete: accepts a JavaScript function taking a single argument, the new color, that will be called when the new color is selected
  • +onChangeComplete: +accepts a JavaScript function taking a single argument, the new +color, that will be called when the new color is +selected
-

Since this React component calls a configurable function (i.e., onChangeComplete) when the input (i.e., color) value changes, we can supply a function to inform Shiny about these changes. You could, in theory, do this by writing your own custom Shiny input wrapper around this component, but reactR provides some conventions to make it much easier. These conventions have two main parts (R and JavaScript):

+

Since this React component calls a configurable function (i.e., +onChangeComplete) when the input (i.e., color) value +changes, we can supply a function to inform Shiny about these changes. +You could, in theory, do this by writing your own custom Shiny input +wrapper around this component, but reactR provides some +conventions to make it much easier. These conventions have two main +parts (R and JavaScript):

    -
  1. Use reactR::createReactShinyInput() to construct the user-facing R input and route any user-supplied options (e.g., the default input value and other configuration) to the React component. This part was already done for us in the R/colorpicker.R file of our colorpicker project:
  2. +
  3. Use reactR::createReactShinyInput() to construct the +user-facing R input and route any user-supplied options (e.g., the +default input value and other configuration) +to the React component. This part was already done for us in the +R/colorpicker.R file of our colorpicker project:
- +
+colorpickerInput <- function(inputId, default = "") {
+  reactR::createReactShinyInput(
+    inputId = inputId,
+    class = "colorpicker",
+    dependencies = htmltools::htmlDependency(
+      name = "colorpicker-input",
+      version = "1.0.0",
+      src = "www/colorpicker/colorpicker",
+      package = "colorpicker",
+      script = "colorpicker.js"
+    ),
+    default = default,
+    configuration = list(),
+    container = htmltools::tags$span
+  )
+}
    -
  1. Design an intermediate React component that routes information from colorpickerInput() to the <SketchPicker> component and also inform Shiny when a new color is chosen. This intermediate component should be a functional component with three arguments:
  2. +
  3. Design an intermediate React component that routes +information from colorpickerInput() to the +<SketchPicker> component and also inform Shiny when a +new color is chosen. This intermediate component should be a functional +component with three arguments:
  • -configuration: The JSON equivalent of the configuration argument from reactR::createReactShinyInput(). In this particular example, configuration isn’t used.
  • +configuration: The JSON equivalent of the +configuration argument from +reactR::createReactShinyInput(). In this particular +example, configuration isn’t used.
  • -value: The input’s values over time, beginning with the default supplied from reactR::createReactShinyInput().
  • +value: The input’s values over time, beginning with the +default supplied from +reactR::createReactShinyInput().
  • -setValue: A JavaScript function to call with the input’s new value when one is created. This function is not user supplied, but rather an internal hook for informing Shiny about changes to the component’s current state (i.e. value).
  • +setValue: A JavaScript function to call with the +input’s new value when one is created. This function is not user +supplied, but rather an internal hook for informing Shiny about changes +to the component’s current state (i.e. value).
-

Consider the following intermediate component, PickerInput. Note how this intermediate component allows one to set the default value from R and also calls setValue() inside onChangeComplete in order to inform Shiny about new color values. Finally, reactR.reactShinyInput() registers this intermediate component as a custom Shiny input binding named colorpicker.

- -

Open the srcjs/colorpicker.jsx file in your colorpicker project and paste this code into it. After saving the file, run yarn run webpack in the terminal, re-install the package, then run shiny::runApp() again

-

When you select new colors, you should see the textOutput update accordingly.

-

You might have noticed that the input showed up initially without a color selected. That’s because in app.R we didn’t supply a default argument to the colorpickerInput function inside our ui.

-

Try replacing the call to colorpickerInput with this: colorpickerInput("textInput", default = "#a76161")

-

Now when you run the app, the color should start as a shade of red.

+

Consider the following intermediate component, +PickerInput. Note how this intermediate component allows +one to set the default value from R and also calls +setValue() inside onChangeComplete in order to +inform Shiny about new color values. Finally, +reactR.reactShinyInput() registers this intermediate +component as a custom Shiny input binding named +colorpicker.

+
import { reactShinyInput } from 'reactR';
+import { SketchPicker } from 'react-color';
+
+const PickerInput = ({ configuration, value, setValue }) => {
+  return (
+    <SketchPicker
+      color={ value }
+      onChangeComplete={ color => setValue(color.hex) }
+    />
+  );
+};
+
+// Note the first argument here should match the `class` 
+// argument of the reactR::createReactShinyInput() from step 1
+reactShinyInput('.colorpicker', 'colorpicker', PickerInput);
+

Open the srcjs/colorpicker.jsx file in your colorpicker +project and paste this code into it. After saving the file, run +yarn run webpack in the terminal, re-install the package, +then run shiny::runApp() again

+

When you select new colors, you should see the +textOutput update accordingly.

+

You might have noticed that the input showed up initially without a +color selected. That’s because in app.R we didn’t supply a +default argument to the colorpickerInput +function inside our ui.

+

Try replacing the call to colorpickerInput with this: +colorpickerInput("textInput", default = "#a76161")

+

Now when you run the app, the color should start as a shade of +red.

-
-

-Further learning

-

This tutorial walked you through the steps taken to wrap the react-color library in a Shiny input. The full example package is accessible at https://github.com/react-R/colorpicker-example. Our intention is keep creating example packages under the https://github.com/react-R organization, so head there if you’d like to see other examples of interfacing with React.

+
+

Further learning +

+

This tutorial walked you through the steps taken to wrap the +react-color library in a Shiny input. The full example +package is accessible at https://github.com/react-R/colorpicker-example. Our +intention is keep creating example packages under the https://github.com/react-R organization, so head there +if you’d like to see other examples of interfacing with React.

- +
-

Site built with pkgdown 1.3.0.

+

+

Site built with pkgdown 2.0.7.

+
+ + + diff --git a/docs/articles/intro_inputs_files/accessible-code-block-0.0.1/empty-anchor.js b/docs/articles/intro_inputs_files/accessible-code-block-0.0.1/empty-anchor.js new file mode 100644 index 0000000..ca349fd --- /dev/null +++ b/docs/articles/intro_inputs_files/accessible-code-block-0.0.1/empty-anchor.js @@ -0,0 +1,15 @@ +// Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> +// v0.0.1 +// Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. + +document.addEventListener('DOMContentLoaded', function() { + const codeList = document.getElementsByClassName("sourceCode"); + for (var i = 0; i < codeList.length; i++) { + var linkList = codeList[i].getElementsByTagName('a'); + for (var j = 0; j < linkList.length; j++) { + if (linkList[j].innerHTML === "") { + linkList[j].setAttribute('aria-hidden', 'true'); + } + } + } +}); diff --git a/docs/articles/intro_reactR.html b/docs/articles/intro_reactR.html index 1547436..be5d8a2 100644 --- a/docs/articles/intro_reactR.html +++ b/docs/articles/intro_reactR.html @@ -12,18 +12,21 @@ - - - + + + + + - - + - + + +
+ +
-
-

-Why reactR?

-

react has become incredibly popular, and the ecosystem around react is robust. reactR aims to allow R users to more easily incorporate react and JSX.

+
+

Why reactR? +

+

react has become +incredibly popular, and the ecosystem around react is +robust. reactR aims to allow R users to more +easily incorporate react and JSX.

-
-

-Install

-
install.packages("reactR")
-
-# for the latest development version
-#  install from Github
-# devtools::install_github("timelyportfolio/reactR")
+
+

Install +

+
install.packages("reactR")
+
+# for the latest development version
+#  install from Github
+# devtools::install_github("timelyportfolio/reactR")
-
-

-Quick Example

-

Let’s use react to render a simple h1 HTML element below.

+
+

Quick Example +

+

Let’s use react to render a simple h1 HTML +element below.

-
library(reactR)
-library(htmltools)
-
## Warning: package 'htmltools' was built under R version 3.4.4
- + +
## Warning: package 'htmltools' was built under R version 4.3.3
+
+attachDependencies(
+  tags$script(
+  "
+    ReactDOM.render(
+      React.createElement(
+        'h1',
+        null,
+        'Powered by React'
+      ),
+      document.getElementById('react-heading-here')
+    )
+  "
+  ),
+  html_dependency_react()
+)
-
-

-Blog Post

-

For more on how we can use R and React, see the blog post React in R. Also, there are many more examples in the Github repo at inst/examples.

+
+

Blog Post +

+

For more on how we can use R and React, see the blog post React in R. Also, +there are many more examples in the Github repo at inst/examples.

-
-

-Using JSX

-

JSX helps ease some of the burden caused by React.createElement. reactR provides a babel_transform() function to use JSX. Hopefully, in the future, we can convince RStudio to modify htmltools to work directly with JSX (see issue).

+
+

Using JSX +

+

JSX +helps ease some of the burden caused by +React.createElement. reactR provides a +babel_transform() function to use JSX. +Hopefully, in the future, we can convince RStudio to modify +htmltools to work directly with JSX (see issue).

- +
-

Site built with pkgdown 1.3.0.

+

+

Site built with pkgdown 2.0.7.

+
+ + + diff --git a/docs/articles/intro_reactR_files/accessible-code-block-0.0.1/empty-anchor.js b/docs/articles/intro_reactR_files/accessible-code-block-0.0.1/empty-anchor.js new file mode 100644 index 0000000..ca349fd --- /dev/null +++ b/docs/articles/intro_reactR_files/accessible-code-block-0.0.1/empty-anchor.js @@ -0,0 +1,15 @@ +// Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> +// v0.0.1 +// Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. + +document.addEventListener('DOMContentLoaded', function() { + const codeList = document.getElementsByClassName("sourceCode"); + for (var i = 0; i < codeList.length; i++) { + var linkList = codeList[i].getElementsByTagName('a'); + for (var j = 0; j < linkList.length; j++) { + if (linkList[j].innerHTML === "") { + linkList[j].setAttribute('aria-hidden', 'true'); + } + } + } +}); diff --git a/docs/articles/intro_reactR_files/react-16.12.0/AUTHORS b/docs/articles/intro_reactR_files/react-16.12.0/AUTHORS new file mode 100644 index 0000000..44de798 --- /dev/null +++ b/docs/articles/intro_reactR_files/react-16.12.0/AUTHORS @@ -0,0 +1,696 @@ +39 <8398a7@gmail.com> +Aaron Franks +Aaron Gelter +Adam Bloomston +Adam Krebs +Adam Mark +Adam Solove +Adam Timberlake +Adam Zapletal +Ahmad Wali Sidiqi +Alan Plum +Alan Souza +Alan deLevie +Alastair Hole +Alex +Alex Boatwright +Alex Boyd +Alex Dajani +Alex Lopatin +Alex Mykyta +Alex Pien +Alex Smith +Alex Zelenskiy +Alexander Shtuchkin +Alexander Solovyov +Alexander Tseung +Alexandre Gaudencio +Alexey Raspopov +Alexey Shamrin +Ali Ukani +Andre Z Sanchez +Andreas Savvides +Andreas Svensson +Andres Kalle +Andres Suarez +Andrew Clark +Andrew Cobby +Andrew Davey +Andrew Henderson +Andrew Kulakov +Andrew Rasmussen +Andrew Sokolov +Andrew Zich +Andrey Popp <8mayday@gmail.com> +Anthony van der Hoorn +Anto Aravinth +Antonio Ruberto +Antti Ahti +Anuj Tomar +AoDev +April Arcus +Areeb Malik +Aria Buckles +Aria Stewart +Arian Faurtosh +Artem Nezvigin +Austin Wright +Ayman Osman +Baraa Hamodi +Bartosz Kaszubowski +Basarat Ali Syed +Battaile Fauber +Beau Smith +Ben Alpert +Ben Anderson +Ben Brooks +Ben Foxall +Ben Halpern +Ben Jaffe +Ben Moss +Ben Newman +Ben Ripkens +Benjamin Keen +Benjamin Leiken +Benjamin Woodruff +Benjy Cui +Bill Blanchard +Bill Fisher +Blaine Hatab +Blaine Kasten +Bob Eagan +Bob Ralian +Bob Renwick +Bobby +Bojan Mihelac +Bradley Spaulding +Brandon Bloom +Brandon Tilley +Brenard Cubacub +Brian Cooke +Brian Holt +Brian Hsu +Brian Kim +Brian Kung +Brian Reavis +Brian Rue +Bruno Škvorc +Cam Song +Cam Spiers +Cameron Chamberlain +Cameron Matheson +Carter Chung +Cassus Adam Banko +Cat Chen +Cedric Sohrauer +Cesar William Alvarenga +Changsoon Bok +Charles Marsh +Chase Adams +Cheng Lou +Chitharanjan Das +Chris Bolin +Chris Grovers +Chris Ha +Chris Rebert +Chris Sciolla +Christian Alfoni +Christian Oliff +Christian Roman +Christoffer Sawicki +Christoph Pojer +Christopher Monsanto +Clay Allsopp +Connor McSheffrey +Conor Hastings +Cory House +Cotton Hou +Craig Akimoto +Cristovao Verstraeten +Damien Pellier +Dan Abramov +Dan Fox +Dan Schafer +Daniel Carlsson +Daniel Cousens +Daniel Friesen +Daniel Gasienica +Daniel Hejl +Daniel Hejl +Daniel Lo Nigro +Daniel Mané +Daniel Miladinov +Daniel Rodgers-Pryor +Daniel Schonfeld +Danny Ben-David +Darcy +Daryl Lau +Darío Javier Cravero +Dave Galbraith +David Baker +David Ed Mellum +David Goldberg +David Granado +David Greenspan +David Hellsing +David Hu +David Khourshid +David Mininger +David Neubauer +David Percy +Dean Shi +Denis Sokolov +Deniss Jacenko +Dennis Johnson +Devon Blandin +Devon Harvey +Dmitrii Abramov +Dmitriy Rozhkov +Dmitry Blues +Dmitry Mazuro +Domenico Matteo +Don Abrams +Dongsheng Liu +Dustan Kasten +Dustin Getz +Dylan Harrington +Eduardo Garcia +Edvin Erikson +Elaine Fang +Enguerran +Eric Clemmons +Eric Eastwood +Eric Florenzano +Eric O'Connell +Eric Schoffstall +Erik Harper +Espen Hovlandsdal +Evan Coonrod +Evan Vosberg +Fabio M. Costa +Federico Rampazzo +Felipe Oliveira Carvalho +Felix Gnass +Felix Kling +Fernando Correia +Frankie Bagnardi +François-Xavier Bois +Fred Zhao +Freddy Rangel +Fyodor Ivanishchev +G Scott Olson +G. Kay Lee +Gabe Levi +Gajus Kuizinas +Gareth Nicholson +Garren Smith +Gavin McQuistin +Geert Pasteels +Geert-Jan Brits +George A Sisco III +Georgii Dolzhykov +Gilbert +Glen Mailer +Grant Timmerman +Greg Hurrell +Greg Perkins +Greg Roodt +Gregory +Guangqiang Dong +Guido Bouman +Harry Hull +Harry Marr +Harry Moreno +Harshad Sabne +Hekar Khani +Hendrik Swanepoel +Henrik Nyh +Henry Wong +Henry Zhu +Hideo Matsumoto +Hou Chia +Huang-Wei Chang +Hugo Agbonon +Hugo Jobling +Hyeock Kwon +Héliton Nordt +Ian Obermiller +Ignacio Carbajo +Igor Scekic +Ilia Pavlenkov +Ilya Shuklin +Ilyá Belsky +Ingvar Stepanyan +Irae Carvalho +Isaac Salier-Hellendag +Iurii Kucherov +Ivan Kozik +Ivan Krechetov +Ivan Vergiliev +J. Andrew Brassington +J. Renée Beach +JD Isaacks +JJ Weber +JW +Jack Zhang +Jackie Wung +Jacob Gable +Jacob Greenleaf +Jae Hun Ro +Jaeho Lee +Jaime Mingo +Jake Worth +Jakub Malinowski +James +James Brantly +James Burnett +James Friend +James Ide +James Long +James Pearce +James Seppi +James South +James Wen +Jamie Wong +Jamis Charles +Jamison Dance +Jan Hancic +Jan Kassens +Jan Raasch +Jared Forsyth +Jason +Jason Bonta +Jason Ly +Jason Miller +Jason Quense +Jason Trill +Jason Webster +Jay Jaeho Lee +Jean Lauliac +Jed Watson +Jeff Barczewski +Jeff Carpenter +Jeff Chan +Jeff Hicken +Jeff Kolesky +Jeff Morrison +Jeff Welch +Jeffrey Lin +Jeremy Fairbank +Jesse Skinner +Jignesh Kakadiya +Jim OBrien +Jim Sproch +Jimmy Jea +Jing Chen +Jinwoo Oh +Jinxiu Lee +Jiyeon Seo +Jody McIntyre +Joe Critchley +Joe Stein +Joel Auterson +Johannes Baiter +Johannes Emerich +Johannes Lumpe +John Heroy +John Ryan +John Watson +John-David Dalton +Jon Beebe +Jon Chester +Jon Hester +Jon Madison +Jon Scott Clark +Jon Tewksbury +Jonas Enlund +Jonas Gebhardt +Jonathan Hsu +Jonathan Persson +Jordan Harband +Jordan Walke +Jorrit Schippers +Joseph Nudell +Joseph Savona +Josh Bassett +Josh Duck +Josh Perez +Josh Yudaken +Joshua Evans +Joshua Go +Joshua Goldberg +Joshua Ma +João Valente +Juan Serrano +Julen Ruiz Aizpuru +Julian Viereck +Julien Bordellier +Julio Lopez +Jun Wu +Juraj Dudak +Justas Brazauskas +Justin Jaffray +Justin Robison +Justin Woo +Kale +Kamron Batman +Karl Mikkelsen +Karpich Dmitry +Keito Uchiyama +Ken Powers +Kent C. Dodds +Kevin Cheng <09chengk@gmail.com> +Kevin Coughlin +Kevin Huang +Kevin Lau +Kevin Old +Kevin Robinson +Kewei Jiang +Kier Borromeo +KimCoding +Kirk Steven Hansen +Kit Randel +Kohei TAKATA +Koo Youngmin +Krystian Karczewski +Kunal Mehta +Kurt Ruppel +Kyle Kelley +Kyle Mathews +Laurence Rowe +Laurent Etiemble +Lee Byron +Lee Jaeyoung +Lei +Leland Richardson +Leon Fedotov +Leon Yip +Leonardo YongUk Kim +Levi Buzolic +Levi McCallum +Lily +Logan Allen +Lovisa Svallingson +Ludovico Fischer +Luigy Leon +Luke Horvat +MIKAMI Yoshiyuki +Maher Beg +Manas +Marcin K. +Marcin Kwiatkowski +Marcin Szczepanski +Mariano Desanze +Marjan +Mark Anderson +Mark Funk +Mark Hintz +Mark IJbema +Mark Murphy +Mark Richardson +Mark Rushakoff +Mark Sun +Marlon Landaverde +Marshall Roch +Martin Andert +Martin Hujer +Martin Jul +Martin Konicek +Martin Mihaylov +Masaki KOBAYASHI +Mathieu M-Gosselin +Mathieu Savy +Matias Singers +Matsunoki +Matt Brookes +Matt Dunn-Rankin +Matt Harrison +Matt Huggins +Matt Stow +Matt Zabriskie +Matthew Dapena-Tretter +Matthew Herbst +Matthew Hodgson +Matthew Johnston +Matthew King +Matthew Looi +Matthew Miner +Matthias Le Brun +Matti Nelimarkka +Mattijs Kneppers +Max F. Albrecht <1@178.is> +Max Heiber +Max Stoiber +Maxi Ferreira +Maxim Abramchuk +Merrick Christensen +Mert Kahyaoğlu +Michael Chan +Michael McDermott +Michael Randers-Pehrson +Michael Ridgway +Michael Warner +Michael Wiencek +Michael Ziwisky +Michal Srb +Michelle Todd +Mihai Parparita +Mike D Pilsbury +Mike Groseclose +Mike Nordick +Mikolaj Dadela +Miles Johnson +Minwe LUO +Miorel Palii +Morhaus +Moshe Kolodny +Mouad Debbar +Murad +Murray M. Moss +Nadeesha Cabral +Naman Goel +Nate Hunzaker +Nate Lee +Nathan Smith +Nathan White +Nee <944316342@qq.com> +Neri Marschik +Nguyen Truong Duy +Nicholas Bergson-Shilcock +Nicholas Clawson +Nick Balestra +Nick Fitzgerald +Nick Gavalas +Nick Merwin +Nick Presta +Nick Raienko +Nick Thompson +Nick Williams +Niklas Boström +Ning Xia +Niole Nelson +Oiva Eskola +Oleg +Oleksii Markhovskyi +Oliver Zeigermann +Olivier Tassinari +Owen Coutts +Pablo Lacerda de Miranda +Paolo Moretti +Pascal Hartig +Patrick +Patrick Laughlin +Patrick Stapleton +Paul Benigeri +Paul Harper +Paul O’Shannessy +Paul Seiffert +Paul Shen +Pedro Nauck +Pete Hunt +Peter Blazejewicz +Peter Cottle +Peter Jaros +Peter Newnham +Petri Lehtinen +Petri Lievonen +Pieter Vanderwerff +Pouja Nikray +Prathamesh Sonpatki +Prayag Verma +Preston Parry +Rafael +Rafal Dittwald +Rainer Oviir +Rajat Sehgal +Rajiv Tirumalareddy +Ram Kaniyur +Randall Randall +Ray +Raymond Ha +Reed Loden +Remko Tronçon +Richard D. Worth +Richard Feldman +Richard Kho +Richard Littauer +Richard Livesey +Richard Wood +Rick Beerendonk +Rick Ford +Riley Tomasek +Rob Arnold +Robert Binna +Robert Knight +Robert Sedovsek +Robin Berjon +Robin Frischmann +Roman Pominov +Roman Vanesyan +Russ +Ryan Seddon +Sahat Yalkabov +Saif Hakim +Saiichi Hashimoto +Sam Beveridge +Sam Saccone +Sam Selikoff +Samy Al Zahrani +Sander Spies +Scott Burch +Scott Feeney +Sean Kinsey +Sebastian Markbåge +Sebastian McKenzie +Seoh Char +Sercan Eraslan +Serg +Sergey Generalov +Sergey Rubanov +Seyi Adebajo +Shane O'Sullivan +Shaun Trennery +ShihChi Huang +Shim Won +Shinnosuke Watanabe +Shogun Sea +Shota Kubota +Shripad K +Sibi +Simen Bekkhus +Simon Højberg +Simon Welsh +Simone Vittori +Soichiro Kawamura +Sophia Westwood +Sota Ohara +Spencer Handley +Stefan Dombrowski +Stephen Murphy +Sterling Cobb +Steve Baker <_steve_@outlook.com> +Steven Luscher +Steven Vachon +Stoyan Stefanov +Sundeep Malladi +Sunny Juneja +Sven Helmberger +Sverre Johansen +Sébastien Lorber +Sławomir Laskowski +Taeho Kim +Tay Yang Shun +Ted Kim +Tengfei Guo +Teodor Szente +Thomas Aylott +Thomas Boyt +Thomas Broadley +Thomas Reggi +Thomas Röggla +Thomas Shaddox +Thomas Shafer +ThomasCrvsr +Tienchai Wirojsaksaree +Tim Routowicz +Tim Schaub +Timothy Yung +Timur Carpeev +Tobias Reiss +Tom Duncalf +Tom Haggie +Tom Hauburger +Tom MacWright +Tom Occhino +Tomasz Kołodziejski +Tomoya Suzuki +Tony Spiro +Toru Kobayashi +Trinh Hoang Nhu +Tsung Hung +Tyler Brock +Ustin Zarubin +Vadim Chernysh +Varun Rau +Vasiliy Loginevskiy +Victor Alvarez +Victor Homyakov +Victor Koenders +Ville Immonen +Vincent Riemer +Vincent Siao +Vipul A M +Vitaly Kramskikh +Vitor Balocco +Vjeux +Volkan Unsal +Wander Wang +Wayne Larsen +WickyNilliams +Wincent Colaiuta +Wout Mertens +Xavier Morel +XuefengWu +Yakov Dalinchuk +Yasar icli +YouBao Nong +Yuichi Hagio +Yuriy Dybskiy +Yutaka Nakajima +Yuval Dekel +Zach Bruggeman +Zach Ramaekers +Zacharias +Zeke Sikelianos +Zhangjd +adraeth +arush +brafdlog +chen +clariroid +claudiopro +cutbko +davidxi +dongmeng.ldm +iamchenxin +iamdoron +iawia002 +imagentleman +koh-taka +kohashi85 +laiso +leeyoungalias +li.li +maxprafferty +rgarifullin +songawee +sugarshin +wali-s +yiminghe +youmoo +zhangjg +zwhitchcox +Árni Hermann Reynisson +元彦 +凌恒 +张敏 diff --git a/docs/articles/intro_reactR_files/react-16.12.0/LICENSE.txt b/docs/articles/intro_reactR_files/react-16.12.0/LICENSE.txt new file mode 100644 index 0000000..188fb2b --- /dev/null +++ b/docs/articles/intro_reactR_files/react-16.12.0/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-present, Facebook, Inc. + +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. diff --git a/docs/articles/intro_reactR_files/react-16.12.0/react-dom.min.js b/docs/articles/intro_reactR_files/react-16.12.0/react-dom.min.js new file mode 100644 index 0000000..c932590 --- /dev/null +++ b/docs/articles/intro_reactR_files/react-16.12.0/react-dom.min.js @@ -0,0 +1,242 @@ +/** @license React v16.12.0 + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/* + Modernizr 3.0.0pre (Custom Build) | MIT +*/ +'use strict';(function(la,m){"object"===typeof exports&&"undefined"!==typeof module?module.exports=m(require("react")):"function"===typeof define&&define.amd?define(["react"],m):la.ReactDOM=m(la.React)})(this,function(la){function m(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;cb}return!1}function E(a,b,c,d,e,f){this.acceptsBooleans=2===b||3===b||4===b;this.attributeName=d;this.attributeNamespace=e;this.mustUseProperty=c;this.propertyName=a;this.type=b;this.sanitizeURL= +f}function wa(a){switch(typeof a){case "boolean":case "number":case "object":case "string":case "undefined":return a;default:return""}}function Id(a,b,c,d){var e=C.hasOwnProperty(b)?C[b]:null;var f=null!==e?0===e.type:d?!1:!(2=b.length))throw Error(m(93));b=b[0]}c=b}null==c&&(c="")}a._wrapperState={initialValue:wa(c)}}function Rf(a,b){var c=wa(b.value),d=wa(b.defaultValue);null!=c&&(c=""+c,c!==a.value&&(a.value=c),null==b.defaultValue&&a.defaultValue!== +c&&(a.defaultValue=c));null!=d&&(a.defaultValue=""+d)}function Sf(a,b){b=a.textContent;b===a._wrapperState.initialValue&&""!==b&&null!==b&&(a.value=b)}function Tf(a){switch(a){case "svg":return"http://www.w3.org/2000/svg";case "math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function Od(a,b){return null==a||"http://www.w3.org/1999/xhtml"===a?Tf(b):"http://www.w3.org/2000/svg"===a&&"foreignObject"===b?"http://www.w3.org/1999/xhtml":a}function yc(a,b){var c= +{};c[a.toLowerCase()]=b.toLowerCase();c["Webkit"+a]="webkit"+b;c["Moz"+a]="moz"+b;return c}function zc(a){if(Pd[a])return Pd[a];if(!ib[a])return a;var b=ib[a],c;for(c in b)if(b.hasOwnProperty(c)&&c in Uf)return Pd[a]=b[c];return a}function Na(a){var b=a,c=a;if(a.alternate)for(;b.return;)b=b.return;else{a=b;do b=a,0!==(b.effectTag&1026)&&(c=b.return),a=b.return;while(a)}return 3===b.tag?c:null}function Vf(a){if(13===a.tag){var b=a.memoizedState;null===b&&(a=a.alternate,null!==a&&(b=a.memoizedState)); +if(null!==b)return b.dehydrated}return null}function Wf(a){if(Na(a)!==a)throw Error(m(188));}function Ni(a){var b=a.alternate;if(!b){b=Na(a);if(null===b)throw Error(m(188));return b!==a?null:a}for(var c=a,d=b;;){var e=c.return;if(null===e)break;var f=e.alternate;if(null===f){d=e.return;if(null!==d){c=d;continue}break}if(e.child===f.child){for(f=e.child;f;){if(f===c)return Wf(e),a;if(f===d)return Wf(e),b;f=f.sibling}throw Error(m(188));}if(c.return!==d.return)c=e,d=f;else{for(var g=!1,h=e.child;h;){if(h=== +c){g=!0;c=e;d=f;break}if(h===d){g=!0;d=e;c=f;break}h=h.sibling}if(!g){for(h=f.child;h;){if(h===c){g=!0;c=f;d=e;break}if(h===d){g=!0;d=f;c=e;break}h=h.sibling}if(!g)throw Error(m(189));}}if(c.alternate!==d)throw Error(m(190));}if(3!==c.tag)throw Error(m(188));return c.stateNode.current===c?a:b}function Xf(a){a=Ni(a);if(!a)return null;for(var b=a;;){if(5===b.tag||6===b.tag)return b;if(b.child)b.child.return=b,b=b.child;else{if(b===a)break;for(;!b.sibling;){if(!b.return||b.return===a)return null;b=b.return}b.sibling.return= +b.return;b=b.sibling}}return null}function Oi(a){var b=Qd(a);Rd.forEach(function(c){Sd(c,a,b)});Pi.forEach(function(c){Sd(c,a,b)})}function Td(a,b,c,d){return{blockedOn:a,topLevelType:b,eventSystemFlags:c|32,nativeEvent:d}}function Yf(a,b){switch(a){case "focus":case "blur":xa=null;break;case "dragenter":case "dragleave":ya=null;break;case "mouseover":case "mouseout":za=null;break;case "pointerover":case "pointerout":Fb.delete(b.pointerId);break;case "gotpointercapture":case "lostpointercapture":Gb.delete(b.pointerId)}} +function Hb(a,b,c,d,e){if(null===a||a.nativeEvent!==e)return a=Td(b,c,d,e),null!==b&&(b=Ib(b),null!==b&&Zf(b)),a;a.eventSystemFlags|=d;return a}function Qi(a,b,c,d){switch(b){case "focus":return xa=Hb(xa,a,b,c,d),!0;case "dragenter":return ya=Hb(ya,a,b,c,d),!0;case "mouseover":return za=Hb(za,a,b,c,d),!0;case "pointerover":var e=d.pointerId;Fb.set(e,Hb(Fb.get(e)||null,a,b,c,d));return!0;case "gotpointercapture":return e=d.pointerId,Gb.set(e,Hb(Gb.get(e)||null,a,b,c,d)),!0}return!1}function Ri(a){var b= +Jb(a.target);if(null!==b){var c=Na(b);if(null!==c)if(b=c.tag,13===b){if(b=Vf(c),null!==b){a.blockedOn=b;Ud(a.priority,function(){Si(c)});return}}else if(3===b&&c.stateNode.hydrate){a.blockedOn=3===c.tag?c.stateNode.containerInfo:null;return}}a.blockedOn=null}function Ac(a){if(null!==a.blockedOn)return!1;var b=Vd(a.topLevelType,a.eventSystemFlags,a.nativeEvent);if(null!==b){var c=Ib(b);null!==c&&Zf(c);a.blockedOn=b;return!1}return!0}function $f(a,b,c){Ac(a)&&c.delete(b)}function Ti(){for(Wd=!1;0this.eventPool.length&&this.eventPool.push(a)}function eg(a){a.eventPool=[];a.getPooled=Xi;a.release=Yi}function Dc(a){var b=a.keyCode;"charCode"in a?(a=a.charCode,0===a&&13===b&&(a=13)):a=b;10===a&&(a=13);return 32<=a||13===a?a:0}function Zi(a){var b=this.nativeEvent;return b.getModifierState?b.getModifierState(a):(a=$i[a])?!!b[a]:!1}function Zd(a){return Zi}function aj(a){var b= +a.targetInst,c=b;do{if(!c){a.ancestors.push(c);break}var d=c;if(3===d.tag)d=d.stateNode.containerInfo;else{for(;d.return;)d=d.return;d=3!==d.tag?null:d.stateNode.containerInfo}if(!d)break;b=c.tag;5!==b&&6!==b||a.ancestors.push(c);c=Jb(d)}while(c);for(c=0;c=b)return{node:c, +offset:b-a};a=d}a:{for(;c;){if(c.nextSibling){c=c.nextSibling;break a}c=c.parentNode}c=void 0}c=mg(c)}}function og(a,b){return a&&b?a===b?!0:a&&3===a.nodeType?!1:b&&3===b.nodeType?og(a,b.parentNode):"contains"in a?a.contains(b):a.compareDocumentPosition?!!(a.compareDocumentPosition(b)&16):!1:!1}function pg(){for(var a=window,b=ce();b instanceof a.HTMLIFrameElement;){try{var c="string"===typeof b.contentWindow.location.href}catch(d){c=!1}if(c)a=b.contentWindow;else break;b=ce(a.document)}return b} +function de(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return b&&("input"===b&&("text"===a.type||"search"===a.type||"tel"===a.type||"url"===a.type||"password"===a.type)||"textarea"===b||"true"===a.contentEditable)}function qg(a,b){switch(a){case "button":case "input":case "select":case "textarea":return!!b.autoFocus}return!1}function ee(a,b){return"textarea"===a||"option"===a||"noscript"===a||"string"===typeof b.children||"number"===typeof b.children||"object"===typeof b.dangerouslySetInnerHTML&& +null!==b.dangerouslySetInnerHTML&&null!=b.dangerouslySetInnerHTML.__html}function kb(a){for(;null!=a;a=a.nextSibling){var b=a.nodeType;if(1===b||3===b)break}return a}function rg(a){a=a.previousSibling;for(var b=0;a;){if(a.nodeType===Pa){var c=a.data;if(c===sg||c===fe||c===ge){if(0===b)return a;b--}else c===tg&&b++}a=a.previousSibling}return null}function Jb(a){var b=a[Ba];if(b)return b;for(var c=a.parentNode;c;){if(b=c[Pb]||c[Ba]){c=b.alternate;if(null!==b.child||null!==c&&null!==c.child)for(a=rg(a);null!== +a;){if(c=a[Ba])return c;a=rg(a)}return b}a=c;c=a.parentNode}return null}function Ib(a){a=a[Ba]||a[Pb];return!a||5!==a.tag&&6!==a.tag&&13!==a.tag&&3!==a.tag?null:a}function Qa(a){if(5===a.tag||6===a.tag)return a.stateNode;throw Error(m(33));}function he(a){return a[Ic]||null}function ug(){if(Jc)return Jc;var a,b=ie,c=b.length,d,e="value"in Ca?Ca.value:Ca.textContent,f=e.length;for(a=0;anb||(a.current=ne[nb],ne[nb]=null,nb--)}function y(a,b,c){nb++;ne[nb]=a.current;a.current= +b}function ob(a,b){var c=a.type.contextTypes;if(!c)return Da;var d=a.stateNode;if(d&&d.__reactInternalMemoizedUnmaskedChildContext===b)return d.__reactInternalMemoizedMaskedChildContext;var e={},f;for(f in c)e[f]=b[f];d&&(a=a.stateNode,a.__reactInternalMemoizedUnmaskedChildContext=b,a.__reactInternalMemoizedMaskedChildContext=e);return e}function K(a){a=a.childContextTypes;return null!==a&&void 0!==a}function Lc(a){B(Q,a);B(L,a)}function oe(a){B(Q,a);B(L,a)}function Hg(a,b,c){if(L.current!==Da)throw Error(m(168)); +y(L,b,a);y(Q,c,a)}function Ig(a,b,c){var d=a.stateNode;a=b.childContextTypes;if("function"!==typeof d.getChildContext)return c;d=d.getChildContext();for(var e in d)if(!(e in a))throw Error(m(108,ua(b)||"Unknown",e));return J({},c,{},d)}function Mc(a){var b=a.stateNode;b=b&&b.__reactInternalMemoizedMergedChildContext||Da;Sa=L.current;y(L,b,a);y(Q,Q.current,a);return!0}function Jg(a,b,c){var d=a.stateNode;if(!d)throw Error(m(169));c?(b=Ig(a,b,Sa),d.__reactInternalMemoizedMergedChildContext=b,B(Q,a), +B(L,a),y(L,b,a)):B(Q,a);y(Q,c,a)}function pe(){switch(uj()){case Nc:return 99;case Kg:return 98;case Lg:return 97;case Mg:return 96;case Ng:return 95;default:throw Error(m(332));}}function Og(a){switch(a){case 99:return Nc;case 98:return Kg;case 97:return Lg;case 96:return Mg;case 95:return Ng;default:throw Error(m(332));}}function pb(a,b){a=Og(a);return vj(a,b)}function Pg(a,b,c){a=Og(a);return qe(a,b,c)}function Qg(a){null===oa?(oa=[a],Oc=qe(Nc,Rg)):oa.push(a);return Sg}function ca(){if(null!== +Oc){var a=Oc;Oc=null;Tg(a)}Rg()}function Rg(){if(!re&&null!==oa){re=!0;var a=0;try{var b=oa;pb(99,function(){for(;a=b&&(da=!0),a.firstContext=null)}function ea(a, +b){if(Qc!==a&&!1!==b&&0!==b){if("number"!==typeof b||1073741823===b)Qc=a,b=1073741823;b={context:a,observedBits:b,next:null};if(null===qb){if(null===Rc)throw Error(m(308));qb=b;Rc.dependencies={expirationTime:0,firstContext:b,responders:null}}else qb=qb.next=b}return a._currentValue}function Sc(a){return{baseState:a,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function ve(a){return{baseState:a.baseState, +firstUpdate:a.firstUpdate,lastUpdate:a.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Ea(a,b){return{expirationTime:a,suspenseConfig:b,tag:Wg,payload:null,callback:null,next:null,nextEffect:null}}function Tc(a,b){null===a.lastUpdate?a.firstUpdate=a.lastUpdate=b:(a.lastUpdate.next=b,a.lastUpdate=b)}function Fa(a,b){var c=a.alternate;if(null===c){var d=a.updateQueue;var e=null;null===d&&(d=a.updateQueue= +Sc(a.memoizedState))}else d=a.updateQueue,e=c.updateQueue,null===d?null===e?(d=a.updateQueue=Sc(a.memoizedState),e=c.updateQueue=Sc(c.memoizedState)):d=a.updateQueue=ve(e):null===e&&(e=c.updateQueue=ve(d));null===e||d===e?Tc(d,b):null===d.lastUpdate||null===e.lastUpdate?(Tc(d,b),Tc(e,b)):(Tc(d,b),e.lastUpdate=b)}function Xg(a,b){var c=a.updateQueue;c=null===c?a.updateQueue=Sc(a.memoizedState):Yg(a,c);null===c.lastCapturedUpdate?c.firstCapturedUpdate=c.lastCapturedUpdate=b:(c.lastCapturedUpdate.next= +b,c.lastCapturedUpdate=b)}function Yg(a,b){var c=a.alternate;null!==c&&b===c.updateQueue&&(b=a.updateQueue=ve(b));return b}function Zg(a,b,c,d,e,f){switch(c.tag){case 1:return a=c.payload,"function"===typeof a?a.call(f,d,e):a;case 3:a.effectTag=a.effectTag&-4097|64;case Wg:a=c.payload;e="function"===typeof a?a.call(f,d,e):a;if(null===e||void 0===e)break;return J({},d,e);case Uc:Ga=!0}return d}function Ub(a,b,c,d,e){Ga=!1;b=Yg(a,b);for(var f=b.baseState,g=null,h=0,k=b.firstUpdate,l=f;null!==k;){var m= +k.expirationTime;mt?(z=p,p=null):z=p.sibling;var W=q(e,p,h[t],k);if(null===W){null===p&&(p=z);break}a&&p&&null===W.alternate&&b(e,p);g=f(W,g,t);null===m?l=W:m.sibling=W;m=W;p=z}if(t===h.length)return c(e,p),l;if(null===p){for(;tz?(W=t,t=null):W=t.sibling;var sb=q(e,t,r.value,k);if(null===sb){null===t&&(t=W); +break}a&&t&&null===sb.alternate&&b(e,t);g=f(sb,g,z);null===p?l=sb:p.sibling=sb;p=sb;t=W}if(r.done)return c(e,t),l;if(null===t){for(;!r.done;z++,r=h.next())r=n(e,r.value,k),null!==r&&(g=f(r,g,z),null===p?l=r:p.sibling=r,p=r);return l}for(t=d(e,t);!r.done;z++,r=h.next())r=v(t,e,z,r.value,k),null!==r&&(a&&null!==r.alternate&&t.delete(null===r.key?z:r.key),g=f(r,g,z),null===p?l=r:p.sibling=r,p=r);a&&t.forEach(function(a){return b(e,a)});return l}return function(a,d,f,h){var k="object"===typeof f&&null!== +f&&f.type===va&&null===f.key;k&&(f=f.props.children);var l="object"===typeof f&&null!==f;if(l)switch(f.$$typeof){case $c:a:{l=f.key;for(k=d;null!==k;){if(k.key===l)if(7===k.tag?f.type===va:k.elementType===f.type){c(a,k.sibling);d=e(k,f.type===va?f.props.children:f.props,h);d.ref=Vb(a,k,f);d.return=a;a=d;break a}else{c(a,k);break}else b(a,k);k=k.sibling}f.type===va?(d=Ha(f.props.children,a.mode,h,f.key),d.return=a,a=d):(h=Zc(f.type,f.key,f.props,null,a.mode,h),h.ref=Vb(a,d,f),h.return=a,a=h)}return g(a); +case eb:a:{for(k=f.key;null!==d;){if(d.key===k)if(4===d.tag&&d.stateNode.containerInfo===f.containerInfo&&d.stateNode.implementation===f.implementation){c(a,d.sibling);d=e(d,f.children||[],h);d.return=a;a=d;break a}else{c(a,d);break}else b(a,d);d=d.sibling}d=ye(f,a.mode,h);d.return=a;a=d}return g(a)}if("string"===typeof f||"number"===typeof f)return f=""+f,null!==d&&6===d.tag?(c(a,d.sibling),d=e(d,f,h),d.return=a,a=d):(c(a,d),d=xe(f,a.mode,h),d.return=a,a=d),g(a);if(ad(f))return x(a,d,f,h);if(Eb(f))return A(a, +d,f,h);l&&Yc(a,f);if("undefined"===typeof f&&!k)switch(a.tag){case 1:case 0:throw a=a.type,Error(m(152,a.displayName||a.name||"Component"));}return c(a,d)}}function Ua(a){if(a===Wb)throw Error(m(174));return a}function ze(a,b){y(Xb,b,a);y(Yb,a,a);y(fa,Wb,a);var c=b.nodeType;switch(c){case 9:case 11:b=(b=b.documentElement)?b.namespaceURI:Od(null,"");break;default:c=c===Pa?b.parentNode:b,b=c.namespaceURI||null,c=c.tagName,b=Od(b,c)}B(fa,a);y(fa,b,a)}function tb(a){B(fa,a);B(Yb,a);B(Xb,a)}function hh(a){Ua(Xb.current); +var b=Ua(fa.current);var c=Od(b,a.type);b!==c&&(y(Yb,a,a),y(fa,c,a))}function Ae(a){Yb.current===a&&(B(fa,a),B(Yb,a))}function bd(a){for(var b=a;null!==b;){if(13===b.tag){var c=b.memoizedState;if(null!==c&&(c=c.dehydrated,null===c||c.data===ge||c.data===fe))return b}else if(19===b.tag&&void 0!==b.memoizedProps.revealOrder){if(0!==(b.effectTag&64))return b}else if(null!==b.child){b.child.return=b;b=b.child;continue}if(b===a)break;for(;null===b.sibling;){if(null===b.return||b.return===a)return null; +b=b.return}b.sibling.return=b.return;b=b.sibling}return null}function ih(a,b){return{responder:a,props:b}}function N(){throw Error(m(321));}function Be(a,b){if(null===b)return!1;for(var c=0;cwb&&(wb=p,Vc(wb))):($g(p,k.suspenseConfig),f=k.eagerReducer===a?k.eagerState:a(f,k.action));g=k;k=k.next}while(null!==k&&k!==d);l||(h=g,e=f);Ra(f,b.memoizedState)||(da=!0);b.memoizedState=f;b.baseUpdate=h;b.baseState=e;c.lastRenderedState=f}return[b.memoizedState, +c.dispatch]}function De(a){var b=xb();"function"===typeof a&&(a=a());b.memoizedState=b.baseState=a;a=b.queue={last:null,dispatch:null,lastRenderedReducer:lh,lastRenderedState:a};a=a.dispatch=nh.bind(null,Ia,a);return[b.memoizedState,a]}function Ee(a){return mh(lh,a)}function Fe(a,b,c,d){a={tag:a,create:b,destroy:c,deps:d,next:null};null===ia?(ia={lastEffect:null},ia.lastEffect=a.next=a):(b=ia.lastEffect,null===b?ia.lastEffect=a.next=a:(c=b.next,b.next=a,a.next=c,ia.lastEffect=a));return a}function Ge(a, +b,c,d){var e=xb();bc|=a;e.memoizedState=Fe(b,c,void 0,void 0===d?null:d)}function He(a,b,c,d){var e=cc();d=void 0===d?null:d;var f=void 0;if(null!==H){var g=H.memoizedState;f=g.destroy;if(null!==d&&Be(d,g.deps)){Fe(0,c,f,d);return}}bc|=a;e.memoizedState=Fe(b,c,f,d)}function oh(a,b){return Ge(516,192,a,b)}function ph(a,b){return He(516,192,a,b)}function qh(a,b){if("function"===typeof b)return a=a(),b(a),function(){b(null)};if(null!==b&&void 0!==b)return a=a(),b.current=a,function(){b.current=null}} +function rh(a,b){}function sh(a,b){xb().memoizedState=[a,void 0===b?null:b];return a}function th(a,b){var c=cc();b=void 0===b?null:b;var d=c.memoizedState;if(null!==d&&null!==b&&Be(b,d[1]))return d[0];c.memoizedState=[a,b];return a}function nh(a,b,c){if(!(25>ac))throw Error(m(301));var d=a.alternate;if(a===Ia||null!==d&&d===Ia)if($b=!0,a={expirationTime:Zb,suspenseConfig:null,action:c,eagerReducer:null,eagerState:null,next:null},null===pa&&(pa=new Map),c=pa.get(b),void 0===c)pa.set(b,a);else{for(b= +c;null!==b.next;)b=b.next;b.next=a}else{var e=X(),f=dc.suspense;e=Va(e,a,f);f={expirationTime:e,suspenseConfig:f,action:c,eagerReducer:null,eagerState:null,next:null};var g=b.last;if(null===g)f.next=f;else{var h=g.next;null!==h&&(f.next=h);g.next=f}b.last=f;if(0===a.expirationTime&&(null===d||0===d.expirationTime)&&(d=b.lastRenderedReducer,null!==d))try{var k=b.lastRenderedState,l=d(k,c);f.eagerReducer=d;f.eagerState=l;if(Ra(l,k))return}catch(p){}finally{}Ja(a,e)}}function uh(a,b){var c=ja(5,null, +null,0);c.elementType="DELETED";c.type="DELETED";c.stateNode=b;c.return=a;c.effectTag=8;null!==a.lastEffect?(a.lastEffect.nextEffect=c,a.lastEffect=c):a.firstEffect=a.lastEffect=c}function vh(a,b){switch(a.tag){case 5:var c=a.type;b=1!==b.nodeType||c.toLowerCase()!==b.nodeName.toLowerCase()?null:b;return null!==b?(a.stateNode=b,!0):!1;case 6:return b=""===a.pendingProps||3!==b.nodeType?null:b,null!==b?(a.stateNode=b,!0):!1;case 13:return!1;default:return!1}}function Ie(a){if(Wa){var b=Ka;if(b){var c= +b;if(!vh(a,b)){b=kb(c.nextSibling);if(!b||!vh(a,b)){a.effectTag=a.effectTag&-1025|2;Wa=!1;qa=a;return}uh(qa,c)}qa=a;Ka=kb(b.firstChild)}else a.effectTag=a.effectTag&-1025|2,Wa=!1,qa=a}}function wh(a){for(a=a.return;null!==a&&5!==a.tag&&3!==a.tag&&13!==a.tag;)a=a.return;qa=a}function ed(a){if(a!==qa)return!1;if(!Wa)return wh(a),Wa=!0,!1;var b=a.type;if(5!==a.tag||"head"!==b&&"body"!==b&&!ee(b,a.memoizedProps))for(b=Ka;b;)uh(a,b),b=kb(b.nextSibling);wh(a);if(13===a.tag){a=a.memoizedState;a=null!==a? +a.dehydrated:null;if(!a)throw Error(m(317));a:{a=a.nextSibling;for(b=0;a;){if(a.nodeType===Pa){var c=a.data;if(c===tg){if(0===b){Ka=kb(a.nextSibling);break a}b--}else c!==sg&&c!==fe&&c!==ge||b++}a=a.nextSibling}Ka=null}}else Ka=qa?kb(a.stateNode.nextSibling):null;return!0}function Je(){Ka=qa=null;Wa=!1}function P(a,b,c,d){b.child=null===a?Ke(b,null,c,d):yb(b,a.child,c,d)}function xh(a,b,c,d,e){c=c.render;var f=b.ref;rb(b,e);d=Ce(a,b,c,d,f,e);if(null!==a&&!da)return b.updateQueue=a.updateQueue,b.effectTag&= +-517,a.expirationTime<=e&&(a.expirationTime=0),ra(a,b,e);b.effectTag|=1;P(a,b,d,e);return b.child}function yh(a,b,c,d,e,f){if(null===a){var g=c.type;if("function"===typeof g&&!Le(g)&&void 0===g.defaultProps&&null===c.compare&&void 0===c.defaultProps)return b.tag=15,b.type=g,zh(a,b,g,d,e,f);a=Zc(c.type,null,d,null,b.mode,f);a.ref=b.ref;a.return=b;return b.child=a}g=a.child;if(ea?b:a}function T(a){if(0!==a.lastExpiredTime)a.callbackExpirationTime=1073741823,a.callbackPriority=99,a.callbackNode=Qg(We.bind(null,a));else{var b=kd(a),c=a.callbackNode;if(0===b)null!==c&&(a.callbackNode=null,a.callbackExpirationTime=0,a.callbackPriority=90);else{var d=X();1073741823===b?d=99:1===b||2===b?d=95:(d=10*(1073741821-b)-10*(1073741821-d),d=0>=d?99:250>=d?98:5250>=d?97:95);if(null!==c){var e=a.callbackPriority;if(a.callbackExpirationTime=== +b&&e>=d)return;c!==Sg&&Tg(c)}a.callbackExpirationTime=b;a.callbackPriority=d;b=1073741823===b?Qg(We.bind(null,a)):Pg(d,Sh.bind(null,a),{timeout:10*(1073741821-b)-Y()});a.callbackNode=b}}}function Sh(a,b){hd=0;if(b)return b=X(),Xe(a,b),T(a),null;var c=kd(a);if(0!==c){b=a.callbackNode;if((q&(Z|ka))!==F)throw Error(m(327));Ab();a===S&&c===R||Za(a,c);if(null!==v){var d=q;q|=Z;var e=Th(a);do try{Dj();break}catch(h){Uh(a,h)}while(1);se();q=d;ld.current=e;if(G===md)throw b=nd,Za(a,c),Ya(a,c),T(a),b;if(null=== +v)switch(e=a.finishedWork=a.current.alternate,a.finishedExpirationTime=c,d=G,S=null,d){case $a:case md:throw Error(m(345));case Vh:Xe(a,2=c){a.lastPingedTime=c;Za(a,c);break}}f=kd(a);if(0!==f&&f!==c)break;if(0!==d&&d!==c){a.lastPingedTime=d;break}a.timeoutHandle=Ze(Ma.bind(null,a),e);break}Ma(a);break;case jd:Ya(a,c);d=a.lastSuspendedTime; +c===d&&(a.nextKnownPendingLevel=Ye(e));if(pd&&(e=a.lastPingedTime,0===e||e>=c)){a.lastPingedTime=c;Za(a,c);break}e=kd(a);if(0!==e&&e!==c)break;if(0!==d&&d!==c){a.lastPingedTime=d;break}1073741823!==gc?d=10*(1073741821-gc)-Y():1073741823===sa?d=0:(d=10*(1073741821-sa)-5E3,e=Y(),c=10*(1073741821-c)-e,d=e-d,0>d&&(d=0),d=(120>d?120:480>d?480:1080>d?1080:1920>d?1920:3E3>d?3E3:4320>d?4320:1960*Ej(d/1960))-d,c=d?d=0:(e=g.busyDelayMs|0,f=Y()-(10*(1073741821-f)-(g.timeoutMs|0||5E3)),d=f<=e?0:e+d-f);if(10 component higher in the tree to provide a loading indicator or placeholder to display."+ +Ed(e))}G!==$e&&(G=Vh);f=Qe(f,e);k=d;do{switch(k.tag){case 3:g=f;k.effectTag|=4096;k.expirationTime=b;var z=Oh(k,g,b);Xg(k,z);break a;case 1:g=f;var F=k.type,r=k.stateNode;if(0===(k.effectTag&64)&&("function"===typeof F.getDerivedStateFromError||null!==r&&"function"===typeof r.componentDidCatch&&(null===La||!La.has(r)))){k.effectTag|=4096;k.expirationTime=b;var u=Ph(k,g,b);Xg(k,u);break a}}k=k.return}while(null!==k)}v=Zh(v)}catch(w){b=w;continue}break}while(1)}function Th(a){a=ld.current;ld.current= +dd;return null===a?dd:a}function $g(a,b){ahc&&(hc=a)}function Fj(){for(;null!==v;)v=$h(v)}function Dj(){for(;null!==v&&!Kj();)v=$h(v)}function $h(a){var b=Lj(a.alternate,a,R);a.memoizedProps=a.pendingProps;null===b&&(b=Zh(a));ai.current=null;return b}function Zh(a){v=a;do{var b=v.alternate;a=v.return;if(0===(v.effectTag&2048)){a:{var c=b;b=v;var d=R;var e=b.pendingProps;switch(b.tag){case 2:break;case 16:break;case 15:case 0:break; +case 1:K(b.type)&&Lc(b);break;case 3:tb(b);oe(b);e=b.stateNode;e.pendingContext&&(e.context=e.pendingContext,e.pendingContext=null);(null===c||null===c.child)&&ed(b)&&zb(b);bi(b);break;case 5:Ae(b);var f=Ua(Xb.current);d=b.type;if(null!==c&&null!=b.stateNode)Mj(c,b,d,e,f),c.ref!==b.ref&&(b.effectTag|=128);else if(e){var g=Ua(fa.current);if(ed(b)){e=b;c=e.stateNode;var h=e.type;g=e.memoizedProps;c[Ba]=e;c[Ic]=g;d=void 0;switch(h){case "iframe":case "object":case "embed":x("load",c);break;case "video":case "audio":for(var k= +0;k\x3c/script>",c=c.removeChild(c.firstChild)):"string"===typeof e.is?c=c.createElement(d,{is:e.is}):(c=c.createElement(d),"select"===d&&(g=c,e.multiple?g.multiple=!0:e.size&&(g.size=e.size))):c=c.createElementNS(g,d);c[Ba]=h;c[Ic]=e;Nj(c,b,!1,!1);b.stateNode=c;var p=be(d,e);switch(d){case "iframe":case "object":case "embed":x("load",c);h=e;break;case "video":case "audio":for(h=0;he.tailExpiration&&1f&&(f=c),h>f&&(f=h),d=d.sibling;e.childExpirationTime=f}if(null!==b)return b;null!==a&&0===(a.effectTag&2048)&&(null===a.firstEffect&&(a.firstEffect=v.firstEffect),null!==v.lastEffect&&(null!==a.lastEffect&&(a.lastEffect.nextEffect=v.firstEffect),a.lastEffect=v.lastEffect),1a?b:a}function Ma(a){var b=pe();pb(99,Pj.bind(null,a,b));return null}function Pj(a,b){do Ab();while(null!==ic);if((q&(Z|ka))!==F)throw Error(m(327));var c=a.finishedWork,d=a.finishedExpirationTime;if(null=== +c)return null;a.finishedWork=null;a.finishedExpirationTime=0;if(c===a.current)throw Error(m(177));a.callbackNode=null;a.callbackExpirationTime=0;a.callbackPriority=90;a.nextKnownPendingLevel=0;var e=Ye(c);a.firstPendingTime=e;d<=a.lastSuspendedTime?a.firstSuspendedTime=a.lastSuspendedTime=a.nextKnownPendingLevel=0:d<=a.firstSuspendedTime&&(a.firstSuspendedTime=d-1);d<=a.lastPingedTime&&(a.lastPingedTime=0);d<=a.lastExpiredTime&&(a.lastExpiredTime=0);a===S&&(v=S=null,R=0);1h&&(l=h,h=g,g=l),l=ng(r,g),p= +ng(r,h),l&&p&&(1!==w.rangeCount||w.anchorNode!==l.node||w.anchorOffset!==l.offset||w.focusNode!==p.node||w.focusOffset!==p.offset)&&(u=u.createRange(),u.setStart(l.node,l.offset),w.removeAllRanges(),g>h?(w.addRange(u),w.extend(p.node,p.offset)):(u.setEnd(p.node,p.offset),w.addRange(u))))));u=[];for(w=r;w=w.parentNode;)1===w.nodeType&&u.push({element:w,left:w.scrollLeft,top:w.scrollTop});"function"===typeof r.focus&&r.focus();for(r=0;r=b&&a<=b}function Ya(a,b){var c=a.firstSuspendedTime,d=a.lastSuspendedTime;cb||0===c)a.lastSuspendedTime=b;b<=a.lastPingedTime&&(a.lastPingedTime=0);b<=a.lastExpiredTime&&(a.lastExpiredTime=0)}function Qh(a,b){b>a.firstPendingTime&&(a.firstPendingTime=b);var c=a.firstSuspendedTime;0!==c&&(b>=c?a.firstSuspendedTime=a.lastSuspendedTime=a.nextKnownPendingLevel=0:b>=a.lastSuspendedTime&&(a.lastSuspendedTime=b+1),b>a.nextKnownPendingLevel&&(a.nextKnownPendingLevel= +b))}function Xe(a,b){var c=a.lastExpiredTime;if(0===c||c>b)a.lastExpiredTime=b}function sd(a,b,c,d){var e=b.current,f=X(),g=dc.suspense;f=Va(f,e,g);a:if(c){c=c._reactInternalFiber;b:{if(Na(c)!==c||1!==c.tag)throw Error(m(170));var h=c;do{switch(h.tag){case 3:h=h.stateNode.context;break b;case 1:if(K(h.type)){h=h.stateNode.__reactInternalMemoizedMergedChildContext;break b}}h=h.return}while(null!==h);throw Error(m(171));}if(1===c.tag){var k=c.type;if(K(k)){c=Ig(c,k,h);break a}}c=h}else c=Da;null=== +b.context?b.context=c:b.pendingContext=c;b=Ea(f,g);b.payload={element:a};d=void 0===d?null:d;null!==d&&(b.callback=d);Fa(e,b);Ja(e,f);return f}function ff(a){a=a.current;if(!a.child)return null;switch(a.child.tag){case 5:return a.child.stateNode;default:return a.child.stateNode}}function di(a,b){a=a.memoizedState;null!==a&&null!==a.dehydrated&&a.retryTime
-
-
-
+
-
-
- + +
+ + + - - + diff --git a/docs/bootstrap-toc.css b/docs/bootstrap-toc.css new file mode 100644 index 0000000..5a85941 --- /dev/null +++ b/docs/bootstrap-toc.css @@ -0,0 +1,60 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ + +/* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ + +/* All levels of nav */ +nav[data-toggle='toc'] .nav > li > a { + display: block; + padding: 4px 20px; + font-size: 13px; + font-weight: 500; + color: #767676; +} +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 19px; + color: #563d7c; + text-decoration: none; + background-color: transparent; + border-left: 1px solid #563d7c; +} +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 18px; + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-left: 2px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} +nav[data-toggle='toc'] .nav .nav > li > a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + font-size: 12px; + font-weight: normal; +} +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 29px; +} +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 28px; + font-weight: 500; +} + +/* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ +nav[data-toggle='toc'] .nav > .active > ul { + display: block; +} diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js new file mode 100644 index 0000000..1cdd573 --- /dev/null +++ b/docs/bootstrap-toc.js @@ -0,0 +1,159 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ +(function() { + 'use strict'; + + window.Toc = { + helpers: { + // return all matching elements in the set, or their descendants + findOrFilter: function($el, selector) { + // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ + // http://stackoverflow.com/a/12731439/358804 + var $descendants = $el.find(selector); + return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); + }, + + generateUniqueIdBase: function(el) { + var text = $(el).text(); + var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); + return anchor || el.tagName.toLowerCase(); + }, + + generateUniqueId: function(el) { + var anchorBase = this.generateUniqueIdBase(el); + for (var i = 0; ; i++) { + var anchor = anchorBase; + if (i > 0) { + // add suffix + anchor += '-' + i; + } + // check if ID already exists + if (!document.getElementById(anchor)) { + return anchor; + } + } + }, + + generateAnchor: function(el) { + if (el.id) { + return el.id; + } else { + var anchor = this.generateUniqueId(el); + el.id = anchor; + return anchor; + } + }, + + createNavList: function() { + return $(''); + }, + + createChildNavList: function($parent) { + var $childList = this.createNavList(); + $parent.append($childList); + return $childList; + }, + + generateNavEl: function(anchor, text) { + var $a = $(''); + $a.attr('href', '#' + anchor); + $a.text(text); + var $li = $('
  • '); + $li.append($a); + return $li; + }, + + generateNavItem: function(headingEl) { + var anchor = this.generateAnchor(headingEl); + var $heading = $(headingEl); + var text = $heading.data('toc-text') || $heading.text(); + return this.generateNavEl(anchor, text); + }, + + // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). + getTopLevel: function($scope) { + for (var i = 1; i <= 6; i++) { + var $headings = this.findOrFilter($scope, 'h' + i); + if ($headings.length > 1) { + return i; + } + } + + return 1; + }, + + // returns the elements for the top level, and the next below it + getHeadings: function($scope, topLevel) { + var topSelector = 'h' + topLevel; + + var secondaryLevel = topLevel + 1; + var secondarySelector = 'h' + secondaryLevel; + + return this.findOrFilter($scope, topSelector + ',' + secondarySelector); + }, + + getNavLevel: function(el) { + return parseInt(el.tagName.charAt(1), 10); + }, + + populateNav: function($topContext, topLevel, $headings) { + var $context = $topContext; + var $prevNav; + + var helpers = this; + $headings.each(function(i, el) { + var $newNav = helpers.generateNavItem(el); + var navLevel = helpers.getNavLevel(el); + + // determine the proper $context + if (navLevel === topLevel) { + // use top level + $context = $topContext; + } else if ($prevNav && $context === $topContext) { + // create a new level of the tree and switch to it + $context = helpers.createChildNavList($prevNav); + } // else use the current $context + + $context.append($newNav); + + $prevNav = $newNav; + }); + }, + + parseOps: function(arg) { + var opts; + if (arg.jquery) { + opts = { + $nav: arg + }; + } else { + opts = arg; + } + opts.$scope = opts.$scope || $(document.body); + return opts; + } + }, + + // accepts a jQuery object, or an options object + init: function(opts) { + opts = this.helpers.parseOps(opts); + + // ensure that the data attribute is in place for styling + opts.$nav.attr('data-toggle', 'toc'); + + var $topContext = this.helpers.createChildNavList(opts.$nav); + var topLevel = this.helpers.getTopLevel(opts.$scope); + var $headings = this.helpers.getHeadings(opts.$scope, topLevel); + this.helpers.populateNav($topContext, topLevel, $headings); + } + }; + + $(function() { + $('nav[data-toggle="toc"]').each(function(i, el) { + var $nav = $(el); + Toc.init($nav); + }); + }); +})(); diff --git a/docs/index.html b/docs/index.html index f17768f..b30fb6c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -12,21 +12,24 @@ - - - + + + + + - - - -
    + + + +
    -
    - - - -
    -