| Title: | A Shiny Dashboard Template Modular System with Chat Bot Support |
|---|---|
| Description: | A template dashboard system with AI agent integrated. Comes with default themes that can be customized. Developers can upload modified templates on 'Github', and users can easily download templates with 'RStudio' project wizard. The key features of the default template include light and dark theme switcher, resizing graphs, synchronizing inputs across sessions, new notification system, fancy progress bars, and card-like flip panels with back sides, as well as various of 'HTML' tool widgets. |
| Authors: | Zhengjia Wang [cph, aut, cre] (ORCID: <https://orcid.org/0000-0001-5629-1116>), ColorlibHQ [cph] (AdminLTE - Bootstrap 4 Admin Dashboard), Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Ivan Sagalaev [ctb, cph] (highlight.js library), Rene Haas [ctb, cph] (OverlayScrollbars library), Zeno Rocha [ctb, cph] (Clipboard.js library) |
| Maintainer: | Zhengjia Wang <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-05-11 09:37:23 UTC |
| Source: | https://github.com/dipterix/shidashi |
Generates an 'accordion' tab-set that only one tab is expanded at a time. This feature is experimental and has bugs in some situations. Please use it at your own risk.
accordion( ..., id = rand_string(prefix = "accordion-"), class = NULL, style_header = NULL, style_body = NULL, env = parent.frame(), extras = list(), root_path = template_root() ) accordion_operate( id, itemId, item_title, method = c("expand", "collapse", "toggle"), session = shiny::getDefaultReactiveDomain() )accordion( ..., id = rand_string(prefix = "accordion-"), class = NULL, style_header = NULL, style_body = NULL, env = parent.frame(), extras = list(), root_path = template_root() ) accordion_operate( id, itemId, item_title, method = c("expand", "collapse", "toggle"), session = shiny::getDefaultReactiveDomain() )
... |
'accordion' items, generated by |
id |
the element id, must be unique |
class |
the additional 'HTML' class |
style_header |
additional 'CSS' styles for header |
style_body |
additional 'CSS' styles for content body |
env |
environment to evaluate |
extras |
key-value pairs that overrides the parameters in
|
root_path |
see |
itemId |
|
item_title |
|
method |
operation, choices are |
session |
|
'shiny.tag.list' 'HTML' tags
if(interactive()) { library(shiny) library(shidashi) accordion( id = "input-set", accordion_item( title = "Input Group A", textInput("input_1", "Input 1"), collapsed = FALSE, footer = "Anim pariatur cliche reprehenderit dolor brunch." ), accordion_item( title = "Input Group B", textInput("input_2", "Input 2"), footer = actionButton("btn1", "OK"), collapsed = FALSE ) ) }if(interactive()) { library(shiny) library(shidashi) accordion( id = "input-set", accordion_item( title = "Input Group A", textInput("input_1", "Input 1"), collapsed = FALSE, footer = "Anim pariatur cliche reprehenderit dolor brunch." ), accordion_item( title = "Input Group B", textInput("input_2", "Input 2"), footer = actionButton("btn1", "OK"), collapsed = FALSE ) ) }
'Accordion' items
accordion_item( title, ..., footer = NULL, class = "", collapsed = TRUE, parentId = rand_string(prefix = "accordion-"), itemId = rand_string(prefix = "accordion-item-"), style_header = NULL, style_body = NULL, root_path = template_root() )accordion_item( title, ..., footer = NULL, class = "", collapsed = TRUE, parentId = rand_string(prefix = "accordion-"), itemId = rand_string(prefix = "accordion-item-"), style_header = NULL, style_body = NULL, root_path = template_root() )
title |
character title to show in the header |
... |
body content |
footer |
footer element, hidden if |
class |
the class of the item |
collapsed |
whether collapsed at the beginning |
parentId |
parent |
itemId |
the item id |
style_header, style_body
|
'CSS' style of item header and body |
root_path |
see |
'shiny.tag.list' 'HTML' tags
Only works in template framework provided by 'shidashi' package,
see use_template
add_class(selector, class, session = shiny::getDefaultReactiveDomain()) remove_class(selector, class, session = shiny::getDefaultReactiveDomain())add_class(selector, class, session = shiny::getDefaultReactiveDomain()) remove_class(selector, class, session = shiny::getDefaultReactiveDomain())
selector |
'CSS' selector |
class |
class to add or to remove from selected elements |
session |
shiny session |
No value is returned
server <- function(input, output, session) { # Add class `hidden` to element with ID `elemid` add_class("#elemid", "hidden") # Remove class `hidden` from element with class `shiny-input-optional` remove_class(".shiny-input-optional", "hidden") }server <- function(input, output, session) { # Add class `hidden` to element with ID `elemid` add_class("#elemid", "hidden") # Remove class `hidden` from element with class `shiny-input-optional` remove_class(".shiny-input-optional", "hidden") }
These functions should be called in 'HTML' templates. Please see vignettes for details.
adminlte_ui(root_path = template_root()) adminlte_sidebar( root_path = template_root(), settings_file = "modules.yaml", shared_id = rand_string(26) )adminlte_ui(root_path = template_root()) adminlte_sidebar( root_path = template_root(), settings_file = "modules.yaml", shared_id = rand_string(26) )
root_path |
the root path of the website project; see
|
settings_file |
the settings file containing the module information |
shared_id |
a shared identification by session to synchronize the inputs; assigned internally. |
'HTML' tags
Usually used along with card,
card2, and card_tabset. See tools
parameters in these functions accordingly.
as_badge(badge = NULL)as_badge(badge = NULL)
badge |
characters, |
When badge is NULL or empty, then as_badge
returns empty strings. When badge is a "shiny.tag" object,
then 'HTML' class 'right' and 'badge' will be appended.
When badge is a string, it should follow the syntax of
"message|class". The text before "|" will be the badge
message, and the text after the "|" becomes the class string.
'HTML' tags
# Basic usage as_badge("New") # Add class `bg-red` and `no-padding` as_badge("New|bg-red no-padding")# Basic usage as_badge("New") # Add class `bg-red` and `no-padding` as_badge("New|bg-red no-padding")
Convert characters, shiny icons into 'fontawesome' 4
as_icon(icon = NULL, class = "fas")as_icon(icon = NULL, class = "fas")
icon |
character or |
class |
icon class; change this when you are using 'fontawesome'
professional version. The choices are |
'HTML' tag
if(interactive()) { as_icon("bookmark", class = "far") as_icon("bookmark", class = "fas") # no icon as_icon(NULL) }if(interactive()) { as_icon("bookmark", class = "far") as_icon("bookmark", class = "fas") # no icon as_icon(NULL) }
This function is a template function that should be called
in 'HTML' templates before closing the "</body>" tag.
When open_drawer = TRUE, an additional button is rendered
that fires a "button.click" shidashi-event with
type = "open_drawer".
Module server code (or chatbot_server) can observe
this event via get_event and call
drawer_open / shiny::renderUI to fill the
drawer with content.
back_top_button( icon = "chevron-up", title = "Jump to", open_drawer = TRUE, drawer_icon = "ellipsis" )back_top_button( icon = "chevron-up", title = "Jump to", open_drawer = TRUE, drawer_icon = "ellipsis" )
icon |
the icon for back-to-top button |
title |
the expanded menu title |
open_drawer |
logical; whether to include a drawer-toggle
button. Defaults to |
drawer_icon |
the icon for the drawer-toggle button;
defaults to |
'HTML' tags
back_top_button() back_top_button("rocket") back_top_button("rocket", drawer_icon = "robot")back_top_button() back_top_button("rocket") back_top_button("rocket", drawer_icon = "robot")
Returns Bootstrap 5 HTML dependencies provided by
bslib. Intended to be called from HTML templates so that
headContent() renders Bootstrap 5 CSS and JavaScript.
bslib_dependency(...)bslib_dependency(...)
... |
additional arguments passed to |
An tagList containing Bootstrap 5 dependencies
Card-like 'HTML' element
card( title, ..., footer = NULL, tools = NULL, inputId = NULL, class = "", class_header = "", class_body = "", class_foot = "", style_header = NULL, style_body = NULL, start_collapsed = FALSE, resizable = FALSE, root_path = template_root() ) card2( title, body_main, body_side = NULL, footer = NULL, tools = NULL, inputId = NULL, class = "", class_header = "", class_body = "min-height-400", class_foot = "", style_header = NULL, style_body = NULL, start_collapsed = FALSE, root_path = template_root() ) card2_open(inputId, session = shiny::getDefaultReactiveDomain()) card2_close(inputId, session = shiny::getDefaultReactiveDomain()) card2_toggle(inputId, session = shiny::getDefaultReactiveDomain()) card_operate( inputId, title, method, session = shiny::getDefaultReactiveDomain() )card( title, ..., footer = NULL, tools = NULL, inputId = NULL, class = "", class_header = "", class_body = "", class_foot = "", style_header = NULL, style_body = NULL, start_collapsed = FALSE, resizable = FALSE, root_path = template_root() ) card2( title, body_main, body_side = NULL, footer = NULL, tools = NULL, inputId = NULL, class = "", class_header = "", class_body = "min-height-400", class_foot = "", style_header = NULL, style_body = NULL, start_collapsed = FALSE, root_path = template_root() ) card2_open(inputId, session = shiny::getDefaultReactiveDomain()) card2_close(inputId, session = shiny::getDefaultReactiveDomain()) card2_toggle(inputId, session = shiny::getDefaultReactiveDomain()) card_operate( inputId, title, method, session = shiny::getDefaultReactiveDomain() )
title |
the title of the card |
... |
the body content of the card |
footer |
the footer of the card; will be hidden if
|
tools |
a list of tools or badges to be displayed at
top-right corner, generated by |
inputId |
the id of the card |
class |
the 'HTML' class of the entire card |
class_header |
the the 'HTML' class of the card header |
class_body |
the the 'HTML' class of the card body |
class_foot |
the the 'HTML' class of the card footer |
style_header |
'CSS' style of the header |
style_body |
'CSS' style of the body |
start_collapsed |
whether the card starts as collapsed |
resizable |
whether the card body can be resized vertically; notice that if true, then the default padding for body will be zero |
root_path |
see |
body_main, body_side
|
used by |
session |
shiny session domain |
method |
action to expand, minimize, or remove the cards;
choices are |
'HTML' tags
library(shiny) library(shidashi) # Used for example only ns <- I session <- MockShinySession$new() # -------------- Basic usage ------------- card( title = "Badges", div( class = "padding-20", p( "Add badges to the top-right corder. ", "Use \"|\" to indicate the badge classes; ", "for example: \"badge-info\", \"badge-warning\"..." ), hr(), p( "Use `resizable = TRUE` to make card resizable." ) ), tools = list( as_badge("New|badge-info"), as_badge("3|badge-warning") ), class_body = "height-300", resizable = TRUE ) # ---------------- With tools ----------------- card( title = "Default Tools", plotOutput( ns("card_defaulttool_plot"), height = "100%" ), tools = list( card_tool( widget = "link", href = "https://github.com/dipterix" ), card_tool(widget = "collapse"), card_tool(widget = "maximize") ), class_body = "height-300", resizable = TRUE ) # -------------- Card2 example -------------- card2( title = "Card2 Example", body_main = plotOutput( outputId = ns("card2_plot"), height = "100%" ), body_side = fluidRow( column( 6L, textInput( ns("card2_plot_title"), "Plot title" ) ), column( 6L, sliderInput( ns("card2_plot_npts"), "# of points", min = 1, max = 100, value = 10, step = 1, round = TRUE ) ) ), tools = list( card_tool(widget = "link", href = "https://github.com/dipterix"), card_tool(widget = "collapse"), card_tool(widget = "maximize") ), class_body = "height-300" )library(shiny) library(shidashi) # Used for example only ns <- I session <- MockShinySession$new() # -------------- Basic usage ------------- card( title = "Badges", div( class = "padding-20", p( "Add badges to the top-right corder. ", "Use \"|\" to indicate the badge classes; ", "for example: \"badge-info\", \"badge-warning\"..." ), hr(), p( "Use `resizable = TRUE` to make card resizable." ) ), tools = list( as_badge("New|badge-info"), as_badge("3|badge-warning") ), class_body = "height-300", resizable = TRUE ) # ---------------- With tools ----------------- card( title = "Default Tools", plotOutput( ns("card_defaulttool_plot"), height = "100%" ), tools = list( card_tool( widget = "link", href = "https://github.com/dipterix" ), card_tool(widget = "collapse"), card_tool(widget = "maximize") ), class_body = "height-300", resizable = TRUE ) # -------------- Card2 example -------------- card2( title = "Card2 Example", body_main = plotOutput( outputId = ns("card2_plot"), height = "100%" ), body_side = fluidRow( column( 6L, textInput( ns("card2_plot_title"), "Plot title" ) ), column( 6L, sliderInput( ns("card2_plot_npts"), "# of points", min = 1, max = 100, value = 10, step = 1, round = TRUE ) ) ), tools = list( card_tool(widget = "link", href = "https://github.com/dipterix"), card_tool(widget = "collapse"), card_tool(widget = "maximize") ), class_body = "height-300" )
Create a badge widget located at card header
card_badge(text = NULL, class = NULL, ...) card_recalculate_badge( text = "Recalculate needed", class = NULL, event_name = "run_analysis", ... ) enable_recalculate_badge(text = "Recalculate needed", ...) disable_recalculate_badge(text = "Up-to-date", ...) set_card_badge( id = NULL, class = NULL, text = NULL, add_class = NULL, remove_class = NULL, session = shiny::getDefaultReactiveDomain() )card_badge(text = NULL, class = NULL, ...) card_recalculate_badge( text = "Recalculate needed", class = NULL, event_name = "run_analysis", ... ) enable_recalculate_badge(text = "Recalculate needed", ...) disable_recalculate_badge(text = "Up-to-date", ...) set_card_badge( id = NULL, class = NULL, text = NULL, add_class = NULL, remove_class = NULL, session = shiny::getDefaultReactiveDomain() )
text |
inner text content of the badge |
class |
additional 'HTML' class of the badge; for
|
... |
additional 'HTML' tag attributes |
event_name |
name of the event to trigger |
id |
the badge 'HTML' ID to be changed, will be enclosed with
session namespace |
add_class, remove_class
|
add or remove class |
session |
shiny session |
library(shidashi) # UI: a Bootstrap badge with green background card_badge("Ready", class = "bg-green shidashi-output-status") # server server <- function(input, output, session) { shiny::observe({ # ... check if the inputs have changed set_card_badge( class = "shidashi-output-status", text = "Refresh needed", add_class = "bg-warning", remove_class = "bg-success disabled" ) }) }library(shidashi) # UI: a Bootstrap badge with green background card_badge("Ready", class = "bg-green shidashi-output-status") # server server <- function(input, output, session) { shiny::observe({ # ... check if the inputs have changed set_card_badge( class = "shidashi-output-status", text = "Refresh needed", add_class = "bg-warning", remove_class = "bg-success disabled" ) }) }
To insert, remove, or active card panels, see
card_tabset_operate.
card_tabset( ..., inputId = rand_string(prefix = "tabset-"), title = NULL, names = NULL, active = NULL, tools = NULL, footer = NULL, class = "", class_header = "", class_body = "", class_foot = "" )card_tabset( ..., inputId = rand_string(prefix = "tabset-"), title = NULL, names = NULL, active = NULL, tools = NULL, footer = NULL, class = "", class_header = "", class_body = "", class_foot = "" )
... |
'HTML' tags; each tag will be placed into a card |
inputId |
the id of the card-set, must start with letters |
title |
the title of the card-set |
names |
title of the tabs |
active |
the title that will be active on load |
tools |
a list of tools or badges generated by
|
footer |
the footer element of the card-set |
class |
the 'HTML' class the of card-set |
class_header, class_body, class_foot
|
additional 'HTML' class the of card header, body, and footer accordingly |
'HTML' tags
library(shiny) library(shidashi) # Fake session to operate on card_tabset without shiny session <- MockShinySession$new() card_tabset( inputId = "card_set", title = "Cardset with Tools", `Tab 1` = p("Tab content 1"), class_body = "height-500", tools = list( as_badge( "New|badge-success" ), card_tool( widget = "collapse" ), card_tool( widget = "maximize" ) ) ) card_tabset_insert( inputId = "card_set", title = "Tab 2", p("New content"), session = session ) card_tabset_activate( inputId = "card_set", title = "Tab 1", session = session ) card_tabset_remove( inputId = "card_set", title = "Tab 2", session = session )library(shiny) library(shidashi) # Fake session to operate on card_tabset without shiny session <- MockShinySession$new() card_tabset( inputId = "card_set", title = "Cardset with Tools", `Tab 1` = p("Tab content 1"), class_body = "height-500", tools = list( as_badge( "New|badge-success" ), card_tool( widget = "collapse" ), card_tool( widget = "maximize" ) ) ) card_tabset_insert( inputId = "card_set", title = "Tab 2", p("New content"), session = session ) card_tabset_activate( inputId = "card_set", title = "Tab 1", session = session ) card_tabset_remove( inputId = "card_set", title = "Tab 2", session = session )
card_tabset
Add, active, or remove a card within card_tabset
card_tabset_insert( inputId, title, ..., active = TRUE, notify_on_failure = TRUE, session = shiny::getDefaultReactiveDomain() ) card_tabset_remove( inputId, title, notify_on_failure = TRUE, session = shiny::getDefaultReactiveDomain() ) card_tabset_activate( inputId, title, notify_on_failure = TRUE, session = shiny::getDefaultReactiveDomain() )card_tabset_insert( inputId, title, ..., active = TRUE, notify_on_failure = TRUE, session = shiny::getDefaultReactiveDomain() ) card_tabset_remove( inputId, title, notify_on_failure = TRUE, session = shiny::getDefaultReactiveDomain() ) card_tabset_activate( inputId, title, notify_on_failure = TRUE, session = shiny::getDefaultReactiveDomain() )
inputId |
the element id of |
title |
the title of the card to insert, activate, or to remove |
... |
the content of the card |
active |
whether to set the card to be active once added |
notify_on_failure |
whether to show notifications on failure |
session |
shiny session domain |
These functions execute session$sendCustomMessage and return
whatever value generated by that function; usually nothing.
The icons cane be displayed at header line within
accordion, card, card2,
card_tabset. See their examples.
card_tool( inputId = NULL, title = NULL, widget = c("maximize", "collapse", "remove", "flip", "refresh", "link", "custom"), icon, class = "", href = "#", target = "_blank", start_collapsed = FALSE, ... )card_tool( inputId = NULL, title = NULL, widget = c("maximize", "collapse", "remove", "flip", "refresh", "link", "custom"), icon, class = "", href = "#", target = "_blank", start_collapsed = FALSE, ... )
inputId |
the button id, only necessary when |
title |
the tip message to show when the mouse cursor hovers on the icon |
widget |
the icon widget type; choices are |
icon |
icon to use if you are unsatisfied with the default ones |
class |
additional class for the tool icons |
href, target
|
used when |
start_collapsed |
used when |
... |
passed to the tag as attributes |
There are 7 widget types:
"maximize"allow the elements to maximize themselves to full-screen
"collapse"allow the elements to collapse
"remove""flip"used together with flip_box,
to allow card body to flip over
"refresh"refresh all shiny outputs
"link"open a hyper-link pointing to external websites
"custom"turn the icon into a actionButton.
in this case, inputId must be specified.
'HTML' tags to be included in tools parameter in
accordion, card, card2,
card_tabset
Generates outputs that can be written to clipboards with one click
clipboardOutput( outputId = rand_string(prefix = "clipboard"), message = "Copy to clipboard", clip_text = "", class = NULL, as_card_tool = FALSE ) renderClipboard( expr, env = parent.frame(), quoted = FALSE, outputArgs = list() )clipboardOutput( outputId = rand_string(prefix = "clipboard"), message = "Copy to clipboard", clip_text = "", class = NULL, as_card_tool = FALSE ) renderClipboard( expr, env = parent.frame(), quoted = FALSE, outputArgs = list() )
outputId |
the output id |
message |
tool tip to show when mouse hovers on the element |
clip_text |
the initial text to copy to clipboards |
class |
'HTML' class of the element |
as_card_tool |
whether to make the output as |
expr |
expression to evaluate; the results will replace
|
env |
environment to evaluate |
quoted |
whether |
outputArgs |
used to replace default arguments of |
'HTML' elements that can write to clip-board once users click on them.
clipboardOutput(clip_text = "Hey there")clipboardOutput(clip_text = "Hey there")
Send messages to the client to open, close, or toggle the off-canvas drawer panel on the right side of the dashboard.
drawer_open(session = shiny::getDefaultReactiveDomain()) drawer_close(session = shiny::getDefaultReactiveDomain()) drawer_toggle(session = shiny::getDefaultReactiveDomain())drawer_open(session = shiny::getDefaultReactiveDomain()) drawer_close(session = shiny::getDefaultReactiveDomain()) drawer_toggle(session = shiny::getDefaultReactiveDomain())
session |
shiny session |
No value is returned (called for side effect).
server <- function(input, output, session) { # Open the drawer drawer_open() # Close the drawer drawer_close() # Toggle the drawer drawer_toggle() }server <- function(input, output, session) { # Open the drawer drawer_open() # Close the drawer drawer_close() # Toggle the drawer drawer_toggle() }
fire_event sets a reactive event value on the current session.
When global = TRUE, the event is propagated to all sessions that
share the same shared_id (i.e. other browser tabs for the same
user).
get_event reads the current value of an event key from the
session registry.
get_theme is a convenience wrapper around
get_event("theme.changed") that returns the current dashboard theme.
All three functions must be called inside a Shiny server context.
fire_event( key, value, session = shiny::getDefaultReactiveDomain(), global = FALSE ) get_event(key, session = shiny::getDefaultReactiveDomain(), default = NULL) get_theme(session = shiny::getDefaultReactiveDomain())fire_event( key, value, session = shiny::getDefaultReactiveDomain(), global = FALSE ) get_event(key, session = shiny::getDefaultReactiveDomain(), default = NULL) get_theme(session = shiny::getDefaultReactiveDomain())
key |
a single character string identifying the event type |
value |
the event payload (any R object) |
session |
a Shiny session (defaults to the current reactive domain) |
global |
logical; if |
default |
value to return when the event has not been fired yet
(used by |
get_theme and get_event auto-register the session if needed
and must be called inside a reactive context
(observe, observeEvent,
reactive, render functions).
fire_event returns NULL invisibly.
get_event returns the last value fired for key, or
default if none.
get_theme returns a named list with three character elements:
Either "light" or "dark".
Hex color string for text / foreground elements.
Hex color string for the page background.
Before the browser fires its first theme event, the light-theme fallback
list(theme = "light", background = "#FFFFFF", foreground = "#000000")
is returned.
library(shiny) server <- function(input, output, session) { # fire an event shidashi::fire_event("my_event", list(a = 1), session = session) # read it back observe({ evt <- shidashi::get_event("my_event", session = session) print(evt) }) # get_theme must be called within a reactive context output$plot <- renderPlot({ theme <- shidashi::get_theme() par(bg = theme$background, fg = theme$foreground) plot(1:10) }) }library(shiny) server <- function(input, output, session) { # fire an event shidashi::fire_event("my_event", list(a = 1), session = session) # read it back observe({ evt <- shidashi::get_event("my_event", session = session) print(evt) }) # get_theme must be called within a reactive context output$plot <- renderPlot({ theme <- shidashi::get_theme() par(bg = theme$background, fg = theme$foreground) plot(1:10) }) }
Generate 'HTML' tags with 'flex' layout
flex_container( ..., style = NULL, direction = c("row", "column"), wrap = c("wrap", "nowrap", "wrap-reverse"), justify = c("flex-start", "center", "flex-end", "space-around", "space-between"), align_box = c("stretch", "flex-start", "center", "flex-end", "baseline"), align_content = c("stretch", "flex-start", "flex-end", "space-between", "space-around", "center") ) flex_item( ..., size = 1, style = NULL, order = NULL, flex = as.character(size), align = c("flex-start", "flex-end", "center"), class = NULL, .class = "fill-width padding-5" ) flex_break(..., class = NULL)flex_container( ..., style = NULL, direction = c("row", "column"), wrap = c("wrap", "nowrap", "wrap-reverse"), justify = c("flex-start", "center", "flex-end", "space-around", "space-between"), align_box = c("stretch", "flex-start", "center", "flex-end", "baseline"), align_content = c("stretch", "flex-start", "flex-end", "space-between", "space-around", "center") ) flex_item( ..., size = 1, style = NULL, order = NULL, flex = as.character(size), align = c("flex-start", "flex-end", "center"), class = NULL, .class = "fill-width padding-5" ) flex_break(..., class = NULL)
... |
for |
style |
the additional 'CSS' style for containers or inner items |
direction, wrap, justify, align_box, align_content
|
'CSS' styles for 'flex' containers |
size |
numerical relative size of the item; will be ignored if
|
order, align, flex
|
CSS' styles for 'flex' items |
class, .class
|
class to add to the elements |
'HTML' tags
x <- flex_container( style = "position:absolute;height:100vh;top:0;left:0;width:100%", flex_item(style = 'background-color:black;'), flex_item(style = 'background-color:red;') ) # You can view it via `htmltools::html_print(x)`x <- flex_container( style = "position:absolute;height:100vh;top:0;left:0;width:100%", flex_item(style = 'background-color:black;'), flex_item(style = 'background-color:red;') ) # You can view it via `htmltools::html_print(x)`
An 'HTML' container that can flip
flip_box( front, back, active_on = c("click", "click-front", "manual"), inputId = NULL, class = NULL ) flip(inputId, session = shiny::getDefaultReactiveDomain())flip_box( front, back, active_on = c("click", "click-front", "manual"), inputId = NULL, class = NULL ) flip(inputId, session = shiny::getDefaultReactiveDomain())
front |
'HTML' elements to show in the front |
back |
'HTML' elements to show when the box is flipped |
active_on |
the condition when a box should be flipped; choices are
|
inputId |
element 'HTML' id; must be specified if |
class |
'HTML' class |
session |
shiny session; default is current active domain |
flip_box returns 'HTML' tags; flip should be called
from shiny session, and returns nothing
# More examples are available in demo library(shiny) library(shidashi) session <- MockShinySession$new() flip_box(front = info_box("Side A"), back = info_box("Side B"), inputId = 'flip_box1') flip('flip_box1', session = session)# More examples are available in demo library(shiny) library(shidashi) session <- MockShinySession$new() flip_box(front = info_box("Side A"), back = info_box("Side B"), inputId = 'flip_box1') flip('flip_box1', session = session)
R expressions in charactersGet re-formatted R expressions in characters
format_text_r( expr, quoted = FALSE, reformat = TRUE, width.cutoff = 80L, indent = 2, wrap = TRUE, args.newline = TRUE, blank = FALSE, ... ) html_highlight_code( expr, class = NULL, quoted = FALSE, reformat = TRUE, copy_on_click = TRUE, width.cutoff = 80L, indent = 2, wrap = TRUE, args.newline = TRUE, blank = FALSE, ..., hover = c("overflow-visible-on-hover", "overflow-auto") )format_text_r( expr, quoted = FALSE, reformat = TRUE, width.cutoff = 80L, indent = 2, wrap = TRUE, args.newline = TRUE, blank = FALSE, ... ) html_highlight_code( expr, class = NULL, quoted = FALSE, reformat = TRUE, copy_on_click = TRUE, width.cutoff = 80L, indent = 2, wrap = TRUE, args.newline = TRUE, blank = FALSE, ..., hover = c("overflow-visible-on-hover", "overflow-auto") )
expr |
|
quoted |
whether |
reformat |
whether to reformat |
width.cutoff, indent, wrap, args.newline, blank, ...
|
passed to
|
class |
class of |
copy_on_click |
whether to copy to clipboard if user clicks on the code; default is true |
hover |
mouse hover behavior |
format_text_r returns characters,
html_highlight_code returns the 'HTML' tags wrapping expressions
in <pre> tag
s <- format_text_r(print(local({a<-1;a+1}))) cat(s) x <- info_box("Message", icon = "cogs") s <- format_text_r(get_construct_string(x), width.cutoff = 15L, quoted = TRUE) cat(s)s <- format_text_r(print(local({a<-1;a+1}))) cat(s) x <- info_box("Message", icon = "cogs") s <- format_text_r(get_construct_string(x), width.cutoff = 15L, quoted = TRUE) cat(s)
R expression used to generate the 'HTML' tagsThis function only works on the elements generated by this package
get_construct_string(x)get_construct_string(x)
x |
'HTML' tags |
Quoted R expressions that can generate the 'HTML' tags
x <- info_box("Message") get_construct_string(x)x <- info_box("Message") get_construct_string(x)
Guess the 'AdminLTE' body class for modules, used internally
guess_body_class(cls)guess_body_class(cls)
cls |
the class string of the |
The proposed class for <body> tag
Escape HTML strings so that they will be displayed 'as-is' in websites.
html_asis(s, space = TRUE)html_asis(s, space = TRUE)
s |
characters |
space |
whether to also escape white space, default is true. |
An R string
html_asis("<a><----> <b>")html_asis("<a><----> <b>")
Combine 'HTML' classes to produce nice, clean 'HTML' class
string via combine_html_class, or to remove a class via
remove_html_class
combine_html_class(...) remove_html_class(target, class)combine_html_class(...) remove_html_class(target, class)
... |
one or more characters, classes to combine; duplicated classes will be removed |
target |
characters, class list |
class |
one or more characters, classes to be removed from |
A character string of new 'HTML' class
# Combine classes "a b c d e" combine_html_class("a", "b a", c("c", " d", "b"), list("e ", "a")) # Remove class remove_html_class("a b c e", c("b", "c "))# Combine classes "a b c d e" combine_html_class("a", "b a", c("c", " d", "b"), list("e ", "a")) # Remove class remove_html_class("a b c e", c("b", "c "))
Store the reusing 'HTML' segments in the
views folder. This function should be used in the
'index.html' template
include_view(file, ..., .env = parent.frame(), .root_path = template_root())include_view(file, ..., .env = parent.frame(), .root_path = template_root())
file |
files in the template |
... |
ignored |
.env, .root_path
|
internally used |
rendered 'HTML' segments
## Not run: # in your 'index.html' file <html> <header> {{ shidashi::include_view("header.html") }} </header> <body> </body> <!-- Before closing html tag --> {{ shidashi::include_view("footer.html") }} </html> ## End(Not run)## Not run: # in your 'index.html' file <html> <header> {{ shidashi::include_view("header.html") }} </header> <body> </body> <!-- Before closing html tag --> {{ shidashi::include_view("footer.html") }} </html> ## End(Not run)
Generates 'HTML' info box
info_box( ..., icon = "envelope", class = "", class_icon = "bg-info", class_content = "", root_path = template_root() )info_box( ..., icon = "envelope", class = "", class_icon = "bg-info", class_content = "", root_path = template_root() )
... |
box content |
icon |
the box icon; default is |
class |
class of the box container |
class_icon |
class of the icon |
class_content |
class of the box body |
root_path |
see |
'HTML' tags
library(shiny) library(shidashi) info_box("Message", icon = "cogs") info_box( icon = "thumbs-up", span(class = "info-box-text", "Likes"), span(class = "info-box-number", "12,320"), class_icon = "bg-red" ) info_box("No icons", icon = NULL)library(shiny) library(shidashi) info_box("Message", icon = "cogs") info_box( icon = "thumbs-up", span(class = "info-box-text", "Likes"), span(class = "info-box-number", "12,320"), class_icon = "bg-red" ) info_box("No icons", icon = NULL)
Creates a fresh environment holding all per-application global stores
(session registry, per-module input registries, etc.).
This function is designed to be called from a ‘global.R’ file
generated by render(), not for user's call.
init_app(env = parent.frame())init_app(env = parent.frame())
env |
environment where the application is initialized into. |
Nothing.
init_app(env = new.env())init_app(env = new.env())
MCP Tool Generator FunctionCreates a wrapper around a generator function to ensure it returns valid
Model Context Protocol (MCP) tool definitions. The wrapper validates
input and filters output to contain only 'ellmer::ToolDef' objects.
mcp_wrapper(generator)mcp_wrapper(generator)
generator |
A function that accepts a 'session' parameter and returns
either a single tool object or a list/vector of such objects; see
|
The wrapper performs the following validations: - Ensures 'generator' is a function - Checks that 'generator' accepts a 'session' parameter
The returned function automatically handles both single tool definitions
and lists of tools, providing a consistent interface for MCP tool
registration.
A wrapped function with class 'shidashi_mcp_wrapper' that:
- Accepts a 'session' parameter
- Calls the generator function with the session
- Normalizes the output to a list
- Filters to keep only valid tool objects
- Returns a list of tool objects (possibly empty)
# Define a generator function that returns tool definitions my_tool_generator <- function(session) { # Define MCP tools using ellmer package tool_rnorm <- tool( function(n, mean = 0, sd = 1) { shiny::updateNumericInput(session, "rnorm", value = rnorm) }, description = "Draw numbers from a random normal distribution", arguments = list( n = type_integer("The number of observations. Must be positive"), mean = type_number("The mean value of the distribution."), sd = type_number("The standard deviation of the distribution.") ) ) # or `list(tool_rnorm)` tool_rnorm } # Wrap the generator wrapped_generator <- mcp_wrapper(my_tool_generator)# Define a generator function that returns tool definitions my_tool_generator <- function(session) { # Define MCP tools using ellmer package tool_rnorm <- tool( function(n, mean = 0, sd = 1) { shiny::updateNumericInput(session, "rnorm", value = rnorm) }, description = "Draw numbers from a random normal distribution", arguments = list( n = type_integer("The number of observations. Must be positive"), mean = type_number("The mean value of the distribution."), sd = type_number("The standard deviation of the distribution.") ) ) # or `list(tool_rnorm)` tool_rnorm } # Wrap the generator wrapped_generator <- mcp_wrapper(my_tool_generator)
Emits a minimal .shidashi-drawer container with a
uiOutput placeholder inside, plus the drawer
overlay. The drawer starts empty; module server code fills it
dynamically via shiny::renderUI.
Typical usage in a ‘module-ui.html’ template:
{{ shidashi::module_drawer() }}
Then in the module server:
output$shidashi_drawer <- shiny::renderUI({
shiny::tagList(
shiny::h5("My settings"),
shiny::p("Custom drawer content here.")
)
})
The ns() function from the module's template evaluation
environment is used automatically so that the output ID is
properly scoped to the module namespace.
module_drawer(output_id = "shidashi_drawer")module_drawer(output_id = "shidashi_drawer")
output_id |
character; the output ID for the
|
A shiny::tagList containing the drawer div and
its overlay.
current_module returns the information of the currently
running module. It looks up the .module_id variable in the calling
environment (set automatically when a module is loaded), then retrieves
the corresponding row from the module table.
active_module returns a reactive value with
information about the module that is currently visible in the iframe
tab (or the standalone module if no iframe manager is present).
Unlike current_module which is static and always returns the module
whose server code is running, active_module dynamically tracks
which module the user is looking at from any context.
switch_module programmatically switches the active
module in the dashboard UI.
It sends a shidashi.switch_module message to the JavaScript
front-end. When called from a module running inside an iframe, the
handler automatically forwards the request to the parent window via
postMessage so that the sidebar highlight, tab bar, and iframe
all update correctly.
module_info(root_path = template_root(), settings_file = "modules.yaml") current_module( session = shiny::getDefaultReactiveDomain(), root_path = template_root() ) active_module( session = shiny::getDefaultReactiveDomain(), root_path = template_root() ) switch_module(module_id, session = shiny::getDefaultReactiveDomain()) load_module( root_path = template_root(), request = list(QUERY_STRING = "/"), env = parent.frame() )module_info(root_path = template_root(), settings_file = "modules.yaml") current_module( session = shiny::getDefaultReactiveDomain(), root_path = template_root() ) active_module( session = shiny::getDefaultReactiveDomain(), root_path = template_root() ) switch_module(module_id, session = shiny::getDefaultReactiveDomain()) load_module( root_path = template_root(), request = list(QUERY_STRING = "/"), env = parent.frame() )
root_path |
the root path of the website project |
settings_file |
the settings file containing the module information |
session |
shiny reactive domain; used to extract the module id from
the URL query string when |
module_id |
character string; the target module identifier (must match an entry in ‘modules.yaml’). |
request |
'HTTP' request string |
env |
environment to load module variables into |
The module files are stored in modules/ folder in your
project. The folder names are the module id. Within each folder,
there should be one "server.R", R/, and a
"module-ui.html".
The R/ folder stores R code files that generate variables,
which will be available to the other two files. These variables, along
with some built-ins, will be used to render "module-ui.html".
The built-in functions are
shiny name-space function; should be used to generate the id for inputs and outputs. This strategy avoids conflict id effectively.
a variable of the module id
a function that returns the module label
The "server.R" has access to all the code in R/ as well.
Therefore it is highly recommended that you write each 'UI' component
side-by-side with their corresponding server functions and call
these server functions in "server.R".
active_module works by reading the
'@shidashi_active_module@' Shiny input that is set by the
JavaScript front-end whenever a module tab is activated.
Because it accesses session$rootScope()$input, the return value
is reactive: when called inside an observe or reactive
context it will re-fire whenever the user switches modules.
If the input has not been set yet (e.g. before any module is opened),
the function falls back to current_module().
A data frame with the following columns that contain the module information:
idmodule id, folder name
orderdisplay order in side-bar
groupgroup menu name if applicable, otherwise NA
labelthe readable label to be displayed on the side-bar
iconicon that will be displayed ahead of label, will be
passed to as_icon
badgebadge text that will be displayed
following the module label, will be passed to as_badge
urlthe relative 'URL' address of the module.
current_module: a named list with id, group,
label, icon, badge, and url of the current
module, or NULL if no module is active.
active_module: a named list with id, group,
label, icon, badge, and url of the
currently active (visible) module, or NULL if no module is active.
library(shiny) module_info() # load master module load_module() # load specific module module_data <- load_module( request = list(QUERY_STRING = "/?module=module_id")) env <- module_data$environment if (interactive()) { # get module title env$module_title() # generate module-specific shiny id env$ns("input1") # generate part of the UI env$ui() }library(shiny) module_info() # load master module load_module() # load specific module module_data <- load_module( request = list(QUERY_STRING = "/?module=module_id")) env <- module_data$environment if (interactive()) { # get module title env$module_title() # generate module-specific shiny id env$ns("input1") # generate part of the UI env$ui() }
The 'Bootstrap' notification
show_notification( message, title = "Notification!", subtitle = "", type = c("default", "info", "warning", "success", "danger", "white", "dark"), close = TRUE, position = c("topRight", "topLeft", "bottomRight", "bottomLeft"), autohide = TRUE, fixed = TRUE, delay = 5000, icon = NULL, collapse = "", session = shiny::getDefaultReactiveDomain(), class = NULL, ... ) clear_notifications(class = NULL, session = shiny::getDefaultReactiveDomain())show_notification( message, title = "Notification!", subtitle = "", type = c("default", "info", "warning", "success", "danger", "white", "dark"), close = TRUE, position = c("topRight", "topLeft", "bottomRight", "bottomLeft"), autohide = TRUE, fixed = TRUE, delay = 5000, icon = NULL, collapse = "", session = shiny::getDefaultReactiveDomain(), class = NULL, ... ) clear_notifications(class = NULL, session = shiny::getDefaultReactiveDomain())
message |
notification body content, can be 'HTML' tags |
title, subtitle
|
title and subtitle of the notification |
type |
type of the notification; can be |
close |
whether to allow users to close the notification |
position |
where the notification should be; choices are
|
autohide |
whether to automatically hide the notification |
fixed |
whether the position should be fixed |
delay |
integer in millisecond to hide the notification if
|
icon |
the icon of the title |
collapse |
if |
session |
shiny session domain |
class |
the extra class of the notification, can be used for style
purposes, or by |
... |
other options; see https://adminlte.io/docs/3.1//javascript/toasts.html#options |
Both functions should be used in shiny reactive contexts. The messages will be sent to shiny 'JavaScript' interface and nothing will be returned.
## Not run: # the examples must run in shiny reactive context show_notification( message = "This validation process has finished. You are welcome to proceed.", autohide = FALSE, title = "Success!", subtitle = "type='success'", type = "success" ) show_notification( message = "This notification has title and subtitle", autohide = FALSE, title = "Hi there!", subtitle = "Welcome!", icon = "kiwi-bird", class = "notification-auto" ) # only clear notifications with class "notification-auto" clear_notifications("notification-auto") ## End(Not run)## Not run: # the examples must run in shiny reactive context show_notification( message = "This validation process has finished. You are welcome to proceed.", autohide = FALSE, title = "Success!", subtitle = "type='success'", type = "success" ) show_notification( message = "This notification has title and subtitle", autohide = FALSE, title = "Hi there!", subtitle = "Welcome!", icon = "kiwi-bird", class = "notification-auto" ) # only clear notifications with class "notification-auto" clear_notifications("notification-auto") ## End(Not run)
Sends a message to the client to open the specified URL in a new browser window/tab.
open_url(url, target = "_blank", session = shiny::getDefaultReactiveDomain())open_url(url, target = "_blank", session = shiny::getDefaultReactiveDomain())
url |
character string, the URL to open |
target |
the |
session |
shiny session |
No value is returned (called for side effect).
For detailed usage, see demo application by
running render().
progressOutput( outputId, ..., description = "Initializing", width = "100%", class = "bg-primary", value = 0, size = c("md", "sm", "xs") ) renderProgress(expr, env = parent.frame(), quoted = FALSE, outputArgs = list())progressOutput( outputId, ..., description = "Initializing", width = "100%", class = "bg-primary", value = 0, size = c("md", "sm", "xs") ) renderProgress(expr, env = parent.frame(), quoted = FALSE, outputArgs = list())
outputId |
the element id of the progress |
... |
extra elements on the top of the progress bar |
description |
descriptive message below the progress bar |
width |
width of the progress |
class |
progress class, default is |
value |
initial value, ranging from 0 to 100; default is 0 |
size |
size of the progress bar; choices are |
expr |
R expression that should return a named list of |
env |
where to evaluate |
quoted |
whether |
outputArgs |
a list of other parameters in |
progressOutput returns 'HTML' tags containing progress bars
that can be rendered later via shiny_progress or
renderProgress. renderProgress returns shiny render functions
internally.
library(shiny) library(shidashi) progressOutput("sales_report_prog1", description = "6 days left!", "Add Products to Cart", span(class="float-end", "123/150"), value = 123/150 * 100) # server function server <- function(input, output, session, ...) { output$sales_report_prog1 <- renderProgress({ return(list( value = 140 / 150 * 100, description = "5 days left!" )) }) }library(shiny) library(shidashi) progressOutput("sales_report_prog1", description = "6 days left!", "Add Products to Cart", span(class="float-end", "123/150"), value = 123/150 * 100) # server function server <- function(input, output, session, ...) { output$sales_report_prog1 <- renderProgress({ return(list( value = 140 / 150 * 100, description = "5 days left!" )) }) }
Reads the binary envelope written by stream_to_js and
returns the header and decoded body as a list.
read_stream_vis(path)read_stream_vis(path)
path |
Character scalar. Absolute path to a |
A list with components:
headerNamed list parsed from the JSON header
(contains data_type, signature, timestamp,
and any extra fields).
dataDecoded body: a raw vector for
"raw", an R object for "json", or a numeric/integer
vector for "int32", "float32", "float64".
MCP AccessRegister shiny inputs and outputs for MCP (Model Context
Protocol) agent access.
register_input() wraps a shiny input constructor to
register metadata. It evaluates expr and returns the UI element.
register_output() is a server-side function that registers a
render function call (e.g. renderPlot({...})), assigns it to
session$output, registers the MCP output spec, and sets
up download-widget handlers. The UI overlay icons are injected
entirely by JS.
register_input( expr, inputId, update, description = "", writable = TRUE, quoted = FALSE, env = parent.frame() ) register_output( expr, outputId, description = "", quoted = FALSE, env = parent.frame(), ..., output_opts = list(), download_function = NULL, download_type = c("image", "htmlwidget", "threeBrain", "no-download", "data", "stream_viz"), extension = NULL, session = shiny::getDefaultReactiveDomain() )register_input( expr, inputId, update, description = "", writable = TRUE, quoted = FALSE, env = parent.frame() ) register_output( expr, outputId, description = "", quoted = FALSE, env = parent.frame(), ..., output_opts = list(), download_function = NULL, download_type = c("image", "htmlwidget", "threeBrain", "no-download", "data", "stream_viz"), extension = NULL, session = shiny::getDefaultReactiveDomain() )
expr |
For |
inputId |
character string. The |
update |
character string. The fully qualified update function,
e.g. |
description |
character string. A human-readable description of
the input or output purpose, exposed to |
writable |
logical (default |
quoted |
logical (default |
env |
the environment in which to evaluate |
outputId |
character string. The |
... |
reserved for future use. |
output_opts |
a named list of extra options for the output (e.g. width, height defaults). |
download_function |
a custom download handler function. When
|
download_type |
character string. One of |
extension |
character vector of allowed file extension for
download, or |
session |
the |
register_input returns the evaluated UI element.
register_output is called for its side effects (assigning
the render function and registering widgets) and returns NULL
invisibly.
## Not run: # inside a shidashi module UI function: ns <- shiny::NS("demo") register_input( expr = shiny::sliderInput( inputId = ns("threshold"), label = "Threshold", min = 0, max = 1, value = 0.5 ), inputId = "threshold", update = "shiny::updateSliderInput", description = "Filter threshold for the plot" ) # inside a shidashi module server function: register_output( expr = renderPlot({ plot(iris) }), outputId = "my_plot", description = "Scatter plot of iris data", download_type = "image" ) ## End(Not run)## Not run: # inside a shidashi module UI function: ns <- shiny::NS("demo") register_input( expr = shiny::sliderInput( inputId = ns("threshold"), label = "Threshold", min = 0, max = 1, value = 0.5 ), inputId = "threshold", update = "shiny::updateSliderInput", description = "Filter threshold for the plot" ) # inside a shidashi module server function: register_output( expr = renderPlot({ plot(iris) }), outputId = "my_plot", description = "Scatter plot of iris data", download_type = "image" ) ## End(Not run)
Shiny session registration and cross-tab synchronization
register_session(session) unregister_session(session) enable_input_broadcast( session = shiny::getDefaultReactiveDomain(), once = FALSE ) disable_input_broadcast(session = shiny::getDefaultReactiveDomain()) enable_input_sync(session = shiny::getDefaultReactiveDomain(), once = FALSE) disable_input_sync(session = shiny::getDefaultReactiveDomain()) get_handler(name, session = shiny::getDefaultReactiveDomain()) set_handler(name, handler, session = shiny::getDefaultReactiveDomain())register_session(session) unregister_session(session) enable_input_broadcast( session = shiny::getDefaultReactiveDomain(), once = FALSE ) disable_input_broadcast(session = shiny::getDefaultReactiveDomain()) enable_input_sync(session = shiny::getDefaultReactiveDomain(), once = FALSE) disable_input_sync(session = shiny::getDefaultReactiveDomain()) get_handler(name, session = shiny::getDefaultReactiveDomain()) set_handler(name, handler, session = shiny::getDefaultReactiveDomain())
session |
A Shiny session object or session proxy (created by
|
once |
Logical; if |
name |
A single character string identifying a named slot in the
session's handler list (used by |
handler |
A Shiny Observer object created by |
register_session() — Call once at the top of every Shiny
module server function. It is idempotent: calling it a second time on the
same session safely refreshes the session object and URL in the registry
entry without re-creating observers.
Internally it creates an entry in the application-global session registry
(initialized by init_app), resolves a shared_id token
shared across browser tabs from the ?shared_id=... URL query string
(or generates a random 26-character string when absent), sets up the
per-session reactive event bus, and — for named module sessions — sends a
shidashi.register_module_token custom message to bind the module
namespace to its session token on the JavaScript side.
unregister_session() — Removes the session entry from the
registry and destroys all attached observers. This is called automatically
when the session ends via the onSessionEnded hook installed by
register_session(). Direct calls are only needed for explicit early
cleanup (e.g. in tests).
Each registered session maintains a named slot list for Shiny
Observer objects called handlers. This provides a lightweight
system for attaching module-level life-cycle hooks that are tied to the
session's lifetime.
User-defined handlers — get_handler() / set_handler()
set_handler(name, handler) installs handler under name,
first suspending and destroying any Observer already stored there.
Pass handler = NULL to clear the slot. Returns FALSE
invisibly if the session is already closed.
get_handler(name) retrieves the stored Observer (or
NULL). It auto-registers the session if not yet registered and
returns NULL gracefully if the session is closed.
Three handler names are reserved for internal shidashi infrastructure and
will raise an error if passed to set_handler:
"event_handler", "broadcast_handler", and
"input_sync_handler".
Built-in cross-tab sync handlers
shidashi installs two opt-in Observer slots in every registered
session (both start suspended):
enable_input_broadcast() /
disable_input_broadcast())Continuously monitors the
session's input values and, whenever they change, pushes a
snapshot to the client via shidashi.cache_session_input.
Other browser tabs sharing the same shared_id can read this
cached snapshot to restore or compare input state.
enable_input_sync() /
disable_input_sync())Listens for serialized input maps
broadcast by other sessions sharing the same
shared_id via the root-session @shidashi@ input.
Values differing from the local input are written into the
session's private inputs reactiveValues. Messages
from the same session are ignored to prevent feedback loops.
Both observers run at priority -100000 (after all ordinary reactive
computations have settled). Use once = TRUE to trigger a single
cycle without permanently resuming the observer. The disable_*
variants suspend the observer and are silent no-ops when the session has
already ended.
init_app() # global.R, once per app start
|
v
register_session(session) # top of each module server()
|
v
... reactive code ...
get_handler() / set_handler() # attach user-defined session observers
enable_input_broadcast() # optional: push inputs to browser cache
enable_input_sync() # optional: receive peer-tab inputs
|
v
session ends -> unregister_session() # runs automatically
register_session returns the session token (session$token)
invisibly; it is idempotent and safe to call multiple times for the same
session.
unregister_session returns NULL invisibly; it is idempotent.
enable_input_broadcast, disable_input_broadcast,
enable_input_sync, and disable_input_sync all return
invisibly. They are silent no-ops when the session is already closed.
get_handler returns the named Observer object stored under
name, or NULL if the slot is empty or the session is closed.
set_handler returns TRUE invisibly when it successfully
installs the handler, or FALSE invisibly when the session is already
closed.
library(shiny) # --- Basic usage in a module server --- server <- function(input, output, session) { shidashi::register_session(session) # opt-in to cross-tab input broadcast (suspended by default) shidashi::enable_input_broadcast(session) # opt-in to receive inputs from peer tabs shidashi::enable_input_sync(session) # get_theme must be called within a reactive context output$plot <- renderPlot({ theme <- shidashi::get_theme() par(bg = theme$background, fg = theme$foreground) plot(1:10) }) } # --- Named handler: attach a reusable session-scoped observer --- server2 <- function(input, output, session) { shidashi::register_session(session) cleanup <- shiny::observe({ # ... module-level teardown logic ... shidashi::set_handler("my_cleanup", NULL, session) }, suspended = TRUE, domain = session) shidashi::set_handler("my_cleanup", cleanup, session) # retrieve and resume the observer elsewhere in the same session h <- shidashi::get_handler("my_cleanup", session) if (!is.null(h)) h$resume() }library(shiny) # --- Basic usage in a module server --- server <- function(input, output, session) { shidashi::register_session(session) # opt-in to cross-tab input broadcast (suspended by default) shidashi::enable_input_broadcast(session) # opt-in to receive inputs from peer tabs shidashi::enable_input_sync(session) # get_theme must be called within a reactive context output$plot <- renderPlot({ theme <- shidashi::get_theme() par(bg = theme$background, fg = theme$foreground) plot(1:10) }) } # --- Named handler: attach a reusable session-scoped observer --- server2 <- function(input, output, session) { shidashi::register_session(session) cleanup <- shiny::observe({ # ... module-level teardown logic ... shidashi::set_handler("my_cleanup", NULL, session) }, suspended = TRUE, domain = session) shidashi::set_handler("my_cleanup", cleanup, session) # retrieve and resume the observer elsewhere in the same session h <- shidashi::get_handler("my_cleanup", session) if (!is.null(h)) h$resume() }
Render a 'shidashi' project
render( root_path = template_root(), ..., prelaunch = NULL, prelaunch_quoted = FALSE, launch_browser = TRUE, as_job = TRUE, test_mode = getOption("shiny.testmode", FALSE) )render( root_path = template_root(), ..., prelaunch = NULL, prelaunch_quoted = FALSE, launch_browser = TRUE, as_job = TRUE, test_mode = getOption("shiny.testmode", FALSE) )
root_path |
the project path, default is the demo folder from
|
... |
additional parameters passed to |
prelaunch |
expression to execute before launching the session; the expression will execute in a brand new session |
prelaunch_quoted |
whether the expression is quoted; default is false |
launch_browser |
whether to launch browser; default is |
as_job |
whether to run as 'RStudio' jobs; this options is only available when 'RStudio' is available |
test_mode |
whether to test the project; this options is helpful when you want to debug the project without relaunching shiny applications |
This functions runs a 'shiny' application, and returns the job id if 'RStudio' is available.
template_root() if(interactive()) { render() }template_root() if(interactive()) { render() }
Server-side render function for streamVizOutput.
The expression should evaluate to a stream_viz object.
renderStreamViz(expr, env = parent.frame(), quoted = FALSE)renderStreamViz(expr, env = parent.frame(), quoted = FALSE)
expr |
An R expression that returns a |
env |
Environment in which to evaluate |
quoted |
Logical. Whether |
A server-side render function for use with Shiny.
streamVizOutput, updateStreamViz
Forces outdated output to reset and show a silent message.
reset_output( outputId, message = "This output has been reset", session = shiny::getDefaultReactiveDomain() )reset_output( outputId, message = "This output has been reset", session = shiny::getDefaultReactiveDomain() )
outputId |
output ID |
message |
output message |
session |
shiny reactive domain |
No value
Wrapper of shiny progress that can run without shiny
shiny_progress( title, max = 1, ..., quiet = FALSE, session = shiny::getDefaultReactiveDomain(), shiny_auto_close = FALSE, log = NULL, outputId = NULL )shiny_progress( title, max = 1, ..., quiet = FALSE, session = shiny::getDefaultReactiveDomain(), shiny_auto_close = FALSE, log = NULL, outputId = NULL )
title |
the title of the progress |
max |
max steps of the procedure |
... |
passed to initialization method of |
quiet |
whether the progress needs to be quiet |
session |
shiny session domain |
shiny_auto_close |
whether to close the progress once function exits |
log |
alternative log function |
outputId |
the element id of |
a list of functions that controls the progress
{ progress <- shiny_progress("Procedure A", max = 10) for(i in 1:10) { progress$inc(sprintf("Step %s", i)) Sys.sleep(0.1) } progress$close() } if(interactive()) { library(shiny) ui <- fluidPage( fluidRow( column(12, actionButton("click", "Click me")) ) ) server <- function(input, output, session) { observeEvent(input$click, { progress <- shiny_progress("Procedure B", max = 10, shiny_auto_close = TRUE) for(i in 1:10) { progress$inc(sprintf("Step %s", i)) Sys.sleep(0.1) } }) } shinyApp(ui, server) }{ progress <- shiny_progress("Procedure A", max = 10) for(i in 1:10) { progress$inc(sprintf("Step %s", i)) Sys.sleep(0.1) } progress$close() } if(interactive()) { library(shiny) ui <- fluidPage( fluidRow( column(12, actionButton("click", "Click me")) ) ) server <- function(input, output, session) { observeEvent(input$click, { progress <- shiny_progress("Procedure B", max = 10, shiny_auto_close = TRUE) for(i in 1:10) { progress$inc(sprintf("Step %s", i)) Sys.sleep(0.1) } }) } shinyApp(ui, server) }
Please write your own version. This function is designed for demo-use only.
show_ui_code( x, class = NULL, code_only = FALSE, as_card = FALSE, card_title = "", class_body = "bg-gray-70", width.cutoff = 80L, indent = 2, wrap = TRUE, args.newline = TRUE, blank = FALSE, copy_on_click = TRUE, ... )show_ui_code( x, class = NULL, code_only = FALSE, as_card = FALSE, card_title = "", class_body = "bg-gray-70", width.cutoff = 80L, indent = 2, wrap = TRUE, args.newline = TRUE, blank = FALSE, copy_on_click = TRUE, ... )
x |
'HTML' tags generated by this package |
class |
additional 'HTML' class |
code_only |
whether to show code only |
as_card |
whether to wrap results in |
card_title, class_body
|
used by |
width.cutoff, indent, wrap, args.newline, blank, copy_on_click, ...
|
passed
to |
'HTML' tags
html_highlight_code
MCP Tool GeneratorCreates a closure that produces an
ellmer::tool dispatching on an action enumerator:
readmeReturns the full SKILL.md instructions. Must be
called first to unlock other actions.
referenceReturns content from a reference file in the
skill directory (gated behind readme).
scriptExecutes a script in the scripts/
subdirectory via processx::run() (gated behind readme).
skill_wrapper(skill_path)skill_wrapper(skill_path)
skill_path |
Path to the skill directory containing |
The returned tool enforces a soft gate: calling reference or
script before readme is allowed, but if the call
errors the message is augmented with a condensed summary (~200
tokens) instructing the AI to read the full instructions first.
This minimizes token waste (the summary is only sent on failure).
The gate state is per-instance: each call to the wrapper produces
a closure with an independent readme_unlocked flag.
A function with class c("shidashi_skill_wrapper", "function")
that returns an ellmer::ToolDef object.
skill_dir <- system.file( "builtin-templates/bslib-bare/agents/skills/greet", package = "shidashi" ) wrapper <- skill_wrapper(skill_dir) tool_def <- wrapper() cat(tool_def(action = "readme"))skill_dir <- system.file( "builtin-templates/bslib-bare/agents/skills/greet", package = "shidashi" ) wrapper <- skill_wrapper(skill_dir) tool_def <- wrapper() cat(tool_def(action = "readme"))
Combines session$token with id to produce the string used
both by stream_path (as the filename stem) and by the browser
as the URL path component under stream/.
stream_file_id(id, session = shiny::getDefaultReactiveDomain(), token = NULL)stream_file_id(id, session = shiny::getDefaultReactiveDomain(), token = NULL)
id |
Character scalar. The base stream identifier (no path separators). |
session |
Shiny session object. Defaults to the active reactive domain. |
token |
Character scalar or |
Character scalar: "{token}_{id}".
stream_path, stream_viz,
updateStreamViz
Call once in the server function to set up the directory that
stream_path and stream_to_js will write to.
When running inside a shidashi template the directory is automatically
resolved from the template root; when running in plain Shiny a temporary
directory is created and registered with
addResourcePath so that the browser can fetch
stream/{token}_{id}.bin. An optional cleanup hook is registered
to remove this session's files when the session ends.
stream_init(session = shiny::getDefaultReactiveDomain())stream_init(session = shiny::getDefaultReactiveDomain())
session |
Shiny session object. Defaults to the currently active reactive domain. |
Invisibly returns the absolute path to the stream directory.
Returns the full path to the binary file that will be served at
stream/{token}_{id}.bin. The filename embeds the session token so
that simultaneous Shiny sessions never overwrite each other's data.
Call stream_init at least once per session before relying on
this function.
stream_path(id, session = shiny::getDefaultReactiveDomain())stream_path(id, session = shiny::getDefaultReactiveDomain())
id |
Character scalar. Stream identifier. Must be a valid file-name component (no path separators). |
session |
Shiny session object. Defaults to the currently active reactive domain. |
Invisible character scalar: absolute path to the .bin file.
Serializes data together with a JSON header into the binary
envelope expected by the JavaScript window.shidashi.fetchStreamData(id)
method.
stream_to_js( abspath, data, type = c("raw", "json", "int32", "float32", "float64"), ... )stream_to_js( abspath, data, type = c("raw", "json", "int32", "float32", "float64"), ... )
abspath |
Character scalar. Absolute path to the target |
data |
The data to serialize. See Details for how each |
type |
Character scalar. One of |
... |
Additional named scalar values to embed in the JSON header and
expose to the JavaScript caller via |
Wire format
[endianFlag: 1 byte] [headerLen: uint32 LE] [header: UTF-8 JSON] [body]
endianFlag is always 0x01 (little-endian).
header is a JSON object containing at minimum data_type
plus any extra fields passed via ....
Body encoding by type
"raw"Passed through verbatim; data must be a
raw vector or will be coerced via as.raw().
"json"data is serialized with
jsonlite::toJSON(auto_unbox = TRUE).
"int32"data is coerced to integer and written as
4-byte little-endian signed integers.
"float32"data is coerced to double and written as
4-byte little-endian IEEE 754 single-precision floats.
"float64"data is coerced to double and written as
8-byte little-endian IEEE 754 double-precision floats.
Invisibly returns abspath.
Creates a multi-channel signal viewer widget that fetches its data from
the binary stream file produced by stream_to_js.
stream_viz( outputId, session = shiny::getDefaultReactiveDomain(), stream_id = NULL, width = NULL, height = NULL, refresh_rate = 33, show_controls = TRUE, streaming = FALSE, token = NULL )stream_viz( outputId, session = shiny::getDefaultReactiveDomain(), stream_id = NULL, width = NULL, height = NULL, refresh_rate = 33, show_controls = TRUE, streaming = FALSE, token = NULL )
outputId |
Character scalar. The output ID matching the
corresponding |
session |
Shiny session object. Defaults to the active reactive
domain. Together with |
stream_id |
Character scalar or |
width, height
|
Widget dimensions (passed to |
refresh_rate |
Numeric scalar (milliseconds). Polling interval used
when the viewer is in active streaming mode (play button pressed).
Lower values give smoother animation but increase CPU/network load.
Default |
show_controls |
Logical. Whether to display the hover toolbar
(play/pause, zoom, reset, export). Default |
streaming |
Logical. Whether to start active streaming immediately
when the widget is rendered. Default |
token |
Character scalar or |
The outputId together with session is used to auto-compute
the token-qualified stream file identifier via
stream_file_id. You can override this by passing an
explicit stream_id.
Use updateStreamViz for in-place updates without recreating
the widget.
An htmlwidgets object.
streamVizOutput, renderStreamViz,
updateStreamViz, stream_file_id
Use in a Shiny UI to reserve a slot for a multi-channel signal viewer that is driven by binary stream data.
streamVizOutput(outputId, width = "100%", height = "400px")streamVizOutput(outputId, width = "100%", height = "400px")
outputId |
Character scalar. Output ID that matches the corresponding
|
width, height
|
CSS width and height of the widget container. |
An HTML output element suitable for inclusion in a Shiny UI.
renderStreamViz, updateStreamViz
Configure template options that are shared across the sessions
template_settings template_settings_set(...) template_settings_get(name, default = NULL) template_root()template_settings template_settings_set(...) template_settings_get(name, default = NULL) template_root()
... |
key-value pair to set options |
name |
character, key of the value |
default |
default value if the key is missing |
An object of class list of length 3.
The settings is designed to store static key-value pairs that
are shared across the sessions. The most important key is
"root_path", which should be a path pointing to the template
folder.
template_settings_get returns the values represented by the
corresponding keys, or the default value if key is missing.
# Get current website root path template_root()# Get current website root path template_root()
Sends a custom Shiny message that causes the browser to re-fetch the binary
stream file and re-render the signal viewer without tearing down and
recreating the widget. Call this after writing new data with
stream_to_js. The outputId is used both
to locate the widget as the stream file identifier — it must
match the id passed to stream_path.
updateStreamViz( outputId, streaming = NULL, token = NULL, session = shiny::getDefaultReactiveDomain() )updateStreamViz( outputId, streaming = NULL, token = NULL, session = shiny::getDefaultReactiveDomain() )
outputId |
Character scalar. The output ID passed to
|
streaming |
Logical or |
token |
Character scalar or |
session |
Shiny session object. Defaults to the active reactive domain. |
Invisibly NULL.
streamVizOutput, stream_to_js,
stream_file_id
Download 'shidashi' templates from 'Github'
use_template( path, user = "dipterix", theme = "bslib", repo = "shidashi-templates", branch = "main", ... )use_template( path, user = "dipterix", theme = "bslib", repo = "shidashi-templates", branch = "main", ... )
path |
the path to create 'shidashi' project |
user |
'Github' user name |
theme |
the theme to download |
repo |
repository if the name is other than |
branch |
branch name if other than |
... |
ignored |
To publish a 'shidashi' template, create a 'Github' repository
called 'shidashi-templates', or fork the
built-in templates.
The theme is the sub-folder of the template repository.
An easy way to use a template in your project is through the 'RStudio' project widget. In the 'RStudio' navigation bar, go to "File" menu, click on the "New Project..." button, select the "Create a new project" option, and find the item that creates 'shidashi' templates. Use the widget to set up template directory.
the target project path