├── .Rbuildignore
├── .gitignore
├── DESCRIPTION
├── NAMESPACE
├── R
├── utils-pipe.R
├── utils.R
└── vue.R
├── README.md
├── _pkgdown.yml
├── docs
├── authors.html
├── docsearch.css
├── docsearch.js
├── index.html
├── link.svg
├── pkgdown.css
├── pkgdown.js
├── pkgdown.yml
└── reference
│ ├── appendDependencies.html
│ ├── index.html
│ ├── pipe.html
│ ├── vue.html
│ ├── vueProxy.html
│ ├── vueUpdateShinyInputs.html
│ └── vueUsePlugin.html
├── inst
├── examples
│ ├── apexcharts.R
│ ├── basic-vtags.R
│ ├── basic.R
│ ├── colorpicker.R
│ ├── elementui.R
│ ├── mint.R
│ ├── sunburst.R
│ └── treeview.R
└── htmlwidgets
│ ├── lib
│ └── vue
│ │ └── vue.js
│ ├── vue.js
│ └── vue.yaml
├── man
├── appendDependencies.Rd
├── pipe.Rd
├── vtag.Rd
├── vue.Rd
├── vueProxy.Rd
├── vueUpdateShinyInputs.Rd
└── vueUsePlugin.Rd
└── vuer.Rproj
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^docs$
2 | ^_pkgdown\.yml$
3 | ^.*\.Rproj$
4 | ^\.Rproj\.user$
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: vuer
2 | Title: Harness the Power of Vue in R
3 | Version: 0.1
4 | Authors@R:
5 | person(given = "Ramnath",
6 | family = "Vaidyanathan",
7 | role = c("aut", "cre"),
8 | email = "ramnath@datacamp.com")
9 | Description: vuer is an R package that makes it easy to use Vue components and build Vue apps.
10 | License: MIT + file LICENSE
11 | Encoding: UTF-8
12 | LazyData: true
13 | URL: https://github.com/ramnathv/vuer
14 | BugReports: https://github.com/ramnathv/vuer/issues
15 | RoxygenNote: 6.1.1
16 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | export("%>%")
4 | export(Vue)
5 | export(appendDependencies)
6 | export(renderVue)
7 | export(vtag)
8 | export(vtags)
9 | export(vue)
10 | export(vueComponents)
11 | export(vueOutput)
12 | export(vueProxy)
13 | export(vueUpdateData)
14 | export(vueUpdateShinyInputs)
15 | export(vueUsePlugin)
16 | import(htmltools)
17 | import(htmlwidgets)
18 | importFrom(htmltools,tags)
19 | importFrom(magrittr,"%>%")
20 | importFrom(purrr,map)
21 |
--------------------------------------------------------------------------------
/R/utils-pipe.R:
--------------------------------------------------------------------------------
1 | #' Pipe operator
2 | #'
3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details.
4 | #'
5 | #' @name %>%
6 | #' @rdname pipe
7 | #' @keywords internal
8 | #' @export
9 | #' @importFrom magrittr %>%
10 | #' @usage lhs \%>\% rhs
11 | NULL
12 |
--------------------------------------------------------------------------------
/R/utils.R:
--------------------------------------------------------------------------------
1 | asPropsList <- function (x, name = "name", value = "value"){
2 | x <- as.list(x)
3 | nms <- names(x)
4 | lapply(seq_along(x), function(i) {
5 | l <- list()
6 | l[name] <- nms[i]
7 | l[value] <- x[i]
8 | l
9 | })
10 | }
11 |
12 |
13 | #' Use a vue Plugin
14 | #'
15 | #'
16 | #' @export
17 | vueUsePlugin <- function(fun){
18 | tags$script(sprintf("Vue.use(%s)", fun))
19 | }
20 |
21 | #' Append html dependencies
22 | #'
23 | #' NOTE: This function has been copied over from shinydashboard
24 | #' @export
25 | appendDependencies <- function (x, value){
26 | if (inherits(value, "html_dependency"))
27 | value <- list(value)
28 | old <- attr(x, "html_dependencies", TRUE)
29 | htmlDependencies(x) <- c(old, value)
30 | x
31 | }
32 |
33 | #' @importFrom purrr map
34 | #' @importFrom htmltools tags
35 | #' @export vtags
36 | vtags <- names(htmltools::tags) %>%
37 | purrr::map(~ function(...){
38 | vtag(.x, list(...))
39 | }) %>%
40 | rlang::set_names(names(tags))
41 |
42 | #' Vue Tag
43 | #'
44 | #'
45 | #' @export
46 | #' @examples
47 | #' vtag("input", list(type = "text", vmodel = "message"))
48 | vtag <- function(`_tag_name`, varArgs){
49 | if (!is.null(names(varArgs))){
50 | names(varArgs) <- gsub("^v(.*)", "v-\\1", names(varArgs))
51 | names(varArgs) <- gsub(
52 | "^v-([^\\.]*)(\\.)(.*)$", "v-\\1:\\3", names(varArgs)
53 | )
54 | }
55 | htmltools::tag(`_tag_name`, varArgs)
56 | }
57 |
--------------------------------------------------------------------------------
/R/vue.R:
--------------------------------------------------------------------------------
1 | #' Create a Vue App
2 | #'
3 | #'
4 | #' @import htmlwidgets
5 | #'
6 | #' @export
7 | #' @import htmltools
8 | #' @import htmlwidgets
9 | vue <- function(html, data = list(), dependencies = list(), watch = list(),
10 | id = NULL, ..., width = "100%", height = "auto", elementId = NULL) {
11 |
12 | if (!is.null(html)){
13 | if (is.null(html$attribs$id)){
14 | html$attribs$id <- paste0('vue-', htmlwidgets:::createWidgetId())
15 | }
16 | id <- html$attribs$id
17 | html_rendered <- htmltools::renderTags(html)
18 | } else {
19 | html_rendered <- list(html = "")
20 | }
21 |
22 | trim_underscore <- function(x){
23 | as.list(gsub("(^.*)\\_$", "\\1", x))
24 | }
25 |
26 | if (length(data) > 0 && is.list(data)){
27 | to_watch <- names(data)[endsWith(names(data), "_")]
28 | watch <- if (length(to_watch) > 0){
29 | append(watch, do.call(vueUpdateShinyInputs, trim_underscore(to_watch)))
30 | } else {
31 | list()
32 | }
33 | names(data) <- trim_underscore(names(data))
34 | }
35 |
36 | # forward options using x
37 | x = list(
38 | html = html_rendered$html,
39 | app = list(
40 | el = paste0("#", id),
41 | data = data,
42 | watch = watch,
43 | components = vueComponents$get(),
44 | ...
45 | )
46 | )
47 |
48 | # create widget
49 | htmlwidgets::createWidget(
50 | name = 'vue',
51 | x,
52 | width = width,
53 | height = height,
54 | package = 'vuer',
55 | elementId = elementId,
56 | dependencies = append(
57 | html_rendered$dependencies, dependencies
58 | )
59 | )
60 | }
61 |
62 | #' Create a Vue App
63 | #'
64 | #'
65 | #' @export
66 | #' @import htmltools
67 | #' @examples
68 | #' library(htmltools)
69 | #' tags$div(
70 | #' tags$label('Enter your name'),
71 | #' tags$input(type = "text", "v-model" = "name"),
72 | #' tags$p("Hello {{name}}")
73 | #' ) %>%
74 | #' Vue(data = list(name = ""))
75 | #'
76 | #' if (interactive()){
77 | #' library(shiny)
78 | #' ui <- tags$div(
79 | #' tags$label('Enter your name'),
80 | #' tags$input(type = "text", "v-model" = "name"),
81 | #' textOutput("greeting")
82 | #' ) %>%
83 | #' Vue(data = list(name_ = ""))
84 | #' server <- function(input, output, session){
85 | #' output$greeting <- renderText({
86 | #' paste("Hello", input$name)
87 | #' })
88 | #' }
89 | #' shinyApp(ui = ui, server = server)
90 | #' }
91 | Vue <- function(html, data = list(), dependencies = list(), ...,
92 | elementId = NULL){
93 | if (is.null(html$attribs$id)){
94 | html$attribs$id <- paste0('vue-', htmlwidgets:::createWidgetId())
95 | }
96 | tagList(
97 | html,
98 | vue(html = NULL, data = data, dependencies = dependencies,
99 | elementId = elementId,
100 | id = html$attribs$id, ...
101 | )
102 | ) %>%
103 | browsable()
104 | }
105 |
106 | #' Shiny bindings for hello
107 | #'
108 | #' Output and render functions for using hello within Shiny
109 | #' applications and interactive Rmd documents.
110 | #'
111 | #' @param outputId output variable to read from
112 | #' @param width,height Must be a valid CSS unit (like \code{'100\%'},
113 | #' \code{'400px'}, \code{'auto'}) or a number, which will be coerced to a
114 | #' string and have \code{'px'} appended.
115 | #' @param expr An expression that generates a hello
116 | #' @param env The environment in which to evaluate \code{expr}.
117 | #' @param quoted Is \code{expr} a quoted expression (with \code{quote()})? This
118 | #' is useful if you want to save an expression in a variable.
119 | #'
120 | #' @name vue
121 | #'
122 | #' @export
123 | vueOutput <- function(outputId, width = '100%', height = '400px'){
124 | htmlwidgets::shinyWidgetOutput(outputId, 'vue', width, height, package = 'vuepkg')
125 | }
126 |
127 | #' @rdname vue
128 | #' @export
129 | renderVue <- function(expr, env = parent.frame(), quoted = FALSE) {
130 | if (!quoted) { expr <- substitute(expr) } # force quoted
131 | htmlwidgets::shinyRenderWidget(expr, helloOutput, env, quoted = TRUE)
132 | }
133 |
134 |
135 | #' Send commands to a Vue instance in a Shiny app
136 | #'
137 | #'
138 | #' @examples
139 | #' ui <- div(
140 | #' tags$label("Enter username"),
141 | #' tags$input(type = 'text', "v-model" = "username"),
142 | #' tags$p("Vue -> Vue: Hello {{username}}"),
143 | #' actionButton("set_name", "Shiny -> Vue"),
144 | #' verbatimTextOutput("username")
145 | #' ) %>%
146 | #' vue(
147 | #' data = list(username = ""),
148 | #' # Vue UI -> Shiny UI
149 | #' watch = vue_watch("username"),
150 | #' elementId = "app"
151 | #' )
152 | #' server <- function(input, output, session){
153 | #' # Shiny server -> Vue UI
154 | #' observeEvent(input$set_name, {
155 | #' vueProxy("app") %>%
156 | #' updateProp("username", "Ramnath")
157 | #' })
158 | #' output$username <- renderPrint({
159 | #' paste("Vue -> Shiny:", input$username)
160 | #' })
161 | #' }
162 | #' shiny::shinyApp(ui = ui, server = server)
163 | #' @export
164 | vueProxy <- function(outputId, session = shiny::getDefaultReactiveDomain(),
165 | deferUntilFlush = TRUE){
166 | if (is.null(session)){
167 | stop("vueProxy() must be called from the server function of a Shiny app")
168 | }
169 | structure(list(
170 | id = session$ns(outputId),
171 | rawId = outputId,
172 | session = session,
173 | deferUntilFlush = deferUntilFlush
174 | ), class = 'vue_proxy'
175 | )
176 | }
177 |
178 | #' Update data in a Vue instance
179 | #' @export
180 | #' @rdname vueProxy
181 | vueUpdateData <- function(proxy, ...){
182 | message <- list(id = proxy$id, data = asPropsList(list(...)))
183 | proxy$session$sendCustomMessage(type = "updateProp", message = message)
184 | return(proxy)
185 | }
186 |
187 | #' Update Shiny Input
188 | #'
189 | #' @export
190 | vueUpdateShinyInputs <- function(...){
191 | dots <- list(...)
192 | dots %>%
193 | purrr::map(~ {
194 | htmlwidgets::JS(sprintf("function(val){
195 | console.log(val)
196 | Shiny.setInputValue('%s', val)
197 | }", .x))
198 | }) %>%
199 | rlang::set_names(dots)
200 | }
201 |
202 |
203 |
204 | .generator <- function(){
205 | .vueComponents <- list()
206 | list(
207 | get = function(){
208 | return(.vueComponents)
209 | },
210 | register = function(..., .list = NULL){
211 | if (is.null(.list)) .list = list(...)
212 | .list <- .list %>%
213 | purrr::map(htmlwidgets::JS)
214 | .vueComponents <<- modifyList(.vueComponents, .list)
215 | },
216 | reset = function(){
217 | .vueComponents <<- list()
218 | }
219 | )
220 | }
221 |
222 | #' @export
223 | vueComponents <- .generator()
224 |
225 |
226 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vuer
2 |
3 | [](https://www.tidyverse.org/lifecycle/#experimental)
4 |
5 | `vuer` is an R package that makes it easy to use Vue components and build Vue apps.
6 |
7 | > Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. It is designed from the ground up to be incrementally adoptable, and can easily scale between a library and a framework depending on different use cases.
8 |
9 |
10 | ## Installation
11 |
12 | You can install `vuer` from github using `remotes` or `devtools`.
13 |
14 | ```r
15 | remotes::install_github('ramnathv/vuer')
16 | ```
17 |
18 | ## Usage
19 |
20 | ### Example 1: Hello World
21 |
22 | We can use `vuer` to create purely client-side web-apps taking advantage of its simple API and two-way data bindings. In this simple example, we let a user enter their name and display a greeting message.
23 |
24 | ```r
25 | tags$div(style = 'height:100px;width:400px;',
26 | tags$label('Enter your name: '),
27 | tags$input(type = "text", "v-model" = "name"),
28 | tags$p(class = "lead", "Hello {{name}}")
29 | ) %>%
30 | appendDependencies(
31 | htmldeps::html_dependency_bootstrap('cosmo')
32 | ) %>%
33 | Vue(data = list(name = ""))
34 | ```
35 |
36 | 
37 |
38 | The power of `vuer` starts truly shining when we are able to let Vue communicate with Shiny. This opens up an unlimited range of possibilities that we will explore in detail. The next two examples explore how Vue and Shiny can communicate with each other.
39 |
40 | ### Example 2: Vue -> Shiny
41 |
42 | It is dead-simple to let Vue communicate with Shiny. All it takes is adding an underscore at the end of any data variable passed to `Vue`. This automatically sets up watcher functions to update shiny when the underlying value changes, thereby triggering any reactive paths that depend on it. This example is very similar to the first one in that we let a user enter their name and display a greeting message. The key difference is that the greeting message is from Shiny on the server side.
43 |
44 | ```r
45 | ui <- fluidPage(theme = shinythemes::shinytheme("cosmo"),
46 | tags$div(
47 | tags$label('Enter your name'),
48 | tags$input(type = "text", "v-model" = "name"),
49 | uiOutput("greeting")
50 | ) %>%
51 | Vue(
52 | data = list(name_ = "")
53 | )
54 | )
55 |
56 |
57 | server <- function(input, output, session){
58 | output$greeting <- renderUI({
59 | tags$p(paste("Hello", input$name))
60 | })
61 | }
62 |
63 | shinyApp(ui = ui, server = server)
64 | ```
65 |
66 |
67 | ### Example 3: Shiny -> Vue
68 |
69 | It is equally easy to let Shiny communicate with Vue. In this example we pass the coordinates of a plot brush to Vue and display it as JSON.
70 |
71 | ```r
72 | library(shiny)
73 | library(ggplot2)
74 | library(vuer)
75 | ui <- fluidPage(theme = shinythemes::shinytheme("cosmo"),
76 | titlePanel(title = 'Shiny -> Vue'),
77 | mainPanel(
78 | plotOutput('plot', brush = brushOpts('plot_brush'), height = '300'),
79 | tags$pre("v-if" = "plot_brush !== null",
80 | tags$code("{{plot_brush}}")
81 | ) %>%
82 | Vue(data = list(plot_brush = c()), elementId = "app")
83 | )
84 | )
85 |
86 | server <- function(input, output, session){
87 | output$plot <- renderPlot({
88 | ggplot(mtcars, aes(x = mpg, y = wt)) +
89 | geom_point()
90 | })
91 | observeEvent(input$plot_brush, {
92 | vueProxy("app") %>%
93 | vueUpdateData(plot_brush = input$plot_brush$coords_img)
94 | })
95 | }
96 | shinyApp(ui = ui, server = server)
97 | ```
98 |
99 | 
100 |
101 |
102 | ## Acknowledgements
103 |
104 | This package was inspired by Kenton Russell's [experiments](https://github.com/timelyportfolio/vueR) using Vue in R, as well as the efforts taken by the [react-R](https://github.com/react-R/reactR) team in integrating `React.js` with R.
105 |
--------------------------------------------------------------------------------
/_pkgdown.yml:
--------------------------------------------------------------------------------
1 | template:
2 | params:
3 | bootswatch: cosmo
4 |
5 | navbar:
6 | type: inverse
7 |
--------------------------------------------------------------------------------
/docs/authors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Authors • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
95 |
96 |
97 |
98 |
101 |
102 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/docs/docsearch.css:
--------------------------------------------------------------------------------
1 | /* Docsearch -------------------------------------------------------------- */
2 | /*
3 | Source: https://github.com/algolia/docsearch/
4 | License: MIT
5 | */
6 |
7 | .algolia-autocomplete {
8 | display: block;
9 | -webkit-box-flex: 1;
10 | -ms-flex: 1;
11 | flex: 1
12 | }
13 |
14 | .algolia-autocomplete .ds-dropdown-menu {
15 | width: 100%;
16 | min-width: none;
17 | max-width: none;
18 | padding: .75rem 0;
19 | background-color: #fff;
20 | background-clip: padding-box;
21 | border: 1px solid rgba(0, 0, 0, .1);
22 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175);
23 | }
24 |
25 | @media (min-width:768px) {
26 | .algolia-autocomplete .ds-dropdown-menu {
27 | width: 175%
28 | }
29 | }
30 |
31 | .algolia-autocomplete .ds-dropdown-menu::before {
32 | display: none
33 | }
34 |
35 | .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] {
36 | padding: 0;
37 | background-color: rgb(255,255,255);
38 | border: 0;
39 | max-height: 80vh;
40 | }
41 |
42 | .algolia-autocomplete .ds-dropdown-menu .ds-suggestions {
43 | margin-top: 0
44 | }
45 |
46 | .algolia-autocomplete .algolia-docsearch-suggestion {
47 | padding: 0;
48 | overflow: visible
49 | }
50 |
51 | .algolia-autocomplete .algolia-docsearch-suggestion--category-header {
52 | padding: .125rem 1rem;
53 | margin-top: 0;
54 | font-size: 1.3em;
55 | font-weight: 500;
56 | color: #00008B;
57 | border-bottom: 0
58 | }
59 |
60 | .algolia-autocomplete .algolia-docsearch-suggestion--wrapper {
61 | float: none;
62 | padding-top: 0
63 | }
64 |
65 | .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column {
66 | float: none;
67 | width: auto;
68 | padding: 0;
69 | text-align: left
70 | }
71 |
72 | .algolia-autocomplete .algolia-docsearch-suggestion--content {
73 | float: none;
74 | width: auto;
75 | padding: 0
76 | }
77 |
78 | .algolia-autocomplete .algolia-docsearch-suggestion--content::before {
79 | display: none
80 | }
81 |
82 | .algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header {
83 | padding-top: .75rem;
84 | margin-top: .75rem;
85 | border-top: 1px solid rgba(0, 0, 0, .1)
86 | }
87 |
88 | .algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column {
89 | display: block;
90 | padding: .1rem 1rem;
91 | margin-bottom: 0.1;
92 | font-size: 1.0em;
93 | font-weight: 400
94 | /* display: none */
95 | }
96 |
97 | .algolia-autocomplete .algolia-docsearch-suggestion--title {
98 | display: block;
99 | padding: .25rem 1rem;
100 | margin-bottom: 0;
101 | font-size: 0.9em;
102 | font-weight: 400
103 | }
104 |
105 | .algolia-autocomplete .algolia-docsearch-suggestion--text {
106 | padding: 0 1rem .5rem;
107 | margin-top: -.25rem;
108 | font-size: 0.8em;
109 | font-weight: 400;
110 | line-height: 1.25
111 | }
112 |
113 | .algolia-autocomplete .algolia-docsearch-footer {
114 | width: 110px;
115 | height: 20px;
116 | z-index: 3;
117 | margin-top: 10.66667px;
118 | float: right;
119 | font-size: 0;
120 | line-height: 0;
121 | }
122 |
123 | .algolia-autocomplete .algolia-docsearch-footer--logo {
124 | background-image: url("data:image/svg+xml;utf8, ");
125 | background-repeat: no-repeat;
126 | background-position: 50%;
127 | background-size: 100%;
128 | overflow: hidden;
129 | text-indent: -9000px;
130 | width: 100%;
131 | height: 100%;
132 | display: block;
133 | transform: translate(-8px);
134 | }
135 |
136 | .algolia-autocomplete .algolia-docsearch-suggestion--highlight {
137 | color: #FF8C00;
138 | background: rgba(232, 189, 54, 0.1)
139 | }
140 |
141 |
142 | .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight {
143 | box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5)
144 | }
145 |
146 | .algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content {
147 | background-color: rgba(192, 192, 192, .15)
148 | }
149 |
--------------------------------------------------------------------------------
/docs/docsearch.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | // register a handler to move the focus to the search bar
4 | // upon pressing shift + "/" (i.e. "?")
5 | $(document).on('keydown', function(e) {
6 | if (e.shiftKey && e.keyCode == 191) {
7 | e.preventDefault();
8 | $("#search-input").focus();
9 | }
10 | });
11 |
12 | $(document).ready(function() {
13 | // do keyword highlighting
14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */
15 | var mark = function() {
16 |
17 | var referrer = document.URL ;
18 | var paramKey = "q" ;
19 |
20 | if (referrer.indexOf("?") !== -1) {
21 | var qs = referrer.substr(referrer.indexOf('?') + 1);
22 | var qs_noanchor = qs.split('#')[0];
23 | var qsa = qs_noanchor.split('&');
24 | var keyword = "";
25 |
26 | for (var i = 0; i < qsa.length; i++) {
27 | var currentParam = qsa[i].split('=');
28 |
29 | if (currentParam.length !== 2) {
30 | continue;
31 | }
32 |
33 | if (currentParam[0] == paramKey) {
34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20"));
35 | }
36 | }
37 |
38 | if (keyword !== "") {
39 | $(".contents").unmark({
40 | done: function() {
41 | $(".contents").mark(keyword);
42 | }
43 | });
44 | }
45 | }
46 | };
47 |
48 | mark();
49 | });
50 | });
51 |
52 | /* Search term highlighting ------------------------------*/
53 |
54 | function matchedWords(hit) {
55 | var words = [];
56 |
57 | var hierarchy = hit._highlightResult.hierarchy;
58 | // loop to fetch from lvl0, lvl1, etc.
59 | for (var idx in hierarchy) {
60 | words = words.concat(hierarchy[idx].matchedWords);
61 | }
62 |
63 | var content = hit._highlightResult.content;
64 | if (content) {
65 | words = words.concat(content.matchedWords);
66 | }
67 |
68 | // return unique words
69 | var words_uniq = [...new Set(words)];
70 | return words_uniq;
71 | }
72 |
73 | function updateHitURL(hit) {
74 |
75 | var words = matchedWords(hit);
76 | var url = "";
77 |
78 | if (hit.anchor) {
79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor;
80 | } else {
81 | url = hit.url + '?q=' + escape(words.join(" "));
82 | }
83 |
84 | return url;
85 | }
86 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Harness the Power of Vue in R • vuer
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
66 |
67 |
68 |
71 |
72 |
vuer
is an R package that makes it easy to use Vue components and build Vue apps.
73 |
74 | Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. It is designed from the ground up to be incrementally adoptable, and can easily scale between a library and a framework depending on different use cases.
75 |
76 |
77 |
78 | Installation
79 |
You can install vuer
from github using remotes
or devtools
.
80 |
81 |
82 |
83 |
84 | Usage
85 |
86 |
87 | Example 1: Hello World
88 |
We can use vuer
to create purely client-side web-apps taking advantage of its simple API and two-way data bindings. In this simple example, we let a user enter their name and display a greeting message.
89 |
98 |
99 |
The power of vuer
starts truly shining when we are able to let Vue communicate with Shiny. This opens up an unlimited range of possibilities that we will explore in detail. The next two examples explore how Vue and Shiny can communicate with each other.
100 |
101 |
102 |
103 | Example 2: Vue -> Shiny
104 |
It is dead-simple to let Vue communicate with Shiny. All it takes is adding an underscore at the end of any data variable passed to Vue
. This automatically sets up watcher functions to update shiny when the underlying value changes, thereby triggering any reactive paths that depend on it. This example is very similar to the first one in that we let a user enter their name and display a greeting message. The key difference is that the greeting message is from Shiny on the server side.
105 |
124 |
125 |
126 |
127 | Example 3: Shiny -> Vue
128 |
It is equally easy to let Shiny communicate with Vue. In this example we pass the coordinates of a plot brush to Vue and display it as JSON.
129 |
library (shiny)
130 | library (ggplot2)
131 | library (vuer)
132 | ui <- fluidPage (theme = shinythemes:: shinytheme ("cosmo" ),
133 | titlePanel (title = 'Shiny -> Vue' ),
134 | mainPanel (
135 | plotOutput ('plot' , brush = brushOpts ('plot_brush' ), height = '300' ),
136 | tags$ pre ("v-if" = "plot_brush !== null" ,
137 | tags$ code ("{{plot_brush}}" )
138 | ) %>%
139 | Vue (data = list (plot_brush = c ()), elementId = "app" )
140 | )
141 | )
142 |
143 | server <- function (input, output, session){
144 | output$ plot <- renderPlot ({
145 | ggplot (mtcars, aes (x = mpg, y = wt)) +
146 | geom_point ()
147 | })
148 | observeEvent (input$ plot_brush, {
149 | vueProxy ("app" ) %>%
150 | vueUpdateData (plot_brush = input$ plot_brush$ coords_img)
151 | })
152 | }
153 | shinyApp (ui = ui, server = server)
154 |
155 |
156 |
157 |
158 |
159 | Acknowledgements
160 |
This package was inspired by Kenton Russell’s experiments using Vue in R, as well as the efforts taken by the react-R team in integrating React.js
with R.
161 |
162 |
163 |
164 |
165 |
197 |
198 |
199 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
--------------------------------------------------------------------------------
/docs/link.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/pkgdown.css:
--------------------------------------------------------------------------------
1 | /* Sticky footer */
2 |
3 | /**
4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/
5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css
6 | *
7 | * .Site -> body > .container
8 | * .Site-content -> body > .container .row
9 | * .footer -> footer
10 | *
11 | * Key idea seems to be to ensure that .container and __all its parents__
12 | * have height set to 100%
13 | *
14 | */
15 |
16 | html, body {
17 | height: 100%;
18 | }
19 |
20 | body > .container {
21 | display: flex;
22 | height: 100%;
23 | flex-direction: column;
24 |
25 | padding-top: 60px;
26 | }
27 |
28 | body > .container .row {
29 | flex: 1 0 auto;
30 | }
31 |
32 | footer {
33 | margin-top: 45px;
34 | padding: 35px 0 36px;
35 | border-top: 1px solid #e5e5e5;
36 | color: #666;
37 | display: flex;
38 | flex-shrink: 0;
39 | }
40 | footer p {
41 | margin-bottom: 0;
42 | }
43 | footer div {
44 | flex: 1;
45 | }
46 | footer .pkgdown {
47 | text-align: right;
48 | }
49 | footer p {
50 | margin-bottom: 0;
51 | }
52 |
53 | img.icon {
54 | float: right;
55 | }
56 |
57 | img {
58 | max-width: 100%;
59 | }
60 |
61 | /* Fix bug in bootstrap (only seen in firefox) */
62 | summary {
63 | display: list-item;
64 | }
65 |
66 | /* Typographic tweaking ---------------------------------*/
67 |
68 | .contents .page-header {
69 | margin-top: calc(-60px + 1em);
70 | }
71 |
72 | /* Section anchors ---------------------------------*/
73 |
74 | a.anchor {
75 | margin-left: -30px;
76 | display:inline-block;
77 | width: 30px;
78 | height: 30px;
79 | visibility: hidden;
80 |
81 | background-image: url(./link.svg);
82 | background-repeat: no-repeat;
83 | background-size: 20px 20px;
84 | background-position: center center;
85 | }
86 |
87 | .hasAnchor:hover a.anchor {
88 | visibility: visible;
89 | }
90 |
91 | @media (max-width: 767px) {
92 | .hasAnchor:hover a.anchor {
93 | visibility: hidden;
94 | }
95 | }
96 |
97 |
98 | /* Fixes for fixed navbar --------------------------*/
99 |
100 | .contents h1, .contents h2, .contents h3, .contents h4 {
101 | padding-top: 60px;
102 | margin-top: -40px;
103 | }
104 |
105 | /* Static header placement on mobile devices */
106 | @media (max-width: 767px) {
107 | .navbar-fixed-top {
108 | position: absolute;
109 | }
110 | .navbar {
111 | padding: 0;
112 | }
113 | }
114 |
115 |
116 | /* Sidebar --------------------------*/
117 |
118 | #sidebar {
119 | margin-top: 30px;
120 | }
121 | #sidebar h2 {
122 | font-size: 1.5em;
123 | margin-top: 1em;
124 | }
125 |
126 | #sidebar h2:first-child {
127 | margin-top: 0;
128 | }
129 |
130 | #sidebar .list-unstyled li {
131 | margin-bottom: 0.5em;
132 | }
133 |
134 | .orcid {
135 | height: 16px;
136 | vertical-align: middle;
137 | }
138 |
139 | /* Reference index & topics ----------------------------------------------- */
140 |
141 | .ref-index th {font-weight: normal;}
142 |
143 | .ref-index td {vertical-align: top;}
144 | .ref-index .icon {width: 40px;}
145 | .ref-index .alias {width: 40%;}
146 | .ref-index-icons .alias {width: calc(40% - 40px);}
147 | .ref-index .title {width: 60%;}
148 |
149 | .ref-arguments th {text-align: right; padding-right: 10px;}
150 | .ref-arguments th, .ref-arguments td {vertical-align: top;}
151 | .ref-arguments .name {width: 20%;}
152 | .ref-arguments .desc {width: 80%;}
153 |
154 | /* Nice scrolling for wide elements --------------------------------------- */
155 |
156 | table {
157 | display: block;
158 | overflow: auto;
159 | }
160 |
161 | /* Syntax highlighting ---------------------------------------------------- */
162 |
163 | pre {
164 | word-wrap: normal;
165 | word-break: normal;
166 | border: 1px solid #eee;
167 | }
168 |
169 | pre, code {
170 | background-color: #f8f8f8;
171 | color: #333;
172 | }
173 |
174 | pre code {
175 | overflow: auto;
176 | word-wrap: normal;
177 | white-space: pre;
178 | }
179 |
180 | pre .img {
181 | margin: 5px 0;
182 | }
183 |
184 | pre .img img {
185 | background-color: #fff;
186 | display: block;
187 | height: auto;
188 | }
189 |
190 | code a, pre a {
191 | color: #375f84;
192 | }
193 |
194 | a.sourceLine:hover {
195 | text-decoration: none;
196 | }
197 |
198 | .fl {color: #1514b5;}
199 | .fu {color: #000000;} /* function */
200 | .ch,.st {color: #036a07;} /* string */
201 | .kw {color: #264D66;} /* keyword */
202 | .co {color: #888888;} /* comment */
203 |
204 | .message { color: black; font-weight: bolder;}
205 | .error { color: orange; font-weight: bolder;}
206 | .warning { color: #6A0366; font-weight: bolder;}
207 |
208 | /* Clipboard --------------------------*/
209 |
210 | .hasCopyButton {
211 | position: relative;
212 | }
213 |
214 | .btn-copy-ex {
215 | position: absolute;
216 | right: 0;
217 | top: 0;
218 | visibility: hidden;
219 | }
220 |
221 | .hasCopyButton:hover button.btn-copy-ex {
222 | visibility: visible;
223 | }
224 |
225 | /* mark.js ----------------------------*/
226 |
227 | mark {
228 | background-color: rgba(255, 255, 51, 0.5);
229 | border-bottom: 2px solid rgba(255, 153, 51, 0.3);
230 | padding: 1px;
231 | }
232 |
233 | /* vertical spacing after htmlwidgets */
234 | .html-widget {
235 | margin-bottom: 10px;
236 | }
237 |
--------------------------------------------------------------------------------
/docs/pkgdown.js:
--------------------------------------------------------------------------------
1 | /* http://gregfranko.com/blog/jquery-best-practices/ */
2 | (function($) {
3 | $(function() {
4 |
5 | $("#sidebar")
6 | .stick_in_parent({offset_top: 40})
7 | .on('sticky_kit:bottom', function(e) {
8 | $(this).parent().css('position', 'static');
9 | })
10 | .on('sticky_kit:unbottom', function(e) {
11 | $(this).parent().css('position', 'relative');
12 | });
13 |
14 | $('body').scrollspy({
15 | target: '#sidebar',
16 | offset: 60
17 | });
18 |
19 | $('[data-toggle="tooltip"]').tooltip();
20 |
21 | var cur_path = paths(location.pathname);
22 | var links = $("#navbar ul li a");
23 | var max_length = -1;
24 | var pos = -1;
25 | for (var i = 0; i < links.length; i++) {
26 | if (links[i].getAttribute("href") === "#")
27 | continue;
28 | // Ignore external links
29 | if (links[i].host !== location.host)
30 | continue;
31 |
32 | var nav_path = paths(links[i].pathname);
33 |
34 | var length = prefix_length(nav_path, cur_path);
35 | if (length > max_length) {
36 | max_length = length;
37 | pos = i;
38 | }
39 | }
40 |
41 | // Add class to parent , and enclosing if in dropdown
42 | if (pos >= 0) {
43 | var menu_anchor = $(links[pos]);
44 | menu_anchor.parent().addClass("active");
45 | menu_anchor.closest("li.dropdown").addClass("active");
46 | }
47 | });
48 |
49 | function paths(pathname) {
50 | var pieces = pathname.split("/");
51 | pieces.shift(); // always starts with /
52 |
53 | var end = pieces[pieces.length - 1];
54 | if (end === "index.html" || end === "")
55 | pieces.pop();
56 | return(pieces);
57 | }
58 |
59 | // Returns -1 if not found
60 | function prefix_length(needle, haystack) {
61 | if (needle.length > haystack.length)
62 | return(-1);
63 |
64 | // Special case for length-0 haystack, since for loop won't run
65 | if (haystack.length === 0) {
66 | return(needle.length === 0 ? 0 : -1);
67 | }
68 |
69 | for (var i = 0; i < haystack.length; i++) {
70 | if (needle[i] != haystack[i])
71 | return(i);
72 | }
73 |
74 | return(haystack.length);
75 | }
76 |
77 | /* Clipboard --------------------------*/
78 |
79 | function changeTooltipMessage(element, msg) {
80 | var tooltipOriginalTitle=element.getAttribute('data-original-title');
81 | element.setAttribute('data-original-title', msg);
82 | $(element).tooltip('show');
83 | element.setAttribute('data-original-title', tooltipOriginalTitle);
84 | }
85 |
86 | if(ClipboardJS.isSupported()) {
87 | $(document).ready(function() {
88 | var copyButton = " ";
89 |
90 | $(".examples, div.sourceCode").addClass("hasCopyButton");
91 |
92 | // Insert copy buttons:
93 | $(copyButton).prependTo(".hasCopyButton");
94 |
95 | // Initialize tooltips:
96 | $('.btn-copy-ex').tooltip({container: 'body'});
97 |
98 | // Initialize clipboard:
99 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', {
100 | text: function(trigger) {
101 | return trigger.parentNode.textContent;
102 | }
103 | });
104 |
105 | clipboardBtnCopies.on('success', function(e) {
106 | changeTooltipMessage(e.trigger, 'Copied!');
107 | e.clearSelection();
108 | });
109 |
110 | clipboardBtnCopies.on('error', function() {
111 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy');
112 | });
113 | });
114 | }
115 | })(window.jQuery || window.$)
116 |
--------------------------------------------------------------------------------
/docs/pkgdown.yml:
--------------------------------------------------------------------------------
1 | pandoc: 2.3.1
2 | pkgdown: 1.3.0
3 | pkgdown_sha: ~
4 | articles: []
5 |
6 |
--------------------------------------------------------------------------------
/docs/reference/appendDependencies.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Append html dependencies — appendDependencies • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
98 |
99 |
100 |
101 |
106 |
107 |
108 |
109 |
NOTE: This function has been copied over from shinydashboard
110 |
111 |
112 |
113 |
appendDependencies (x , value )
114 |
115 |
116 |
117 |
123 |
124 |
125 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/docs/reference/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Function reference • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
95 |
96 |
97 |
98 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | All functions
114 |
115 |
116 |
117 |
118 |
119 |
120 | appendDependencies()
121 |
122 | Append html dependencies
123 |
124 |
125 |
126 | Vue()
127 |
128 | Create a Vue App
129 |
130 |
131 |
132 | vueProxy()
vueUpdateData()
133 |
134 | Send commands to a Vue instance in a Shiny app
135 |
136 |
137 |
138 | vueUpdateShinyInputs()
139 |
140 | Update Shiny Input
141 |
142 |
143 |
144 | vueUsePlugin()
145 |
146 | Use a vue Plugin
147 |
148 |
149 |
150 |
151 |
152 |
158 |
159 |
160 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
--------------------------------------------------------------------------------
/docs/reference/pipe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Pipe operator — %>% • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
98 |
99 |
100 |
101 |
106 |
107 |
108 |
109 |
See magrittr::%>%
for details.
110 |
111 |
112 |
113 |
lhs %>% rhs
114 |
115 |
116 |
117 |
123 |
124 |
125 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/docs/reference/vue.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Create a Vue App — Vue • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
98 |
99 |
100 |
101 |
106 |
107 |
108 |
109 |
Create a Vue App
110 |
111 |
112 |
113 |
Vue (html , data = list (), dependencies = list (), ... ,
114 | elementId = NULL )
115 |
116 |
117 |
Examples
118 |
# NOT RUN {
119 | library (htmltools )
120 | tags $div (
121 | tags $label ('Enter your name' ),
122 | tags $input (type = "text" , "v-model" = "name" ),
123 | tags $p ("Hello {{name}}" )
124 | ) %>%
125 | Vue (data = list (name = "" ))
126 |
127 | if (interactive ()){
128 | library (shiny )
129 | ui <- tags $div (
130 | tags $label ('Enter your name' ),
131 | tags $input (type = "text" , "v-model" = "name" ),
132 | textOutput ("greeting" )
133 | ) %>%
134 | Vue (data = list (name_ = "" ))
135 | server <- function (input , output , session ){
136 | output $greeting <- renderText ({
137 | paste ("Hello" , input $name )
138 | })
139 | }
140 | shinyApp (ui = ui , server = server )
141 | }
142 | # }
143 |
144 |
152 |
153 |
154 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/docs/reference/vueProxy.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Send commands to a Vue instance in a Shiny app — vueProxy • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
99 |
100 |
101 |
102 |
107 |
108 |
109 |
110 |
Send commands to a Vue instance in a Shiny app
111 |
Update data in a Vue instance
112 |
113 |
114 |
115 |
vueProxy (outputId , session = shiny :: getDefaultReactiveDomain (),
116 | deferUntilFlush = TRUE )
117 |
118 | vueUpdateData (proxy , ... )
119 |
120 |
121 |
Examples
122 |
# NOT RUN {
123 | ui <- div (
124 | tags $label ("Enter username" ),
125 | tags $input (type = 'text' , "v-model" = "username" ),
126 | tags $p ("Vue -> Vue: Hello {{username}}" ),
127 | actionButton ("set_name" , "Shiny -> Vue" ),
128 | verbatimTextOutput ("username" )
129 | ) %>%
130 | vue (
131 | data = list (username = "" ),
132 | # Vue UI -> Shiny UI
133 | watch = vue_watch ("username" ),
134 | elementId = "app"
135 | )
136 | server <- function (input , output , session ){
137 | # Shiny server -> Vue UI
138 | observeEvent (input $set_name , {
139 | vueProxy ("app" ) %>%
140 | updateProp ("username" , "Ramnath" )
141 | })
142 | output $username <- renderPrint ({
143 | paste ("Vue -> Shiny:" , input $username )
144 | })
145 | }
146 | shiny :: shinyApp (ui = ui , server = server )
147 | # }
148 |
149 |
157 |
158 |
159 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/docs/reference/vueUpdateShinyInputs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Update Shiny Input — vueUpdateShinyInputs • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
98 |
99 |
100 |
101 |
106 |
107 |
108 |
109 |
Update Shiny Input
110 |
111 |
112 |
113 |
vueUpdateShinyInputs (... )
114 |
115 |
116 |
117 |
123 |
124 |
125 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/docs/reference/vueUsePlugin.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Use a vue Plugin — vueUsePlugin • vuer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
98 |
99 |
100 |
101 |
106 |
107 |
108 |
109 |
Use a vue Plugin
110 |
111 |
112 |
113 |
vueUsePlugin (fun )
114 |
115 |
116 |
117 |
123 |
124 |
125 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/inst/examples/apexcharts.R:
--------------------------------------------------------------------------------
1 | library(vuer)
2 |
3 | htmlDependenciesApexCharts <- function(){
4 | list(
5 | htmltools::htmlDependency(
6 | name = 'apexcharts',
7 | version = '2.7.0',
8 | src = c(href = 'https://unpkg.com/apexcharts/dist'),
9 | script = 'apexcharts.js'
10 | ),
11 | htmltools::htmlDependency(
12 | name = 'vue-apexcharts',
13 | version = '1.3.0',
14 | src = c(href = "https://unpkg.com/vue-apexcharts/dist"),
15 | script = 'vue-apexcharts.js'
16 | )
17 | )
18 | }
19 |
20 | vueApexChart <- function(...){
21 | vueComponents$register(apexchart = 'VueApexCharts')
22 | htmltools::tag("apexchart", list(...)) %>%
23 | appendDependencies(htmlDependenciesApexCharts())
24 | }
25 |
26 | data <- list(
27 | chartOptions = list(
28 | chart = list(
29 | xaxis = list(
30 | categories = as.character(1991:1998)
31 | )
32 | )
33 | ),
34 | series = list(
35 | list(name = 'series-1', data = sample(40:100, 8))
36 | )
37 | )
38 |
39 | library(shiny)
40 | ui <- div(
41 | vueApexChart(height = 350, ":series" = "series", type = "bar",
42 | ":options" = "chartOptions"
43 | ),
44 | actionButton("update_data", "Update Data")
45 | ) %>%
46 | vue(data = data, elementId = "chart")
47 |
48 | server <- function(input, output, session){
49 | observeEvent(input$update_data, {
50 | vueProxy("chart") %>%
51 | vueUpdateData(series = list(list(data = sample(40:80, 8))))
52 | })
53 | }
54 |
55 | shinyApp(ui = ui, server = server)
56 |
--------------------------------------------------------------------------------
/inst/examples/basic-vtags.R:
--------------------------------------------------------------------------------
1 | library(htmltools)
2 | library(vuer)
3 |
4 | # Example 1: Hello World
5 |
6 | vtags$div("{{ message }}") %>%
7 | Vue(data = list(message = 'Hello World'))
8 |
9 | # Example 2:
10 |
11 |
12 | vtags$span(
13 | vbind.title = "message",
14 | "Hover your mouse over me for a few seconds to see my dynamically bound title!"
15 | ) %>%
16 | Vue(data = list(
17 | message = htmlwidgets::JS("'You loaded me on ' + new Date()")
18 | ))
19 |
20 | # Example 3:
21 |
22 | tags$div(id = 'app',
23 | vtags$h3("Use the checkbox to toggle visibility of the message"),
24 | vtags$input(type = "checkbox", vmodel = "seen"),
25 | vtags$span(vif = "seen", "Now you see me again")
26 | ) %>%
27 | Vue(data = list(seen = TRUE))
28 |
29 | # Example 4: Lists
30 |
31 | vtags$li(vfor = "column in columns", "{{ column }}") %>%
32 | tags$ul(id = 'app') %>%
33 | Vue(data = list(columns = names(mtcars)))
34 |
35 | # Example 5:
36 |
37 | tags$div(id = 'app',
38 | vtags$input(type = 'text', vmodel = "message"),
39 | tags$p("{{ message }}"),
40 | vtags$button(von.click = "reverseMessage", "Reverse Message")
41 | ) %>%
42 | Vue(
43 | data = list(message = 'Hello World'),
44 | methods = list(
45 | reverseMessage = htmlwidgets::JS("function(){
46 | this.message = this.message.split('').reverse().join('')
47 | }")
48 | )
49 | )
50 |
51 |
--------------------------------------------------------------------------------
/inst/examples/basic.R:
--------------------------------------------------------------------------------
1 | library(htmltools)
2 | library(vuer)
3 | library(magrittr)
4 |
5 | # Example 1: Hello World
6 |
7 | tags$div("{{ message }}") %>%
8 | Vue(data = list(message = 'Hello World'))
9 |
10 | # Example 2:
11 |
12 |
13 | tags$span(
14 | "v-bind:title" = "message",
15 | "Hover your mouse over me for a few seconds to see my dynamically bound title!"
16 | ) %>%
17 | Vue(data = list(
18 | message = htmlwidgets::JS("'You loaded me on ' + new Date()")
19 | ))
20 |
21 | # Example 3:
22 |
23 | tags$div(id = 'app',
24 | tags$h3("Use the checkbox to toggle visibility of the message"),
25 | tags$input(type = "checkbox", "v-model" = "seen"),
26 | tags$span("v-if" = "seen", "Now you see me again")
27 | ) %>%
28 | Vue(data = list(seen = TRUE))
29 |
30 | # Example 4: Lists
31 |
32 | tags$li("v-for" = "column in columns", "{{ column }}") %>%
33 | tags$ul(id = 'app') %>%
34 | Vue(data = list(columns = names(mtcars)))
35 |
36 | # Example 5:
37 |
38 | tags$div(id = 'app',
39 | tags$input(type = 'text', "v-model" = "message"),
40 | tags$p("{{ message }}"),
41 | tags$button("v-on:click" = "reverseMessage", "Reverse Message")
42 | ) %>%
43 | Vue(
44 | data = list(message = 'Hello World'),
45 | methods = list(
46 | reverseMessage = htmlwidgets::JS("function(){
47 | this.message = this.message.split('').reverse().join('')
48 | }")
49 | )
50 | )
51 |
52 | # Example 6
53 |
54 | tags$div(id = "app",
55 | tags$button("v-on:click" = "handleClick",
56 | "Clicked {{ count }} {{ count === 1 ? 'time' : 'times' }}"
57 | )
58 | ) %>%
59 | Vue(
60 | data = list(count = 0),
61 | methods = list(
62 | handleClick = htmlwidgets::JS("function(){
63 | this.count += 1
64 | }")
65 | )
66 | )
67 |
--------------------------------------------------------------------------------
/inst/examples/colorpicker.R:
--------------------------------------------------------------------------------
1 | library(vuer)
2 | library(ggplot2)
3 | library(shiny)
4 |
5 | html_dependencies_vue_color <- function(){
6 | list(
7 | htmltools::htmlDependency(
8 | name = 'vue-color',
9 | version = '2.7.0',
10 | src = c(href = 'https://unpkg.com/vue-color/dist'),
11 | script = 'vue-color.min.js'
12 | )
13 | )
14 | }
15 |
16 | vueColorPickerInput <- function(type = types, ...){
17 | types <- c('compact', 'chrome', 'swatches', 'sketch')
18 | types %>%
19 | purrr::map(~ {
20 | .x %>%
21 | stringi::stri_trans_totitle() %>%
22 | paste0('VueColor.', .)
23 | }) %>%
24 | rlang::set_names(paste0(types, '-picker')) %>%
25 | vueComponents$register(.list = .)
26 | type <- match.arg(type)
27 | htmltools::tag(
28 | sprintf("%s-picker", type), list("v-model" = "colors", ...)
29 | ) %>%
30 | appendDependencies(html_dependencies_vue_color())
31 | }
32 |
33 |
34 | vueColorPickerInput(type = "sketch") %>%
35 | Vue(data = list(colors_ = '#fff'))
36 |
37 | ui <- div(
38 | vueColorPickerInput(type = "sketch"),
39 | shiny::plotOutput('plot')
40 | ) %>%
41 | Vue(
42 | data = list(colors_ = '#fff')
43 | )
44 |
45 | server <- function(input, output, session){
46 | output$plot <- renderPlot({
47 | mycolor <- if (is.null(input$colors)) 'black' else input$colors$hex[1]
48 | ggplot(mtcars, (aes(x = wt, y = mpg))) +
49 | geom_point(color = mycolor)
50 | })
51 | output$colors <- renderText({
52 | input$colors$hex[1]
53 | })
54 | }
55 |
56 | shiny::shinyApp(ui = ui, server = server)
57 |
--------------------------------------------------------------------------------
/inst/examples/elementui.R:
--------------------------------------------------------------------------------
1 | library(vuer)
2 |
3 | htmlDependenciesElementUI <- function(){
4 | list(
5 | htmlDependency(
6 | name = 'vue',
7 | version = '2.6.6',
8 | src = system.file('htmlwidgets', 'lib','vue', package = 'vuer'),
9 | script = "vue.js"
10 | ),
11 | htmlDependency(
12 | name = 'element-ui',
13 | version = '2.6.0',
14 | src = c(href = "https://unpkg.com/element-ui/lib"),
15 | script = "index.js",
16 | stylesheet = "theme-chalk/index.css"
17 | )
18 | )
19 | }
20 |
21 |
22 |
23 | create_tags <- function(types, prefix){
24 | types %>%
25 | purrr::map(~ {
26 | function(...){
27 | vtag(paste0(prefix, '-', .x), list(...))
28 | }
29 | }) %>%
30 | rlang::set_names(
31 | types %>%
32 | stringr::str_replace("-", "_")
33 | )
34 | }
35 |
36 |
37 | types <- c('button', 'color-picker')
38 | el_tags <- create_tags(types, 'el')
39 |
40 | el_tags$button(type = 'Primary', "Primary") %>%
41 | appendDependencies(htmlDependenciesElementUI()) %>%
42 | Vue()
43 |
44 | el_tags$color_picker("v-model" = "color") %>%
45 | appendDependencies(htmlDependenciesElementUI()) %>%
46 | Vue(data = list(color = '#fff'))
47 |
48 |
--------------------------------------------------------------------------------
/inst/examples/mint.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 | #### Mint examples #######################################
3 | mint <- htmlDependency(
4 | name = "mint-ui",
5 | version = "2.0.5",
6 | src = c(href="https://unpkg.com/mint-ui/lib"),
7 | script = "index.js",
8 | stylesheet = "style.css"
9 | )
10 |
11 | ui <- tags$div(
12 | #tags$script("Vue.use(MINT)"),
13 | vtag("mt-switch",list(vmodel ="value","{{value ? 'on' : 'off'}}")),
14 | vtag(
15 | "mt-checklist",
16 | list(
17 | title="checkbox list",
18 | vmodel = "checkbox_value",
19 | vbind.options = "['Item A', 'Item B', 'Item C']"
20 | )
21 | ),
22 | tags$p("Vue: {{ value }}"),
23 | textOutput('value'),
24 | textOutput('checkbox_value')
25 | ) %>%
26 | Vue(
27 | data = list(
28 | value_ = TRUE,
29 | checkbox_value_ = list()
30 | )
31 | ) %>%
32 | shinydashboard:::appendDependencies(mint)
33 |
34 |
35 |
36 | server <- function(input, output, session){
37 | output$value <- renderText({
38 | paste("Shiny:", input$value)
39 | })
40 | output$checkbox_value <- renderText({
41 | paste("Shiny:", input$checkbox_value)
42 | })
43 | }
44 |
45 | shinyApp(ui = ui, server = server)
46 |
--------------------------------------------------------------------------------
/inst/examples/sunburst.R:
--------------------------------------------------------------------------------
1 | # Load Libraries ----
2 | library(shiny)
3 | library(treemap)
4 | library(vuer)
5 | library(magrittr)
6 | library(htmltools)
7 | library(htmlwidgets)
8 | library(d3r)
9 | jsFun <- function(body, ...){
10 | args <- paste(c(...), collapse = ",")
11 | htmlwidgets::JS(sprintf("function(%s){%s}", args, body))
12 | }
13 |
14 | # Define Dependencies ----
15 | html_dependencies_d2b <- function(){
16 | list(
17 | d3r::d3_dep_v4(offline = FALSE),
18 | htmltools::htmlDependency(
19 | name = "d2b",
20 | version = "0.0.24",
21 | src = c(href = "https://unpkg.com/d2b@0.0.24/build/"),
22 | script = "d2b.min.js"
23 | )
24 | )
25 | }
26 |
27 | # Define Chart Generator
28 | vueSunburstChart <- function(...){
29 | vuer::vueComponents$register(
30 | "sunburst-chart" = "d2b.vueChartSunburst"
31 | )
32 | tag('sunburst-chart', list(...)) %>%
33 | appendDependencies(html_dependencies_d2b())
34 | }
35 |
36 |
37 |
38 | # UI ----
39 | ui <- tags$div(style = 'height:400px',
40 | vueSunburstChart(":data" = "chart_data", ":config" = "chart_config"),
41 | actionButton('update_data', 'Update Data')
42 | ) %>%
43 | Vue(
44 | data = list(
45 | chart_data_ = d3r::d3_nest(
46 | treemap::random.hierarchical.data(),
47 | value_cols = "x"
48 | ),
49 | chart_config = jsFun("
50 | chart.label((d) => d.name);
51 | chart.sunburst().size((d) => d.x);
52 | ", "chart")
53 | ),
54 | elementId = 'mychart',
55 | width = '100%'
56 | )
57 |
58 |
59 | # Server ----
60 | server <- function(input, output, session){
61 | observeEvent(input$update_data, {
62 | vueProxy('mychart') %>%
63 | vueUpdateData(
64 | chart_data = d3r::d3_nest(
65 | treemap::random.hierarchical.data(),
66 | value_cols = "x"
67 | )
68 | )
69 | })
70 | }
71 |
72 | shinyApp(ui = ui, server = server)
73 |
--------------------------------------------------------------------------------
/inst/examples/treeview.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 | library(vuer)
3 |
4 | html_deps_vue_tree_view <- function(){
5 | htmltools::htmlDependency(
6 | name = 'vue-json-tree-view',
7 | version = '2.0.6',
8 | src = c(href = "https://unpkg.com/vue-json-tree-view@2.0.6/dist"),
9 | script = 'vue-json-tree-view.min.js'
10 | )
11 | }
12 |
13 | vueJsonTreeOutput <- function(...){
14 | tagList(
15 | tag('tree-view', list(...)) %>%
16 | appendDependencies(html_deps_vue_tree_view()),
17 | tags$script('Vue.use(TreeView)')
18 | )
19 | }
20 |
21 | ## Example 1:
22 | div(vueJsonTreeOutput(":data" = "data")) %>%
23 | Vue(data = list(data = list(x = 1, y = 2)))
24 |
25 |
26 | ## Example 2:
27 | ui <- fluidPage(
28 | titlePanel("Shiny with Vue"),
29 | mainPanel(
30 | fluidRow(
31 | plotOutput('plot1', brush = brushOpts(id = 'plot_brush')),
32 | vueJsonTreeOutput(":data" = "data")
33 | ) %>%
34 | vuepkg::Vue(
35 | data = list(data = list()),
36 | elementId = "app"
37 | )
38 | )
39 | )
40 |
41 | server <- function(input,output,session){
42 | output$plot1 <- renderPlot({
43 | require(ggplot2)
44 | ggplot(mtcars, aes(x = mpg, y = wt)) +
45 | geom_point()
46 | })
47 | observeEvent(input$plot_brush, {
48 | vueProxy("app") %>%
49 | vueUpdateData(data = input$plot_brush)
50 | })
51 | }
52 |
53 | shinyApp(ui = ui, server = server)
54 |
55 |
--------------------------------------------------------------------------------
/inst/htmlwidgets/lib/vue/vue.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Vue.js v2.6.6
3 | * (c) 2014-2019 Evan You
4 | * Released under the MIT License.
5 | */
6 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Vue=t()}(this,function(){"use strict";var e=Object.freeze({});function t(e){return null==e}function n(e){return null!=e}function r(e){return!0===e}function i(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function o(e){return null!==e&&"object"==typeof e}var a=Object.prototype.toString;function s(e){return"[object Object]"===a.call(e)}function c(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function u(e){return n(e)&&"function"==typeof e.then&&"function"==typeof e.catch}function l(e){return null==e?"":Array.isArray(e)||s(e)&&e.toString===a?JSON.stringify(e,null,2):String(e)}function f(e){var t=parseFloat(e);return isNaN(t)?e:t}function p(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i-1)return e.splice(n,1)}}var m=Object.prototype.hasOwnProperty;function y(e,t){return m.call(e,t)}function g(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}var _=/-(\w)/g,b=g(function(e){return e.replace(_,function(e,t){return t?t.toUpperCase():""})}),$=g(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),w=/\B([A-Z])/g,x=g(function(e){return e.replace(w,"-$1").toLowerCase()});var C=Function.prototype.bind?function(e,t){return e.bind(t)}:function(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n};function A(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function k(e,t){for(var n in t)e[n]=t[n];return e}function O(e){for(var t={},n=0;n0,W=K&&K.indexOf("edge/")>0,Z=(K&&K.indexOf("android"),K&&/iphone|ipad|ipod|ios/.test(K)||"ios"===V),G=(K&&/chrome\/\d+/.test(K),K&&/phantomjs/.test(K),K&&K.match(/firefox\/(\d+)/)),X={}.watch,Y=!1;if(U)try{var Q={};Object.defineProperty(Q,"passive",{get:function(){Y=!0}}),window.addEventListener("test-passive",null,Q)}catch(e){}var ee=function(){return void 0===H&&(H=!U&&!z&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),H},te=U&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ne(e){return"function"==typeof e&&/native code/.test(e.toString())}var re,ie="undefined"!=typeof Symbol&&ne(Symbol)&&"undefined"!=typeof Reflect&&ne(Reflect.ownKeys);re="undefined"!=typeof Set&&ne(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var oe=S,ae=0,se=function(){this.id=ae++,this.subs=[]};se.prototype.addSub=function(e){this.subs.push(e)},se.prototype.removeSub=function(e){h(this.subs,e)},se.prototype.depend=function(){se.target&&se.target.addDep(this)},se.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t-1)if(o&&!y(i,"default"))a=!1;else if(""===a||a===x(e)){var c=Pe(String,i.type);(c<0||s0&&(at((u=e(u,(a||"")+"_"+c))[0])&&at(f)&&(s[l]=ve(f.text+u[0].text),u.shift()),s.push.apply(s,u)):i(u)?at(f)?s[l]=ve(f.text+u):""!==u&&s.push(ve(u)):at(u)&&at(f)?s[l]=ve(f.text+u.text):(r(o._isVList)&&n(u.tag)&&t(u.key)&&n(a)&&(u.key="__vlist"+a+"_"+c+"__"),s.push(u)));return s}(e):void 0}function at(e){return n(e)&&n(e.text)&&!1===e.isComment}function st(e,t){if(e){for(var n=Object.create(null),r=ie?Reflect.ownKeys(e):Object.keys(e),i=0;idocument.createEvent("Event").timeStamp&&(an=function(){return performance.now()});var cn=0,un=function(e,t,n,r,i){this.vm=e,i&&(e._watcher=this),e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++cn,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new re,this.newDepIds=new re,this.expression="","function"==typeof t?this.getter=t:(this.getter=function(e){if(!F.test(e)){var t=e.split(".");return function(e){for(var n=0;nrn&&Yt[n].id>e.id;)n--;Yt.splice(n+1,0,e)}else Yt.push(e);tn||(tn=!0,Xe(sn))}}(this)},un.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||o(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){Re(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},un.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},un.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},un.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var ln={enumerable:!0,configurable:!0,get:S,set:S};function fn(e,t,n){ln.get=function(){return this[t][n]},ln.set=function(e){this[t][n]=e},Object.defineProperty(e,n,ln)}function pn(e){e._watchers=[];var t=e.$options;t.props&&function(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[];e.$parent&&be(!1);var o=function(o){i.push(o);var a=Me(o,t,n,e);xe(r,o,a),o in e||fn(e,"_props",o)};for(var a in t)o(a);be(!0)}(e,t.props),t.methods&&function(e,t){e.$options.props;for(var n in t)e[n]="function"!=typeof t[n]?S:C(t[n],e)}(e,t.methods),t.data?function(e){var t=e.$options.data;s(t=e._data="function"==typeof t?function(e,t){ue();try{return e.call(t,t)}catch(e){return Re(e,t,"data()"),{}}finally{le()}}(t,e):t||{})||(t={});var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);for(;i--;){var o=n[i];r&&y(r,o)||(a=void 0,36!==(a=(o+"").charCodeAt(0))&&95!==a&&fn(e,"_data",o))}var a;we(t,!0)}(e):we(e._data={},!0),t.computed&&function(e,t){var n=e._computedWatchers=Object.create(null),r=ee();for(var i in t){var o=t[i],a="function"==typeof o?o:o.get;r||(n[i]=new un(e,a||S,S,dn)),i in e||vn(e,i,o)}}(e,t.computed),t.watch&&t.watch!==X&&function(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i-1:"string"==typeof e?e.split(",").indexOf(t)>-1:(n=e,"[object RegExp]"===a.call(n)&&e.test(t));var n}function Cn(e,t){var n=e.cache,r=e.keys,i=e._vnode;for(var o in n){var a=n[o];if(a){var s=wn(a.componentOptions);s&&!t(s)&&An(n,o,r,i)}}}function An(e,t,n,r){var i=e[t];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),e[t]=null,h(n,t)}!function(t){t.prototype._init=function(t){var n=this;n._uid=gn++,n._isVue=!0,t&&t._isComponent?function(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r;var i=r.componentOptions;n.propsData=i.propsData,n._parentListeners=i.listeners,n._renderChildren=i.children,n._componentTag=i.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}(n,t):n.$options=Ne(_n(n.constructor),t||{},n),n._renderProxy=n,n._self=n,function(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}(n),function(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&Jt(e,t)}(n),function(t){t._vnode=null,t._staticTrees=null;var n=t.$options,r=t.$vnode=n._parentVnode,i=r&&r.context;t.$slots=ct(n._renderChildren,i),t.$scopedSlots=e,t._c=function(e,n,r,i){return Pt(t,e,n,r,i,!1)},t.$createElement=function(e,n,r,i){return Pt(t,e,n,r,i,!0)};var o=r&&r.data;xe(t,"$attrs",o&&o.attrs||e,null,!0),xe(t,"$listeners",n._parentListeners||e,null,!0)}(n),Xt(n,"beforeCreate"),function(e){var t=st(e.$options.inject,e);t&&(be(!1),Object.keys(t).forEach(function(n){xe(e,n,t[n])}),be(!0))}(n),pn(n),function(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}(n),Xt(n,"created"),n.$options.el&&n.$mount(n.$options.el)}}(bn),function(e){var t={get:function(){return this._data}},n={get:function(){return this._props}};Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=Ce,e.prototype.$delete=Ae,e.prototype.$watch=function(e,t,n){if(s(t))return yn(this,e,t,n);(n=n||{}).user=!0;var r=new un(this,e,t,n);if(n.immediate)try{t.call(this,r.value)}catch(e){Re(e,this,'callback for immediate watcher "'+r.expression+'"')}return function(){r.teardown()}}}(bn),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this;if(Array.isArray(e))for(var i=0,o=e.length;i1?A(t):t;for(var n=A(arguments,1),r='event handler for "'+e+'"',i=0,o=t.length;iparseInt(this.max)&&An(a,s[0],s,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}}};!function(e){var t={get:function(){return P}};Object.defineProperty(e,"config",t),e.util={warn:oe,extend:k,mergeOptions:Ne,defineReactive:xe},e.set=Ce,e.delete=Ae,e.nextTick=Xe,e.observable=function(e){return we(e),e},e.options=Object.create(null),I.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,k(e.options.components,On),function(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=A(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}(e),function(e){e.mixin=function(e){return this.options=Ne(this.options,e),this}}(e),$n(e),function(e){I.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&s(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}(e)}(bn),Object.defineProperty(bn.prototype,"$isServer",{get:ee}),Object.defineProperty(bn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(bn,"FunctionalRenderContext",{value:St}),bn.version="2.6.6";var Sn=p("style,class"),Tn=p("input,textarea,option,select,progress"),En=function(e,t,n){return"value"===n&&Tn(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},jn=p("contenteditable,draggable,spellcheck"),Nn=p("events,caret,typing,plaintext-only"),Ln=function(e,t){return Rn(t)||"false"===t?"false":"contenteditable"===e&&Nn(t)?t:"true"},Mn=p("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),In="http://www.w3.org/1999/xlink",Dn=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Pn=function(e){return Dn(e)?e.slice(6,e.length):""},Rn=function(e){return null==e||!1===e};function Fn(e){for(var t=e.data,r=e,i=e;n(i.componentInstance);)(i=i.componentInstance._vnode)&&i.data&&(t=Hn(i.data,t));for(;n(r=r.parent);)r&&r.data&&(t=Hn(t,r.data));return function(e,t){if(n(e)||n(t))return Bn(e,Un(t));return""}(t.staticClass,t.class)}function Hn(e,t){return{staticClass:Bn(e.staticClass,t.staticClass),class:n(e.class)?[e.class,t.class]:t.class}}function Bn(e,t){return e?t?e+" "+t:e:t||""}function Un(e){return Array.isArray(e)?function(e){for(var t,r="",i=0,o=e.length;i-1?dr(e,t,n):Mn(t)?Rn(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):jn(t)?e.setAttribute(t,Ln(t,n)):Dn(t)?Rn(n)?e.removeAttributeNS(In,Pn(t)):e.setAttributeNS(In,t,n):dr(e,t,n)}function dr(e,t,n){if(Rn(n))e.removeAttribute(t);else{if(J&&!q&&"TEXTAREA"===e.tagName&&"placeholder"===t&&""!==n&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}var vr={create:fr,update:fr};function hr(e,r){var i=r.elm,o=r.data,a=e.data;if(!(t(o.staticClass)&&t(o.class)&&(t(a)||t(a.staticClass)&&t(a.class)))){var s=Fn(r),c=i._transitionClasses;n(c)&&(s=Bn(s,Un(c))),s!==i._prevClass&&(i.setAttribute("class",s),i._prevClass=s)}}var mr,yr,gr,_r,br,$r,wr={create:hr,update:hr},xr=/[\w).+\-_$\]]/;function Cr(e){var t,n,r,i,o,a=!1,s=!1,c=!1,u=!1,l=0,f=0,p=0,d=0;for(r=0;r=0&&" "===(h=e.charAt(v));v--);h&&xr.test(h)||(u=!0)}}else void 0===i?(d=r+1,i=e.slice(0,r).trim()):m();function m(){(o||(o=[])).push(e.slice(d,r).trim()),d=r+1}if(void 0===i?i=e.slice(0,r).trim():0!==d&&m(),o)for(r=0;r-1?{exp:e.slice(0,_r),key:'"'+e.slice(_r+1)+'"'}:{exp:e,key:null};yr=e,_r=br=$r=0;for(;!Br();)Ur(gr=Hr())?Vr(gr):91===gr&&zr(gr);return{exp:e.slice(0,br),key:e.slice(br+1,$r)}}(e);return null===n.key?e+"="+t:"$set("+n.exp+", "+n.key+", "+t+")"}function Hr(){return yr.charCodeAt(++_r)}function Br(){return _r>=mr}function Ur(e){return 34===e||39===e}function zr(e){var t=1;for(br=_r;!Br();)if(Ur(e=Hr()))Vr(e);else if(91===e&&t++,93===e&&t--,0===t){$r=_r;break}}function Vr(e){for(var t=e;!Br()&&(e=Hr())!==t;);}var Kr,Jr="__r",qr="__c";function Wr(e,t,n){var r=Kr;return function i(){null!==t.apply(null,arguments)&&Xr(e,i,n,r)}}var Zr=ze&&!(G&&Number(G[1])<=53);function Gr(e,t,n,r){if(Zr){var i=on,o=t;t=o._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=i||0===e.timeStamp||e.target.ownerDocument!==document)return o.apply(this,arguments)}}Kr.addEventListener(e,t,Y?{capture:n,passive:r}:n)}function Xr(e,t,n,r){(r||Kr).removeEventListener(e,t._wrapper||t,n)}function Yr(e,r){if(!t(e.data.on)||!t(r.data.on)){var i=r.data.on||{},o=e.data.on||{};Kr=r.elm,function(e){if(n(e[Jr])){var t=J?"change":"input";e[t]=[].concat(e[Jr],e[t]||[]),delete e[Jr]}n(e[qr])&&(e.change=[].concat(e[qr],e.change||[]),delete e[qr])}(i),nt(i,o,Gr,Xr,Wr,r.context),Kr=void 0}}var Qr,ei={create:Yr,update:Yr};function ti(e,r){if(!t(e.data.domProps)||!t(r.data.domProps)){var i,o,a=r.elm,s=e.data.domProps||{},c=r.data.domProps||{};for(i in n(c.__ob__)&&(c=r.data.domProps=k({},c)),s)t(c[i])&&(a[i]="");for(i in c){if(o=c[i],"textContent"===i||"innerHTML"===i){if(r.children&&(r.children.length=0),o===s[i])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===i||o!==s[i])if("value"===i){a._value=o;var u=t(o)?"":String(o);ni(a,u)&&(a.value=u)}else if("innerHTML"===i&&Kn(a.tagName)&&t(a.innerHTML)){(Qr=Qr||document.createElement("div")).innerHTML=""+o+" ";for(var l=Qr.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else a[i]=o}}}function ni(e,t){return!e.composing&&("OPTION"===e.tagName||function(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}(e,t)||function(e,t){var r=e.value,i=e._vModifiers;if(n(i)){if(i.number)return f(r)!==f(t);if(i.trim)return r.trim()!==t.trim()}return r!==t}(e,t))}var ri={create:ti,update:ti},ii=g(function(e){var t={},n=/:(.+)/;return e.split(/;(?![^(]*\))/g).forEach(function(e){if(e){var r=e.split(n);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t});function oi(e){var t=ai(e.style);return e.staticStyle?k(e.staticStyle,t):t}function ai(e){return Array.isArray(e)?O(e):"string"==typeof e?ii(e):e}var si,ci=/^--/,ui=/\s*!important$/,li=function(e,t,n){if(ci.test(t))e.style.setProperty(t,n);else if(ui.test(n))e.style.setProperty(x(t),n.replace(ui,""),"important");else{var r=pi(t);if(Array.isArray(n))for(var i=0,o=n.length;i-1?t.split(hi).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function yi(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(hi).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?e.setAttribute("class",n):e.removeAttribute("class")}}function gi(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&k(t,_i(e.name||"v")),k(t,e),t}return"string"==typeof e?_i(e):void 0}}var _i=g(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),bi=U&&!q,$i="transition",wi="animation",xi="transition",Ci="transitionend",Ai="animation",ki="animationend";bi&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(xi="WebkitTransition",Ci="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Ai="WebkitAnimation",ki="webkitAnimationEnd"));var Oi=U?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()};function Si(e){Oi(function(){Oi(e)})}function Ti(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),mi(e,t))}function Ei(e,t){e._transitionClasses&&h(e._transitionClasses,t),yi(e,t)}function ji(e,t,n){var r=Li(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===$i?Ci:ki,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c0&&(n=$i,l=a,f=o.length):t===wi?u>0&&(n=wi,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?$i:wi:null)?n===$i?o.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===$i&&Ni.test(r[xi+"Property"])}}function Mi(e,t){for(;e.length1}function Hi(e,t){!0!==t.data.show&&Di(t)}var Bi=function(e){var o,a,s={},c=e.modules,u=e.nodeOps;for(o=0;ov?_(e,t(i[y+1])?null:i[y+1].elm,i,d,y,o):d>y&&$(0,r,p,v)}(p,h,y,o,l):n(y)?(n(e.text)&&u.setTextContent(p,""),_(p,null,y,0,y.length-1,o)):n(h)?$(0,h,0,h.length-1):n(e.text)&&u.setTextContent(p,""):e.text!==i.text&&u.setTextContent(p,i.text),n(v)&&n(d=v.hook)&&n(d=d.postpatch)&&d(e,i)}}}function A(e,t,i){if(r(i)&&n(e.parent))e.parent.data.pendingInsert=t;else for(var o=0;o-1,a.selected!==o&&(a.selected=o);else if(j(Ji(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function Ki(e,t){return t.every(function(t){return!j(t,e)})}function Ji(e){return"_value"in e?e._value:e.value}function qi(e){e.target.composing=!0}function Wi(e){e.target.composing&&(e.target.composing=!1,Zi(e.target,"input"))}function Zi(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Gi(e){return!e.componentInstance||e.data&&e.data.transition?e:Gi(e.componentInstance._vnode)}var Xi={model:Ui,show:{bind:function(e,t,n){var r=t.value,i=(n=Gi(n)).data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i?(n.data.show=!0,Di(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value;!r!=!t.oldValue&&((n=Gi(n)).data&&n.data.transition?(n.data.show=!0,r?Di(n,function(){e.style.display=e.__vOriginalDisplay}):Pi(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}}},Yi={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Qi(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?Qi(Ut(t.children)):e}function eo(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[b(o)]=i[o];return t}function to(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}var no=function(e){return e.tag||Bt(e)},ro=function(e){return"show"===e.name},io={name:"transition",props:Yi,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(no)).length){var r=this.mode,o=n[0];if(function(e){for(;e=e.parent;)if(e.data.transition)return!0}(this.$vnode))return o;var a=Qi(o);if(!a)return o;if(this._leaving)return to(e,o);var s="__transition-"+this._uid+"-";a.key=null==a.key?a.isComment?s+"comment":s+a.tag:i(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key;var c=(a.data||(a.data={})).transition=eo(this),u=this._vnode,l=Qi(u);if(a.data.directives&&a.data.directives.some(ro)&&(a.data.show=!0),l&&l.data&&!function(e,t){return t.key===e.key&&t.tag===e.tag}(a,l)&&!Bt(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=k({},c);if("out-in"===r)return this._leaving=!0,rt(f,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),to(e,o);if("in-out"===r){if(Bt(a))return u;var p,d=function(){p()};rt(c,"afterEnter",d),rt(c,"enterCancelled",d),rt(f,"delayLeave",function(e){p=e})}}return o}}},oo=k({tag:String,moveClass:String},Yi);function ao(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function so(e){e.data.newPos=e.elm.getBoundingClientRect()}function co(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}delete oo.mode;var uo={Transition:io,TransitionGroup:{props:oo,beforeMount:function(){var e=this,t=this._update;this._update=function(n,r){var i=Wt(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,i(),t.call(e,n,r)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=eo(this),s=0;s-1?Wn[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:Wn[e]=/HTMLUnknownElement/.test(t.toString())},k(bn.options.directives,Xi),k(bn.options.components,uo),bn.prototype.__patch__=U?Bi:S,bn.prototype.$mount=function(e,t){return function(e,t,n){var r;return e.$el=t,e.$options.render||(e.$options.render=de),Xt(e,"beforeMount"),r=function(){e._update(e._render(),n)},new un(e,r,S,{before:function(){e._isMounted&&!e._isDestroyed&&Xt(e,"beforeUpdate")}},!0),n=!1,null==e.$vnode&&(e._isMounted=!0,Xt(e,"mounted")),e}(this,e=e&&U?Gn(e):void 0,t)},U&&setTimeout(function(){P.devtools&&te&&te.emit("init",bn)},0);var lo=/\{\{((?:.|\r?\n)+?)\}\}/g,fo=/[-.*+?^${}()|[\]\/\\]/g,po=g(function(e){var t=e[0].replace(fo,"\\$&"),n=e[1].replace(fo,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")});var vo={staticKeys:["staticClass"],transformNode:function(e,t){t.warn;var n=Ir(e,"class");n&&(e.staticClass=JSON.stringify(n));var r=Mr(e,"class",!1);r&&(e.classBinding=r)},genData:function(e){var t="";return e.staticClass&&(t+="staticClass:"+e.staticClass+","),e.classBinding&&(t+="class:"+e.classBinding+","),t}};var ho,mo={staticKeys:["staticStyle"],transformNode:function(e,t){t.warn;var n=Ir(e,"style");n&&(e.staticStyle=JSON.stringify(ii(n)));var r=Mr(e,"style",!1);r&&(e.styleBinding=r)},genData:function(e){var t="";return e.staticStyle&&(t+="staticStyle:"+e.staticStyle+","),e.styleBinding&&(t+="style:("+e.styleBinding+"),"),t}},yo=function(e){return(ho=ho||document.createElement("div")).innerHTML=e,ho.textContent},go=p("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),_o=p("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),bo=p("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),$o=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,wo=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,xo="[a-zA-Z_][\\-\\.0-9_a-zA-Za-zA-Z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]*",Co="((?:"+xo+"\\:)?"+xo+")",Ao=new RegExp("^<"+Co),ko=/^\s*(\/?)>/,Oo=new RegExp("^<\\/"+Co+"[^>]*>"),So=/^]+>/i,To=/^",""":'"',"&":"&","
":"\n"," ":"\t","'":"'"},Mo=/&(?:lt|gt|quot|amp|#39);/g,Io=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,Do=p("pre,textarea",!0),Po=function(e,t){return e&&Do(e)&&"\n"===t[0]};function Ro(e,t){var n=t?Io:Mo;return e.replace(n,function(e){return Lo[e]})}var Fo,Ho,Bo,Uo,zo,Vo,Ko,Jo,qo=/^@|^v-on:/,Wo=/^v-|^@|^:/,Zo=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,Go=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Xo=/^\(|\)$/g,Yo=/^\[.*\]$/,Qo=/:(.*)$/,ea=/^:|^\.|^v-bind:/,ta=/\.[^.]+/g,na=/^v-slot(:|$)|^#/,ra=/[\r\n]/,ia=/\s+/g,oa=g(yo),aa="_empty_";function sa(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:va(t),rawAttrsMap:{},parent:n,children:[]}}function ca(e,t){Fo=t.warn||kr,Vo=t.isPreTag||T,Ko=t.mustUseProp||T,Jo=t.getTagNamespace||T;t.isReservedTag;Bo=Or(t.modules,"transformNode"),Uo=Or(t.modules,"preTransformNode"),zo=Or(t.modules,"postTransformNode"),Ho=t.delimiters;var n,r,i=[],o=!1!==t.preserveWhitespace,a=t.whitespace,s=!1,c=!1;function u(e){if(l(e),s||e.processed||(e=ua(e,t)),i.length||e===n||n.if&&(e.elseif||e.else)&&fa(n,{exp:e.elseif,block:e}),r&&!e.forbidden)if(e.elseif||e.else)a=e,(u=function(e){var t=e.length;for(;t--;){if(1===e[t].type)return e[t];e.pop()}}(r.children))&&u.if&&fa(u,{exp:a.elseif,block:a});else{if(e.slotScope){var o=e.slotTarget||'"default"';(r.scopedSlots||(r.scopedSlots={}))[o]=e}r.children.push(e),e.parent=r}var a,u;e.children=e.children.filter(function(e){return!e.slotScope}),l(e),e.pre&&(s=!1),Vo(e.tag)&&(c=!1);for(var f=0;f]*>)","i")),p=e.replace(f,function(e,n,r){return u=r.length,jo(l)||"noscript"===l||(n=n.replace(//g,"$1").replace(//g,"$1")),Po(l,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""});c+=e.length-p.length,e=p,k(l,c-u,c)}else{var d=e.indexOf("<");if(0===d){if(To.test(e)){var v=e.indexOf("--\x3e");if(v>=0){t.shouldKeepComment&&t.comment(e.substring(4,v),c,c+v+3),x(v+3);continue}}if(Eo.test(e)){var h=e.indexOf("]>");if(h>=0){x(h+2);continue}}var m=e.match(So);if(m){x(m[0].length);continue}var y=e.match(Oo);if(y){var g=c;x(y[0].length),k(y[1],g,c);continue}var _=C();if(_){A(_),Po(_.tagName,e)&&x(1);continue}}var b=void 0,$=void 0,w=void 0;if(d>=0){for($=e.slice(d);!(Oo.test($)||Ao.test($)||To.test($)||Eo.test($)||(w=$.indexOf("<",1))<0);)d+=w,$=e.slice(d);b=e.substring(0,d)}d<0&&(b=e),b&&x(b.length),t.chars&&b&&t.chars(b,c-b.length,c)}if(e===n){t.chars&&t.chars(e);break}}function x(t){c+=t,e=e.substring(t)}function C(){var t=e.match(Ao);if(t){var n,r,i={tagName:t[1],attrs:[],start:c};for(x(t[0].length);!(n=e.match(ko))&&(r=e.match(wo)||e.match($o));)r.start=c,x(r[0].length),r.end=c,i.attrs.push(r);if(n)return i.unarySlash=n[1],x(n[0].length),i.end=c,i}}function A(e){var n=e.tagName,c=e.unarySlash;o&&("p"===r&&bo(n)&&k(r),s(n)&&r===n&&k(n));for(var u=a(n)||!!c,l=e.attrs.length,f=new Array(l),p=0;p=0&&i[a].lowerCasedTag!==s;a--);else a=0;if(a>=0){for(var u=i.length-1;u>=a;u--)t.end&&t.end(i[u].tag,n,o);i.length=a,r=a&&i[a-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,o):"p"===s&&(t.start&&t.start(e,[],!1,n,o),t.end&&t.end(e,n,o))}k()}(e,{warn:Fo,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,shouldDecodeNewlinesForHref:t.shouldDecodeNewlinesForHref,shouldKeepComment:t.comments,outputSourceRange:t.outputSourceRange,start:function(e,o,a,l){var f=r&&r.ns||Jo(e);J&&"svg"===f&&(o=function(e){for(var t=[],n=0;nc&&(s.push(o=e.slice(c,i)),a.push(JSON.stringify(o)));var u=Cr(r[1].trim());a.push("_s("+u+")"),s.push({"@binding":u}),c=i+r[0].length}return c-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),Lr(e,"change","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+Fr(t,"$$a.concat([$$v])")+")}else{$$i>-1&&("+Fr(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+Fr(t,"$$c")+"}",null,!0)}(e,r,i);else if("input"===o&&"radio"===a)!function(e,t,n){var r=n&&n.number,i=Mr(e,"value")||"null";Sr(e,"checked","_q("+t+","+(i=r?"_n("+i+")":i)+")"),Lr(e,"change",Fr(t,i),null,!0)}(e,r,i);else if("input"===o||"textarea"===o)!function(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?Jr:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=Fr(t,l);c&&(f="if($event.target.composing)return;"+f),Sr(e,"value","("+t+")"),Lr(e,u,f,null,!0),(s||a)&&Lr(e,"blur","$forceUpdate()")}(e,r,i);else if(!P.isReservedTag(o))return Rr(e,r,i),!1;return!0},text:function(e,t){t.value&&Sr(e,"textContent","_s("+t.value+")",t)},html:function(e,t){t.value&&Sr(e,"innerHTML","_s("+t.value+")",t)}},isPreTag:function(e){return"pre"===e},isUnaryTag:go,mustUseProp:En,canBeLeftOpenTag:_o,isReservedTag:Jn,getTagNamespace:qn,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}(ga)},wa=g(function(e){return p("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(e?","+e:""))});function xa(e,t){e&&(_a=wa(t.staticKeys||""),ba=t.isReservedTag||T,function e(t){t.static=function(e){if(2===e.type)return!1;if(3===e.type)return!0;return!(!e.pre&&(e.hasBindings||e.if||e.for||d(e.tag)||!ba(e.tag)||function(e){for(;e.parent;){if("template"!==(e=e.parent).tag)return!1;if(e.for)return!0}return!1}(e)||!Object.keys(e).every(_a)))}(t);if(1===t.type){if(!ba(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var n=0,r=t.children.length;n|^function\s*\(/,Aa=/\([^)]*?\);*$/,ka=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,Oa={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},Sa={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},Ta=function(e){return"if("+e+")return null;"},Ea={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:Ta("$event.target !== $event.currentTarget"),ctrl:Ta("!$event.ctrlKey"),shift:Ta("!$event.shiftKey"),alt:Ta("!$event.altKey"),meta:Ta("!$event.metaKey"),left:Ta("'button' in $event && $event.button !== 0"),middle:Ta("'button' in $event && $event.button !== 1"),right:Ta("'button' in $event && $event.button !== 2")};function ja(e,t){var n=t?"nativeOn:":"on:",r="",i="";for(var o in e){var a=Na(e[o]);e[o]&&e[o].dynamic?i+=o+","+a+",":r+='"'+o+'":'+a+","}return r="{"+r.slice(0,-1)+"}",i?n+"_d("+r+",["+i.slice(0,-1)+"])":n+r}function Na(e){if(!e)return"function(){}";if(Array.isArray(e))return"["+e.map(function(e){return Na(e)}).join(",")+"]";var t=ka.test(e.value),n=Ca.test(e.value),r=ka.test(e.value.replace(Aa,""));if(e.modifiers){var i="",o="",a=[];for(var s in e.modifiers)if(Ea[s])o+=Ea[s],Oa[s]&&a.push(s);else if("exact"===s){var c=e.modifiers;o+=Ta(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(i+=function(e){return"if(!$event.type.indexOf('key')&&"+e.map(La).join("&&")+")return null;"}(a)),o&&(i+=o),"function($event){"+i+(t?"return "+e.value+"($event)":n?"return ("+e.value+")($event)":r?"return "+e.value:e.value)+"}"}return t||n?e.value:"function($event){"+(r?"return "+e.value:e.value)+"}"}function La(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=Oa[e],r=Sa[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}var Ma={on:function(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}},bind:function(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+","+(t.modifiers&&t.modifiers.prop?"true":"false")+(t.modifiers&&t.modifiers.sync?",true":"")+")"}},cloak:S},Ia=function(e){this.options=e,this.warn=e.warn||kr,this.transforms=Or(e.modules,"transformCode"),this.dataGenFns=Or(e.modules,"genData"),this.directives=k(k({},Ma),e.directives);var t=e.isReservedTag||T;this.maybeComponent=function(e){return!!e.component||!t(e.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1};function Da(e,t){var n=new Ia(t);return{render:"with(this){return "+(e?Pa(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function Pa(e,t){if(e.parent&&(e.pre=e.pre||e.parent.pre),e.staticRoot&&!e.staticProcessed)return Ra(e,t);if(e.once&&!e.onceProcessed)return Fa(e,t);if(e.for&&!e.forProcessed)return Ba(e,t);if(e.if&&!e.ifProcessed)return Ha(e,t);if("template"!==e.tag||e.slotTarget||t.pre){if("slot"===e.tag)return function(e,t){var n=e.slotName||'"default"',r=Ka(e,t),i="_t("+n+(r?","+r:""),o=e.attrs||e.dynamicAttrs?Wa((e.attrs||[]).concat(e.dynamicAttrs||[]).map(function(e){return{name:b(e.name),value:e.value,dynamic:e.dynamic}})):null,a=e.attrsMap["v-bind"];!o&&!a||r||(i+=",null");o&&(i+=","+o);a&&(i+=(o?"":",null")+","+a);return i+")"}(e,t);var n;if(e.component)n=function(e,t,n){var r=t.inlineTemplate?null:Ka(t,n,!0);return"_c("+e+","+Ua(t,n)+(r?","+r:"")+")"}(e.component,e,t);else{var r;(!e.plain||e.pre&&t.maybeComponent(e))&&(r=Ua(e,t));var i=e.inlineTemplate?null:Ka(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(i?","+i:"")+")"}for(var o=0;o ':'
',Qa.innerHTML.indexOf("
")>0}var rs=!!U&&ns(!1),is=!!U&&ns(!0),os=g(function(e){var t=Gn(e);return t&&t.innerHTML}),as=bn.prototype.$mount;return bn.prototype.$mount=function(e,t){if((e=e&&Gn(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=os(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=function(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}(e));if(r){var i=ts(r,{outputSourceRange:!1,shouldDecodeNewlines:rs,shouldDecodeNewlinesForHref:is,delimiters:n.delimiters,comments:n.comments},this),o=i.render,a=i.staticRenderFns;n.render=o,n.staticRenderFns=a}}return as.call(this,e,t)},bn.compile=ts,bn});
--------------------------------------------------------------------------------
/inst/htmlwidgets/vue.js:
--------------------------------------------------------------------------------
1 | HTMLWidgets.widget({
2 |
3 | name: 'vue',
4 |
5 | type: 'output',
6 |
7 | factory: function(el, width, height) {
8 |
9 | // TODO: define shared variables for this instance
10 | var app = {};
11 | Vue.config.devtools = true;
12 |
13 | return {
14 |
15 | renderValue: function(x) {
16 | if (x.html !== ""){
17 | el.innerHTML = x.html;
18 | }
19 | // x.app.el = "#" + el.id;
20 | app = new Vue(x.app);
21 | },
22 |
23 | resize: function(width, height) {
24 |
25 | // TODO: code to re-render the widget with a new size
26 |
27 | },
28 |
29 | getApp: function(){
30 | return(app);
31 | }
32 |
33 | };
34 | }
35 | });
36 |
37 | function get_vue_app(id){
38 |
39 | var htmlWidgetsObj = HTMLWidgets.find("#" + id);
40 |
41 | var app;
42 |
43 | if (typeof htmlWidgetsObj != 'undefined') {
44 | app = htmlWidgetsObj.getApp();
45 | }
46 |
47 | return(app);
48 | }
49 |
50 | if (HTMLWidgets.shinyMode) {
51 | Shiny.addCustomMessageHandler('updateProp',
52 | function(message) {
53 | console.log(JSON.stringify(message));
54 | // var app = HTMLWidgets.find("#" + message.id).getApp();
55 | var app = get_vue_app(message.id);
56 | var data = message.data;
57 | if (typeof app != 'undefined'){
58 | message.data.map(d => app[d.name] = d.value);
59 | }
60 | });
61 | }
62 |
--------------------------------------------------------------------------------
/inst/htmlwidgets/vue.yaml:
--------------------------------------------------------------------------------
1 | dependencies:
2 | - name: vue
3 | version: 2.6.6
4 | src: htmlwidgets/lib/vue
5 | script: vue.js
6 |
--------------------------------------------------------------------------------
/man/appendDependencies.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{appendDependencies}
4 | \alias{appendDependencies}
5 | \title{Append html dependencies}
6 | \usage{
7 | appendDependencies(x, value)
8 | }
9 | \description{
10 | NOTE: This function has been copied over from shinydashboard
11 | }
12 |
--------------------------------------------------------------------------------
/man/pipe.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils-pipe.R
3 | \name{\%>\%}
4 | \alias{\%>\%}
5 | \title{Pipe operator}
6 | \usage{
7 | lhs \%>\% rhs
8 | }
9 | \description{
10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details.
11 | }
12 | \keyword{internal}
13 |
--------------------------------------------------------------------------------
/man/vtag.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{vtag}
4 | \alias{vtag}
5 | \title{Vue Tag}
6 | \usage{
7 | vtag(`_tag_name`, varArgs)
8 | }
9 | \description{
10 | Vue Tag
11 | }
12 | \examples{
13 | vtag("input", list(type = "text", vmodel = "message"))
14 | }
15 |
--------------------------------------------------------------------------------
/man/vue.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/vue.R
3 | \name{Vue}
4 | \alias{Vue}
5 | \title{Create a Vue App}
6 | \usage{
7 | Vue(html, data = list(), dependencies = list(), ...,
8 | elementId = NULL)
9 | }
10 | \description{
11 | Create a Vue App
12 | }
13 | \examples{
14 | library(htmltools)
15 | tags$div(
16 | tags$label('Enter your name'),
17 | tags$input(type = "text", "v-model" = "name"),
18 | tags$p("Hello {{name}}")
19 | ) \%>\%
20 | Vue(data = list(name = ""))
21 |
22 | if (interactive()){
23 | library(shiny)
24 | ui <- tags$div(
25 | tags$label('Enter your name'),
26 | tags$input(type = "text", "v-model" = "name"),
27 | textOutput("greeting")
28 | ) \%>\%
29 | Vue(data = list(name_ = ""))
30 | server <- function(input, output, session){
31 | output$greeting <- renderText({
32 | paste("Hello", input$name)
33 | })
34 | }
35 | shinyApp(ui = ui, server = server)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/man/vueProxy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/vue.R
3 | \name{vueProxy}
4 | \alias{vueProxy}
5 | \alias{vueUpdateData}
6 | \title{Send commands to a Vue instance in a Shiny app}
7 | \usage{
8 | vueProxy(outputId, session = shiny::getDefaultReactiveDomain(),
9 | deferUntilFlush = TRUE)
10 |
11 | vueUpdateData(proxy, ...)
12 | }
13 | \description{
14 | Send commands to a Vue instance in a Shiny app
15 |
16 | Update data in a Vue instance
17 | }
18 | \examples{
19 | ui <- div(
20 | tags$label("Enter username"),
21 | tags$input(type = 'text', "v-model" = "username"),
22 | tags$p("Vue -> Vue: Hello {{username}}"),
23 | actionButton("set_name", "Shiny -> Vue"),
24 | verbatimTextOutput("username")
25 | ) \%>\%
26 | vue(
27 | data = list(username = ""),
28 | # Vue UI -> Shiny UI
29 | watch = vue_watch("username"),
30 | elementId = "app"
31 | )
32 | server <- function(input, output, session){
33 | # Shiny server -> Vue UI
34 | observeEvent(input$set_name, {
35 | vueProxy("app") \%>\%
36 | updateProp("username", "Ramnath")
37 | })
38 | output$username <- renderPrint({
39 | paste("Vue -> Shiny:", input$username)
40 | })
41 | }
42 | shiny::shinyApp(ui = ui, server = server)
43 | }
44 |
--------------------------------------------------------------------------------
/man/vueUpdateShinyInputs.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/vue.R
3 | \name{vueUpdateShinyInputs}
4 | \alias{vueUpdateShinyInputs}
5 | \title{Update Shiny Input}
6 | \usage{
7 | vueUpdateShinyInputs(...)
8 | }
9 | \description{
10 | Update Shiny Input
11 | }
12 |
--------------------------------------------------------------------------------
/man/vueUsePlugin.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{vueUsePlugin}
4 | \alias{vueUsePlugin}
5 | \title{Use a vue Plugin}
6 | \usage{
7 | vueUsePlugin(fun)
8 | }
9 | \description{
10 | Use a vue Plugin
11 | }
12 |
--------------------------------------------------------------------------------
/vuer.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: knitr
13 | LaTeX: XeLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source
21 | PackageRoxygenize: rd,collate,namespace
22 |
--------------------------------------------------------------------------------