diff --git a/DESCRIPTION b/DESCRIPTION index ee67411..25a9af3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: rclipboard Title: Shiny/R Wrapper for 'clipboard.js' -Version: 0.1.6 +Version: 0.2.0 Author: Sebastien Bihorel Maintainer: Sebastien Bihorel Description: Leverages the functionality of 'clipboard.js', a JavaScript library @@ -14,4 +14,4 @@ Encoding: UTF-8 LazyData: true URL: https://github.com/sbihorel/rclipboard/ BugReports: https://github.com/sbihorel/rclipboard/issues/ -Imports: shiny +Imports: shiny, bslib diff --git a/NAMESPACE b/NAMESPACE index 8206113..478e2c7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,2 +1,3 @@ export('rclipboardSetup', 'rclipButton', 'rclipLink') -importFrom('shiny', 'actionButton', 'actionLink', 'singleton', 'tagList', 'tags') \ No newline at end of file +importFrom('shiny', 'actionButton', 'actionLink', 'singleton', 'tagList', 'tags', 'validate', 'need') +importFrom('bslib', 'tooltip') \ No newline at end of file diff --git a/NEWS b/NEWS index 2ddadda..dcded77 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,13 @@ -Version 0.1.4 +Version 0.2.0 +* Support for bslib::tooltip +* Upgrade to clipboard.js v2.0.11 + +Version 0.1.6 +* Bug fix +Version 0.1.5 +* Bug fix + +Version 0.1.4 * Add rclipLink * Upgrade to clipboard.js v2.0.8 \ No newline at end of file diff --git a/R/rclipButton.R b/R/rclipButton.R index 100318a..74b4d16 100644 --- a/R/rclipButton.R +++ b/R/rclipButton.R @@ -1,12 +1,54 @@ -rclip_fun <- function(FUN = actionButton, inputId, label, clipText, modal = FALSE, ...) -{ - tagList( - FUN( +rclip_fun <- function( + FUN = actionButton, + inputId, + label, + clipText, + tooltip, + placement, + options, + modal = FALSE, + ... +) { + + if ( !missing(tooltip) && length(tooltip) > 0 ){ + shiny::validate( + shiny::need( is.character(tooltip), message = 'tooltip must be a character string' ) + ) + if ( !missing(placement) && length(placement) > 0){ + shiny::validate( + shiny::need( is.character(placement), message = 'placement must be a character string' ) + ) + } else { + placement <- 'auto' + } + if ( !missing(options) && length(options) > 0){ + shiny::validate( + shiny::need( is.list(options), message = 'options must be a list') + ) + } else { + options <- list() + } + btn <- bslib::tooltip( + FUN( + inputId = inputId, + label = label, + ..., + `data-clipboard-text` = clipText + ), + tooltip[1], + placement = placement[1], + options = options + ) + } else { + btn <- FUN( inputId = inputId, label = label, ..., `data-clipboard-text` = clipText - ), + ) + } + tagList( + btn, tags$script( sprintf( ifelse( @@ -20,9 +62,18 @@ rclip_fun <- function(FUN = actionButton, inputId, label, clipText, modal = FALS ) } -rclipButton <- function(inputId, label, clipText, modal = FALSE, ...) -{ - rclip_fun(actionButton, inputId, label, clipText, modal = modal, ...) +rclipButton <- function( + inputId, + label, + clipText, + modal = FALSE, + tooltip, + placement, + options, + ... + ){ + rclip_fun(actionButton, inputId, label, clipText, modal = modal, + tooltip = tooltip, placement = placement, options = options,...) } rclipLink <- function(inputId, label, clipText, modal = FALSE, ...) diff --git a/R/rclipboardSetup.R b/R/rclipboardSetup.R index 4466531..108da4a 100644 --- a/R/rclipboardSetup.R +++ b/R/rclipboardSetup.R @@ -7,5 +7,4 @@ rclipboardSetup <- function() ) ) ) -} - +} \ No newline at end of file diff --git a/README.md b/README.md index d453cb5..6470bae 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,35 @@ -# rclipboard: clipboard.js for R/Shiny Applications + +[![CRAN status](https://www.r-pkg.org/badges/version/rclipboard)](https://CRAN.R-project.org/package=rclipboard) +[![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) + + +# rclipboard: clipboard.js for R/Shiny applications -### Introduction [clipboard.js](https://clipboardjs.com/) is a super light javascript framework, which provides copy-to-clipboard functionality using HTML5. The simple `rclipboard` R package is simple and leverages `clipboard.js` functionality to provide a reactive copy-to-clipboard UI button component, called `rclipButton`, and a reactive copy-to-clipboard UI link component, called `rclipLink`, for -[Shiny](https://shiny.rstudio.com/) R applications. - -### Example - -This example works when deployed on a Shiny server or when it is run from -RStudio. However, because of limitations in the web engine of RStudio versions -prior to 1.2, the rclipButton does not work natively when the application is run -locally. A workaround must be implemented in the form of an observeEvent associated -to the rclipButton and using the clipr function from the clipr package. - -This workaround is not required if you run your applications in RStudio versions -\>= 1.2. +[Shiny](https://shiny.posit.co/) R applications. +While `rclipButton` and `rclipLink` will work in applications that use native +`shiny` UI constructors, the code below illustrates a marginally more complex +example in which a tooltip is displayed when hovering on top of the button thanks +to the use of UI constructors from the `bslib` package. ```R -library(rclipboard) library(shiny) +library(bslib) +library(rclipboard) # The UI -ui <- bootstrapPage( +ui <- bslib::page_fluid( rclipboardSetup(), # Add a text input textInput("copytext", "Copy this:", "Zlika!"), - + # UI ouputs for the copy-to-clipboard buttons uiOutput("clip"), @@ -42,26 +40,21 @@ ui <- bootstrapPage( # The server server <- function(input, output) { - + # Add clipboard buttons output$clip <- renderUI({ - output$clip <- renderUI({ - rclipButton( - inputId = "clipbtn", - label = "rclipButton Copy", - clipText = input$copytext, - icon = icon("clipboard") - ) - }) + rclipButton( + inputId = "clipbtn", + label = "rclipButton Copy", + clipText = input$copytext, + icon = icon("clipboard"), + tooltip = "Click me... I dare you!", + placement = "top", + options = list(delay = list(show = 800, hide = 100), trigger = "hover") + ) }) - # Workaround for execution within RStudio version < 1.2 - if (interactive()){ - observeEvent(input$clipbtn, clipr::write_clip(input$copytext)) - } - } shinyApp(ui = ui, server = server) - ``` diff --git a/man/rclipButton.Rd b/man/rclipButton.Rd index 79669b2..74cb0e3 100644 --- a/man/rclipButton.Rd +++ b/man/rclipButton.Rd @@ -4,7 +4,7 @@ \title{Action button or action link to send information to clipboard} \description{Creates an action button or link that will send user-defined text to the OS clipboard.} \usage{ -rclipButton(inputId, label, clipText, modal = FALSE, ...) +rclipButton(inputId, label, clipText, modal = FALSE, tooltip, placement, options, ...) rclipLink(inputId, label, clipText, modal = FALSE, ...) } \arguments{ @@ -14,14 +14,17 @@ rclipLink(inputId, label, clipText, modal = FALSE, ...) \item{clipText}{A single scalar character variable to be sent to the clipboard.} \item{modal}{A logical flag indicating whether the button will be shown in a modal window (TRUE) or not (NOT).} + \item{tooltip}{A strip to display in a tooltip (using the \code{bslib} package)} + \item{placement}{The placement of the tooltip relative to the button} + \item{options}{List of options for the tooltip} \item{...}{Additional arguments (e.g. \code{icon} or \code{width}) passed down - to \code{\link[shiny]{actionButton}} or \code{\link[shiny]{actionLink}}.} + to \code{\link[shiny]{actionButton}} or \code{\link[shiny]{actionLink}}. } } \references{ https://clipboardjs.com/ } \seealso{ - \code{\link{rclipboardSetup}} + \code{\link{rclipboardSetup}}, \code{\link[bslib]{tooltip}} } \author{ Sebastien Bihorel @@ -57,7 +60,10 @@ server <- function(input, output) { inputId = "clipbtn", label = "rclipButton Copy", clipText = input$copytext, - icon = icon("clipboard")) + icon = icon("clipboard"), + tooltip = "Click me to copy the content of the text field to the clipboard!", + options = list(delay = list(show = 800, hide = 100), trigger = "hover") + ) }) }