@nurix/etna 0.20.36 → 0.20.38

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.
Files changed (212) hide show
  1. package/data/catalog/rules/frontend.md +5 -5
  2. package/data/catalog/rules/pnpm.md +2 -2
  3. package/data/catalog/skills/nustack/SKILL.md +2 -2
  4. package/data/catalog/skills/nustack/references/cli-design.md +35 -35
  5. package/data/catalog/skills/nustack/references/monorepo-master-list.md +6 -6
  6. package/data/catalog/skills/nustack/references/monorepo-setup.md +13 -13
  7. package/data/catalog/skills/nustack/references/publishing.md +40 -39
  8. package/data/harness-index.json +1 -1
  9. package/data/harnesses/code/harness.json +2 -2
  10. package/data/harnesses/code/hooks/approved-packages.md +1 -2
  11. package/data/harnesses/code/rules/frontend.md +5 -5
  12. package/data/harnesses/code/rules/pnpm.md +2 -2
  13. package/data/harnesses/code/skills/boundary/SKILL.md +33 -22
  14. package/data/harnesses/code/skills/boundary/references/index.md +2 -4
  15. package/data/harnesses/code/skills/boundary/references/mechanisms.md +3 -10
  16. package/data/harnesses/code/skills/boundary/references/packs/build-config-runtime.md +1 -1
  17. package/data/harnesses/code/skills/boundary/references/packs/frontend.md +17 -17
  18. package/data/harnesses/code/skills/boundary/references/packs/generic-tail.md +1 -1
  19. package/data/harnesses/code/skills/brainstorm/README.md +11 -13
  20. package/data/harnesses/code/skills/brainstorm/SKILL.md +150 -132
  21. package/data/harnesses/code/skills/brainstorm/references/doctrine.md +48 -51
  22. package/data/harnesses/code/skills/brainstorm/references/harvest.md +51 -56
  23. package/data/harnesses/code/skills/brainstorm/references/session-schema.md +48 -42
  24. package/data/harnesses/code/skills/design/SKILL.md +31 -35
  25. package/data/harnesses/code/skills/design/components/charts.md +121 -43
  26. package/data/harnesses/code/skills/design/components/collections.md +209 -41
  27. package/data/harnesses/code/skills/design/components/feedback.md +86 -25
  28. package/data/harnesses/code/skills/design/components/hooks.md +198 -12
  29. package/data/harnesses/code/skills/design/components/index.md +93 -71
  30. package/data/harnesses/code/skills/design/components/inputs.md +249 -157
  31. package/data/harnesses/code/skills/design/components/layout.md +98 -38
  32. package/data/harnesses/code/skills/design/components/media.md +46 -25
  33. package/data/harnesses/code/skills/design/components/motion.md +56 -46
  34. package/data/harnesses/code/skills/design/components/navigation.md +54 -15
  35. package/data/harnesses/code/skills/design/components/overlays.md +51 -41
  36. package/data/harnesses/code/skills/design/components/setup.md +84 -5
  37. package/data/harnesses/code/skills/design/components/typography.md +72 -22
  38. package/data/harnesses/code/skills/design/components/utils.md +47 -13
  39. package/data/harnesses/code/skills/design/data/chrome/board-column.md +12 -12
  40. package/data/harnesses/code/skills/design/data/chrome/data-table.md +6 -6
  41. package/data/harnesses/code/skills/design/data/chrome/side-panel.md +15 -15
  42. package/data/harnesses/code/skills/design/data/chrome/sidebar.md +25 -25
  43. package/data/harnesses/code/skills/design/data/chrome/stat-cards.md +22 -22
  44. package/data/harnesses/code/skills/design/data/chrome/topbar.md +12 -12
  45. package/data/harnesses/code/skills/design/data/iconography.md +2 -2
  46. package/data/harnesses/code/skills/design/references/compose.md +14 -16
  47. package/data/harnesses/code/skills/design/references/emission.md +6 -6
  48. package/data/harnesses/code/skills/design/references/foundations.md +5 -5
  49. package/data/harnesses/code/skills/design/references/intake.md +6 -6
  50. package/data/harnesses/code/skills/design/references/object-pass.md +1 -1
  51. package/data/harnesses/code/skills/design/references/ship-gate.md +5 -5
  52. package/data/harnesses/code/skills/design/references/ux-patterns/Readme.md +4 -4
  53. package/data/harnesses/code/skills/design/references/ux-patterns/ai-layer.md +1 -1
  54. package/data/harnesses/code/skills/design/references/ux-patterns/container-choice.md +1 -1
  55. package/data/harnesses/code/skills/design/references/ux-patterns/dashboards.md +1 -1
  56. package/data/harnesses/code/skills/design/references/ux-patterns/modes.md +1 -1
  57. package/data/harnesses/code/skills/design/references/ux-patterns/object-model.md +2 -2
  58. package/data/harnesses/code/skills/design/references/ux-patterns/promotion-demotion.md +1 -1
  59. package/data/harnesses/code/skills/design/references/ux-patterns/settings.md +1 -1
  60. package/data/harnesses/code/skills/design/references/ux-patterns/standard-pages.md +1 -1
  61. package/data/harnesses/code/skills/design/scripts/README-validator.md +20 -8
  62. package/data/harnesses/code/skills/design/scripts/validate-design-md.mjs +15 -10
  63. package/data/harnesses/code/skills/documentation/SKILL.md +5 -5
  64. package/data/harnesses/code/skills/documentation/references/examples.md +22 -22
  65. package/data/harnesses/code/skills/documentation/references/frontmatter.md +3 -3
  66. package/data/harnesses/code/skills/documentation/references/instruction-style.md +3 -3
  67. package/data/harnesses/code/skills/documentation/references/source-comments.md +3 -3
  68. package/data/harnesses/code/skills/documentation/references/style-guide.md +5 -5
  69. package/data/harnesses/code/skills/documentation/references/untemplated.md +8 -8
  70. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +3 -2
  71. package/data/harnesses/code/skills/documentation/templates/Readme.md +1 -1
  72. package/data/harnesses/code/skills/documentation/templates/acceptance-criteria.md +1 -1
  73. package/data/harnesses/code/skills/documentation/templates/api-reference.md +1 -1
  74. package/data/harnesses/code/skills/documentation/templates/architecture-decision.md +3 -7
  75. package/data/harnesses/code/skills/documentation/templates/behavioral-checklist.md +1 -1
  76. package/data/harnesses/code/skills/documentation/templates/changelog-entry.md +1 -1
  77. package/data/harnesses/code/skills/documentation/templates/changelog-index.md +1 -1
  78. package/data/harnesses/code/skills/documentation/templates/docs-readme.md +3 -3
  79. package/data/harnesses/code/skills/documentation/templates/doctrine.md +1 -1
  80. package/data/harnesses/code/skills/documentation/templates/domain-model.md +1 -1
  81. package/data/harnesses/code/skills/documentation/templates/environment-registry.md +1 -1
  82. package/data/harnesses/code/skills/documentation/templates/feature.md +3 -3
  83. package/data/harnesses/code/skills/documentation/templates/handover.md +2 -2
  84. package/data/harnesses/code/skills/documentation/templates/implementation-map.md +1 -1
  85. package/data/harnesses/code/skills/documentation/templates/migration-runbook.md +1 -1
  86. package/data/harnesses/code/skills/documentation/templates/non-goals.md +1 -1
  87. package/data/harnesses/code/skills/documentation/templates/operations-procedure.md +2 -2
  88. package/data/harnesses/code/skills/documentation/templates/package.md +1 -1
  89. package/data/harnesses/code/skills/documentation/templates/protected-files.md +1 -1
  90. package/data/harnesses/code/skills/documentation/templates/root-readme.md +1 -1
  91. package/data/harnesses/code/skills/documentation/templates/security-overview.md +1 -1
  92. package/data/harnesses/code/skills/documentation/templates/system-overview.md +1 -1
  93. package/data/harnesses/code/skills/documentation/templates/system.md +1 -1
  94. package/data/harnesses/code/skills/documentation/templates/testing-strategy.md +1 -1
  95. package/data/harnesses/code/skills/documentation/templates/ux-behavior.md +3 -5
  96. package/data/harnesses/code/skills/issue-bridge/SKILL.md +51 -16
  97. package/data/harnesses/code/skills/issue-bridge/references/trackers/github.md +5 -5
  98. package/data/harnesses/code/skills/issue-bridge/references/trackers/jira.md +11 -8
  99. package/data/harnesses/code/skills/issue-bridge/references/trackers/linear.md +16 -11
  100. package/data/harnesses/code/skills/nustack-graph/SKILL.md +38 -29
  101. package/data/harnesses/code/skills/polygraph/references/dispatch.md +31 -18
  102. package/data/harnesses/code/skills/polygraph/references/rows.md +11 -6
  103. package/data/harnesses/code/skills/schema-design/SKILL.md +39 -41
  104. package/data/harnesses/code/skills/test/SKILL.md +38 -42
  105. package/data/harnesses/code/skills/testing/SKILL.md +83 -73
  106. package/data/harnesses/code/skills/workflow-mapper/SKILL.md +156 -193
  107. package/data/harnesses/code/skills/workflow-mapper/references/patterns.md +15 -15
  108. package/data/harnesses/delivery/harness.json +2 -2
  109. package/data/harnesses/delivery/skills/brainstorm/README.md +11 -13
  110. package/data/harnesses/delivery/skills/brainstorm/SKILL.md +150 -132
  111. package/data/harnesses/delivery/skills/brainstorm/references/doctrine.md +48 -51
  112. package/data/harnesses/delivery/skills/brainstorm/references/harvest.md +51 -56
  113. package/data/harnesses/delivery/skills/brainstorm/references/session-schema.md +48 -42
  114. package/data/harnesses/delivery/skills/cost-report/SKILL.md +10 -10
  115. package/data/harnesses/delivery/skills/documentation/SKILL.md +5 -5
  116. package/data/harnesses/delivery/skills/documentation/references/examples.md +22 -22
  117. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +3 -3
  118. package/data/harnesses/delivery/skills/documentation/references/instruction-style.md +3 -3
  119. package/data/harnesses/delivery/skills/documentation/references/source-comments.md +3 -3
  120. package/data/harnesses/delivery/skills/documentation/references/style-guide.md +5 -5
  121. package/data/harnesses/delivery/skills/documentation/references/untemplated.md +8 -8
  122. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +3 -2
  123. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +1 -1
  124. package/data/harnesses/delivery/skills/documentation/templates/acceptance-criteria.md +1 -1
  125. package/data/harnesses/delivery/skills/documentation/templates/api-reference.md +1 -1
  126. package/data/harnesses/delivery/skills/documentation/templates/architecture-decision.md +3 -7
  127. package/data/harnesses/delivery/skills/documentation/templates/behavioral-checklist.md +1 -1
  128. package/data/harnesses/delivery/skills/documentation/templates/changelog-entry.md +1 -1
  129. package/data/harnesses/delivery/skills/documentation/templates/changelog-index.md +1 -1
  130. package/data/harnesses/delivery/skills/documentation/templates/docs-readme.md +3 -3
  131. package/data/harnesses/delivery/skills/documentation/templates/doctrine.md +1 -1
  132. package/data/harnesses/delivery/skills/documentation/templates/domain-model.md +1 -1
  133. package/data/harnesses/delivery/skills/documentation/templates/environment-registry.md +1 -1
  134. package/data/harnesses/delivery/skills/documentation/templates/feature.md +3 -3
  135. package/data/harnesses/delivery/skills/documentation/templates/handover.md +2 -2
  136. package/data/harnesses/delivery/skills/documentation/templates/implementation-map.md +1 -1
  137. package/data/harnesses/delivery/skills/documentation/templates/migration-runbook.md +1 -1
  138. package/data/harnesses/delivery/skills/documentation/templates/non-goals.md +1 -1
  139. package/data/harnesses/delivery/skills/documentation/templates/operations-procedure.md +2 -2
  140. package/data/harnesses/delivery/skills/documentation/templates/package.md +1 -1
  141. package/data/harnesses/delivery/skills/documentation/templates/protected-files.md +1 -1
  142. package/data/harnesses/delivery/skills/documentation/templates/root-readme.md +1 -1
  143. package/data/harnesses/delivery/skills/documentation/templates/security-overview.md +1 -1
  144. package/data/harnesses/delivery/skills/documentation/templates/system-overview.md +1 -1
  145. package/data/harnesses/delivery/skills/documentation/templates/system.md +1 -1
  146. package/data/harnesses/delivery/skills/documentation/templates/testing-strategy.md +1 -1
  147. package/data/harnesses/delivery/skills/documentation/templates/ux-behavior.md +3 -5
  148. package/data/harnesses/delivery/skills/escalate/SKILL.md +11 -11
  149. package/data/harnesses/delivery/skills/prompt-eval/SKILL.md +8 -8
  150. package/data/harnesses/delivery/skills/prompt-library/SKILL.md +30 -9
  151. package/data/harnesses/delivery/skills/route/SKILL.md +8 -8
  152. package/data/harnesses/etna/harness.json +2 -2
  153. package/data/harnesses/etna/skills/boundary/SKILL.md +33 -22
  154. package/data/harnesses/etna/skills/boundary/references/index.md +2 -4
  155. package/data/harnesses/etna/skills/boundary/references/mechanisms.md +3 -10
  156. package/data/harnesses/etna/skills/boundary/references/packs/build-config-runtime.md +1 -1
  157. package/data/harnesses/etna/skills/boundary/references/packs/frontend.md +17 -17
  158. package/data/harnesses/etna/skills/boundary/references/packs/generic-tail.md +1 -1
  159. package/data/harnesses/etna/skills/brainstorm/README.md +11 -13
  160. package/data/harnesses/etna/skills/brainstorm/SKILL.md +150 -132
  161. package/data/harnesses/etna/skills/brainstorm/references/doctrine.md +48 -51
  162. package/data/harnesses/etna/skills/brainstorm/references/harvest.md +51 -56
  163. package/data/harnesses/etna/skills/brainstorm/references/session-schema.md +48 -42
  164. package/data/harnesses/etna/skills/documentation/SKILL.md +5 -5
  165. package/data/harnesses/etna/skills/documentation/references/examples.md +22 -22
  166. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +3 -3
  167. package/data/harnesses/etna/skills/documentation/references/instruction-style.md +3 -3
  168. package/data/harnesses/etna/skills/documentation/references/source-comments.md +3 -3
  169. package/data/harnesses/etna/skills/documentation/references/style-guide.md +5 -5
  170. package/data/harnesses/etna/skills/documentation/references/untemplated.md +8 -8
  171. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +3 -2
  172. package/data/harnesses/etna/skills/documentation/templates/Readme.md +1 -1
  173. package/data/harnesses/etna/skills/documentation/templates/acceptance-criteria.md +1 -1
  174. package/data/harnesses/etna/skills/documentation/templates/api-reference.md +1 -1
  175. package/data/harnesses/etna/skills/documentation/templates/architecture-decision.md +3 -7
  176. package/data/harnesses/etna/skills/documentation/templates/behavioral-checklist.md +1 -1
  177. package/data/harnesses/etna/skills/documentation/templates/changelog-entry.md +1 -1
  178. package/data/harnesses/etna/skills/documentation/templates/changelog-index.md +1 -1
  179. package/data/harnesses/etna/skills/documentation/templates/docs-readme.md +3 -3
  180. package/data/harnesses/etna/skills/documentation/templates/doctrine.md +1 -1
  181. package/data/harnesses/etna/skills/documentation/templates/domain-model.md +1 -1
  182. package/data/harnesses/etna/skills/documentation/templates/environment-registry.md +1 -1
  183. package/data/harnesses/etna/skills/documentation/templates/feature.md +3 -3
  184. package/data/harnesses/etna/skills/documentation/templates/handover.md +2 -2
  185. package/data/harnesses/etna/skills/documentation/templates/implementation-map.md +1 -1
  186. package/data/harnesses/etna/skills/documentation/templates/migration-runbook.md +1 -1
  187. package/data/harnesses/etna/skills/documentation/templates/non-goals.md +1 -1
  188. package/data/harnesses/etna/skills/documentation/templates/operations-procedure.md +2 -2
  189. package/data/harnesses/etna/skills/documentation/templates/package.md +1 -1
  190. package/data/harnesses/etna/skills/documentation/templates/protected-files.md +1 -1
  191. package/data/harnesses/etna/skills/documentation/templates/root-readme.md +1 -1
  192. package/data/harnesses/etna/skills/documentation/templates/security-overview.md +1 -1
  193. package/data/harnesses/etna/skills/documentation/templates/system-overview.md +1 -1
  194. package/data/harnesses/etna/skills/documentation/templates/system.md +1 -1
  195. package/data/harnesses/etna/skills/documentation/templates/testing-strategy.md +1 -1
  196. package/data/harnesses/etna/skills/documentation/templates/ux-behavior.md +3 -5
  197. package/data/harnesses/etna/skills/workflow-mapper/SKILL.md +156 -193
  198. package/data/harnesses/etna/skills/workflow-mapper/references/patterns.md +15 -15
  199. package/data/harnesses/hr/harness.json +2 -2
  200. package/data/harnesses/hr/skills/evaluator/SKILL.md +71 -73
  201. package/data/harnesses/hr/skills/evaluator/criteria/code-quality.md +28 -47
  202. package/data/harnesses/hr/skills/evaluator/criteria/deployment-readiness.md +33 -43
  203. package/data/harnesses/hr/skills/evaluator/criteria/maintainability.md +34 -46
  204. package/data/harnesses/hr/skills/evaluator/criteria/mechanical-ambition.md +13 -13
  205. package/data/harnesses/hr/skills/evaluator/criteria/problem-substantiveness.md +7 -7
  206. package/data/harnesses/hr/skills/evaluator/criteria/testing.md +36 -41
  207. package/data/harnesses/hr/skills/evaluator/criteria/ux-mechanics.md +25 -11
  208. package/data/harnesses/hr/skills/evaluator/criteria/value-articulation.md +7 -7
  209. package/data/harnesses/hr/skills/evaluator/preflight.md +27 -46
  210. package/data/harnesses/hr/skills/interview-eval/SKILL.md +37 -42
  211. package/data/harnesses/hr/skills/interview-eval/rubric.md +21 -23
  212. package/package.json +2 -2
