# Shiny Bindings

## Overview

`shiny.webawesome` does not try to forward every browser event emitted
by every Web Awesome component into Shiny.

Instead, the package generates a curated binding surface that fits
Shiny’s reactive input model. In practice, that means the package favors
bindings that represent committed, meaningful Shiny input state rather
than transient browser telemetry.

This article describes the current binding categories, the design
philosophy behind them, and representative examples.

## Binding Categories

The current generated binding surface uses three categories:

### Durable semantic values

This is the default binding model.

The binding subscribes to a supported commit/value event and then reads
the component’s current durable state. Examples include:

- [`wa_select()`](https://www.shiny-webawesome.org/reference/wa_select.md)
  reading its current selected value
- [`wa_dialog()`](https://www.shiny-webawesome.org/reference/wa_dialog.md)
  exposing its current `open` state
- [`wa_tree()`](https://www.shiny-webawesome.org/reference/wa_tree.md)
  exposing its current selected item ids

The important idea is that Shiny receives the semantic state the user
would care about, not the raw browser event name.

### Action-style bindings

Some components are inherently action-like in Shiny. For those, the
binding uses action semantics rather than pretending the component
exposes a durable value payload.

The canonical example is
[`wa_button()`](https://www.shiny-webawesome.org/reference/wa_button.md),
whose Shiny input behaves like an action input that invalidates on each
click.

### Action-with-payload bindings

Some rare components need both:

- action invalidation semantics
- a separate companion payload input exposing the latest committed
  payload

The canonical current example is
[`wa_dropdown()`](https://www.shiny-webawesome.org/reference/wa_dropdown.md).

For `wa_dropdown(input_id = "menu", ...)`:

- `input$menu` behaves like an action counter and invalidates on every
  selection, including repeated selection of the same item
- `input$menu_value` exposes the latest selected item value

This split is useful because repeated same-item selections should still
invalidate Shiny even when the latest payload value does not change.

## Design Philosophy

The package’s binding model follows a few rules:

- bindings should expose the Shiny contract, not simply mirror raw
  browser event names
- default bindings should prefer committed semantic state
- action-like controls should use action semantics only through explicit
  policy
- action-with-payload contracts should remain narrow and explicit

This keeps the reactive surface smaller and easier to reason about.

It also preserves a clear boundary between:

- browser-local interaction handling
- Shiny-reactive input publication

If a browser-side interaction does not belong in the package’s curated
binding surface, it is usually a better fit for browser-side code or the
package’s command/helper layer.

## Examples

``` r
library(shiny.webawesome)

binding_preview <- wa_select(
  "favorite_letter",
  wa_option("A", value = "a"),
  wa_option("B", value = "b"),
  wa_option("C", value = "c")
)

cat(as.character(binding_preview), sep = "\n")
```

    ## <wa-select id="favorite_letter">
    ##   <wa-option value="a">A</wa-option>
    ##   <wa-option value="b">B</wa-option>
    ##   <wa-option value="c">C</wa-option>
    ## </wa-select>

### Example: durable semantic value

[`wa_select()`](https://www.shiny-webawesome.org/reference/wa_select.md)
is a representative durable-value binding.

``` r
library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Semantic binding",
  wa_select(
    "favorite_letter",
    wa_option("A", value = "a"),
    wa_option("B", value = "b"),
    wa_option("C", value = "c")
  ),
  verbatimTextOutput("selected_value")
)

server <- function(input, output, session) {
  output$selected_value <- renderPrint({
    input$favorite_letter
  })
}

shinyApp(ui, server)
```

Here, the Shiny input reflects the current selected value, not a raw
event stream.

### Example: event-driven semantic state

[`wa_dialog()`](https://www.shiny-webawesome.org/reference/wa_dialog.md)
is also a semantic binding, but its Shiny value is derived from
committed dialog lifecycle state rather than a conventional text or
scalar form value.

``` r
library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Semantic dialog state",
  actionButton("open_dialog", "Open dialog"),
  wa_dialog(
    "dialog",
    label = "Example dialog",
    "Dialog body"
  ),
  verbatimTextOutput("dialog_state")
)

server <- function(input, output, session) {
  observeEvent(input$open_dialog, {
    wa_call_method("dialog", "show", session = session)
  })

  output$dialog_state <- renderPrint({
    input$dialog
  })
}

shinyApp(ui, server)
```

Here, the binding publishes the committed semantic state of the
component: whether the dialog is currently open.

### Example: structured semantic selection

[`wa_tree()`](https://www.shiny-webawesome.org/reference/wa_tree.md) is
another semantic binding, but its Shiny value is a structured selection
derived from selected descendant tree items.

``` r
library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Semantic tree selection",
  wa_tree(
    "navigation_tree",
    selection = "multiple",
    wa_tree_item("Section A", id = "section_a"),
    wa_tree_item("Section B", id = "section_b"),
    wa_tree_item("Section C", id = "section_c")
  ),
  verbatimTextOutput("tree_value")
)

server <- function(input, output, session) {
  output$tree_value <- renderPrint({
    input$navigation_tree
  })
}

shinyApp(ui, server)
```

The Shiny value is a vector of selected descendant `wa-tree-item` ids.
For stable selection values, selectable tree items should have DOM `id`
attributes.

### Example: action-style binding

[`wa_button()`](https://www.shiny-webawesome.org/reference/wa_button.md)
is action-like in Shiny.

``` r
library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Action binding",
  wa_button("run_action", "Run"),
  verbatimTextOutput("click_count")
)

server <- function(input, output, session) {
  output$click_count <- renderPrint({
    input$run_action
  })
}

shinyApp(ui, server)
```

The input invalidates on each click in the same way a Shiny action input
does.

### Example: action-with-payload binding

[`wa_dropdown()`](https://www.shiny-webawesome.org/reference/wa_dropdown.md)
is the current canonical action-with-payload example.

``` r
library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Action with payload",
  wa_dropdown(
    "menu",
    wa_dropdown_item("Alpha", value = "alpha"),
    wa_dropdown_item("Beta", value = "beta"),
    trigger = wa_button("menu_trigger", "Open menu")
  ),
  verbatimTextOutput("action_value"),
  verbatimTextOutput("payload_value")
)

server <- function(input, output, session) {
  output$action_value <- renderPrint({
    input$menu
  })

  output$payload_value <- renderPrint({
    input$menu_value
  })
}

shinyApp(ui, server)
```

In this case:

- `input$menu` is the action-style invalidator
- `input$menu_value` is the latest committed payload state

## Current Bound Components

The package currently generates Shiny bindings for the following
components.

| Component                                                                            | Binding category    | Notes                                              |
|--------------------------------------------------------------------------------------|---------------------|----------------------------------------------------|
| [`wa_button()`](https://www.shiny-webawesome.org/reference/wa_button.md)             | action              | Shiny action-style invalidation on click           |
| [`wa_carousel()`](https://www.shiny-webawesome.org/reference/wa_carousel.md)         | semantic            | durable semantic value                             |
| [`wa_checkbox()`](https://www.shiny-webawesome.org/reference/wa_checkbox.md)         | semantic            | durable semantic value                             |
| [`wa_color_picker()`](https://www.shiny-webawesome.org/reference/wa_color_picker.md) | semantic            | durable semantic value                             |
| [`wa_comparison()`](https://www.shiny-webawesome.org/reference/wa_comparison.md)     | semantic            | durable semantic value                             |
| [`wa_details()`](https://www.shiny-webawesome.org/reference/wa_details.md)           | semantic            | durable semantic value                             |
| [`wa_dialog()`](https://www.shiny-webawesome.org/reference/wa_dialog.md)             | semantic            | event-driven semantic open state                   |
| [`wa_drawer()`](https://www.shiny-webawesome.org/reference/wa_drawer.md)             | semantic            | event-driven semantic open state                   |
| [`wa_dropdown()`](https://www.shiny-webawesome.org/reference/wa_dropdown.md)         | action-with-payload | action invalidator plus `input$<id>_value` payload |
| [`wa_input()`](https://www.shiny-webawesome.org/reference/wa_input.md)               | semantic            | durable semantic value                             |
| [`wa_number_input()`](https://www.shiny-webawesome.org/reference/wa_number_input.md) | semantic            | durable semantic value                             |
| [`wa_radio_group()`](https://www.shiny-webawesome.org/reference/wa_radio_group.md)   | semantic            | durable semantic value                             |
| [`wa_rating()`](https://www.shiny-webawesome.org/reference/wa_rating.md)             | semantic            | durable semantic value                             |
| [`wa_select()`](https://www.shiny-webawesome.org/reference/wa_select.md)             | semantic            | durable semantic value                             |
| [`wa_slider()`](https://www.shiny-webawesome.org/reference/wa_slider.md)             | semantic            | durable semantic value                             |
| [`wa_switch()`](https://www.shiny-webawesome.org/reference/wa_switch.md)             | semantic            | durable semantic value                             |
| [`wa_tab_group()`](https://www.shiny-webawesome.org/reference/wa_tab_group.md)       | semantic            | durable semantic value                             |
| [`wa_textarea()`](https://www.shiny-webawesome.org/reference/wa_textarea.md)         | semantic            | durable semantic value                             |
| [`wa_tree()`](https://www.shiny-webawesome.org/reference/wa_tree.md)                 | semantic            | selected descendant item ids                       |

In the website build, these entries should link to the corresponding
reference pages.

## Relationship to the Command API

Bindings and the command/helper layer solve different problems.

Use generated bindings when the package already exposes the
Shiny-reactive contract you need.

Use the command/helper layer when you need browser-side property or
method interaction that falls outside the generated binding/update
surface.

For more on that boundary, see the Command API guide.
