---
title: "Chart Types"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Chart Types}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

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

## Overview

myIO supports 20 chart types via the `type` argument in `addIoLayer()`.
This vignette shows an example of each.

All examples use built-in R datasets so you can copy and run them directly.

## Layer Compatibility

Chart types are organized into compatibility groups. You can freely combine
types within compatible groups (e.g. point + line + area), but standalone
types like treemap or gauge cannot be mixed with other types.

| Group | Types |
|-------|-------|
| Continuous axes | `line`, `point`, `area`, `candlestick`, `bracket`, `qq` |
| Categorical axes | `bar`, `groupedBar`, `waterfall`, `boxplot`, `violin`, `comparison` |
| Binned axes | `histogram`, `ridgeline` |
| Matrix axes | `heatmap` |
| Calendar | `calendarHeatmap` |
| Standalone | `hexbin`, `treemap`, `donut`, `gauge`, `sankey` |

Continuous, categorical, and binned groups can be combined with each other.
Matrix and standalone groups cannot be mixed with other groups.

---

## Basic Charts

### Line Chart

```{r line, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "line",
    color = "steelblue",
    label = "temperature",
    data = airquality,
    mapping = list(x_var = "Day", y_var = "Temp")
  )
```

### Point (Scatter) Chart

```{r point, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "point",
    color = "coral",
    label = "scatter",
    data = mtcars,
    mapping = list(x_var = "wt", y_var = "mpg")
  )
```

### Bar Chart

```{r bar, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "bar",
    color = "steelblue",
    label = "bars",
    data = mtcars,
    mapping = list(x_var = "cyl", y_var = "mpg")
  ) |>
  defineCategoricalAxis(xAxis = TRUE)
```

### Area Chart

Area charts require `x_var`, `low_y`, and `high_y` in the mapping:

```{r area, eval = FALSE}
aq <- airquality[complete.cases(airquality), ]
aq$TempLow <- aq$Temp - 5
aq$TempHigh <- aq$Temp + 5

myIO() |>
  addIoLayer(
    type = "area",
    color = "lightsteelblue",
    label = "area",
    data = aq,
    mapping = list(x_var = "Day", low_y = "TempLow", high_y = "TempHigh")
  )
```

### Grouped Bar Chart

```{r grouped-bar, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "groupedBar",
    color = "steelblue",
    label = "grouped",
    data = mtcars,
    mapping = list(x_var = "cyl", y_var = "mpg")
  ) |>
  defineCategoricalAxis(xAxis = TRUE)
```

### Histogram

Histograms use a `value` mapping instead of `x_var`/`y_var`:

```{r histogram, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "histogram",
    color = "steelblue",
    label = "hist",
    data = mtcars,
    mapping = list(value = "mpg")
  )
```

### Donut Chart

```{r donut, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "donut",
    color = c("#E69F00", "#56B4E9", "#009E73"),
    label = "donut",
    data = aggregate(mpg ~ cyl, data = mtcars, FUN = mean),
    mapping = list(x_var = "cyl", y_var = "mpg")
  )
```

### Gauge Chart

Gauges use a `value` mapping:

```{r gauge, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "gauge",
    color = "steelblue",
    label = "gauge",
    data = data.frame(value = 0.75),
    mapping = list(value = "value")
  )
```

### Hexbin Chart

```{r hexbin, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "hexbin",
    color = "steelblue",
    label = "hexbin",
    data = mtcars,
    mapping = list(x_var = "wt", y_var = "mpg", radius = 20)
  )
```

### Treemap

Treemaps use a different mapping with `level_1` and `level_2` instead of
`x_var` and `y_var`:

```{r treemap, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "treemap",
    label = "cars",
    data = mtcars,
    mapping = list(level_1 = "vs", level_2 = "cyl")
  )
```

---

## Phase 2 Charts

### Heatmap

Heatmaps display a matrix of values with a continuous color scale. Both axes
are categorical. Mapping requires `x_var`, `y_var`, and `value`:

```{r heatmap, eval = FALSE}
df <- expand.grid(
  quarter = c("Q1", "Q2", "Q3", "Q4"),
  segment = c("Low", "Mid", "High"),
  stringsAsFactors = FALSE
)
df$value <- c(2, 4, 6, 5, 7, 9, 4, 6, 8, 3, 5, 7)

myIO() |>
  addIoLayer(
    type = "heatmap",
    color = "#4E79A7",
    label = "Revenue",
    data = df,
    mapping = list(x_var = "quarter", y_var = "segment", value = "value")
  ) |>
  defineCategoricalAxis(xAxis = TRUE, yAxis = TRUE) |>
  setAxisFormat(xLabel = "Quarter", yLabel = "Segment")
```

