# Visualization grammar authoring reference

Use these builders only when a chart property must change according to the
current data point's numeric value. They produce JSON-safe rule data; they do not
execute callbacks or render a chart.

## Import

In the Deno TypeScript sandbox, import from the module specifier published in
`capabilities.json`:

```ts
import { color, greaterThan, value, when } from 'npm:@rippling/rippling-sdk/lib/charts';
```

## Builders

- `value` reads the current data point's plotted numeric value.
- `literal(scalar)` explicitly creates a constant. Bare numbers, strings,
  booleans, and `null` are converted to literals automatically.
- `equals(left, right)`, `isNot(left, right)`, `lessThan(left, right)`,
  `greaterThan(left, right)`, `lessOrEqual(left, right)`, and
  `greaterOrEqual(left, right)` return a condition.
- `when(condition, ifTrue, ifFalse?)` returns `ifTrue` when the condition is true
  and `ifFalse` otherwise. Both results are colour strings; the omitted false
  branch becomes `null` to preserve the chart's default colour.
- `color(when(...))` marks the conditional result as a color rule.

Example: highlight values over 20 and otherwise preserve the chart's default
color.

```ts
const conditionalColor = color(when(greaterThan(value, 20), '$token:categorical.series-5'));
```

The builders return plain data that renderers and editors can read. Always use
the builders above. Do not hand-author the serialized `$rule` object shown here:

```json
{
  "channel": "color",
  "$rule": {
    "kind": "ifElse",
    "cond": {
      "kind": "greaterThan",
      "left": { "kind": "value" },
      "right": { "kind": "literal", "value": 20 }
    },
    "then": { "kind": "literal", "value": "$token:categorical.series-5" },
    "else": { "kind": "literal", "value": null }
  }
}
```

## Current limits

The current contract supports only the `color` channel and per-point `value`.
It has one fixed, non-recursive shape: comparisons contain only `value` or
literal operands, and `when` contains one comparison plus two colour literals.
Do not place comparisons, `when(...)`, or `color(...)` inside another operand or
branch.

Rules do not calculate aggregates such as maximum, average, or percentile. Chart
code may calculate a finite scalar threshold from its data first and then use
that scalar in a rule. For example, after computing an 80th-percentile
`threshold`, use
`color(when(greaterOrEqual(value, threshold), highlightColor))` to highlight the
top 20%. The rule remains a per-point comparison; the surrounding chart code
owns the aggregate calculation.

Other data fields, compound boolean logic, opacity, label visibility, and other
output channels are not supported. Keep static colors as ordinary chart values
rather than wrapping them in rules.
