# Shiny Modules
#
# irid components work naturally inside standard Shiny modules. Use
# iridOutput() and renderIrid() to embed a irid component tree inside a
# module's UI and server functions, exactly like any other Shiny output. The
# reactive state lives inside the module's server function, so each module
# instance is fully independent.
#
# This example instantiates two counter modules side by side, each with a
# display component and a controls component that share the same reactiveVal.

library(irid)
library(shiny)
library(bslib)

# irid components -----------------------------------------------------------

CountDisplay <- function(count) {
  tags$h2(
    class = "text-center display-4",
    \() count()
  )
}

CountControls <- function(count) {
  tags$div(
    tags$input(
      type = "range", min = 0, max = 100,
      value = reactiveProxy(get = count, set = \(v) count(as.numeric(v)))
    ),
    tags$button(
      class = "btn btn-outline-secondary btn-sm",
      disabled = \() count() == 0,
      onClick = \() count(0),
      "Reset"
    )
  )
}

# shiny module ---------------------------------------------------------------

counter_ui <- function(id) {
  ns <- NS(id)
  card(
    card_header(id),
    card_body(
      iridOutput(ns("display")),
      iridOutput(ns("controls"))
    )
  )
}

counter_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    count <- reactiveVal(0)
    output$display <- renderIrid(CountDisplay(count))
    output$controls <- renderIrid(CountControls(count))
  })
}

# shiny app ------------------------------------------------------------------

ui <- page_fluid(
  tags$h3("Irid + Shiny Modules"),
  layout_columns(
    counter_ui("A"),
    counter_ui("B")
  )
)

server <- function(input, output, session) {
  counter_server("A")
  counter_server("B")
}

shinyApp(ui, server)