### Calendar Heatmap

Calendar heatmaps render daily values as a GitHub-contributions-style grid:
one cell per day, seven rows per week, with month labels across the top. The
chart is scoped to a single calendar year in v1.2. Mapping requires `date`
(any Date or ISO `"YYYY-MM-DD"` string) and `value` (numeric):

```{r calendar-heatmap, eval = FALSE}
set.seed(42)
df <- data.frame(
  day     = as.Date("2026-01-01") + 0:364,
  commits = rpois(365, lambda = 3)
)

myIO() |>
  addIoLayer(
    type = "calendarHeatmap",
    color = "#4E79A7",
    label = "Daily commits",
    data = df,
    mapping = list(date = "day", value = "commits")
  )
```

Use `options$weekStart = "monday"` for ISO week ordering. Two calendars
linked via `linkCharts(a, b, on = "day", cursor = TRUE)` synchronize the
hover crosshair by date across both charts.

### Candlestick (OHLC)

Candlestick charts show open-high-low-close data. Green bars indicate close
>= open, red bars indicate close < open. Mapping requires `x_var`, `open`,
`high`, `low`, and `close`:

```{r candlestick, eval = FALSE}
df <- data.frame(
  day = 1:10,
  open  = c(10, 12, 11, 14, 13, 15, 14, 16, 15, 17),
  high  = c(14, 15, 14, 17, 16, 18, 17, 19, 18, 20),
  low   = c(9,  11, 10, 13, 12, 14, 13, 15, 14, 16),
  close = c(12, 11, 14, 13, 15, 14, 16, 15, 17, 19)
)

myIO() |>
  addIoLayer(
    type = "candlestick",
    label = "Price",
    data = df,
    mapping = list(
      x_var = "day", open = "open",
      high = "high", low = "low", close = "close"
    )
  ) |>
  setAxisFormat(xAxis = ".0f", yAxis = "$,.0f",
                xLabel = "Day", yLabel = "Price")
```

### Waterfall

Waterfall charts show how an initial value is affected by sequential positive
and negative changes. The `cumulative` transform is auto-applied. Mark summary
rows with a `total` mapping:

```{r waterfall, eval = FALSE}
df <- data.frame(
  step  = c("Revenue", "COGS", "Gross Profit", "OpEx", "Net Income"),
  value = c(500, -200, NA, -150, NA),
  is_total = c(FALSE, FALSE, TRUE, FALSE, TRUE)
)

myIO() |>
  addIoLayer(
    type = "waterfall",
    label = "P&L",
    data = df,
    mapping = list(x_var = "step", y_var = "value", total = "is_total")
  ) |>
  defineCategoricalAxis(xAxis = TRUE) |>
  setAxisFormat(yAxis = "$,.0f", xLabel = "Step", yLabel = "Amount")
```

### Sankey

Sankey diagrams show flows between nodes. Mapping requires `source`, `target`,
and `value`. This is a standalone type and cannot be mixed with other charts:

```{r sankey, eval = FALSE}
df <- data.frame(
  source = c("Budget", "Budget", "Sales", "Sales", "Marketing"),
  target = c("Sales", "Marketing", "Revenue", "Leads", "Leads"),
  value  = c(40, 20, 30, 10, 15)
)

myIO() |>
  addIoLayer(
    type = "sankey",
    color = c("#4E79A7", "#F28E2B", "#E15759", "#76B7B2", "#59A14F"),
    label = "Flow",
    data = df,
    mapping = list(source = "source", target = "target", value = "value")
  )
```

### Boxplot (Composite)

Boxplots are composite charts that automatically expand into area (IQR box),
point (whiskers, median), and optional outlier layers. Mapping requires
`x_var` (categorical) and `y_var` (numeric):

```{r boxplot, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "boxplot",
    color = "#4E79A7",
    label = "Sepal Length",
    data = iris,
    mapping = list(x_var = "Species", y_var = "Sepal.Length"),
    options = list(showOutliers = TRUE)
  ) |>
  setAxisFormat(xLabel = "Species", yLabel = "Sepal Length (cm)")
```