@@ -2,75 +2,153 @@
2
2
 
3
3
  > Generated reference (regen-owned; see [index.md](index.md)). Binds only under `primitives: nurix`.
4
4
 
5
- Three tiers, all consuming the canonical `ChartSeries[]` / `ChartPoint` data contract (re-exported from `@nurix/components/charts`) and resolving color through tokens — no chart takes hex literals as its primary color path.
5
+ Components: Spark, Chart, ChartErrorCard, StatusTimeline, plus the chart kernel helpers
6
6
 
7
- - **Tier 0 — marks only:** `spark`
8
- - **Tier 1 — inline charts:** `bar-graph`, `line-graph`, `pie-graph`, `progress-bar`, `sparkline`, plus the standalone families `funnel`, `gauge`, `heatmap`, `radar`, `ring`; shared chrome in `chart-primitives`
9
- - **Tier 2 — composable dashboard shells:** the `charts` subpath (visx-based)
7
+ Four entry points, all resolving colour through the `--chart-*` tokens — no chart takes a hex literal as its colour path:
10
8
 
11
- > The old `chart` subpath (a dead recharts wrapper) was removed with the 2026-07 chart adoption — it no longer exists; the `charts` family below replaced it.
9
+ - **Tier 0 — marks only:** `Spark` (`element/spark`) — an axis-less inline trend.
10
+ - **Tier 1 — spec-native charts:** `Chart` (`block/chart`) — one component rendering fourteen families from a serializable `{ config, theme?, data? }` spec.
11
+ - **Status strip:** `StatusTimeline` (`compound/status-timeline`) — one stacked bar per day, no axis; not a bar chart.
12
+ - **Kernel:** `lib/chart-kernel` (+ `/arc`, `/colors`, `/line`) — the data contract, colour policy, formatters and geometry, for a bespoke mark neither `Chart` nor `Spark` draws.
12
13
 
