---
title: "Transforms & Theming"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Transforms & Theming}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(myIO)
```

## Transforms

Transforms derive new data from an existing layer before rendering. You
specify a transform with the `transform` argument in `addIoLayer()`.

### Available Transforms

| Transform | Description | Used by |
|-----------|-------------|---------|
| `"identity"` | Default. Passes data through unchanged. | All types |
| `"lm"` | Fits a linear model and returns fitted values. | `line` |
| `"loess"` | LOESS non-linear smoothing. Options: `span`, `degree`, `n_grid`. | `line` |
| `"polynomial"` | Polynomial regression. Options: `degree`, `n_grid`. | `line` |
| `"ci"` | Confidence or prediction interval band. Options: `method`, `level`, `interval`. | `area` |
| `"smooth"` | Simple or exponential moving average. Options: `method` (`"sma"`/`"ema"`), `window`, `alpha`. | `line` |
| `"mean"` | Group mean aggregation. | `point`, `bar` |
| `"mean_ci"` | Group mean ± confidence interval. Options: `level`, `method` (`"t"`/`"se"`). | `rangeBar` |
| `"residuals"` | Regression residuals vs. fitted values. Options: `method`. | `point` |
| `"summary"` | General aggregation. Options: `stat` (`"count"`/`"sum"`/`"sd"`/`"var"`/`"min"`/`"max"`). | `point`, `bar` |
| `"cumulative"` | Computes running totals with base/cumulative columns. | `waterfall` (auto-applied) |
| `"quantiles"` | Computes Q1, median, Q3, whisker bounds per group. | `boxplot` (internal) |
| `"median"` | Computes group medians. | `boxplot`, `violin` (internal) |
| `"outliers"` | Returns rows beyond 1.5x IQR fences. | `boxplot` (internal) |
| `"density"` | Kernel density estimation via `stats::density()`. | `violin`, `ridgeline` (internal) |

Transforms marked "internal" are applied automatically by composite chart
types. The first 10 transforms are user-facing — use them directly in
`addIoLayer()`.

### Linear Model Trend Line

Add a trend line to a scatter plot by combining a `"point"` layer with a
`"line"` layer that uses `transform = "lm"`:

```{r lm-example, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "point",
    color = "#E69F00",
    label = "points",
    data = mtcars,
    mapping = list(x_var = "wt", y_var = "mpg")
  ) |>
  addIoLayer(
    type = "line",
    transform = "lm",
    color = "red",
    label = "trend",
    data = mtcars,
    mapping = list(x_var = "wt", y_var = "mpg")
  )
```

The `lm` transform fits `y ~ x` using `stats::lm()` and replaces the y
values with the fitted values. The resulting line is sorted by x so it
renders as a smooth trend.

### Cumulative Transform (Waterfall)

The `"cumulative"` transform is auto-applied when you use `type = "waterfall"`.
It computes running totals and produces `_base_y` and `_cumulative_y` columns
that the waterfall renderer uses for floating bars:

```{r cumulative-example, eval = FALSE}
df <- data.frame(
  step  = c("Start", "Sales", "Returns", "Total"),
  value = c(100, 50, -20, NA),
  is_total = c(FALSE, FALSE, FALSE, TRUE)
)

myIO() |>
  addIoLayer(
    type = "waterfall",
    label = "bridge",
    data = df,
    mapping = list(x_var = "step", y_var = "value", total = "is_total")
  ) |>
  defineCategoricalAxis(xAxis = TRUE)
```

### Confidence Interval Band

Overlay a confidence interval on a scatter plot:

```{r ci-example, eval = FALSE}
myIO(data = mtcars) |>
  addIoLayer(type = "point", color = "#4E79A7", label = "Data",
    mapping = list(x_var = "wt", y_var = "mpg")) |>
  addIoLayer(type = "line", color = "#E15759", label = "Trend",
    transform = "lm",
    mapping = list(x_var = "wt", y_var = "mpg")) |>
  addIoLayer(type = "area", color = "#E15759", label = "95% CI",
    transform = "ci",
    mapping = list(x_var = "wt", y_var = "mpg"),
    options = list(level = 0.95))
```

The `ci` transform accepts `method` (`"lm"` or `"loess"`), `level` (default
0.95), and `interval` (`"confidence"` or `"prediction"`). The mapping only
needs `x_var` and `y_var` — `low_y`/`high_y` are auto-injected.

### LOESS Smoothing

Non-linear smoothing with adjustable span:

```{r loess-example, eval = FALSE}
myIO(data = mtcars) |>
  addIoLayer(type = "point", color = "#4E79A7", label = "Data",
    mapping = list(x_var = "wt", y_var = "mpg")) |>
  addIoLayer(type = "line", color = "#E15759", label = "LOESS",
    transform = "loess",
    mapping = list(x_var = "wt", y_var = "mpg"),
    options = list(span = 0.5))
