@rokkit/cli 1.7.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,6 +48,12 @@ the vocabulary — cite it, don't restate it.
48
48
  - **Accessibility is not free.** Colour-only encoding fails for print/colourblind — patterns
49
49
  (`pattern` channel) dual-code series. Interactive charts need `keyboard`/`onselect` and the
50
50
  `role`/`aria-label` the geoms provide.
51
+ - **Plane annotations go first, and the theory fixes the frame.** `Region`, `Hull` and `Contour`
52
+ describe the metric plane, and SVG paints in document order — placed after `Plot.Point` they
53
+ paint over it. A `Region` never moves the scales, so a plane defined by theory (Martin's
54
+ `[0,1]×[0,1]`) needs `xDomain`/`yDomain` on `PlotChart`, or a zone shrinks to wherever the rows
55
+ fall. `Rule slope` is ignored on a band axis. Thresholds on skewed metrics belong at a high
56
+ percentile of the data (p95), not a guessed constant.
51
57
  - **Evidence beats assertion.** You do not say "it themes" — you build and snapshot and paste what
52
58
  you saw.
53
59
 
@@ -67,6 +73,9 @@ the vocabulary — cite it, don't restate it.
67
73
  8. Is there a colour-independent encoding (pattern) where accessibility/print matters, and are
68
74
  interactive charts keyboard/aria-enabled?
69
75
  9. Does the chart hold up in light AND dark mode (no invisible marks, no overflow)?
76
+ 10. Are `Region` / `Hull` / `Contour` placed before the marks they sit behind, and is the domain
77
+ fixed where a region — not the data — defines the frame? Do many overlapping hulls default to
78
+ off rather than stacking into mud?
70
79
 
71
80
  ## Procedure
72
81
 
@@ -80,7 +89,8 @@ results than blind grep. Fall back to Grep/Glob only if a tool errors or returns
80
89
  `orientation`, `alpha`, and preset config.
81
90
  3. Grep the app's `.svelte` for the smells: `<Plot ` (stale root), `<GeomBar`/`<GeomLine` used as a
82
91
  root, `opacity=` on a chart, `stack\b` as a boolean prop, `palette=` / `preset=` on a chart,
83
- raw `#[0-9a-fA-F]{3,8}`/`oklch(`/`rgb(` inside chart props. Map each hit to the correct
92
+ raw `#[0-9a-fA-F]{3,8}`/`oklch(`/`rgb(` inside chart props, and a `Plot.Region`/`Plot.Hull`/
93
+ `Plot.Contour` that follows a `Plot.Point` in the same chart. Map each hit to the correct
84
94
  channel/preset fix.
85
95
  4. If a new palette/pattern/symbol was added, verify it's in the right registry
86
96
  (`categoricalPalette` /
@@ -58,6 +58,11 @@ don't restate it.
58
58
  hardcoded `font-family:` or arbitrary `font-[...]` in component markup; map it to the right class.
59
59
  - Faces belong in config, not per-component. If a needed face isn't declared, the fix is to add it
60
60
  to `typography:` (a styling-config change — hand off to the styles review), not to inline it.
61
+ - Heading LEVELS come from `[data-heading='1'..'4']` rules in `@rokkit/themes` (face, size,
62
+ weight, line-height and tracking together): a title takes `data-heading="2"`, and prose under
63
+ `data-prose` gets its `h1`–`h4` styled. Flag a hand-built heading (`text-2xl font-semibold`
64
+ on a title, or a per-component `font-size` for a heading) and map it to `data-heading`.
65
+ There are no `--text-*` scale tokens — a `var(--text-…)` read is a bug.
61
66
 
62
67
  ## Procedure
63
68
 
@@ -97,7 +102,7 @@ don't have. A piped/`| tail` exit status reports the pipe, not the command: read
97
102
  tier · the simpler rewrite (when demotable).
98
103
  - **Custom icons** — findings: unloaded collections, snippet-for-an-icon, inline SVG → `i-*` class.
99
104
  - **Typography** — hardcoded `font-family`/`font-[...]` findings → `font-heading/body/mono` (or a
100
- `typography:` config addition to hand off).
105
+ `typography:` config addition to hand off); hand-built headings → `data-heading`.
101
106
  - **Contract hygiene** — off-contract usage (wrong data prop, manual focus, `onclick` on `[data-path]`).
102
107
  - **Verification evidence** — the pasted build output + Playwright snapshot summary (light/dark).
103
108
  - **### Verdict PASS/FAIL** — PASS only when each usage is at the simplest tier that works, icons and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/cli",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Command line utilities for icon bundling and conversion.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@mdi/svg": "^7.4.47",
31
- "@rokkit/unocss": "1.7.0",
31
+ "@rokkit/unocss": "1.8.0",
32
32
  "sade": "^1.8.1",