13
14
  ## Spark
14
15
 
15
- Tier-0 inline mark — no axes, no chrome. Import from `@nurix/components/element/spark`.
16
+ Tier-0 trend mark for a stat card or a caption — no axes, no legend, no tooltip, never a tab stop. Import from `@nurix/components/element/spark`. Install the `spark` peer family first: `@mantine/charts @mantine/core recharts`, plus `@mantine/hooks` (which `@mantine/core` peers on); no `MantineProvider` or Mantine stylesheet is needed.
16
17
 
17
- **Props:** `series` (`ChartSeries[]` or plain `number[]`), `type` [line|bar|pie], `filled`, `fillOpacity`, `strokeWidth` (line), `gap` (bar), `width`, `height`, `useTokens` (default false: self-contained oklch; true: `--chart-N` tokens)
18
+ **Props:** `values` (`(number | null)[]` — a `null` is a gap, never a zero), `family` [line|area|bar|pie] (default `line`), `width` / `height` (default `100`×`30` px; a class such as `w-full` overrides the width), `color` (any CSS colour, default `currentColor`), `strokeWidth` (line and area, default `1.5`), `gap` (bar, default `2`), `colors` (pie, per slice; default the `--chart-N` palette), `animate` (default `false`), `label`
19
+
20
+ - The props are a union on `family`: `strokeWidth` on bar, `gap` on line or area, `colors` off pie, and `width` or `color` on pie are type errors. A pie is a `height`×`height` square.
21
+ - It paints in `currentColor`, so a muted caption gives a muted spark; pass `color="var(--chart-1)"` for a token colour.
22
+ - It is `aria-hidden` until `label` names it (then `role="img"`) — a trend beside its number is decorative; a spark standing alone wants a label.
23
+ - A table's sparkline column is `block/table`'s `TableSparkline`, never a hand-embedded `Spark`.
18
24
 
19
25
  ```tsx
20
- <Spark series={[4, 6, 5, 9, 7, 12]} type="line" filled width={96} height={24} />
26
+ <Spark values={[4, 6, null, 9, 7, 12]} family="area" color="var(--chart-1)" className="w-full" />
21
27
  ```
22
28
 
23
- ## Inline charts
29
+ ## Chart
30
+
31
+ The spec-native chart. Import `Chart` from `@nurix/components/block/chart`. Install the `charts` and `animated-number` peer families first: `@visx/curve @visx/event @visx/grid @visx/group @visx/heatmap @visx/pattern @visx/responsive @visx/scale @visx/shape d3-array @number-flow/react`.
32
+
33
+ **Props:** `config` (what the chart means — `version`, `family`, `title`, `format`, `overlays`, `encode`, and `x` on cartesian families), `theme` (how it is presented — `context`, `motion`, `color`, `chrome`, `interaction`, `labels`), `data` (typed by `config.family`), `loading`, `onHoverChange`, `onRangeChange`, `pinnedIndex` / `defaultPinnedIndex` / `onPinnedIndexChange`, `onValidationIssue`, `replayNonce` (bump to replay enter motion), plus `ref`, `className` and any div prop, landing on the one root in every state.
34
+
35
+ - **Validation is internal and always on** — `withDefaultVersion` → `migrateSpec` → `validateChartSpec` → `diagnoseChart` → `normalize` on every render. An invalid spec never throws and never renders blank: it renders `ChartErrorCard` (`errors`, `labels`) naming the first violation's JSON Pointer. Warnings render the chart and report through `onValidationIssue`, once per distinct set.
36
+ - **`version` is `CURRENT_VERSION` (2).** A stored spec carries its own `version`; only the JSX boundary defaults a missing one. `migrateSpec` walks a spec forward only, so a spec newer than the installed renderer is rejected, never downgraded.
37
+ - **Every colour field takes a token slot, never a literal:** `chart-1`…`chart-5` (categorical, wrapping after five), `chart-positive`, `chart-negative`, `chart-diverging-mid`, `chart-scale-01`…`chart-scale-05`. `theme.color.palette` reorders the five categorical slots; an explicit series `color` wins over it.
38
+ - **Size comes from the parent.** `Chart` sets only `w-full`. The `cell`/`card` backend stretches into its parent's box; the `dashboard` backend renders nothing until it measures a non-zero ancestor — an unsized parent is a silently empty chart either way.
39
+ - **Emit-loop pre-flight:** `validateChartSpec(spec)` returns `{ ok, value | errors }`; `diagnoseChart(spec)` returns `{ errors, warnings }` over the data values (log scale over non-positive values, a palette wrap, date-like x on a category axis) — treat both as blocking before storing an artifact. `explainSpec(spec)` reports which default supplied each resolved value. `normalize` and `withDefaultVersion` are exported beside them.
40
+
41
+ ### Context
42
+
43
+ `theme.context` is `cell`, `card` or `dashboard`; it picks density defaults, the capability envelope and the backend. An omitted context resolves from the host — `cell` inside a `data-mode="inline"` or `data-density="compact"` ancestor, otherwise `card`. **A host never implies `dashboard`**, so a dashboard-only family needs `theme: { context: "dashboard" }` or it fails validation with the recorded reason.
24
44
 
25
- Import via `@nurix/components/<subpath>`; each ships a matching skeleton.
45
+ | Context | Chrome | Interaction | Motion (`auto`) | Families admitted |
46
+ | --- | --- | --- | --- | --- |
47
+ | `cell` | none | hover off unless turned on | none, whatever the request | line, area, bar, pie, progress, ring, gauge, stat |
48
+ | `card` | value labels and legend, off by default | hover on, pin off | enter | line, area, bar, pie, progress, ring, gauge, stat |
49
+ | `dashboard` | grid horizontal and both axes on; value labels and legend admissible | hover with a crosshair; `range` opt-in | full | line, area, bar, composed, scatter, funnel, heatmap-calendar, heatmap-matrix, radar |
26
50
 