Options: `showOutliers` (default TRUE), `whiskerType` ("tukey" or "minmax").

### Violin (Composite)

Violin plots show the distribution shape via a mirrored kernel density
estimate. They expand into area (density), optional box (IQR), and optional
median point layers:

```{r violin, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "violin",
    color = "#59A14F",
    label = "Distribution",
    data = iris,
    mapping = list(x_var = "Species", y_var = "Sepal.Length"),
    options = list(showBox = TRUE, showMedian = TRUE)
  ) |>
  setAxisFormat(xLabel = "Species", yLabel = "Sepal Length (cm)")
```

Options: `showBox` (TRUE), `showMedian` (TRUE), `showPoints` (FALSE),
`bandwidth` (KDE bandwidth, default "nrd0").

### Ridgeline (Composite)

Ridgeline plots stack multiple density curves vertically for comparing
distributions across groups. They expand into one area sub-layer per group
value. Mapping requires `x_var` (numeric values), `y_var` (numeric), and
`group` (categorical):

```{r ridgeline, eval = FALSE}
df <- mtcars
df$cyl <- as.character(df$cyl)

myIO() |>
  addIoLayer(
    type = "ridgeline",
    color = c("#4E79A7", "#F28E2B", "#E15759"),
    label = "MPG by Cylinders",
    data = df,
    mapping = list(x_var = "hp", y_var = "mpg", group = "cyl"),
    options = list(overlap = 0.5)
  ) |>
  setAxisFormat(xLabel = "Horsepower", yLabel = "Density")
```

Options: `overlap` (0-1, default 0.6), `bandwidth` (KDE bandwidth).

### Q-Q Plot (Composite)

Q-Q (quantile-quantile) plots compare sample quantiles against a theoretical
distribution to assess normality. The composite expands into a point layer
(Q-Q scatter), a reference line (through Q1/Q3), and an optional confidence
envelope. Only `y_var` is required in the mapping:

```{r qq, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "qq",
    color = "#4E79A7",
    label = "MPG Normality",
    data = mtcars,
    mapping = list(y_var = "mpg")
  ) |>
  setAxisFormat(xLabel = "Theoretical Quantiles", yLabel = "Sample Quantiles")
```

Options: `envelope` (TRUE), `conf_level` (0.95), `distribution` ("norm"),
`qfunc` (custom quantile function). Supports grouped Q-Q via `group` mapping.

### Comparison (Composite)

Comparison plots combine boxplots with pairwise significance brackets showing
p-values from hypothesis tests. The composite expands into boxplot sub-layers
plus a bracket layer with test results:

```{r comparison, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "comparison",
    color = "#4E79A7",
    label = "Species Comparison",
    data = iris,
    mapping = list(x_var = "Species", y_var = "Sepal.Width"),
    options = list(method = "t.test", p_adjust = "bonferroni")
  ) |>
  setAxisFormat(xLabel = "Species", yLabel = "Sepal Width (cm)")
```

Options: `method` ("t.test" or "wilcox.test"), `p_adjust` ("none", "bonferroni",
"holm", "BH"), `comparisons` (list of specific pairs), `showOutliers` (TRUE).

### Bracket (Standalone Layer)

Brackets can also be added as a standalone layer on top of any grouped chart.
Use `transform = "pairwise_test"` to compute significance tests:

```{r bracket, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "boxplot", color = "#4E79A7",
    label = "Sepal Width", data = iris,
    mapping = list(x_var = "Species", y_var = "Sepal.Width")
  ) |>
  addIoLayer(
    type = "bracket", label = "Tests",
    transform = "pairwise_test", data = iris,
    mapping = list(x_var = "Species", y_var = "Sepal.Width"),
    options = list(method = "wilcox.test", p_adjust = "holm")
  )
```

---

## Combining Chart Types

You can overlay compatible chart types on a single widget. Here we layer
points, a connecting line, and a linear model trend line:

```{r combined, eval = FALSE}
myIO() |>
  addIoLayer(
    type = "point",
    color = "steelblue",
    label = "points",
    data = mtcars,
    mapping = list(x_var = "wt", y_var = "mpg")
  ) |>
  addIoLayer(
    type = "line",
    color = "orange",
    label = "line",
    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")
  )
```
