@graphysdk/viz-engine 0.0.1-plugins.8 → 0.0.1-plugins.9

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.
package/dist/index.d.ts CHANGED
@@ -408,6 +408,8 @@ export declare interface AppearanceSpec {
408
408
  */
409
409
  cornerRadius: number;
410
410
  /**
411
+ * How non-matched observations are de-emphasised when a highlight is active.
412
+ * See {@link HighlightStyle}: `'dim'` lowers opacity, `'desaturate'` greys them out.
411
413
  * @default 'dim'
412
414
  */
413
415
  highlightStyle: HighlightStyle;
@@ -503,8 +505,11 @@ declare interface Axes {
503
505
  * Groups all axis-related settings per axis.
504
506
  */
505
507
  declare interface AxesConfig {
508
+ /** Configuration for the horizontal (x) axis. */
506
509
  x: XAxisConfig;
510
+ /** Configuration for the primary vertical (y) axis. */
507
511
  y: YAxisConfig;
512
+ /** Configuration for the secondary y axis, present only on dual-axis charts. */
508
513
  ySecondary?: YAxisConfig;
509
514
  }
510
515
 
@@ -580,7 +585,9 @@ export declare interface AxisTickCandidate {
580
585
  * Configuration for a single axis's ticks
581
586
  */
582
587
  declare interface AxisTicksConfig {
588
+ /** Whether tick marks and their labels are drawn for this axis. */
583
589
  isVisible: boolean;
590
+ /** Which ticks to label — see {@link AxisLabelMode} (`'auto'` = all, `'edges'` = first/last only). */
584
591
  mode: AxisLabelMode;
585
592
  }
586
593
 
@@ -703,7 +710,7 @@ declare interface BaseGeomOptions<T extends GeomParams> {
703
710
  * (average line); `stat.smooth({ method })` fits a regression curve (trendline).
704
711
  * @default 'identity'
705
712
  */
706
- stat?: StatName | StatInput;
713
+ stat?: StatLayerInput | StatLayerInput[];
707
714
  /**
708
715
  * How sibling marks sharing an x position are arranged. `'identity'` overlaps them; `'stack'` stacks by
709
716
  * `color`; `'dodge'` places them side by side; `'fill'` stacks then normalises each column to 100% (also
@@ -922,6 +929,12 @@ declare type BuiltinParams<G extends string> = G extends GeomName ? Extract<Buil
922
929
  geom: G;
923
930
  }>['params'] : Record<string, unknown>;
924
931
 
932
+ /***************************************************************
933
+ * Transform Input
934
+ ***************************************************************/
935
+ /** The built-in transforms; their `transformType` literals form the closed {@link TransformType}. */
936
+ declare type BuiltinTransformInput = ReshapeTransformInput | FilterTransformInput | SortTransformInput | AggregateTransformInput | ConstantTransformInput;
937
+
925
938
  /**
926
939
  * Caching decorator for any TextMeasurer implementation.
927
940
  *
@@ -1611,7 +1624,7 @@ export declare interface CompiledSpec {
1611
1624
  annotations: CompiledAnnotations;
1612
1625
  }
1613
1626
 
1614
- declare interface CompiledStat {
1627
+ export declare interface CompiledStat {
1615
1628
  /** The transformed dataset. */
1616
1629
  data: Dataset;
1617
1630
  /** Any mapping overrides produced by the stat (e.g., `y` → `'count'` for `CountStat`). */
@@ -1878,7 +1891,15 @@ declare interface ConfigCompilerInput {
1878
1891
  * Any omitted group or field falls back to its resolved default.
1879
1892
  */
1880
1893
  declare type ConfigInput = Omit<DeepPartial<ConfigSpec>, 'legend' | 'content'> & {
1894
+ /**
1895
+ * Legend overrides. Overridden from the deep-partial default so it accepts the
1896
+ * flat {@link LegendConfigInput} (`{ position, display }`) rather than a nested partial.
1897
+ */
1881
1898
  legend?: LegendConfigInput;
1899
+ /**
1900
+ * Content overrides. Overridden from the deep-partial default so titles/source
1901
+ * accept the author-friendly {@link ContentInput} shape (strings or rich objects).
1902
+ */
1882
1903
  content?: ContentInput;
1883
1904
  };
1884
1905
 
@@ -1886,7 +1907,9 @@ declare type ConfigInput = Omit<DeepPartial<ConfigSpec>, 'legend' | 'content'> &
1886
1907
  * Config specification with type tag
1887
1908
  */
1888
1909
  declare interface ConfigItem {
1910
+ /** Discriminant marking this as a config item in a pipeable spec. */
1889
1911
  type: 'config';
1912
+ /** The author-supplied partial configuration to merge over the defaults. */
1890
1913
  config: ConfigInput;
1891
1914
  }
1892
1915
 
@@ -1896,13 +1919,26 @@ declare interface ConfigItem {
1896
1919
  * partial {@link ConfigInput} to `config(...)` instead.
1897
1920
  */
1898
1921
  export declare interface ConfigSpec {
1922
+ /**
1923
+ * Locale used to interpret raw string values into numbers/dates (e.g. which
1924
+ * thousands/decimal separators to expect). Acts as the fallback for output
1925
+ * formatting when no separate `formattingLocale` is supplied.
1926
+ * @default 'en-US'
1927
+ */
1899
1928
  parsingLocale: Locale;
1929
+ /** Legend placement and display mode. */
1900
1930
  legend: LegendConfig;
1931
+ /** Per-axis settings for the x, y, and optional secondary y axes. */
1901
1932
  axes: AxesConfig;
1933
+ /** Plot panel framing (the box drawn around the data area). */
1902
1934
  panel: PanelConfig;
1935
+ /** Big-number summary figure shown above or inside the chart. */
1903
1936
  headline: HeadlineConfig;
1937
+ /** Chart-wide number formatting applied by the renderer to every numeric value. */
1904
1938
  numberFormat: NumberFormatConfig;
1939
+ /** Titles, subtitle, caption, and source attribution. */
1905
1940
  content: ContentConfig;
1941
+ /** Render-only styling: text scale, background, border, corner radius, highlight style. */
1906
1942
  appearance: AppearanceSpec;
1907
1943
  }
1908
1944
 
@@ -2251,12 +2287,15 @@ declare interface CreateCommandMetadataOptions {
2251
2287
  }
2252
2288
 
2253
2289
  /**
2254
- * Builds a compiler instance. Pass `geoms` to register custom (or override built-in) geom
2255
- * definitions per-instance — there is no global registry to mutate, so injected geoms never bleed
2256
- * across instances. An injected geom whose `type` matches a built-in overrides it (last write wins).
2290
+ * Builds a compiler instance. Pass `geoms` / `stats` / `transforms` to register custom (or override
2291
+ * built-in) definitions per-instance — there is no global registry to mutate, so injected definitions
2292
+ * never bleed across instances. An injected definition whose `type` matches a built-in overrides it
2293
+ * (last write wins).
2257
2294
  */
2258
2295
  export declare const createCompiler: (opts?: {
2259
2296
  geoms?: readonly Geom[];
2297
+ stats?: readonly Stat[];
2298
+ transforms?: readonly TransformStrategy[];
2260
2299
  }) => Compiler;
2261
2300
 
2262
2301
  /**
@@ -2266,19 +2305,26 @@ export declare const createCompiler: (opts?: {
2266
2305
  export declare function createEmptyHighlight(strategy: HighlightStrategy | null): CompiledLayerHighlight | null;
2267
2306
 
2268
2307
  /**
2269
- * Builds a Graphy authoring surface for a set of custom geoms and/or annotations: a `geom` builder that
2270
- * merges the built-in methods with one method per registered custom geom, an `annotation` builder that
2271
- * merges the built-in kinds with one method per registered annotation kind, plus the standard
2272
- * `createSpec`. The 90% case stays the plain `import { geom, annotation, createSpec }`; reach for this only
2273
- * when authoring custom geoms (decision 8) or custom annotations (ADR-035). Registration is per-instance
2274
- * geoms are injected to `createCompiler({ geoms })`; annotations need no compile-side registry (coordinate
2275
- * resolution is generic), only the render plugin via `<GraphProvider annotationPlugins={[...]}>`.
2308
+ * Builds a Graphy authoring surface for a set of custom geoms, stats, transforms, and/or annotations: a
2309
+ * `geom` builder merging the built-in methods with one per registered custom geom, a `stat` builder
2310
+ * merging the built-in stats with one per registered custom stat, a `transform` builder merging the
2311
+ * built-in transforms with one per registered custom transform, an `annotation` builder merging the
2312
+ * built-in kinds with one per registered annotation kind, plus the standard `createSpec`. The 90% case
2313
+ * stays the plain `import { geom, stat, transform, annotation, createSpec }`; reach for this only when
2314
+ * authoring custom geoms (ADR-033), stats/transforms (ADR-039), or annotations (ADR-035). Registration is
2315
+ * per-instance — geoms, stats, and transforms are injected to `createCompiler({ geoms, stats, transforms })`;
2316
+ * annotations need no compile-side registry (coordinate resolution is generic), only the render plugin via
2317
+ * `<GraphProvider annotationPlugins={[...]}>`.
2276
2318
  */
2277
- export declare function createGraphyBuilder<const Geoms extends readonly Geom[] = readonly [], const Annotations extends readonly AnnotationDef[] = readonly []>(options: {
2319
+ export declare function createGraphyBuilder<const Geoms extends readonly Geom[] = readonly [], const Stats extends readonly StatDef[] = readonly [], const Transforms extends readonly TransformDef[] = readonly [], const Annotations extends readonly AnnotationDef[] = readonly []>(options: {
2278
2320
  geoms?: Geoms;
2321
+ stats?: Stats;
2322
+ transforms?: Transforms;
2279
2323
  annotations?: Annotations;
2280
2324
  }): {
2281
2325
  geom: typeof geom & CustomGeomBuilders<Geoms>;
2326
+ stat: typeof stat & CustomStatBuilders<Stats>;
2327
+ transform: typeof transform & CustomTransformBuilders<Transforms>;
2282
2328
  annotation: typeof annotation & CustomAnnotationBuilders<Annotations>;
2283
2329
  createSpec: typeof createSpec;
2284
2330
  };
@@ -2411,7 +2457,7 @@ declare type CustomGeomBuilders<Geoms extends readonly Geom[]> = {
2411
2457
  */
2412
2458
  declare interface CustomGeomOptions<TParams extends object, TAes extends string> {
2413
2459
  aes?: Partial<Record<TAes, AestheticValue>>;
2414
- stat?: StatName | StatInput;
2460
+ stat?: StatLayerInput | StatLayerInput[];
2415
2461
  position?: PositionType;
2416
2462
  yScaleType?: YScaleType;
2417
2463
  params?: Partial<TParams>;
@@ -2448,6 +2494,46 @@ declare type CustomPaletteInput = {
2448
2494
 
2449
2495
  export declare type CustomPalettesInput = Record<string, string[]>;
2450
2496
 
2497
+ /**
2498
+ * One builder method per registered custom stat, keyed by its `type` and typed from its definition — so
2499
+ * `stat.shareOfTotal(...)` exists because `shareOfTotal` was registered, with options checked against the
2500
+ * stat's resolved spec. The options argument is required only when the stat declares a required option;
2501
+ * a stat with no options or only optional ones is callable with none.
2502
+ */
2503
+ declare type CustomStatBuilders<Stats extends readonly StatDef[]> = {
2504
+ [Definition in Stats[number] as Definition['type']]: Partial<StatOptionsOf<Definition>> extends StatOptionsOf<Definition> ? (options?: StatOptionsOf<Definition>) => CustomStatInput : (options: StatOptionsOf<Definition>) => CustomStatInput;
2505
+ };
2506
+
2507
+ /**
2508
+ * A custom stat's serialised input — its registered `type` plus arbitrary plain-data options. Produced
2509
+ * by the `stat.<type>(...)` method of `createGraphyBuilder({ stats })`; carried on a layer's `stat`
2510
+ * field and passed through resolution unchanged (it is already a resolved spec).
2511
+ */
2512
+ export declare interface CustomStatInput extends StatSpecBase {
2513
+ [option: string]: unknown;
2514
+ }
2515
+
2516
+ /**
2517
+ * One builder method per registered custom transform, keyed by its `transformType` and typed from its
2518
+ * definition — so `transform.topN(...)` exists because `topN` was registered, with options checked
2519
+ * against the transform's options. The options argument is required only when the transform declares a
2520
+ * required option; a transform with no options or only optional ones is callable with none.
2521
+ */
2522
+ declare type CustomTransformBuilders<Transforms extends readonly TransformDef[]> = {
2523
+ [Definition in Transforms[number] as Definition['transformType']]: Partial<TransformOptionsOf<Definition>> extends TransformOptionsOf<Definition> ? (options?: TransformOptionsOf<Definition>) => CustomTransformInput : (options: TransformOptionsOf<Definition>) => CustomTransformInput;
2524
+ };
2525
+
2526
+ /**
2527
+ * A custom transform's serialised input — its registered `transformType` plus plain-data options.
2528
+ * Produced by the `transform.<type>(...)` method of `createGraphyBuilder({ transforms })`; carried on a
2529
+ * spec or layer `transforms` array and dispatched by `transformType` like any built-in.
2530
+ */
2531
+ export declare interface CustomTransformInput {
2532
+ type: 'transform';
2533
+ transformType: string;
2534
+ options?: Record<string, unknown>;
2535
+ }
2536
+
2451
2537
  /**
2452
2538
  * The raw input dataset to visualize, structured as a table of `columns` + `rows`. This is what you
2453
2539
  * hand to the compiler and to `<GraphProvider data>` — the untransformed, pre-compile shape, distinct
@@ -2842,9 +2928,13 @@ declare type DatetimeTickIntervalUnit = 'hour' | 'day' | 'week' | 'month' | 'qua
2842
2928
  /**
2843
2929
  * Recursively makes every property of `T` optional.
2844
2930
  * Unlike the built-in `Partial`, this applies to nested objects as well.
2931
+ *
2932
+ * An `unknown`/`any` property is treated as a leaf (kept as-is) rather than recursed into — recursing an
2933
+ * open value bag like `Record<string, unknown>` would otherwise rewrite each `unknown` value to `{}`,
2934
+ * making the original value un-assignable to its own `DeepPartial`.
2845
2935
  */
2846
2936
  declare type DeepPartial<T> = {
2847
- [K in keyof T]?: T[K] extends Array<infer U> ? Array<DeepPartial<U>> : NonNullable<T[K]> extends object ? DeepPartial<NonNullable<T[K]>> : T[K];
2937
+ [K in keyof T]?: unknown extends T[K] ? T[K] : T[K] extends Array<infer U> ? Array<DeepPartial<U>> : NonNullable<T[K]> extends object ? DeepPartial<NonNullable<T[K]>> : T[K];
2848
2938
  };
2849
2939
 
2850
2940
  export declare const DEFAULT_COLOR_PALETTE: string[];
@@ -2881,6 +2971,46 @@ export declare function defineAnnotation<const TType extends string, TParams ext
2881
2971
  coordinates?: AnnotationArity;
2882
2972
  }): AnnotationDef<TParams, TType>;
2883
2973
 
2974
+ /**
2975
+ * Declares a custom stat — the grammar-correct home for a per-group derived value (share-of-total,
2976
+ * running total, rank, z-score). The `compute` receives the layer dataset, the effective mapping, the
2977
+ * resolved spec, and a `column` namespacing helper; it returns the transformed dataset plus any mapping
2978
+ * rebinding (`{ y: column('share') }`), exactly as the built-in `count`/`smooth` stats do.
2979
+ *
2980
+ * `TSpec` is the resolved spec interface (its `type` literal plus options). Declare it so the builder
2981
+ * method `stat.<type>(options)` is typed; the compute reads `input.spec` narrowed to it.
2982
+ *
2983
+ * @example
2984
+ * interface ShareStatSpec { type: 'shareOfTotal'; field: string }
2985
+ * export const shareOfTotal = defineStat<ShareStatSpec>({
2986
+ * type: 'shareOfTotal',
2987
+ * computedColumns: ['share'],
2988
+ * computedVariables: ['y'],
2989
+ * compute: ({ data, spec, column }) => {
2990
+ * const total = data.getValues(spec.field, { type: 'numeric', skipNulls: true }).reduce((a, b) => a + b, 0);
2991
+ * const share = column('share');
2992
+ * const values = data.getValues(spec.field, { type: 'numeric' }).map((v) => (v ?? 0) / total);
2993
+ * return { data: data.addVariable(share, 'numeric', values), mapping: { y: share } };
2994
+ * },
2995
+ * });
2996
+ */
2997
+ export declare function defineStat<const TSpec extends StatSpecBase = StatSpecBase>(manifest: StatDefinitionManifest<TSpec>): StatDef<TSpec>;
2998
+
2999
+ /**
3000
+ * Declares a custom transform — mapping-blind, whole-table reshaping (top-N-with-"Other", an exotic
3001
+ * fold/pivot) the five built-ins don't cover. Prefer a stat (`defineStat`) for any per-group derived
3002
+ * value; reach for a transform only to reshape the table itself. The `apply` receives the dataset and
3003
+ * the transform's options and returns a new dataset.
3004
+ *
3005
+ * @example
3006
+ * interface TopNOptions { valueName: string; n: number }
3007
+ * export const topN = defineTransform<'topN', TopNOptions>({
3008
+ * transformType: 'topN',
3009
+ * apply: (data, { valueName }) => data.orderBy(valueName, 'desc'), // …keep first n, fold rest into "Other"…
3010
+ * });
3011
+ */
3012
+ export declare function defineTransform<const TType extends string, TOptions extends object = object>(manifest: TransformDefinitionManifest<TType, TOptions>): TransformDef<TType, TOptions>;
3013
+
2884
3014
  declare interface DifferenceArrowDimensions {
2885
3015
  /** Gap between the arrow start point and its anchored observation. */
2886
3016
  arrowStartGap: number;
@@ -3495,8 +3625,10 @@ declare interface GeomMappingValidationInput {
3495
3625
  /** A built-in geom's name — the default vocabulary the spec builder offers out of the box. */
3496
3626
  export declare type GeomName = (typeof GEOM_NAMES)[number];
3497
3627
 
3628
+ /** {@link BaseGeomOptions} specialised to geom `G`, so its `params` is typed to that geom's param shape. */
3498
3629
  declare type GeomOptions<G extends GeomName> = BaseGeomOptions<GeomParamsMap[G]>;
3499
3630
 
3631
+ /** Union of every built-in geom's params type; the upper bound for {@link BaseGeomOptions}'s generic. */
3500
3632
  declare type GeomParams = GeomParamsMap[keyof GeomParamsMap];
3501
3633
 
3502
3634
  /**
@@ -4476,13 +4608,27 @@ declare interface LayerCompilerInput {
4476
4608
  */
4477
4609
  declare type LayerInput = BuiltinLayerInput | CustomLayerInput;
4478
4610
 
4611
+ /**
4612
+ * Geom-agnostic fields shared by every layer input, before resolution. Builders produce this shape (with
4613
+ * `geom` and `params` added per geom); all fields are optional and filled with defaults during resolution.
4614
+ */
4479
4615
  declare interface LayerInputBase {
4616
+ /** Discriminant marking this spec item as a layer. */
4480
4617
  type: 'layer';
4618
+ /** Optional stable identifier for the layer; auto-assigned during resolution when omitted. */
4481
4619
  id?: string;
4620
+ /**
4621
+ * Layer-level aesthetic mapping (the builder's `aes`), shallow-merged OVER the spec-level mapping for this
4622
+ * layer only. Retargets a channel per layer or pins a constant via `{ y: { value } }`.
4623
+ */
4482
4624
  mapping?: AesMapping;
4483
- stat?: StatName | StatInput;
4625
+ /** Statistical transform(s) applied before positioning — a single stat or a pipeline. @default 'identity' */
4626
+ stat?: StatLayerInput | StatLayerInput[];
4627
+ /** How sibling marks sharing an x position are arranged (`'stack'`, `'dodge'`, `'fill'`, `'identity'`). Default is per-geom. */
4484
4628
  position?: PositionType;
4629
+ /** Which Y axis the layer binds to — `'secondary'` targets the right-hand axis in a dual-axis combo. @default 'primary' */
4485
4630
  yScaleType?: YScaleType;
4631
+ /** Per-observation value labels drawn on the marks. @default off */
4486
4632
  dataLabels?: DataLabelsInput;
4487
4633
  /**
4488
4634
  * Ordered transforms applied to this layer's view of the data, on top of any
@@ -4497,6 +4643,7 @@ declare interface LayerInputBase {
4497
4643
  interactive?: boolean;
4498
4644
  }
4499
4645
 
4646
+ /** A built-in layer input narrowed to geom `G`: the shared base plus that geom's tag and partial `params`. */
4500
4647
  declare type LayerInputOf<G extends GeomName> = LayerInputBase & {
4501
4648
  geom: G;
4502
4649
  params?: Partial<GeomParamsMap[G]>;
@@ -4507,18 +4654,32 @@ declare type LayerInputOf<G extends GeomName> = LayerInputBase & {
4507
4654
  */
4508
4655
  declare type LayerSpec = BuiltinLayerSpec | CustomLayerSpec;
4509
4656
 
4657
+ /**
4658
+ * Geom-agnostic fields shared by every resolved layer spec. Mirrors {@link LayerInputBase} with all fields
4659
+ * required and defaults applied (`stat` resolved to {@link ResolvedStatSpec}[], `dataLabels` fully expanded).
4660
+ */
4510
4661
  declare interface LayerSpecBase {
4662
+ /** Discriminant marking this spec item as a layer. */
4511
4663
  type: 'layer';
4664
+ /** Resolved stable identifier for the layer (always present after resolution). */
4512
4665
  id: string;
4666
+ /** Resolved aesthetic mapping for this layer, merged from spec-level and layer-level inputs. */
4513
4667
  mapping: AesMapping;
4514
- stat: StatSpec;
4668
+ /** Resolved statistical-transform pipeline (empty array means identity). */
4669
+ stat: ResolvedStatSpec[];
4670
+ /** Resolved arrangement of sibling marks at the same x position. */
4515
4671
  position: PositionType;
4672
+ /** Resolved Y-axis binding (`'primary'` or `'secondary'`). */
4516
4673
  yScaleType: YScaleType;
4674
+ /** Resolved ordered transforms applied to this layer's view of the data. */
4517
4675
  transforms: TransformInput[];
4676
+ /** Whether the layer participates in hover hit-detection. */
4518
4677
  interactive: boolean;
4678
+ /** Resolved per-observation data-labels configuration. */
4519
4679
  dataLabels: DataLabelsConfig;
4520
4680
  }
4521
4681
 
4682
+ /** A resolved built-in layer spec narrowed to geom `G`: the shared base plus that geom's tag and full `params`. */
4522
4683
  declare type LayerSpecOf<G extends GeomName> = LayerSpecBase & {
4523
4684
  geom: G;
4524
4685
  params: GeomParamsMap[G];
@@ -4554,7 +4715,7 @@ declare interface LayerValidationCheckInput {
4554
4715
  declare interface LayerValidationInput {
4555
4716
  layerId: string;
4556
4717
  geom: GeomIdentity;
4557
- stat: StatSpec;
4718
+ stat: ResolvedStatSpec[];
4558
4719
  /** `spec.mapping` merged with `layer.mapping` */
4559
4720
  effectiveMapping: AesMapping;
4560
4721
  /** Layer's dataset after its own transforms have been applied */
@@ -4593,6 +4754,9 @@ declare class LayerValidator {
4593
4754
  * without a `validateMapping` hook impose none.
4594
4755
  */
4595
4756
  private validateGeomMapping;
4757
+ /** Unions the `computedVariables` of every stat in the layer's pipeline — any aesthetic computed by
4758
+ * any stage is waived from the pre-stat existence/required checks. */
4759
+ private collectComputedVariables;
4596
4760
  /**
4597
4761
  * Rejects a layer whose coord is absent from the geom's declared `supportedCoordTypes` (e.g. a rule
4598
4762
  * has no meaning under polar pie/donut coords). The supported set lives on the geom definition, so
@@ -5136,7 +5300,9 @@ declare interface PaletteScaleSpec {
5136
5300
  * Panel configuration
5137
5301
  */
5138
5302
  declare interface PanelConfig {
5303
+ /** Border drawn around the plot panel (the data area). */
5139
5304
  border: {
5305
+ /** Whether the panel border is rendered. */
5140
5306
  isVisible: boolean;
5141
5307
  };
5142
5308
  }
@@ -5694,6 +5860,12 @@ export declare interface ResolvedObservationAnchor extends AnchorPosition {
5694
5860
  color: string | undefined;
5695
5861
  }
5696
5862
 
5863
+ /**
5864
+ * A fully-resolved stat spec: a built-in {@link StatSpec} or a custom stat's `{ type, ...options }`.
5865
+ * What the {@link StatCompiler} dispatches on and a stat's `compute` receives.
5866
+ */
5867
+ export declare type ResolvedStatSpec = StatSpec | CustomStatInput;
5868
+
5697
5869
  /**
5698
5870
  * A custom annotation's coordinate resolved to normalized panel space, in **top-left [0,1]** — the
5699
5871
  * space the draw function paints in. `observation` is attached only for a snap-to-observation
@@ -6485,6 +6657,18 @@ export declare class SpecResolver {
6485
6657
  }): Spec;
6486
6658
  }
6487
6659
 
6660
+ /**
6661
+ * Render a {@link SpecInput} as fluent builder source — `pipe(createSpec({…}), geom.x(…), scale.x(…),
6662
+ * config({…}))` — emitting only values that differ from their defaults. Returns `null` when the spec
6663
+ * contains something the builder form cannot faithfully represent (a custom geom, a transform, a polar
6664
+ * coord, …), so the caller can fall back to a literal object and never lose data.
6665
+ *
6666
+ * The defaults are static (data-independent), so this needs no dataset. Position scales are emitted in
6667
+ * the inferred `scale.x(opts)` form on purpose: the resolver only applies context defaults (e.g. a bar
6668
+ * chart's `zero: true`) to inferred scales, so converting them to an explicit type would change the chart.
6669
+ */
6670
+ export declare function specToBuilderSource(input: SpecInput): string | null;
6671
+
6488
6672
  export declare interface StackTotalEntry {
6489
6673
  /** Serialised x value for stable join keys across observations. */
6490
6674
  xKey: string;
@@ -6527,9 +6711,11 @@ declare abstract class Stage<Input, Output> {
6527
6711
 
6528
6712
  /**
6529
6713
  * Base class for statistical transformations applied to layer data (e.g. binning, counting, smoothing).
6714
+ * Built-ins use a literal {@link StatName}; custom stats authored with `defineStat` carry any registered
6715
+ * `type` string ({@link StatIdentity}).
6530
6716
  */
6531
- declare abstract class Stat {
6532
- abstract readonly type: StatName;
6717
+ export declare abstract class Stat {
6718
+ abstract readonly type: StatIdentity;
6533
6719
  /**
6534
6720
  * Aesthetics this stat will compute (e.g. count computes 'y'). Used by validation to skip existence checks.
6535
6721
  */
@@ -6563,25 +6749,28 @@ export declare const stat: {
6563
6749
  };
6564
6750
 
6565
6751
  /**
6566
- * Resolves a stat by name and delegates computation.
6752
+ * Resolves stats by name and delegates computation. A layer's `stat` is an ordered pipeline (Decision 8):
6753
+ * each step sees the dataset and effective mapping produced by the previous step, so a later stat can read
6754
+ * an earlier stat's emitted column. Returns the net mapping overrides (last-writer-wins) for the caller to
6755
+ * merge over the layer's effective mapping.
6567
6756
  */
6568
6757
  declare class StatCompiler {
6569
6758
  private readonly registry;
6570
6759
  constructor(registry: StatRegistry);
6571
- compute(spec: StatSpec, input: {
6760
+ compute(specs: ResolvedStatSpec[], input: {
6572
6761
  data: Dataset;
6573
6762
  mapping: AesMapping;
6574
6763
  xScaleIsDiscrete: boolean;
6575
6764
  }): CompiledStat;
6576
6765
  }
6577
6766
 
6578
- declare interface StatCompilerInput {
6767
+ export declare interface StatCompilerInput {
6579
6768
  /** The input dataset. */
6580
6769
  data: Dataset;
6581
6770
  /** The effective mapping for the layer. */
6582
6771
  mapping: AesMapping;
6583
- /** The resolved stat spec. Narrow by `spec.type` to access stat-specific params. */
6584
- spec: StatSpec;
6772
+ /** The resolved stat spec (built-in or custom). Narrow by `spec.type` to access stat-specific params. */
6773
+ spec: ResolvedStatSpec;
6585
6774
  /**
6586
6775
  * Whether the x aesthetic resolves to a discrete (band) scale. The `smooth` stat emits one fitted
6587
6776
  * point per observed x when set.
@@ -6589,12 +6778,71 @@ declare interface StatCompilerInput {
6589
6778
  xScaleIsDiscrete: boolean;
6590
6779
  }
6591
6780
 
6781
+ /**
6782
+ * A registered custom stat: a {@link Stat} the compiler consumes, carrying the resolved-spec type so
6783
+ * `createGraphyBuilder({ stats })` can type its `stat.<type>(options)` builder method.
6784
+ */
6785
+ export declare interface StatDef<TSpec extends StatSpecBase = StatSpecBase> extends Stat {
6786
+ readonly type: TSpec['type'] & string;
6787
+ /**
6788
+ * Phantom — carries the resolved-spec type to the type level so the registration-typed builder can
6789
+ * recover the stat's options. Never set at runtime.
6790
+ */
6791
+ readonly __spec?: TSpec;
6792
+ }
6793
+
6794
+ /**
6795
+ * The compute input an authored stat receives: the standard {@link StatCompilerInput}, but with `spec`
6796
+ * narrowed to the stat's own resolved spec `TSpec`, plus a `column` helper that namespaces a declared
6797
+ * computed column to a collision-safe internal name (Decision 9).
6798
+ */
6799
+ export declare interface StatDefinitionInput<TSpec extends StatSpecBase = StatSpecBase> extends Omit<StatCompilerInput, 'spec'> {
6800
+ /** The resolved spec for this stat — its `type` plus the options the builder passed. */
6801
+ spec: TSpec;
6802
+ /**
6803
+ * Namespaces a column declared in `computedColumns` to `\0graphy\0_<type>_<local>` — globally unique,
6804
+ * so a stat's output can never collide with a user column or another stat. Throws on an undeclared name.
6805
+ * Write the returned name into `addVariable`/`addConstantVariable` and into any `mapping` rebinding.
6806
+ */
6807
+ column: (localName: string) => string;
6808
+ }
6809
+
6810
+ /**
6811
+ * The manifest passed to {@link defineStat}. Declares the stat's `type`, the columns it emits
6812
+ * (`computedColumns`, namespaced per-type), the aesthetics it rebinds (`computedVariables`, which waive
6813
+ * the validator's pre-stat existence/required checks), and the `compute` itself.
6814
+ */
6815
+ export declare interface StatDefinitionManifest<TSpec extends StatSpecBase = StatSpecBase> {
6816
+ /** The registered stat name; keys both the registry and the `stat.<type>(...)` builder method. */
6817
+ type: TSpec['type'] & string;
6818
+ /** Local names of the columns `compute` emits via `column(...)`. Namespaced per-type for collision-safety. */
6819
+ computedColumns?: readonly string[];
6820
+ /** Aesthetics `compute` rebinds (e.g. `'y'`). Waives the validator's pre-stat existence/required checks. */
6821
+ computedVariables?: readonly AestheticKey[];
6822
+ /** Derives the layer's summary from its dataset. Not called on an empty dataset (the base short-circuits). */
6823
+ compute: (input: StatDefinitionInput<TSpec>) => CompiledStat;
6824
+ }
6825
+
6826
+ /**
6827
+ * The open identity of a stat: a built-in {@link StatName} or any custom stat's `type` string
6828
+ * registered via `createCompiler({ stats })`. The `& {}` keeps the built-in names as autocomplete
6829
+ * candidates without collapsing the union to bare `string` (mirrors `GeomIdentity`).
6830
+ */
6831
+ export declare type StatIdentity = StatName | (string & {});
6832
+
6592
6833
  /**
6593
6834
  * Any value the `stat` builder produces — passed as the `stat` option of a geom.
6594
6835
  * The string-shorthand variants (`stat.identity()`, `stat.count()`, `stat.mean()`) carry only
6595
6836
  * a `type`; `smooth` additionally carries the regression parameters.
6596
6837
  */
6597
- declare type StatInput = IdentityStatSpec | CountStatSpec | SmoothStatInput | MeanStatSpec;
6838
+ export declare type StatInput = IdentityStatSpec | CountStatSpec | SmoothStatInput | MeanStatSpec;
6839
+
6840
+ /**
6841
+ * A single stat a layer's `stat` option accepts — a built-in name, a built-in {@link StatInput}, or a
6842
+ * custom stat input. A layer's `stat` is one of these or an ordered list of them (Decision 8): each step
6843
+ * sees the previous step's emitted columns, e.g. `[stat.percentOfTotal(...), stat.window({ op: 'rank' })]`.
6844
+ */
6845
+ declare type StatLayerInput = StatName | StatInput | CustomStatInput;
6598
6846
 
6599
6847
  /**
6600
6848
  * Statistical transformation applied to data before rendering.
@@ -6604,19 +6852,37 @@ declare type StatInput = IdentityStatSpec | CountStatSpec | SmoothStatInput | Me
6604
6852
  * - `'smooth'` — Fit a regression curve through `(x, y)` and emit the fitted points
6605
6853
  * - `'mean'` — Reduce the dataset to a single observation holding the mean of `y`
6606
6854
  */
6607
- declare type StatName = 'identity' | 'count' | 'smooth' | 'mean';
6855
+ export declare type StatName = 'identity' | 'count' | 'smooth' | 'mean';
6608
6856
 
6609
6857
  /**
6610
- * Built-in stat implementations keyed by {@link StatName}.
6858
+ * The options a registered custom stat's builder method accepts its resolved spec minus the `type`
6859
+ * discriminant (the builder fills `type`). Recovered structurally from the definition's phantom spec.
6611
6860
  */
6612
- declare class StatRegistry extends Registry<StatName, Stat> {
6613
- constructor();
6861
+ declare type StatOptionsOf<Definition> = Definition extends StatDef<infer TSpec> ? Omit<TSpec, 'type'> : never;
6862
+
6863
+ /**
6864
+ * Stat implementations keyed by `type`. Built-ins are registered first; any custom stats injected via
6865
+ * `createCompiler({ stats })` register afterwards (a custom `type` matching a built-in overrides it,
6866
+ * last write wins) — mirroring `GeomRegistry`.
6867
+ */
6868
+ declare class StatRegistry extends Registry<string, Stat> {
6869
+ constructor(opts?: {
6870
+ stats?: readonly Stat[];
6871
+ });
6614
6872
  }
6615
6873
 
6616
6874
  /**
6617
- * Discriminated union of all resolved stat specs (post-resolution).
6875
+ * Discriminated union of all built-in resolved stat specs (post-resolution).
6876
+ */
6877
+ export declare type StatSpec = IdentityStatSpec | CountStatSpec | SmoothStatSpec | MeanStatSpec;
6878
+
6879
+ /**
6880
+ * The minimal shape every stat spec shares: its `type` discriminant. A custom stat's resolved spec
6881
+ * extends this with arbitrary plain-data options; `defineStat<TSpec>` narrows `TSpec` from it.
6618
6882
  */
6619
- declare type StatSpec = IdentityStatSpec | CountStatSpec | SmoothStatSpec | MeanStatSpec;
6883
+ export declare interface StatSpecBase {
6884
+ type: StatIdentity;
6885
+ }
6620
6886
 
6621
6887
  /**
6622
6888
  * Sticker annotation: a built-in emoji-like image pinned to a single observation.
@@ -6814,32 +7080,71 @@ declare interface TransformCompilerInput {
6814
7080
  transforms: TransformInput[];
6815
7081
  }
6816
7082
 
6817
- /***************************************************************
6818
- * Transform Input
6819
- ***************************************************************/
7083
+ /**
7084
+ * A registered custom transform: a {@link TransformStrategy} the compiler consumes, carrying the option
7085
+ * type so `createGraphyBuilder({ transforms })` can type its `transform.<type>(options)` builder method.
7086
+ */
7087
+ export declare interface TransformDef<TType extends string = string, TOptions extends object = object> extends TransformStrategy {
7088
+ readonly transformType: TType;
7089
+ /**
7090
+ * Phantom — carries the options type to the type level so the registration-typed builder can recover
7091
+ * the transform's options. Never set at runtime.
7092
+ */
7093
+ readonly __options?: TOptions;
7094
+ }
7095
+
7096
+ /**
7097
+ * The manifest passed to {@link defineTransform}. Declares the `transformType` and an `apply` that
7098
+ * reshapes the dataset given the transform's plain-data options.
7099
+ */
7100
+ export declare interface TransformDefinitionManifest<TType extends string = string, TOptions extends object = object> {
7101
+ /** The registered transform name; keys both the registry and the `transform.<type>(...)` builder method. */
7102
+ transformType: TType;
7103
+ /** Reshapes the dataset given the transform's options. Mapping-blind, whole-table surgery. */
7104
+ apply: (data: Dataset, options: TOptions) => Dataset;
7105
+ }
7106
+
7107
+ /**
7108
+ * The open identity of a transform: a built-in {@link TransformType} or any custom transform's
7109
+ * `transformType` string registered via `createCompiler({ transforms })` (mirrors `GeomIdentity`).
7110
+ */
7111
+ export declare type TransformIdentity = TransformType | (string & {});
7112
+
6820
7113
  /**
6821
7114
  * Any value the `transform` builder produces. Transforms run before stats and scaling, in the
6822
7115
  * order they appear, reshaping the dataset that every layer then maps over.
6823
7116
  */
6824
- declare type TransformInput = ReshapeTransformInput | FilterTransformInput | SortTransformInput | AggregateTransformInput | ConstantTransformInput;
7117
+ export declare type TransformInput = BuiltinTransformInput | CustomTransformInput;
6825
7118
 
6826
7119
  /**
6827
- * Built-in transform implementations keyed by transform type.
7120
+ * The options a registered custom transform's builder method accepts — recovered structurally from the
7121
+ * definition's phantom options type.
6828
7122
  */
6829
- declare class TransformRegistry extends Registry<TransformType, TransformStrategy> {
6830
- constructor();
7123
+ declare type TransformOptionsOf<Definition> = Definition extends TransformDef<string, infer TOptions> ? TOptions : never;
7124
+
7125
+ /**
7126
+ * Transform strategies keyed by `transformType`. Built-ins register first; any custom transforms
7127
+ * injected via `createCompiler({ transforms })` register afterwards (a custom `transformType` matching
7128
+ * a built-in overrides it, last write wins) — mirroring `GeomRegistry` / `StatRegistry`.
7129
+ */
7130
+ declare class TransformRegistry extends Registry<string, TransformStrategy> {
7131
+ constructor(opts?: {
7132
+ transforms?: readonly TransformStrategy[];
7133
+ });
6831
7134
  }
6832
7135
 
6833
7136
  /**
6834
- * Strategy interface for compiling a specific transform type.
7137
+ * Strategy interface for compiling a specific transform type. Built-ins use a literal
7138
+ * {@link TransformType}; custom transforms authored with `defineTransform` carry any registered
7139
+ * `transformType` string ({@link TransformIdentity}).
6835
7140
  */
6836
- declare interface TransformStrategy {
6837
- readonly transformType: TransformType;
7141
+ export declare interface TransformStrategy {
7142
+ readonly transformType: TransformIdentity;
6838
7143
  apply: (data: Dataset, transform: TransformInput) => Dataset;
6839
7144
  }
6840
7145
 
6841
- /** Discriminant tag of a {@link TransformInput}. */
6842
- declare type TransformType = TransformInput['transformType'];
7146
+ /** Discriminant tag of a built-in {@link TransformInput}. */
7147
+ export declare type TransformType = BuiltinTransformInput['transformType'];
6843
7148
 
6844
7149
  declare type TrendlineType = 'linear' | 'loess' | 'exponential' | 'logarithmic' | 'quadratic' | 'power' | 'polynomial';
6845
7150
 
@@ -6895,7 +7200,7 @@ declare interface ValueMapping {
6895
7200
  }
6896
7201
 
6897
7202
  /** A column of a variable in the dataset. When `valueFormat` is omitted, the Dataset assigns a type-based default (`numeric → decimal`, `categorical → text`, `temporal → date`). */
6898
- declare type Variable = {
7203
+ export declare type Variable = {
6899
7204
  type: DataType;
6900
7205
  values: DataValue[];
6901
7206
  valueFormat?: ValueFormat;
@@ -6910,7 +7215,7 @@ declare type Variable = {
6910
7215
  export declare function variableFor(axis: ChannelAxis, name: string): string;
6911
7216
 
6912
7217
  /** A map of variable names to their type and values. */
6913
- declare type VariableMap = Record<VariableName, Variable>;
7218
+ export declare type VariableMap = Record<VariableName, Variable>;
6914
7219
 
6915
7220
  /**
6916
7221
  * Binds a channel to a data column by name. `{ variable: 'revenue' }` reads the `revenue` column
@@ -7009,7 +7314,7 @@ declare interface XAxisConfig {
7009
7314
  */
7010
7315
  label: string | null;
7011
7316
  /**
7012
- * Position of the y axis.
7317
+ * Position of the x axis.
7013
7318
  * @default 'bottom'
7014
7319
  */
7015
7320
  position: AxisPosition;