27
- - `bar-graph` — `BarGraph`, `BarGraphSkeleton`
28
- - `line-graph` — `LineGraph`, `LineGraphSkeleton` (re-exports `ChartSeries`)
29
- - `pie-graph` — `PieGraph`, `PieGraphSkeleton` (variants pie|half-pie|doughnut|half-doughnut; doughnut variants take a `center` prop that auto-fits content in the hole)
30
- - `progress-bar` — `ProgressBar`, `ProgressBarSkeleton` (segmented multi-series bars; distinct from the `progress` subpath's shadcn Progress primitive)
31
- - `sparkline` — `Sparkline` (legacy; prefer `Spark` for new work)
51
+ ### Families and their data
32
52
 
33
- ## Standalone chart families
53
+ `config.family` is a closed enum, and each family takes exactly one data class. The cartesian families (`line`, `area`, `bar`, `composed`) require `x: { type: "time" | "category" | "linear", grain? }`; `scatter` requires `x: { type: "linear" | "log" | "time", grain? }`. `grain` is `hour`, `day`, `week`, `month`, `quarter` or `year`. `encode` is the one family-shaped key; an unknown key is a rejection naming the legal keys. Shared knobs keep one shape: `sort` is `"none" | "asc" | "desc"` or `{ by, order }`, `stack` is `"none" | "stacked" | "percent"`, `diverging` is `{ baseline?, positiveColor?, negativeColor? }`.
34
54
 
35
- Each on its own subpath with tooltip/legend/skeleton companions and full types:
55
+ Series data is `{ series: [{ id, label, points: [{ x, y, size? }], color? }] }` — `y` may be `null`, `id` is unique and stable, series order is stacking and draw order.
36
56
 
37
- - `funnel` — `Funnel` (+ `FunnelTooltip`, `FunnelLegend`, `FunnelSkeleton`): ordered stage bands. **Props:** `data: FunnelData`, `orientation`, `variant` (default `halo`), `sort` (`asc` renders a pyramid), `showPercentage`/`showValues`/`showLabels`, `showDrop` (inter-stage drop-off annotation), `showTooltip`, `percentBasis` (default `first`), `color`, `layers`
38
- - `gauge` — `Gauge`, `Bullet`, `GaugeSkeleton`: value on a [min,max] scale. **Props:** `orientation` (arc or horizontal notch track), `value` (null renders the empty state), `min`/`max`, `zones` (threshold color bands), `target` (tick marker), `ticks`, `showTicks`/`showValues`, `valueFormat`, `centerContent` (arc only), `totalNotches`
39
- - `heatmap` — `Heatmap`, `HeatmapSkeleton`, `HeatmapLegend`, `HeatmapTooltip`, `HeatmapXAxis`/`HeatmapYAxis`/`HeatmapSeparator`: calendar contribution grid. **Props:** `data: HeatmapColumn[]`, `xDomain`, `layout` [fluid|fill], `binSize`, `gap`, `cornerRadius`, `levelColors` (defaults to the `--chart-scale-*` tokens)
40
- - `heatmap` (same subpath) — `MatrixHeatmap`, `MatrixHeatmapSkeleton`, `MatrixHeatmapLegend`, `MatrixHeatmapTooltip`: x-by-y cell matrix (`MatrixHeatmapData` dense or cell list), quantized onto the token ramp
41
- - `radar` — `Radar`, `RadarSkeleton`: series polygons over spider axes. **Props:** `data` (`RadarSeries[]` or `ChartSeries[]`), `metrics` (ordered axes; derived when omitted), `levels`, `scaling` [independent|shared] (default `independent` — honest mixed-unit rendering), `maxValue`, `nullMode` [zero|gap], `colors`, `size`
42
- - `ring` — `Ring`, `RingSkeleton`: concentric segmented progress. **Props:** `data: RingDatum[]` (innermost first), `strokeWidth`, `ringGap`, `startAngle`/`endAngle`, `lineCap`, `trackColor`, `animated`, `interactive`, `size`
57
+ - **`line`** — multi-series lines. `encode`: `curve` [linear|smooth|step|stepAfter|stepBefore], `nulls` [gap|bridge] (default `gap`), `markers`, `diverging`, `endpointLabels`.
58
+ - **`area`** — filled series. `encode`: `curve`, `nulls` [gap|bridge], `markers`, `diverging`, `stack`, `band: { lower, upper }` (series ids drawing a range band).
59
+ - **`bar`** — grouped or stacked bars. `encode`: `mode` [categorical|histogram|pareto], `stack`, `horizontal`, `sort` (by `value`, `label` or a series id), `diverging`, `bins`, `binWidth`. **Histogram:** `mode: "histogram"` bins each point's raw `y` samples, so already-binned counts are binned again; `stack` and `sort` are rejected. **Pareto:** fixed descending with a cumulative-percent line; `sort` is rejected.
60
+ - **`composed`** (dashboard) — mixed marks over one shared scale pair. `encode.series` maps each series id to `{ mark: "line" | "area" | "bar", axis?: "left" | "right" }`, at most two y axes.
61
+ - **`scatter`** (dashboard) — x/y point field. `encode`: `yScale` [linear|log], `bubble` (reads `size`), `colorByValue`, `trend` (least-squares line), `quadrant: { x?, y?, shade? }`.
62
+ - **`radar`** (dashboard) — series polygons over spider axes; spokes are the points' categorical `x`. `encode`: `scaling` [independent|shared], `maxValue`, `nulls` [gap|zero] (default `gap`).
63
+ - **`pie`** (cell, card) — data `{ parts: [{ label, value, color? }] }`. `encode`: `donut`, `half`, `sort`, `maxSlices`, `otherThreshold`, `otherLabel` (Other sorts last), `minAngle`, `center` [total|none].
64
+ - **`progress`** (cell, card) — stacked horizontal segments from `parts`, left to right; no `encode` keys; the goal tick is a `target` overlay.
65
+ - **`funnel`** (dashboard) — ordered stage bands from `parts`, top-down. `encode`: `variant` [halo|solid] (`halo` draws concentric rings at ramping opacity), `colorMode` [single|ramp|categorical], `sort` (`asc` renders a pyramid), `showValue`, `showPercent`, `showDrop`.
66
+ - **`gauge`** (cell, card) — data `{ value, min, max }`, the domain required. `encode`: `shape` [arc|linear|bullet], `fill` [solid|gradient|scale]. Threshold bands are `zone` overlays and the goal tick a `target` overlay — `shape: "bullet"` with zones and a target is the bullet chart. Hover is unavailable (one always-visible scalar).
67
+ - **`ring`** (cell, card) — concentric value-vs-max rings. Data `{ rings: [{ label, value, max, color? }] }`, innermost first. `encode`: `endAngle` (narrow it for an arc-gauge look).
68
+ - **`heatmap-calendar`** (dashboard) — contribution grid. Data `{ cells: [{ date, value }] }` with ISO dates. `encode`: `weekStartDay` (0–6), `levels`, `hideGhostCells`.
69
+ - **`heatmap-matrix`** (dashboard) — x-by-y cell matrix on the token ramp. Data `{ cells: [{ x, y, value }] }`. `encode`: `colorScaleType` [sequential|diverging], `divergingMidpoint`, `nulls` [empty|zero|hatch] (default `empty`), `xOrder` / `yOrder` (`none`, `asc`, `desc`, `{ by, order }` or an explicit list), `aggregate` [sum|mean|max|min|count], `highlight` [none|cell|cross], `showValues`.
70
+ - **`stat`** (cell, card) — a KPI. Data `{ value, delta?, history? }` (`history` is points). `encode.visual: { family: "line" | "bar" | "pie" | "gauge" | "ring" | "progress" }` draws a cell-scale mini-chart from stat's own data. A KPI laid out as a page unit is `Stat` (`element/stat`, see [layout](layout.md)).
43
71
 
44
- ## Chart chrome primitives
72
+ ```tsx
73
+ import { Chart } from "@nurix/components/block/chart";
74
+
75
+ <Chart
76
+ config={{
77
+ version: 2,
78
+ family: "line",
79
+ title: "Revenue",
80
+ x: { type: "time", grain: "month" },
81
+ format: { y: { kind: "currency", currency: "USD", compact: true } },
82
+ encode: { curve: "smooth" },
83
+ overlays: [{ type: "line", y: 50000, label: "Target", color: "chart-negative" }],
84
+ }}
85
+ theme={{ context: "dashboard", chrome: { legend: "bottom" } }}
86
+ data={{ series: [{ id: "rev", label: "Revenue", points: [{ x: "2026-01-01", y: 42000 }, { x: "2026-02-01", y: 51000 }] }] }}
87
+ />
88
+
89
+ <Chart
90
+ config={{
91
+ version: 2,
92
+ family: "gauge",
93
+ title: "Quota",
94
+ encode: { shape: "bullet" },
95
+ overlays: [{ type: "zone", from: 0, to: 60, color: "chart-scale-01" }, { type: "target", value: 80 }],
96
+ }}
97
+ data={{ value: 72, min: 0, max: 100 }}
98
+ />
99
+ ```
100
+
101
+ ### Chrome, interaction, overlays and labels
45
102
 
46
- `@nurix/components/chart-primitives` — shared tier-1 chrome: `ChartEmpty` (empty state), `ChartHoverCard` (tooltip surface; `ChartHoverCardRow`), `ChartLegend` (`ChartLegendItem`, `ChartLegendPosition`).
103
+ The shared chart chrome — legend, tooltip, empty and error states — is set by the spec, never composed as children.
47
104
 
48
- ## Dashboard charts (`charts` subpath)
105
+ - **`theme.chrome`:** `grid` [none|horizontal|both], `xAxis` / `yAxis` / `yAxisRight` (`{ ticks, tickMode, format, largeNumbers, orientation }` or `false`), `legend` [none|right|bottom|inline], `valueLabels` (`true` or `{ position: "inside" | "outside", endpointOnly, total }`), `background` (a plot-area pattern). `legend` and `valueLabels` are illegal at `cell`; grid, axes and `background` are dashboard-only.
106
+ - **`theme.interaction`:** `hover`, `pin`, `range` [none|xband|box]. `pin` is legal on bar, pie, scatter, funnel and both heatmaps; `xband` on line, area, bar and composed; `box` on scatter only. Not every handler reaches the host from every renderer — dashboard hover reaches `onHoverChange` only from the two heatmaps, pin reaches `onPinnedIndexChange` only from `funnel`, and no renderer emits `onRangeChange`.
107
+ - **`config.overlays`:** `zone` (`from`, `to`, `color`, `label`), `target` (`value`), `line` (`x` or `y`), `dot` (`{ x, y }` or `{ resolve: "max" | "min" | "average", seriesId }`), `annotation` (`x`, `text`, `variant` [point|event]), `projection` (`seriesId`, `horizon`). Each is legal only on the families its envelope lists — `zone` on the cartesian families, scatter and gauge; `target` on line, area, bar, composed, gauge, progress and ring; `projection` on line and area.
108
+ - **`config.format`:** `x`, `y`, `value` channels, each `{ kind: "compact" | "int" | "percent" | "currency" | "unit" | "date", … }` with optional `prefix` / `suffix`.
109
+ - **`theme.motion`:** [none|enter|full|auto] (default `auto`, resolved by context).
110
+ - **`theme.labels`:** every string the chart writes — `empty` ("No data"), `invalid`, `invalidName`, `more`, `didYouMean`, `total`, `loading`, `retry`.
49
111
 
50
- Composable visx-based shells — a shell provides scales/context, marks draw data ink, chrome and overlays compose as children. All from `@nurix/components/charts`.
112
+ ## StatusTimeline
51
113
 
52
- **Shells:** `AreaChart`, `BarChart` (`BarOrientation`), `LineChart`, `ScatterChart`, `ComposedChart` — plus standalone loading shells `AreaChartLoading`, `BarChartLoading`, `LineChartLoading`
114
+ An uptime/status strip: one stacked bar per day with a shared day card on hover, focus or pin. No axis — a quantitative time series is `Chart`, a single percentage is `element/progress`. Import `StatusTimeline` and `formatDateRange` from `@nurix/components/compound/status-timeline`.
53
115
 
54
- **Recipes & transforms:** `Bullet`, `Histogram` (+ `computeHistogramBins`, `binsToRows`), `ParetoLine` (+ `computeParetoRows`), `BarSort`, `BarStackMode`
116
+ **Props:** `data: StatusTimelineData[]`, `title` (a muted caption that also names the strip), `height` (px, default `50`), `spacing` [none|sm|md|lg] (default `sm`), `roundedCorners` [none|top|all] (default `top`), `isNormalized` (default `true`), `hasTrack`, `animate` (default `false`), `locale`, `labels`, `loading`, `emptyState`, `renderBar(segment, index, { day, total })`, `renderCard`, `renderEvent`, `render`
55
117
 
56
- **Marks:** `Area`, `RangeArea`, `Bar`, `Line` (`DivergingConfig`), `Scatter`, `SeriesBar`, `SeriesMarkers`, `ValueLabels`; curve factories `curveLinear`, `curveMonotoneX`, `curveNatural`, `curveStep`, `curveStepAfter`, `curveStepBefore` (pass to a mark's `curve` prop — never import `@visx/curve` directly)
118
+ - One record per day: `{ day, summary?, bar: [{ intent, height }], card: [{ intent, value }], events: [{ id, name, type, from, to }] }`. `day` is an ISO date read in local time; `summary` is the card's muted header line; event `type` is `incident`, `report` or `maintenance`.
119
+ - `isNormalized` reads `bar[].height` as a percentage of 100 per day — pass raw counts with `isNormalized={false}`, or every bar mis-fills.
120
+ - Colour comes from `intent` (`neutral`, `info`, `success`, `warning`, `danger`) and the `--intent-*` tokens; retint by redeclaring the tokens, never a per-strip colour map.
121
+ - `loading` renders the skeleton; there is no separate skeleton member.
122
+ - `formatDateRange(from?, to?, { locale, labels })` formats an event's range, collapsing a same-day range.
57
123
 
58
- **Chrome:** `XAxis`, `YAxis`, `BarXAxis`, `BarYAxis`, `Grid`, `Background` (pattern presets), `PatternArea`, `PatternCircles`/`PatternHexagons`/`PatternLines`/`PatternWaves`
124
+ ```tsx
125
+ <StatusTimeline
126
+ title="API uptime"
127
+ data={[{
128
+ day: "2026-08-07",
129
+ summary: "1,204 requests",
130
+ bar: [{ intent: "success", height: 92 }, { intent: "warning", height: 8 }],
131
+ card: [{ intent: "success", value: "92%" }, { intent: "warning", value: "8%" }],
132
+ events: [],
133
+ }]}
134
+ />
135
+ ```
59
136
 
60
- **Tooltip & legend:** composable subsystems re-exported whole (`./tooltip`, `./legend` internals)
137
+ ## Chart kernel
61
138
 
62
- **Overlays:** `ReferenceLine`, `ReferenceArea`, `ReferenceDot`, `Annotation` (`AnnotationVariant`), `ProjectionLine`, `ProfitLossLine` + `ProfitLossLegend`, `ChartBrush`
139
+ The coherence-bearing subset of the chart core, for bespoke visualization code that must match the `Chart` system. Reach for it only for a mark neither `Chart` nor `Spark` draws; needing decimation, scatter geometry, thresholds or interaction scheduling is the signal to use a chart family — those stay unpublished.
63
140
 
64
- **Data contract:** `ChartPoint`, `ChartSeries`, `isChartSeriesArray`, `seriesToRows`
141
+ - **`lib/chart-kernel`:** the data contract types `ChartSeries` (`{ id, label, points, color? }`), `ChartPoint` (`{ x, y }`), `ChartSlice`, `ColorableSeries`; the colour policy `resolveSeriesColors(series, { useTokens })` / `resolveSeriesColor(index, explicitColor?, { useTokens })`; `buildColorScale(min, max, kind)` (`sequential` by default over `--chart-scale-01..05`, or `diverging` over `--chart-negative` / `--chart-diverging-mid` / `--chart-positive`); the formatters `formatCompactNumber`, `formatPercent(ratio, precision)`, `intFmt`, `shortDateFmt`, `weekdayDateFmt`, `monthLongFmt`, `monthShortFmt`, `weekdayLongFmt`, `hmsTimeFmt`; and `isChartDataEmpty(series)`.
142
+ - **`lib/chart-kernel/colors`:** `resolveSeriesColors`, `resolveSeriesColor` at a narrower entry.
143
+ - **`lib/chart-kernel/arc`:** `computeSliceAngles(values, startAngle, totalAngle)`, `arcCentroid`, `buildArcPath({ cx, cy, innerRadius, outerRadius, startAngle, endAngle, padAngle?, cornerRadius? })` (wedge and ring paths), `isFullArc(startAngle, endAngle)`.
144
+ - **`lib/chart-kernel/line`:** `resolveLineDomain(values)`, `createLineScales(config)`, `buildPolylinePoints`, `buildAreaPoints`, `buildLinePath(points, scales, curve, connectNulls)`, `buildAreaPath`, `buildBandAreaPath` — `curve` is `linear`, `smooth`, `step`, `stepAfter` or `stepBefore`.
145
+ - Colour resolves explicit override → `var(--chart-1..5)` → self-contained `oklch` fallbacks; pass `{ useTokens: false }` only for a shell with no theme wiring, or the marks stop re-branding with the host stylesheet.
146
+ - The formatter singletons are fixed to `en-US` at module scope and never follow the runtime locale — a localized axis builds its own `Intl` instance.
65
147
 
66
148
  ```tsx
67
- import { LineChart, Line, XAxis, YAxis, Grid, ReferenceLine } from "@nurix/components/charts";
68
-
69
- <LineChart series={revenue}>
70
- <Grid />
71
- <XAxis />
72
- <YAxis />
73
- <Line curve={curveMonotoneX} />
74
- <ReferenceLine y={target} label="Target" />
75
- </LineChart>
149
+ import { resolveSeriesColors } from "@nurix/components/lib/chart-kernel";
150
+ import { computeSliceAngles, buildArcPath } from "@nurix/components/lib/chart-kernel/arc";
151
+
152
+ const colors = resolveSeriesColors(slices);
153
+ const angles = computeSliceAngles(slices.map((s) => s.value), 0, Math.PI * 2);
76
154
  ```
@@ -2,52 +2,59 @@
2
2
 
3
3
  > Generated reference (regen-owned; see [index.md](index.md)). Binds only under `primitives: nurix`.
4
4
 
5
+ Components: Table, UiTable, List, Tree, FieldGrid, AnchoredScroller, Composer, MicInput, StreamingCursor, Marker
6
+
7
+ Each imports from its own subpath as one namespace, with its parts as dotted members, e.g. `import { UiTable } from "@nurix/components/block/ui-table"` then `UiTable.Row`, `UiTable.Cell`. `Table` is the exception: a single generic root whose cell renderers stay flat named exports.
8
+
5
9
  ## Table
6
10
 
7
- Data table with sorting, pagination, and row selection. Zero-config `<Table data columns />` renders bare; selection, sorting, pagination, and resize are opt-in via `tableConfig`.
11
+ Server-driven data table on a TanStack engine (`block/table`). Zero-config `<Table data columns />` renders bare; selection, sorting, pagination, resize and the grid keyboard model are opt-in via `tableConfig`. Install its two optional peer families first — `table` (`@tanstack/react-table`) and `spark` (`@mantine/charts @mantine/core recharts`, for the lazily loaded sparkline cell); a missing peer fails at the bundler with the package named.
8
12
 
9
13
  **Props:**
10
14
 
11
- - `data` - Array of row objects (must have `id` field)
15
+ - `data` - Array of row objects (each must have an `id` string)
12
16
  - `columns` - Array of `ColumnDefinition` objects
13
- - `columnOrder` - Optional column order (defaults to column definition order)
14
- - `pagination` - `{ current, size, total, onChange }`
15
- - `sorting` - `{ columns, direction, onChange }` (max 3 sort columns)
17
+ - `columnOrder` - Composite column ids in display order (defaults to column definition order)
18
+ - `pagination` - `{ current, size, total, onChange }` — controlled and 1-indexed; slice `data` to the current page yourself
19
+ - `sorting` - `{ columns, direction, onChange }` (max 3 sort columns) — `columns` takes composite ids
16
20
  - `onSelect` - Callback with selected row IDs
17
- - `onCellChange` - Write-back from `editable` cells: `({ rowId, columnId, slug, value }) => void` (data stays consumer-controlled)
21
+ - `onCellChange` - Write-back from `editable` cells: `({ rowId, columnId, slug, value }) => void`; fires only on a real commit (a blur that typed nothing emits nothing), and the table never mutates `data`
18
22
  - `loading` - Show loading skeleton
19
- - `tableConfig` - Optional; `{ preset, rowSelection, sort, pagination, header, density, columnBorders, tableBorders, resize, autoHeight }`
23
+ - `error` - `{ message, onRetry? }` — a failed fetch renders in place of the rows; wins over `loading`, which wins over the empty body
24
+ - `tableConfig` - Optional; `{ preset, rowSelection, sort, pagination, header, density, columnBorders, tableBorders, resize, autoHeight, gridAria }`
25
+
26
+ `density` is [compact|comfortable|spacious]; `columnBorders`/`tableBorders` are [none|all]. `preset: "classic"` sets a tinted short header row, comfortable density, the pagination footer and `tableBorders: "all"` in one key, and explicit keys override it. The pagination footer is opt-in (`pagination: true`); `gridAria` adds `role="grid"` with roving-tabindex arrow navigation.
20
27
 
21
- `preset: "classic"` restores the legacy look in one key; `resize` gates column drag handles; the pagination footer is opt-in (`pagination: true`).
28
+ **Composite ids.** `sorting.columns` and `columnOrder` take `getColumnId()`'s `${slug}_${component}` id — `name_text` for a `slug: "name"`, `type: "text"` column. A bare `"name"` silently matches no column.
22
29
 
23
30
  ```tsx
24
31
  <Table
25
- data={users}
32
+ data={pageRows}
26
33
  columns={columns}
27
34
  pagination={{ current: 1, size: 10, total: 100, onChange: setPagination }}
28
- sorting={{ columns: ["name"], direction: "asc", onChange: setSorting }}
35
+ sorting={{ columns: ["name_text"], direction: "asc", onChange: setSorting }}
29
36
  onSelect={setSelectedIds}
30
- tableConfig={{ rowSelection: true, resize: true }}
37
+ tableConfig={{ rowSelection: true, pagination: true, resize: true }}
31
38
  />
32
39
  ```
33
40
 
34
41
  ## ColumnDefinition
35
42
 
36
- Define table columns using the `defineColumn()` helper.
43
+ Define table columns with the `defineColumn()` helper, which fills `component` from `type`, `hidden: false`, and empty `metadata`/`display`.
37
44
 
38
45
  **Fields:**
39
46
 
40
- - `slug` - Field key in data object
47
+ - `slug` - Field key in the row object
41
48
  - `label` - Column header text
42
49
  - `type` - Data type: `text`, `number`, `boolean`, `date`, `enum`, `user`
43
- - `component` - Renderer (defaults from `type`): `text`, `number`, `boolean`, `date`, `select`, `multiselect`, `slider`, `rating`, `status`, `priority`, `assignee`, `sparkline`, `date-range`
50
+ - `component` - Renderer (defaults from `type`: `enum` → `select`, `user` → `assignee`, otherwise the type string): `text`, `number`, `boolean`, `date`, `date-range`, `select`, `multiselect`, `slider`, `rating`, `status`, `priority`, `assignee`, `sparkline`
44
51
  - `hidden` - Hide column
45
52
  - `editable` - Activate the interactive widget; columns render the read-only display variant by default
46
53
  - `metadata` - Component-specific options (see table below)
47
- - `display` - `{ width, sortable }` (width optional — columns are fluid when unset)
48
- - `cell` - Custom render function `(row) => ReactNode`
54
+ - `display` - `{ width, sortable }` (width optional — columns are fluid when unset; `sortable` defaults to true except for `boolean` and `user`)
55
+ - `cell` - Custom render function `(row) => ReactNode`; wins over `component`
49
56
 
50
- For full control, pass your own `cell()` or import a renderer from `@nurix/components/block/table` (`StatusPill`, `SelectCell`, etc.) as an escape hatch.
57
+ For full control, pass your own `cell()` and compose a renderer imported from `@nurix/components/block/table` — `EditableText`, `EditableNumber`, `EditableDate`, `EditableDateRange`, `BooleanCell`, `SliderCell`, `RatingCell`, `SelectCell`, `StatusCell`, `PriorityCell`, `AssigneeChip`, `MultiSelectCell`, `TableSparkline`. Each is a flat export so a consumer pays only for the renderers it imports.
51
58
 
52
59
  ### Metadata options by component
53
60
 
@@ -67,13 +74,13 @@ For full control, pass your own `cell()` or import a renderer from `@nurix/compo
67
74
  import { defineColumn } from "@nurix/components/block/table";
68
75
 
69
76
  const columns = [
70
- defineColumn({
77
+ defineColumn<Row>({
71
78
  slug: "name",
72
79
  label: "Name",
73
80
  type: "text",
74
81
  editable: true,
75
82
  }),
76
- defineColumn({
83
+ defineColumn<Row>({
77
84
  slug: "status",
78
85
  label: "Status",
79
86
  type: "enum",
@@ -82,14 +89,14 @@ const columns = [
82
89
  options: [{ value: "active", label: "Active", color: "#22c55e" }],
83
90
  },
84
91
  }),
85
- defineColumn({
92
+ defineColumn<Row>({
86
93
  slug: "progress",
87
94
  label: "Progress",
88
95
  type: "number",
89
96
  component: "slider",
90
97
  metadata: { min: 0, max: 100 },
91
98
  }),
92
- defineColumn({
99
+ defineColumn<Row>({
93
100
  slug: "createdAt",
94
101
  label: "Created",
95
102
  type: "date",
@@ -98,35 +105,196 @@ const columns = [
98
105
  ];
99
106
  ```
100
107
 
101
- ## PageHeader
108
+ ## UiTable
109
+
110
+ Bare native-table parts (`block/ui-table`) for markup you write yourself — no data model, no sort, no edit machinery. Reach for `Table` the moment the data needs sorting, editable cells or a `defineColumn` column set.
111
+
112
+ **Sub-components:** `UiTable.Header`, `UiTable.Body`, `UiTable.Footer`, `UiTable.Head`, `UiTable.Row`, `UiTable.Cell`, `UiTable.Caption`
113
+
114
+ - The root renders a `data-slot="table-container"` scroll wrapper around the `<table>`; `className` on `UiTable` styles the `<table>`, not the wrapper.
115
+ - Mark a selected row with `data-selected` on `UiTable.Row` (paints on the accent; `data-state="selected"` paints nothing). Body rows take the hover wash; header and footer rows stay still.
116
+ - No built-in loading, empty or error row — it renders exactly the rows it is given.
117
+
118
+ ```tsx
119
+ <UiTable>
120
+ <UiTable.Header>
121
+ <UiTable.Row><UiTable.Head>Invoice</UiTable.Head></UiTable.Row>
122
+ </UiTable.Header>
123
+ <UiTable.Body>
124
+ <UiTable.Row><UiTable.Cell>INV001</UiTable.Cell></UiTable.Row>
125
+ </UiTable.Body>
126
+ </UiTable>
127
+ ```
128
+
129
+ ## List
130
+
131
+ Keyed collection whose rows you draw (`block/list`) — `item.id` is the React key, the selection key, the expand key and what row motion tracks. Rows with typed columns are `Table`; a chat transcript is `AnchoredScroller`. Activity feeds, record history, notification inboxes and card grids are `List` with a recipe.
132
+
133
+ **Sub-components:** `List.Toolbar`, `List.Pagination` (the parts List renders from `toolbar` and `pagination`), `List.ItemErrorBoundary` (wraps every row: a render throw becomes a compact error state while the other rows stand)
134
+
135
+ **Props:** `data`, `renderItem(item, index, { isExpanded, onToggle, view })`, `toolbar` (`{ search: { placeholder, keys }, filters: [{ key, label, options, multiple }], showExpandControls, actions }`), `pagination` (`{ current, size, total, onChange }` — when present, the parent has already filtered, sorted and paged), `expandedIds`/`defaultExpandedIds`/`onExpandedIdsChange` (`string[] | "all"`), `searchValue`/`defaultSearchValue`/`onSearchValueChange`, `filters`/`defaultFilters`/`onFiltersChange`, `onSelect`, `groupBy(item) → { key, label }` (a `Marker` separator before each run), `live` (holds rows arriving above the viewport behind an "N new" pill — keep `data` newest-first), `onLoadMore` + `hasMore` + `loadingMore`, `view` [list|card], `onItemActivate(id)`, `onItemError(error, id)`, `loading`, `error` (`{ message, onRetry? }`), `emptyState`, `labels`, `config` (`{ selection, density, dividers, animation: { type: slide|fade|scale|none }, expandable, pageSizeOptions, cardColumns }`)
136
+
137
+ - No virtualization: every item in `data` renders, so page an unbounded collection with `onLoadMore` or `pagination`.
138
+ - `expandedIds`, `searchValue` and `filters` go controlled the moment the prop is passed — `expandedIds={[]}` locks expansion closed unless `onExpandedIdsChange` drives it.
139
+
140
+ ```tsx
141
+ <List
142
+ data={events}
143
+ renderItem={(event) => <FeedRow event={event} />}
144
+ groupBy={(event) => ({ key: dayKey(event), label: dayLabel(event) })}
145
+ toolbar={{ search: { keys: ["title"] }, filters: [{ key: "type", label: "Type", options }] }}
146
+ onLoadMore={loadOlder}
147
+ hasMore={hasMore}
148
+ loadingMore={isLoading}
149
+ />
150
+ ```
151
+
152
+ ## Tree
153
+
154
+ Hierarchy built from flat records that name their parent (`block/tree`); `useTree` is exported beside it for fully custom markup.
102
155
 
103
- Config-driven page masthead with an optional stat ledger — router-agnostic (the consumer owns navigation). Import from `@nurix/components/block/page-header`.
156
+ **Sub-components:** `Tree.Item`, `Tree.ItemLabel` (returned from `renderItem` when a row needs its own props or `render` element).
104
157
 
105
- **Props:** `title`, `eyebrow` (breadcrumb segments — strings or linked `Crumb`s; last is the current page), `description`, `statusSlot`, `actions`, `stats` (`Stat[]` ledger), `back` (`BackLink`), `onBack`, `onNavigate` (fired with a crumb's/stat's `href`), `statsAlign` [left|right], `tall`
158
+ **Props:** `data`, `getParentId` (`null` for a top-level record), `isItemFolder`, `isItemDisabled`, `renderItem`, `selectionMode` [none|single|multiple], `selectedIds`/`defaultSelectedIds`/`onSelectedIdsChange`, `expandedIds`/`defaultExpandedIds` (an id list or `"all"`; default `[]`)/`onExpandedIdsChange`, `onItemActivate`
159
+
160
+ - Keep the accessor functions stable — the rows re-flatten whenever `data` or an accessor changes identity. Records whose parent id names no record never render.
106
161
 
107
162
  ```tsx
108
- <PageHeader
109
- title="Q3 Pipeline"
110
- eyebrow={["Sales", "Pipelines"]}
111
- actions={<Button size="sm">Export</Button>}
112
- stats={[{ label: "Open deals", value: "142" }, { label: "Won", value: "$1.2M" }]}
163
+ <Tree
164
+ aria-label="Files"
165
+ data={records}
166
+ getParentId={getParentId}
167
+ selectionMode="single"
168
+ onItemActivate={openFile}
169
+ renderItem={(item) => item.getItemData().name}
113
170
  />
114
171
  ```
115
172
 
173
+ ## FieldGrid
174
+
175
+ One record's fields, column-driven and editable in place (`compound/field-grid`) — the description list. Skip it for one labelled form field (`compound/cell`) and for many records (`Table`).
176
+
177
+ **Props:** `columns` (`FieldColumn[]`), `data` (the one record), `onDataChange(slug, value)`, `arrangement` [grid|strip] (default `grid`, the responsive labelled `<dl>`; `strip` is the compact icon-and-value band), `columnsPerRow` (grid only, 1–9, default 6), `labels` (`{ empty, on, off }`)
178
+
179
+ **FieldColumn:** `id`, `slug`, `label`, `type` [text|number|boolean|date|slider|rating|enum|status|priority|assignee|avatar|avatarGroup|chip|timer], `options` (`[{ value, label, color, icon }]`), `readOnly`, `placeholder`, `min`/`max`/`step`, `format` (Intl number options), `colSpan`, `icon` (a Lucide icon, or `true` to pick one from `type` then `slug`), `validate(value)` (a returned message refuses the commit), `cell(value, record)` (wins over `type`)
180
+
181
+ - Editing is opt-in twice: a column is read-only unless it sets `readOnly: false` **and** the grid received `onDataChange`. Each editor commits once (Enter or blur for text, the pick for options, the release for a slider).
182
+ - The grid is naked — the strip's band chrome goes on the call site.
183
+
184
+ ```tsx
185
+ <FieldGrid
186
+ arrangement="strip"
187
+ data={deal}
188
+ onDataChange={(slug, value) => updateDeal(deal.id, { [slug]: value })}
189
+ className="border-y bg-muted/30 px-5 py-3"
190
+ columns={[
191
+ { id: "stage", slug: "stage", label: "Stage", type: "status", options: stages, readOnly: false, icon: true },
192
+ { id: "amount", slug: "amount", label: "Amount", type: "number", format: { style: "currency", currency: "USD" } },
193
+ ]}
194
+ />
195
+ ```
196
+
197
+ ## Page and record headers
198
+
199
+ No page-header block ships: compose the masthead at the call site. A title row and actions sit on a `Row`; a KPI ledger is several `Stat` (`element/stat`) on a `Row` beneath it, documented in [typography](typography.md); a record's labelled fields are `FieldGrid` with `arrangement="strip"`.
200
+
116
201
  ## Conversation surfaces
117
202
 
118
- Chat/AI message chrome; import each from its kebab-case subpath.
203
+ Chat and message-thread chrome; import each from its own subpath.
204
+
205
+ ### AnchoredScroller
206
+
207
+ Scroll region that sticks to the newest message and offers a jump control once the reader scrolls away (`block/anchored-scroller`). Install its optional peer family `anchored-scroller` (`@shadcn/react`) first. A plain scrollable region with no stick-to-bottom behavior is `element/scroll-area`.
208
+
209
+ **Sub-components:** `AnchoredScroller.Provider`, `AnchoredScroller.Viewport`, `AnchoredScroller.Content`, `AnchoredScroller.Item`, `AnchoredScroller.Button`; hooks `useAnchoredScroller`, `useAnchoredScrollerScrollable`, `useAnchoredScrollerVisibility`
210
+
211
+ **Props:** Provider — `shouldAutoScroll`, `defaultScrollPosition`; root — `labels` (`{ region, scrollToEnd, scrollToStart }`); Viewport — `shouldPreserveScrollOnPrepend` (default `true`); Item — `itemId`, `isScrollAnchor`; Button — `direction` [start|end] (default `end`), plus `Button`'s `variant`, `size`, `isIconOnly`
212
+
213
+ - The hooks read the scroll store only from components rendered under `AnchoredScroller.Provider`.
214
+ - Give every Item an `itemId` — `scrollToItem`, `visibleItemIds` and `currentAnchorId` key off it.
215
+
216
+ ```tsx
217
+ <AnchoredScroller.Provider shouldAutoScroll defaultScrollPosition="end">
218
+ <AnchoredScroller labels={{ region: "Support thread" }}>
219
+ <AnchoredScroller.Viewport>
220
+ <AnchoredScroller.Content>
221
+ {messages.map((m) => (
222
+ <AnchoredScroller.Item key={m.id} itemId={m.id} isScrollAnchor={m.isTurnStart}>{renderMessage(m)}</AnchoredScroller.Item>
223
+ ))}
224
+ </AnchoredScroller.Content>
225
+ </AnchoredScroller.Viewport>
226
+ <AnchoredScroller.Button direction="end" />
227
+ </AnchoredScroller>
228
+ </AnchoredScroller.Provider>
229
+ ```
230
+
231
+ ### Composer
232
+
233
+ Chat message composer: textarea, attachments, a footer of controls and a send (`@nurix/components/block/composer`, plus `useStagedFiles`, `composerNoticeVariants`).
234
+
235
+ **Props:** `onSubmit`, `onFilesDropped`, `reason` (blocks every send path and fills the Notice), `loading`, `accept`, `labels`
236
+
237
+ **Sub-components:** `Composer.Header`, `Composer.Attachments`, `Composer.Textarea` (`onEnterSubmit`, `maxRows`), `Composer.Footer` (`start`, `end`), `Composer.Attach` (`onSelect`, `multiple`), `Composer.Send`, `Composer.Notice` (`intent` [neutral|danger])
238
+
239
+ Enter submits (Shift+Enter is a newline) except while `reason` or `loading` holds the send. Render `Composer.Notice` unconditionally so a later reason announces. `useStagedFiles({ maxFiles })` returns `{ files, stage, remove, clear }`.
240
+
241
+ ```tsx
242
+ <Composer onSubmit={send} onFilesDropped={stage} reason={closed ? "The window is closed." : undefined}>
243
+ <Composer.Attachments>{files.map(renderChip)}</Composer.Attachments>
244
+ <Composer.Textarea value={draft} onValueChange={setDraft} />
245
+ <Composer.Footer start={<Composer.Attach onSelect={stage} />} end={<Composer.Send disabled={!draft.trim()} />} />
246
+ <Composer.Notice />
247
+ </Composer>
248
+ ```
249
+
250
+ ### MicInput
251
+
252
+ Microphone toggle with a live level meter, as a latch over the caller's engine or over a built-in recorder (`@nurix/components/compound/mic-input`, plus `useMicInputState`, `useMicRecorder`; recorder mode needs the optional peer `react-voice-visualizer`).
253
+
254
+ **Props:** `pressed`, `onPressedChange`, `onValueCommitted` (latch mode) or `recorder` (from `useMicRecorder()`), `status` [idle|listening|processing|error], `waveform` [true|false|"always"], `onError`, `labels`
255
+
256
+ **Sub-components:** `MicInput.Trigger` (`size` [sm|default|lg]), `MicInput.Meter` (`variant` [static|history], `deviceId`)
257
+
258
+ A denied microphone surfaces only through `onError` (meter) or `recorder.error`. A composer's voice button is a `Button` in `Composer.Footer`.
259
+
260
+ ```tsx
261
+ <MicInput pressed={isRecording} onPressedChange={toggle} status={status}>
262
+ <MicInput.Meter variant="history" />
263
+ <MicInput.Trigger size="sm" />
264
+ </MicInput>
265
+ ```
266
+
267
+ ### StreamingCursor
268
+
269
+ The blinking caret at the tail of a live stream (`effect/streaming-cursor`); inline, `h-[1lh]`, `aria-hidden`, blink shipped in the library stylesheet. Change the element with `render` (no `as` or `asChild`). Before the first token, show `element/loader`; inside a code block, set `compound/code-block`'s `isStreaming` prop instead.
270
+
271
+ ```tsx
272
+ <p>{streamedText}{isStreaming && <StreamingCursor className="ml-0.5" />}</p>
273
+ ```
274
+
275
+ ### Marker
276
+
277
+ Muted full-width row for out-of-band thread content — a date divider or a system event (`element/marker`). It is not a notification badge; an unread dot on an avatar is `Avatar.Badge`.
278
+
279
+ **Sub-components:** `Marker.Icon` (`aria-hidden` — put any meaning in the content text), `Marker.Content`; also `markerVariants`
280
+
281
+ **Props:** `variant` [default|separator|border] (`separator` flanks centered content with hairlines; `border` underlines the row), `render` (non-interactive elements only — an action goes inside `Marker.Content` as a `Link` or `Button`)
282
+
283
+ ```tsx
284
+ <Marker variant="separator">
285
+ <Marker.Content>Today</Marker.Content>
286
+ </Marker>
287
+ ```
119
288
 
120
- - `message` — docs-style message rows: `MessageGroup`, `Message`, `MessageAvatar`, `MessageHeader`, `MessageContent`, `MessageFooter`, `MessageStatus` (`status` [sending|sent|failed…] with icon + `data-status`)
121
- - `message-scroller` — pinned-to-bottom scroll container for feeds: `MessageScrollerProvider`, `MessageScroller`, `MessageScrollerViewport`, `MessageScrollerContent`, `MessageScrollerItem`, `MessageScrollerButton` (jump-to-latest); hooks `useMessageScroller`, `useMessageScrollerScrollable`, `useMessageScrollerVisibility`
122
- - `bubble` — chat-bubble rows: `BubbleGroup`, `Bubble`, `BubbleContent`, `BubbleReactions`
123
- - `attachment` — file chips for composer/thread: `Attachment` (+ `AttachmentGroup`, `AttachmentMedia`, `AttachmentContent`, `AttachmentTitle`, `AttachmentDescription`, `AttachmentActions`, `AttachmentAction`, `AttachmentTrigger`); `size` [default|sm], dashed border in idle state, `data-[state=error]` styling
124
- - `marker` — inline annotation row in a stream: `Marker`, `MarkerIcon`, `MarkerContent`; `variant` [default|separator|border]
289
+ ## Fallback-only concepts
125
290
 
126
- ## Other Collections
291
+ No nurix primitive — build each from its plain-spec fallback in [index.md](index.md):
127
292
 
128
- - `activity-timeline` — `GanttChart`: D3-based activity timeline (`Task`, `TaskStatus`, `ViewMode`, `GanttChartProps` types; `DEFAULT_STATUS_COLORS`, `getTaskDuration` helpers)
129
- - `changes-list` — `ChangesList`: grouped change-history feed (`ChangeItem`, `EntityConfig`, `OperationConfig`, `GroupBy` types)
130
- - `header` — `Header`: config-driven page header taking a single `config: HeaderConfig` (breadcrumbs, profile, status bar, grid, actions sections); sub-components `HeaderBreadcrumbs`, `HeaderActions`, `HeaderSection`, `HeaderCell`
131
- - `list` — `List`: data list with `ListToolbar`, `ListPagination`, `ListItemErrorBoundary`
132
- - `ui-table` — `UiTable`, `UiTableHeader`, `UiTableBody`, `UiTableFooter`, `UiTableHead`, `UiTableRow`, `UiTableCell`, `UiTableCaption`: bare HTML-table primitives; prefer `Table`
293
+ - `gantt-timeline`
294
+ - `chat-bubble`
295
+ - `json-viewer`
296
+ - `virtualized-list`
297
+ - `kanban-board`
298
+ - `event-calendar`
299
+ - `filter-toolbar`
300
+ - `vertical-timeline`