Add aggregation, binning, granularity, sort, and stacking to the Chart Builder

- Per-channel transforms: aggregate (sum/mean/median/min/max), quantitative
  bin, and temporal timeUnit granularity; bin and aggregate are mutually
  exclusive. A field-less "Count of records" measure (Voyager's count(*)).
- Chart-level sort (rank a categorical axis by its measure) and stacking
  (zero / 100% normalize), each shown only when it applies.
- Field type is a fixed N|O|Q|T segmented control with the column's invalid
  types disabled; SegmentedControl gains APG-correct disabled options.
- A crowded-category-axis warning (a raw measure drawing one mark per row over
  a large dataset) and a disabled-Create hint (says why it's disabled).
- Drop the Create success toast — the new snippet is immediately visible.
- Docs: spec §06, research-doc §8 backlog (incl. the cardinality/extent
  profiling TODO), architecture 01 (stable-selector rule) and 05 (builder-local
  preview), and a profiling breadcrumb.
This commit is contained in:
2026-06-06 18:04:24 +03:00
parent c11afc273d
commit af9ee1e4c0
14 changed files with 982 additions and 119 deletions
+4
View File
@@ -84,6 +84,10 @@ export function profileData(
if (columns.length === 0) return naProfile(size);
const sample = sampleRows(rows);
// TODO (backlog: docs/chart-builder-research.md §8 — A3/A4 enabler): in this same
// sample pass, also derive a capped per-column distinct count (cardinality, cap ~50)
// and numeric extent (min/max → sign), surfaced on DatasetProfile, to power the Chart
// Builder's crowded-legend / high-cardinality warnings and its negative-value Size guard.
const columnTypes = columns.map((name) => ({
name,
type: inferColumnType(sample.map((r) => r[name])),