```

### Mean ± CI Error Bars

Group means with confidence intervals:

```{r mean-ci-example, eval = FALSE}
myIO(data = iris) |>
  addIoLayer(type = "rangeBar", color = "#4E79A7", label = "Mean ± 95% CI",
    transform = "mean_ci",
    mapping = list(x_var = "Species", y_var = "Sepal.Length"),
    options = list(level = 0.95)) |>
  defineCategoricalAxis(xAxis = TRUE)
```

### Regression Composite

One-call scatter + trend + CI + R²:

```{r regression-composite, eval = FALSE}
myIO(data = mtcars) |>
  addIoLayer(type = "regression", label = "MPG vs Weight",
    mapping = list(x_var = "wt", y_var = "mpg"),
    options = list(method = "lm", showCI = TRUE, showStats = TRUE))
```

### Moving Average

```{r smooth-example, eval = FALSE}
df <- data.frame(x = 1:100, y = cumsum(rnorm(100)))

myIO(data = df) |>
  addIoLayer(type = "line", color = "#CCCCCC", label = "Raw",
    mapping = list(x_var = "x", y_var = "y")) |>
  addIoLayer(type = "line", color = "#E15759", label = "SMA-10",
    transform = "smooth",
    mapping = list(x_var = "x", y_var = "y"),
    options = list(method = "sma", window = 10))
```

Use `method = "ema"` with `alpha` for exponential moving average.

### Transform + Type Compatibility

Not every transform works with every chart type. The table below shows
valid combinations:

| Type | Supported Transforms |
|------|---------------------|
| `"line"` | `"identity"`, `"lm"`, `"loess"`, `"polynomial"`, `"smooth"` |
| `"point"` | `"identity"`, `"mean"`, `"summary"`, `"residuals"` |
| `"bar"` | `"identity"`, `"mean"`, `"summary"` |
| `"area"` | `"identity"`, `"ci"` |
| `"rangeBar"` | `"identity"`, `"mean_ci"` |
| `"groupedBar"` | `"identity"` |
| `"histogram"` | `"identity"` |
| `"hexbin"` | `"identity"` |
| `"treemap"` | `"identity"` |
| `"donut"` | `"identity"` |
| `"gauge"` | `"identity"` |
| `"heatmap"` | `"identity"` |
| `"candlestick"` | `"identity"` |
| `"waterfall"` | `"identity"`, `"cumulative"` |
| `"sankey"` | `"identity"` |
| `"boxplot"` | `"identity"` |
| `"violin"` | `"identity"` |
| `"ridgeline"` | `"identity"` |
| `"text"` | `"identity"` |

If you pass an incompatible combination, `addIoLayer()` will error with a
clear message.

## Theming

Use `setTheme()` to customize chart appearance with CSS custom properties.

### Basic Theming

```{r theme-basic, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "point",
    color = "#56B4E9",
    label = "scatter",
    data = mtcars,
    mapping = list(x_var = "wt", y_var = "mpg")
  ) |>
  setTheme(
    text_color = "#e0e0e0",
    grid_color = "#333333",
    bg = "#1a1a2e",
    font = "Fira Code, monospace"
  )
```

### Theme Parameters

| Parameter | CSS Property | Description |
|-----------|-------------|-------------|
| `text_color` | `--chart-text-color` | Axis labels and tick text |
| `grid_color` | `--chart-grid-color` | Grid and axis lines |
| `bg` | `--chart-bg` | Chart background color |
| `font` | `--chart-font` | Font family |

### Custom Properties

Pass additional CSS custom properties via `...` (the `chart-` prefix is
added automatically):

```{r theme-custom, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "bar",
    color = "coral",
    label = "bars",
    data = mtcars,
    mapping = list(x_var = "cyl", y_var = "mpg")
  ) |>
  defineCategoricalAxis(xAxis = TRUE) |>
  setTheme(
    bg = "#fafafa",
    text_color = "#333",
    "border-radius" = "8px"
  )
```

### Dark Mode Example

Combine theming with color choices for a dark-mode chart:

```{r dark-mode, eval = FALSE}
aq <- airquality
aq$Month <- paste0("M", aq$Month)

myIO() |>
  addIoLayer(
    type = "line",
    color = c("#00d2ff", "#ff6b6b", "#feca57", "#48dbfb", "#ff9ff3"),
    label = "Month",
    data = aq,
    mapping = list(x_var = "Day", y_var = "Temp", group = "Month")
  ) |>
  setTheme(
    text_color = "#b0b0b0",
    grid_color = "#2d2d2d",
    bg = "#0d1117",
    font = "Inter, system-ui, sans-serif"
  )
```