33
33
  "@iconify/tools": "^5.0.14",
34
34
  "@iconify/types": "^2.0.0",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: charts-rokkit
3
- description: Use when building, styling, customizing, or theming data visualizations with @rokkit/chart in a Svelte 5 app — the ggplot-style geom/aesthetic model (fill/color/pattern/group/size/symbol/alpha/position/orientation + literal-colour tokens), the PlotChart root + Plot.* geom namespace and prebuilt chart shapes, the spec API, and the preset system (colors/patterns/symbols via createChartPreset + ChartProvider, plus how to ADD a new colour palette, pattern, or symbol to the library).
3
+ description: Use when building, styling, customizing, or theming data visualizations with @rokkit/chart in a Svelte 5 app — the ggplot-style geom/aesthetic model (fill/color/pattern/group/size/symbol/alpha/position/orientation + literal-colour tokens), the PlotChart root + Plot.* geom namespace and prebuilt chart shapes, plane annotations (Rule with slope/intercept, Region bands/polygons, Hull per group, density Contour) and the architecture-analysis recipes built from them (Martin's main sequence, hotspots, complexity × coverage, fan-in/fan-out, god modules), the spec API, and the preset system (colors/patterns/symbols via createChartPreset + ChartProvider, plus how to ADD a new colour palette, pattern, or symbol to the library).
4
4
  ---
5
5
 
6
6
  # Charts — Rokkit (`@rokkit/chart`)
@@ -12,7 +12,8 @@ and symbols. There is no per-chart `palette` array prop; customization goes thro
12
12
 
13
13
  ```text
14
14
  data + channels (or spec)
15
- → PlotState (scales, colorMap, patternMap, symbolMap, geom registry, selection, zoom)
15
+ → PlotState (a composition of job classes: config, geoms, frame, channels, orientation,
16
+ interaction, scales, aesthetics, axes — see docs/design/20-chart.md)
16
17
  → PlotChart (SVG: geoms + axes + grid + legend + tooltip + overlays)
17
18
 
18
19
  preset (colors / patterns / symbols / shades / opacity)
@@ -53,19 +54,24 @@ Shapes: `BarChart`, `LineChart`, `AreaChart`, `PieChart`, `ScatterPlot`, `Bubble
53
54
  `Plot` is a **namespace object** (`Plot.Bar`, `Plot.Line`, …), not a component — the root is
54
55
  `PlotChart`. Each member equals its `Geom*` export (`Plot.Bar === GeomBar`); use either. Full set:
55
56
  `Bar`, `Line`, `Area`, `Point`, `Jitter`, `Arc`, `Box`, `Violin`, `Heatmap`, `Hexbin`,
56
- `Candlestick`, `Waterfall`, `Ribbon`, `Rule`, plus overlays `Highlight` / `Trend`.
57
+ `Candlestick`, `Waterfall`, `Ribbon`, `Radar`, `Rule`, `Region`, `Hull`, `Contour`, plus overlays
58
+ `Highlight` / `Trend`.
57
59
 
58
60
  **3. Spec API** (full control from a plain object — same result as composition):
59
61
 
60
62
  ```svelte
61
63
  <PlotChart {data} spec={{
62
64
  geoms: [
63
- { type: 'bar', channels: { x: 'quarter', y: 'revenue', fill: 'product' }, stat: 'sum' },
64
- { type: 'line', channels: { x: 'quarter', y: 'forecast', color: 'class' } }
65
+ { type: 'bar', x: 'quarter', y: 'revenue', fill: 'product', stat: 'sum' },
66
+ { type: 'line', x: 'quarter', y: 'forecast', color: 'class' }
65
67
  ]
66
68
  }} />
67
69
  ```
68
70
 
71
+ Fields go on the geom itself. There is no `channels: { … }` wrapper, and a geom written with one
72
+ draws nothing. Set `x`/`y`/`color` once on the spec and every geom inherits them. A spec value
73
+ overrides the matching prop, except `orientation`, where the prop wins.
74
+
69
75
  ---
70
76
 
71
77
  ## Aesthetic channels
@@ -232,6 +238,56 @@ decorations expose `data-*` hooks: `[data-plot-geom="<type>"]`, `[data-plot-elem
232
238
 
233
239
  ---
234
240
 
241
+ ## Annotating the plane — Rule, Region, Hull, Contour
242
+
243
+ These describe the metric PLANE, not a row. SVG paints in document order, so place them **before**
244
+ the marks they sit behind.
245
+
246
+ ```svelte
247
+ <PlotChart data={components} xDomain={[0, 1]} yDomain={[0, 1]} legend tooltip>
248
+ <Plot.Region name="pain" points={[[0, 0], [0.5, 0], [0, 0.5]]} label="Zone of pain" />
249
+ <Plot.Region name="uselessness" points={[[1, 1], [0.5, 1], [1, 0.5]]} label="Zone of uselessness" />
250
+ <Plot.Hull x="instability" y="abstractness" color="package" />
251
+ <Plot.Contour x="instability" y="abstractness" bandwidth={28} />
252
+ <Plot.Rule slope={-1} intercept={1} label="main sequence" />
253
+ <Plot.Point x="instability" y="abstractness" color="package" size="loc" />
254
+ </PlotChart>
255
+ ```
256
+
257
+ - **`Rule`** — `x` / `y` values, or `slope` + `intercept` (ggplot's abline), clipped to the visible
258
+ domain and labelled at its midpoint along the line. A slope is ignored on a band axis.
259
+ - **`Region`** — `x` / `y` as `[lo, hi]` (a `null` end runs to the axis edge: `[p95, null]`), or a
260
+ polygon `points`. Reads no data, never moves the scales, clipped to the plot. `name` →
261
+ `data-plot-region` for theming; `label` at the centroid or `labelAt`.
262
+ - **`Hull`** — one padded convex hull per value of `fill` / `color`; the group field joins the
263
+ shared palette. A one- or two-member group still draws (dot, capsule).
264
+ - **`Contour`** — kernel-density contours per group; `bandwidth` is in pixels; `filled` for bands.
265
+
266
+ **The frame comes from the theory, not the data.** A region never moves the scales, so fix the
267
+ domain on `PlotChart` (`xDomain` / `yDomain`) when the plane is defined — or a zone shrinks because
268
+ no row happens to fall in it.
269
+
270
+ ### Architecture analysis (recipes, not components)
271
+
272
+ The library ships no architecture vocabulary — the recipes are ordinary geoms over metric rows the
273
+ consumer computes (the learn site measures rokkit itself with
274
+ `apps/learn/scripts/build-architecture-metrics.mjs`):
275
+
276
+ | Recipe | x × y | Annotations |
277
+ |--------|-------|-------------|
278
+ | Main sequence (Robert Martin) | instability `Ce/(Ca+Ce)` × abstractness | zone polygons, `Rule slope={-1} intercept={1}`, `Hull` per package, `Contour` for the pile-up at A = 0 |
279
+ | Hotspots | complexity × churn | `Region x={[p95, null]} y={[p95, null]}` |
280
+ | Complexity × coverage | complexity × coverage | `Region` for complex-and-under-tested, `Rule y={0.8}` |
281
+ | Fan-in × fan-out | fan-out × fan-in | `Region` for hubs and for reaches-everywhere |
282
+ | God modules | complexity × fan-out | `Region` past p95 on both |
283
+
284
+ Martin's metrics are per COMPONENT (a package or top-level folder); per file, most points sit
285
+ exactly on (0,0) or (1,0). Take thresholds as percentiles of the codebase, and the 95th rather than
286
+ the 90th — these distributions are heavy-tailed. For dependency structure and hidden coupling, reach
287
+ for `@rokkit/graph`: `DependencyMatrix`, and edges flagged `overlay` (drawn, never shaping layout).
288
+
289
+ ---
290
+
235
291
  ## Gotchas
236
292
 
237
293
  - The root is **`PlotChart`**, not `<Plot>` — `Plot` is the geom namespace object.
@@ -242,6 +298,8 @@ decorations expose `data-*` hooks: `[data-plot-geom="<type>"]`, `[data-plot-elem
242
298
  - `position="stack"` supersedes the boolean `stack` prop; grouping needs a `fill`/`color`/`group`
243
299
  field (a stack with no group field renders individual bars, not a stacked total).
244
300
  - A literal colour on `fill`/`color` is applied directly — it is **not** a legend group.
301
+ - `Region`, `Hull` and `Contour` placed AFTER `Plot.Point` paint over the points. Put them first.
302
+ - A `Hull` over many overlapping groups stacks translucent fills into mud — offer it as a toggle.
245
303
 
246
304
  ## Verify
247
305
 
@@ -351,6 +351,12 @@ aliases. Usage classes: `font-heading` (display face), `font-body` (UI face), `f
351
351
  <code class="font-mono text-xs text-ink-soft">path/to/file.ts</code>
352
352
  ```
353
353
 
354
+ **Heading levels** come from `[data-heading='1'..'4']` rules in `@rokkit/themes` (face, size,
355
+ weight, line-height and tracking together). Give a title its level with `data-heading="2"` —
356
+ or put prose under `data-prose` and its `h1`–`h4` take the levels — rather than hand-picking
357
+ `text-2xl font-semibold`. There are no `--text-*` scale tokens; override a level with the same
358
+ selector.
359
+
354
360
  ---
355
361
 
356
362
  ## Shape / radius configuration