graphein 0.16.2 → 0.18.0

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
@@ -176,6 +176,11 @@ declare function interpolateOklab(a: RGBA, b: RGBA): Interpolator;
176
176
  /** Get a categorical palette by name (defaults to the 'graphein' palette). */
177
177
  declare function categorical(name?: string): string[];
178
178
  declare const categoricalSchemes: string[];
179
+ /**
180
+ * Derive a categorical palette for dark surfaces while preserving each swatch's
181
+ * OKLCH hue identity. Invalid colors are passed through unchanged.
182
+ */
183
+ declare function adaptPaletteForDarkBackground(palette: readonly string[], background?: string, minContrast?: number): string[];
179
184
  /**
180
185
  * Build a continuous ramp from ordered color stops, interpolating each segment
181
186
  * in OKLab. Endpoints (t=0,1) return the first/last stop exactly.
@@ -642,6 +647,20 @@ interface ThemeTokens {
642
647
  thick: number;
643
648
  };
644
649
  }
650
+ /** Non-fatal theme resolution warning. */
651
+ interface ThemeWarning {
652
+ /** Dot path to the invalid override token. */
653
+ path: string;
654
+ /** Human-readable warning. */
655
+ message: string;
656
+ }
657
+ /** Theme resolution result with non-fatal warnings. */
658
+ interface ResolvedTheme {
659
+ /** Concrete theme tokens after applying valid overrides. */
660
+ tokens: ThemeTokens;
661
+ /** Non-fatal warnings for ignored invalid overrides. */
662
+ warnings: ThemeWarning[];
663
+ }
645
664
  declare const lightTheme: ThemeTokens;
646
665
  declare const darkTheme: ThemeTokens;
647
666
  declare const themes: Record<string, ThemeTokens>;
@@ -654,6 +673,11 @@ type ThemeInput = string | (Partial<ThemeTokens> & {
654
673
  * - an object deep-merges onto a base theme (override.base or override.dark picks it)
655
674
  */
656
675
  declare function resolveTheme(theme?: ThemeInput): ThemeTokens;
676
+ /**
677
+ * Resolve a theme reference into concrete tokens plus non-fatal warnings for
678
+ * invalid color overrides that fell back to the selected base theme.
679
+ */
680
+ declare function resolveThemeChecked(theme?: ThemeInput): ResolvedTheme;
657
681
 
658
682
  /**
659
683
  * Theme-side support for the hand-drawn ("sketch") style.
@@ -1193,6 +1217,19 @@ interface SketchConfig {
1193
1217
  /** Apply the hand-drawn font to titles/labels/axes (default true). */
1194
1218
  font?: boolean;
1195
1219
  }
1220
+ /** Individual panels the debug view can render. */
1221
+ type DebugSection = 'preview' | 'spec' | 'data' | 'validation' | 'report' | 'summary';
1222
+ /**
1223
+ * Debug-view options. Set `debug: true` on any spec to replace the chart with a
1224
+ * diagnostic view, or pass this object to tune it. All fields are plain JSON so
1225
+ * specs still round-trip through `JSON.stringify`. See {@link BaseSpec.debug}.
1226
+ */
1227
+ interface DebugConfig {
1228
+ /** Which panels to show, in order. Omit for all of them. */
1229
+ sections?: DebugSection[];
1230
+ /** Max number of data rows to list in the data table (default 50). */
1231
+ rows?: number;
1232
+ }
1196
1233
  /** Fields shared by all spec types. */
1197
1234
  interface BaseSpec {
1198
1235
  /** Row-oriented (tidy) data. Required for all charts/tables. */
@@ -1230,6 +1267,17 @@ interface BaseSpec {
1230
1267
  * to tune it. Omit (or `false`) for the default clean rendering.
1231
1268
  */
1232
1269
  sketch?: boolean | SketchConfig;
1270
+ /**
1271
+ * Replace the chart with an interactive **debug view** — a live preview of the
1272
+ * real chart alongside the resolved spec (JSON), a sample of the data (with
1273
+ * inferred column types and row count), validation errors/warnings,
1274
+ * render-report diagnostics, and the plain-English summary. `true` shows every
1275
+ * panel; pass a {@link DebugConfig} to select panels or cap the data sample.
1276
+ * Omit (or `false`) to render normally. The original `type` is preserved, so
1277
+ * clearing the flag restores the chart. Rich HTML view in the browser; headless
1278
+ * PNG export (`@graphein/node`) gets a simple text fallback.
1279
+ */
1280
+ debug?: boolean | DebugConfig;
1233
1281
  /**
1234
1282
  * Named selections this visual publishes. Clicking marks, brushing, or
1235
1283
  * changing a slicer updates the param's value on the shared selection store,
@@ -2211,6 +2259,147 @@ declare class CanvasLayer {
2211
2259
  clear(): void;
2212
2260
  }
2213
2261
 
2262
+ /**
2263
+ * Canvas painting for chart "overlay" text (axis labels, titles, legends,
2264
+ * annotation labels). In the browser this text lives in a crisp, selectable
2265
+ * HTML overlay; headless (no DOM) there is no overlay, so the very same text is
2266
+ * painted onto the marks canvas with these helpers.
2267
+ *
2268
+ * The geometry is shared: call sites compute one set of positions and either
2269
+ * realise them as absolutely-positioned DOM nodes (browser) or feed them here
2270
+ * (headless). The transform/width vocabulary the DOM path uses
2271
+ * (`translateX(-50%)`, `translateY(-50%)`, `translate(-50%,-50%) rotate(±90deg)`,
2272
+ * box `width` + `align`) maps deterministically onto canvas
2273
+ * `textAlign`/`textBaseline`/rotation, so both paths land the same pixels.
2274
+ */
2275
+ interface CanvasPillStyle {
2276
+ background: string;
2277
+ border?: string;
2278
+ radius?: number;
2279
+ padX?: number;
2280
+ padY?: number;
2281
+ }
2282
+ interface CanvasTextCmd {
2283
+ /** Anchor x (interpreted per `align`). */
2284
+ x: number;
2285
+ /** Anchor y (interpreted per `baseline`). */
2286
+ y: number;
2287
+ text: string;
2288
+ /** CSS font shorthand (authoritative — already encodes size + weight). */
2289
+ font: string;
2290
+ color: string;
2291
+ /** Font pixel size, used to size the optional pill. */
2292
+ size: number;
2293
+ align?: CanvasTextAlign;
2294
+ baseline?: CanvasTextBaseline;
2295
+ /** Rotation about (x, y), in radians. */
2296
+ rotate?: number;
2297
+ opacity?: number;
2298
+ /** Draw a rounded "pill"/badge behind the text (solid fill + hairline border). */
2299
+ pill?: CanvasPillStyle;
2300
+ }
2301
+ /** Paint a single text command onto a 2D context. Self-contained (save/restore). */
2302
+ declare function paintCanvasText(ctx: CanvasRenderingContext2D, c: CanvasTextCmd): void;
2303
+ /** Option shape shared by the DOM text helpers (axes + chrome). */
2304
+ interface OverlayTextOpts {
2305
+ left: number;
2306
+ top: number;
2307
+ width?: number;
2308
+ text: string;
2309
+ color: string;
2310
+ size: number;
2311
+ align?: 'left' | 'center' | 'right';
2312
+ transform?: string;
2313
+ opacity?: number;
2314
+ pill?: CanvasPillStyle;
2315
+ }
2316
+ /**
2317
+ * Translate an absolutely-positioned overlay text node (left/top/width/align +
2318
+ * a CSS `transform` from the known vocabulary) into the equivalent canvas
2319
+ * command. Keeps the headless output pixel-aligned with the browser overlay.
2320
+ */
2321
+ declare function overlayTextToCanvasCmd(o: OverlayTextOpts, font: string): CanvasTextCmd;
2322
+ type LegendSymbol = 'square' | 'circle' | 'line';
2323
+ /** Total horizontal footprint of a legend swatch (square/circle = 11, line = 14). */
2324
+ declare function legendSwatchWidth(symbol: LegendSymbol | undefined, swatch?: number): number;
2325
+ /**
2326
+ * Paint a legend swatch onto canvas, vertically centered on `midY`. Mirrors the
2327
+ * DOM swatch (square/circle 11px, line 14×3px).
2328
+ */
2329
+ declare function paintLegendSwatch(ctx: CanvasRenderingContext2D, x: number, midY: number, symbol: LegendSymbol | undefined, color: string, swatch?: number): void;
2330
+
2331
+ /**
2332
+ * Label ledger — a record of every text label a chart actually drew.
2333
+ *
2334
+ * Both text chokepoints push here as they render: `axes/draw.ts` for cartesian
2335
+ * charts and `charts/chrome.ts` for every other visual. That gives the render
2336
+ * report one chart-type-agnostic source of truth for text diagnostics — a pie's
2337
+ * callouts, a sankey's node names and a bar chart's tick labels all land in the
2338
+ * same ledger — so clipping and collision checks work everywhere instead of only
2339
+ * where a `CartesianModel` happens to exist.
2340
+ */
2341
+
2342
+ /** What a recorded label is for, so diagnostics can name it meaningfully. */
2343
+ type LabelRole = 'axis-label' | 'axis-title' | 'title' | 'subtitle' | 'legend' | 'data-label' | 'annotation' | 'other';
2344
+ /** One label as drawn, with the box it occupies and the budget it was given. */
2345
+ interface LabelRecord {
2346
+ role: LabelRole;
2347
+ /** The string actually painted (already shortened when it did not fit). */
2348
+ text: string;
2349
+ /** The full string before any truncation. */
2350
+ fullText: string;
2351
+ /** True when `text` had to be shortened to fit `budget`. */
2352
+ truncated: boolean;
2353
+ /** Axis-aligned bounding box in CSS pixels, relative to the surface. */
2354
+ box: Rect;
2355
+ /** Rotation in degrees; 0 for upright text. */
2356
+ angle: number;
2357
+ /** Font pixel size — the box includes line-box leading, this is the ink height. */
2358
+ size: number;
2359
+ /** The width the caller allowed, when it declared one. */
2360
+ budget?: number;
2361
+ /** The axis a tick label belongs to. */
2362
+ axis?: 'x' | 'y';
2363
+ }
2364
+ /** Collects label records for a single render pass. */
2365
+ declare class LabelLedger {
2366
+ readonly records: LabelRecord[];
2367
+ add(record: LabelRecord): void;
2368
+ clear(): void;
2369
+ /** Records matching any of `roles`. */
2370
+ byRole(...roles: LabelRole[]): LabelRecord[];
2371
+ }
2372
+ /**
2373
+ * Record a label when a ledger is present.
2374
+ *
2375
+ * Renderers reach the ledger through a `Surface`, and some callers (headless
2376
+ * targets, unit-test doubles) hand-roll a partial surface object, so the ledger
2377
+ * is treated as best-effort: diagnostics degrade rather than the render failing.
2378
+ */
2379
+ declare function recordLabel(ledger: LabelLedger | undefined, record: LabelRecord): void;
2380
+ /**
2381
+ * Shorten `text` so it fits `budget` pixels, reporting whether it had to be cut.
2382
+ * A missing or non-positive budget means "unconstrained" — the caller had no
2383
+ * room to declare, so the text is left intact rather than blanked.
2384
+ */
2385
+ declare function fitLabel(text: string, budget: number | undefined, font: string): {
2386
+ text: string;
2387
+ truncated: boolean;
2388
+ };
2389
+ /**
2390
+ * Resolve an overlay text node's layout into an axis-aligned bounding box.
2391
+ *
2392
+ * Reuses {@link overlayTextToCanvasCmd} so the box lands exactly where the glyphs
2393
+ * do, including the `translateX(-50%)` / `translateY(-50%)` / `rotate(-45deg)`
2394
+ * transform vocabulary the DOM path uses.
2395
+ */
2396
+ declare function labelBox(o: OverlayTextOpts, font: string): {
2397
+ box: Rect;
2398
+ angle: number;
2399
+ };
2400
+ /** True when two boxes overlap by more than `tolerance` pixels on both axes. */
2401
+ declare function boxesOverlap(a: Rect, b: Rect, tolerance?: number): boolean;
2402
+
2214
2403
  /**
2215
2404
  * A rendering Surface mounted inside a user-provided container. It owns a stack
2216
2405
  * of layers:
@@ -2239,9 +2428,15 @@ declare class Surface {
2239
2428
  * Defaults to false (browser).
2240
2429
  */
2241
2430
  headless: boolean;
2431
+ /**
2432
+ * Every overlay label drawn during the current pass, recorded by the text
2433
+ * helpers in `axes/draw.ts` and `charts/chrome.ts`. The render report reads it
2434
+ * to detect clipped and colliding text for any chart type, cartesian or not.
2435
+ */
2436
+ readonly labels: LabelLedger;
2242
2437
  constructor(container: HTMLElement);
2243
2438
  resize(width: number, height: number, dpr?: number): void;
2244
- /** Clear both canvas layers and empty the HTML overlay. */
2439
+ /** Clear both canvas layers, empty the HTML overlay, and reset the ledger. */
2245
2440
  clear(): void;
2246
2441
  /** Remove all DOM created by this Surface. */
2247
2442
  destroy(): void;
@@ -2510,75 +2705,6 @@ declare function createDiv(className?: string, style?: Partial<CSSStyleDeclarati
2510
2705
  /** Absolute-position a layer to fill its positioned parent. */
2511
2706
  declare const fillParentStyle: Partial<CSSStyleDeclaration>;
2512
2707
 
2513
- /**
2514
- * Canvas painting for chart "overlay" text (axis labels, titles, legends,
2515
- * annotation labels). In the browser this text lives in a crisp, selectable
2516
- * HTML overlay; headless (no DOM) there is no overlay, so the very same text is
2517
- * painted onto the marks canvas with these helpers.
2518
- *
2519
- * The geometry is shared: call sites compute one set of positions and either
2520
- * realise them as absolutely-positioned DOM nodes (browser) or feed them here
2521
- * (headless). The transform/width vocabulary the DOM path uses
2522
- * (`translateX(-50%)`, `translateY(-50%)`, `translate(-50%,-50%) rotate(±90deg)`,
2523
- * box `width` + `align`) maps deterministically onto canvas
2524
- * `textAlign`/`textBaseline`/rotation, so both paths land the same pixels.
2525
- */
2526
- interface CanvasPillStyle {
2527
- background: string;
2528
- border?: string;
2529
- radius?: number;
2530
- padX?: number;
2531
- padY?: number;
2532
- }
2533
- interface CanvasTextCmd {
2534
- /** Anchor x (interpreted per `align`). */
2535
- x: number;
2536
- /** Anchor y (interpreted per `baseline`). */
2537
- y: number;
2538
- text: string;
2539
- /** CSS font shorthand (authoritative — already encodes size + weight). */
2540
- font: string;
2541
- color: string;
2542
- /** Font pixel size, used to size the optional pill. */
2543
- size: number;
2544
- align?: CanvasTextAlign;
2545
- baseline?: CanvasTextBaseline;
2546
- /** Rotation about (x, y), in radians. */
2547
- rotate?: number;
2548
- opacity?: number;
2549
- /** Draw a rounded "pill"/badge behind the text (solid fill + hairline border). */
2550
- pill?: CanvasPillStyle;
2551
- }
2552
- /** Paint a single text command onto a 2D context. Self-contained (save/restore). */
2553
- declare function paintCanvasText(ctx: CanvasRenderingContext2D, c: CanvasTextCmd): void;
2554
- /** Option shape shared by the DOM text helpers (axes + chrome). */
2555
- interface OverlayTextOpts {
2556
- left: number;
2557
- top: number;
2558
- width?: number;
2559
- text: string;
2560
- color: string;
2561
- size: number;
2562
- align?: 'left' | 'center' | 'right';
2563
- transform?: string;
2564
- opacity?: number;
2565
- pill?: CanvasPillStyle;
2566
- }
2567
- /**
2568
- * Translate an absolutely-positioned overlay text node (left/top/width/align +
2569
- * a CSS `transform` from the known vocabulary) into the equivalent canvas
2570
- * command. Keeps the headless output pixel-aligned with the browser overlay.
2571
- */
2572
- declare function overlayTextToCanvasCmd(o: OverlayTextOpts, font: string): CanvasTextCmd;
2573
- type LegendSymbol = 'square' | 'circle' | 'line';
2574
- /** Total horizontal footprint of a legend swatch (square/circle = 11, line = 14). */
2575
- declare function legendSwatchWidth(symbol: LegendSymbol | undefined, swatch?: number): number;
2576
- /**
2577
- * Paint a legend swatch onto canvas, vertically centered on `midY`. Mirrors the
2578
- * DOM swatch (square/circle 11px, line 14×3px).
2579
- */
2580
- declare function paintLegendSwatch(ctx: CanvasRenderingContext2D, x: number, midY: number, symbol: LegendSymbol | undefined, color: string, swatch?: number): void;
2581
-
2582
2708
  /**
2583
2709
  * Text measurement using a shared offscreen canvas context. Falls back to a
2584
2710
  * rough heuristic when no canvas is available (SSR/test). In a non-DOM
@@ -2883,11 +3009,30 @@ declare function lintSpec(spec: ChartSpec): LintFinding[];
2883
3009
  * the right correction is unclear, the error is left for the agent to resolve.
2884
3010
  */
2885
3011
 
3012
+ /** How aggressively {@link repairSpec} may infer missing or misspelled parts. */
3013
+ interface RepairOptions {
3014
+ /**
3015
+ * Repair level. `'safe'` preserves the historical behavior and only applies
3016
+ * validator-provided fixes; `'data'` may additionally infer unambiguous fixes
3017
+ * from the spec's own data array.
3018
+ */
3019
+ level?: 'safe' | 'data';
3020
+ }
3021
+ /** A patch operation plus the human-readable reason it was considered safe. */
3022
+ interface AppliedRepair {
3023
+ /** The JSON Patch operation that was applied. */
3024
+ op: JsonPatchOp;
3025
+ /** Short explanation of why this repair was applied. */
3026
+ rationale: string;
3027
+ }
3028
+ /** Result returned by {@link repairSpec}. */
2886
3029
  interface RepairResult {
2887
3030
  /** The (possibly) corrected spec — a new object; the input is never mutated. */
2888
3031
  spec: unknown;
2889
3032
  /** Patch operations that were applied, in order. Empty when nothing changed. */
2890
3033
  applied: JsonPatchOp[];
3034
+ /** Applied patch operations paired with their repair rationales. */
3035
+ appliedDetails: AppliedRepair[];
2891
3036
  /**
2892
3037
  * Structural errors that remain after repair. `remaining.length === 0` means
2893
3038
  * the repaired spec is valid. Advisory lint warnings are not counted here.
@@ -2900,7 +3045,7 @@ interface RepairResult {
2900
3045
  * correcting the chart `type` changes which channels are required). Pure: the
2901
3046
  * input spec is deep-cloned before any patch is applied.
2902
3047
  */
2903
- declare function repairSpec(spec: unknown): RepairResult;
3048
+ declare function repairSpec(spec: unknown, options?: RepairOptions): RepairResult;
2904
3049
 
2905
3050
  /**
2906
3051
  * Resolve a spec's `sketch` option into concrete, fully-defaulted knobs for the
@@ -2923,6 +3068,28 @@ interface ResolvedSketch extends RoughStyle {
2923
3068
  */
2924
3069
  declare function resolveSketch(spec: ChartSpec): ResolvedSketch | null;
2925
3070
 
3071
+ /** Agent-facing metadata for one chart family and its starter template. */
3072
+ interface ChartTypeInfo {
3073
+ /** The chart type string accepted by {@link starterSpec}. */
3074
+ type: ChartType;
3075
+ /** A one-line description of when to use this chart type. */
3076
+ purpose: string;
3077
+ /** Required channels, fields, or top-level properties needed for validity. */
3078
+ requiredChannels: string[];
3079
+ /** A minimal valid starter spec for this chart type. */
3080
+ example: ChartSpec;
3081
+ }
3082
+ /**
3083
+ * Return a minimal valid starter spec for a chart type, including placeholder
3084
+ * inline data whose fields match the spec's encodings and field references.
3085
+ */
3086
+ declare function starterSpec(type: ChartType): ChartSpec;
3087
+ /**
3088
+ * List every chart type with its purpose, required channels/properties, and a
3089
+ * ready-to-render starter spec.
3090
+ */
3091
+ declare function listChartTypes(): ChartTypeInfo[];
3092
+
2926
3093
  /**
2927
3094
  * Number formatting — a pragmatic subset of the d3-format mini-language, enough
2928
3095
  * for agent-authored specs without a runtime dependency.
@@ -3050,6 +3217,10 @@ interface FrameInput {
3050
3217
  /** Secondary (right) y-axis for dual-axis combo charts; reserves a right gutter. */
3051
3218
  y2Axis?: AxisInput;
3052
3219
  }
3220
+ /** Resolved chrome density, derived only from the available layout size. */
3221
+ type FrameDensity = 'comfortable' | 'compact';
3222
+ /** Chrome rungs removed to keep a viable mark area in very small containers. */
3223
+ type DroppedChrome = 'subtitle' | 'axis-titles' | 'legend' | 'title';
3053
3224
  interface Frame {
3054
3225
  width: number;
3055
3226
  height: number;
@@ -3064,6 +3235,34 @@ interface Frame {
3064
3235
  legendPosition?: LegendPosition;
3065
3236
  /** Resolved x tick-label rotation in degrees (0 = horizontal). */
3066
3237
  xLabelAngle: number;
3238
+ /**
3239
+ * Pixel budget one x tick label may occupy along its own text direction.
3240
+ * Rotated labels are capped so long names can't swallow the plot; renderers
3241
+ * ellipsize to this rather than overflowing the reserved band.
3242
+ */
3243
+ xLabelMaxWidth: number;
3244
+ /** Pixel budget for a left-gutter tick label, capped so one outlier value
3245
+ * can't consume the plot. Renderers ellipsize to it. */
3246
+ yLabelMaxWidth: number;
3247
+ /** Legend items that did not fit and were dropped from {@link legendItems}. */
3248
+ legendOverflow: number;
3249
+ /** Where to draw the "+N more" chip, when {@link legendOverflow} is non-zero. */
3250
+ legendOverflowRect?: Rect;
3251
+ /** Pixel budget for a legend label, capped so long series names can't consume
3252
+ * the plot. Renderers ellipsize to it. */
3253
+ legendLabelMaxWidth: number;
3254
+ /**
3255
+ * Layout density derived from the available plot budget. `comfortable` is the
3256
+ * normal chrome used at dashboard/card sizes; `compact` marks small containers
3257
+ * so renderers can switch to their compact font/spacing ramp. It is never
3258
+ * spec-controlled.
3259
+ */
3260
+ density: FrameDensity;
3261
+ /**
3262
+ * Chrome rungs omitted, in priority order, so the mark area remains viable.
3263
+ * Dropped regions are not reserved in the frame.
3264
+ */
3265
+ dropped: DroppedChrome[];
3067
3266
  }
3068
3267
  declare const TICK_SIZE = 6;
3069
3268
  /**
@@ -3074,6 +3273,8 @@ declare const TICK_SIZE = 6;
3074
3273
  * `spec.padding` over it (`{ ...NO_PADDING, ...spec.padding }`) to allow overrides.
3075
3274
  */
3076
3275
  declare const NO_PADDING: Insets;
3276
+ /** A plot must keep at least this many pixels on each side to render marks. */
3277
+ declare const MIN_VIABLE_PLOT_SIZE = 24;
3077
3278
  /** Reserve space for every region and return the plot rect + positioned chrome. */
3078
3279
  declare function computeFrame(input: FrameInput): Frame;
3079
3280
 
@@ -3757,6 +3958,12 @@ interface ReportInput {
3757
3958
  size: Size;
3758
3959
  /** The resolved cartesian model, when the chart type is cartesian. */
3759
3960
  model?: CartesianModel;
3961
+ /**
3962
+ * Every label the chart drew, from the surface's label ledger. Supplying it
3963
+ * enables the text diagnostics (clipping, collision, occlusion) for *any*
3964
+ * chart type, including the non-cartesian ones that have no model.
3965
+ */
3966
+ labels?: LabelRecord[];
3760
3967
  }
3761
3968
  /**
3762
3969
  * Build the render report for a freshly-drawn chart. Pure: it reads the
@@ -3936,6 +4143,49 @@ declare global {
3936
4143
  }
3937
4144
  declare function render(target: HTMLElement | string, spec: ChartSpec, options?: RenderOptions): ChartInstance;
3938
4145
 
4146
+ /**
4147
+ * Debug view — renders a spec's *internals* instead of the chart, as a diagnostic
4148
+ * aid. Opt in with `debug: true` (or a {@link DebugConfig}) on any spec.
4149
+ *
4150
+ * This is a runtime concern rather than a leaf chart renderer: it composes
4151
+ * `validateSpec` (spec) + a render report (runtime) + `summarize` (analyze) and,
4152
+ * for the live preview, a *nested* chart render. To avoid an import cycle
4153
+ * (`charts → runtime → charts`), the caller injects the `render` function via
4154
+ * {@link DebugViewDeps.renderPreview}; nothing here imports the runtime entry.
4155
+ *
4156
+ * Two surfaces:
4157
+ * - Browser: {@link renderDebugView} builds rich HTML panels in `surface.overlay`.
4158
+ * - Headless (`@graphein/node`): {@link drawDebugCanvas} paints a plain text
4159
+ * fallback (there is no DOM to host the panels).
4160
+ */
4161
+
4162
+ /** Dependencies the browser debug view needs from the runtime (injected to avoid a cycle). */
4163
+ interface DebugViewDeps {
4164
+ /**
4165
+ * Mount the *real* chart (the spec with debug turned off) into `host` and return
4166
+ * the instance. The caller supplies the runtime `render`; this module never
4167
+ * imports it, keeping the module graph acyclic.
4168
+ */
4169
+ renderPreview: (host: HTMLElement, spec: ChartSpec) => ChartInstance;
4170
+ }
4171
+ interface DebugViewResult {
4172
+ /** The mounted live-preview instance, or null when the preview panel is disabled/failed. */
4173
+ preview: ChartInstance | null;
4174
+ /** Report describing the *underlying* chart (from the preview when available). */
4175
+ report: RenderReport;
4176
+ }
4177
+ /**
4178
+ * Build the browser debug view into `surface.overlay` and mount the live preview.
4179
+ * Returns the preview instance (for lifecycle management by the caller) and the
4180
+ * report describing the underlying chart.
4181
+ */
4182
+ declare function renderDebugView(surface: Surface, spec: ChartSpec, tokens: ThemeTokens, size: Size, deps: DebugViewDeps): DebugViewResult;
4183
+ /**
4184
+ * Headless fallback: paint a plain-text dump (type, validation summary, and the
4185
+ * pretty spec JSON) onto the canvas. There is no DOM to host the rich panels.
4186
+ */
4187
+ declare function drawDebugCanvas(surface: Surface, spec: ChartSpec, tokens: ThemeTokens, size: Size): void;
4188
+
3939
4189
  /**
3940
4190
  * DOM spec publishing — makes a rendered chart identifiable and editable by
3941
4191
  * external tools (agents, devtools extensions, page scripts) straight from the
@@ -4097,11 +4347,81 @@ declare function placeViews(views: WiredView[], cols: number, preset: DashboardL
4097
4347
  declare function resolveDashboardSections(views: WiredView[], layout: Pick<ResolvedLayout, 'cols' | 'rowHeight' | 'sections'>): SectionPlan[];
4098
4348
  declare function renderDashboard(target: HTMLElement | string, spec: DashboardSpec, options?: RenderDashboardOptions): DashboardInstance;
4099
4349
 
4350
+ /**
4351
+ * One-call agent drafting loop: validate → repair → render/report → summarize.
4352
+ *
4353
+ * `draft()` is the dependency-free core version of the MCP render loop. It can
4354
+ * run without a DOM (validation/repair/summary only), paint into a caller-owned
4355
+ * headless canvas target, or mount into a browser container when one is supplied.
4356
+ */
4357
+
4358
+ /** Options for {@link draft}. */
4359
+ interface DraftOptions {
4360
+ /**
4361
+ * Auto-apply safe JSON Patch repairs before returning. Defaults to true.
4362
+ * Disable when you need a read-only validation/lint pass over the original
4363
+ * input.
4364
+ */
4365
+ repair?: boolean;
4366
+ /**
4367
+ * How hard repair may try. `'safe'` (the default) applies only the fixes
4368
+ * validation itself proposes; `'data'` additionally infers unambiguous
4369
+ * corrections from the spec's own `data` — a typo'd field name, a missing
4370
+ * `encoding`, a missing `type`. Every inferred change is reported in
4371
+ * {@link DraftResult.repairs} with its rationale, so nothing is silent.
4372
+ */
4373
+ repairLevel?: 'safe' | 'data';
4374
+ /**
4375
+ * Optional headless 2D canvas target. When provided and the repaired spec is
4376
+ * valid, `draft()` paints to this target via {@link renderToContext} and
4377
+ * returns the resulting {@link RenderReport}. This path needs no DOM.
4378
+ */
4379
+ target?: HeadlessTarget;
4380
+ /**
4381
+ * Optional browser container or selector. When provided and `target` is
4382
+ * omitted, `draft()` mounts the chart with {@link render} and returns
4383
+ * `instance.report()` and the instance itself for lifecycle management.
4384
+ */
4385
+ container?: HTMLElement | string;
4386
+ /** Browser render options forwarded when `container` is used. */
4387
+ renderOptions?: RenderOptions;
4388
+ }
4389
+ /** Result of a {@link draft} validation/repair/render pass. */
4390
+ interface DraftResult {
4391
+ /** The original spec or its safely repaired replacement. */
4392
+ spec: unknown;
4393
+ /** True when structural validation passed after optional repair. */
4394
+ valid: boolean;
4395
+ /** True when an optional headless or browser render was attempted. */
4396
+ rendered: boolean;
4397
+ /** JSON Patch operations applied by repair, in order. */
4398
+ patches: JsonPatchOp[];
4399
+ /** The same operations paired with a human-readable rationale for each. */
4400
+ repairs: AppliedRepair[];
4401
+ /** Structural validation errors remaining after optional repair. */
4402
+ errors: ValidationError[];
4403
+ /** Advisory validation/lint findings for the returned spec. */
4404
+ warnings: ValidationError[];
4405
+ /** Vision-free render diagnostics, present only when rendering happened. */
4406
+ report?: RenderReport;
4407
+ /** Browser chart instance, present only when `container` rendering happened. */
4408
+ instance?: ChartInstance;
4409
+ /** Deterministic alt-text style summary, when the valid spec is summarizable. */
4410
+ summary?: string;
4411
+ }
4412
+ /**
4413
+ * Validate a chart spec, apply safe repairs, optionally render it, and return
4414
+ * everything an agent needs for the next iteration. Rendering is skipped when
4415
+ * validation still has errors after repair so invalid specs never reach the
4416
+ * renderer.
4417
+ */
4418
+ declare function draft(spec: ChartSpec | unknown, options?: DraftOptions): DraftResult;
4419
+
4100
4420
  /**
4101
4421
  * graphein — public entry point.
4102
4422
  *
4103
4423
  * The barrel grows as modules land. Keep exports explicit and tree-shakeable.
4104
4424
  */
4105
- declare const VERSION = "0.1.0";
4425
+ declare const VERSION = "0.18.0";
4106
4426
 
4107
- export { type AggOp, type AggregateOp, type AggregateTransform, type AnimateOptions, type AnimationConfig, type AnimationHandle, type Annotation, type AnySpec, type ArcOptions, type AreaOptions, type AreaPoint, type AreaSpec, type AxesConfig, type AxisConfig, type AxisInput, type BackingSize, type BandScale, type BandScaleOptions, type BarSpec, type BaseSlicerSpec, type BaseSpec, type BinLayout, type BinTransform, type BoxSpec, type BuildOptions, type BulletSpec, CARTESIAN_TYPES, CHART_TYPES, type CalculateTransform, type CalendarHeatmapSpec, CanvasLayer, type CanvasPillStyle, type CanvasTextCmd, type CartesianChartSpec, type CartesianInteractionBuilder, type CartesianModel, type CartesianRenderer, type CategoryInsights, type ChartInsights, type ChartInstance, type ChartSpec, type ChartSummary, type ChartType, type ChoroplethSpec, type ColorScale, type ColumnProfile, type ComboAxisModel, type ComboLayer, type ComboLayerModel, type ComboMark, type ComboModel, type ComboSide, type ComboSpec, type Comparable, type ConditionalFormat, type ContinuousScale, type ControllerSelect, type Curve, type CurveType, type CustomRenderer, DEFAULT_ENTRANCE_DURATION, DEFAULT_ROUGH_STYLE, DEFAULT_UPDATE_DURATION, DIM_ALPHA, type DashboardCell, type DashboardInstance, type DashboardLayout, type DashboardResponsiveSpan, type DashboardSection, type DashboardSpec, type DashboardView, type DateRangeSlicerSpec, type Datum, type DecimateOptions, type Dimensions, type DropdownSlicerSpec, type DumbbellSpec, type EasingFunction, type Emphasis, type Encoding, type EntranceContext, ExpressionError, type Extent, FACETABLE_TYPES, FUNCTION_NAMES, type FacetConfig, type FacetLayout, type FacetPanel, type FieldDef, type FieldType, type FieldValue, type FillStyle, type FilterClause, type FilterPredicate, type FilterTransform, type FoldTransform, type Frame, type FrameInput, type FunnelSpec, type GaugeSpec, type GeoFeature, type GeoFeatureCollection, type GeoGeometry, type GeoMultiPolygon, type GeoPolygon, type GeoPosition, type GroupedMap, type HachureSegment, type HeadlessTarget, type HeatmapSpec, type HighlightConfig, type HistogramBin, type HistogramBinDatum, type HistogramModel, type HistogramSpec, type Hover, type IconRule, type Insets, type InsightFamily, type InsightOptions, type Inspector, type InspectorOptions, InteractionController, type InteractionLink, type InteractionModel, type Interpolator, type JsonPatchOp, type KpiComparison, type KpiSpec, type LegendConfig, type LegendHitRegion, type LegendItem, type LegendPosition, type LegendSymbol, type LineOptions, type LineSpec, type LinearScaleOptions, type LintFinding, type ListSlicerSpec, type LiteralPredicate, type LogScaleOptions, type MapProjection, type MarkOptions, type MatrixSpec, type MatrixValueDef, NO_PADDING, type NumberFormatSpec, type OKLCH, type OKLab, type OverlayTextOpts, type PathSink, type PieLabels, type PieSpec, type PivotCell, type PivotFlatRow, type PivotHeaderNode, type PivotOptions, type PivotResult, type PivotValueDef, type Point, type PointRef, type PointScale, type PointScaleOptions, type PointSelection, type PositionedLegendItem, type RGBA, type RangeSelection, type RangeSlicerSpec, type RecommendOptions, type RecommendedChart, type Rect, type RegressionFit, type RenderContext, type RenderDashboardOptions, type RenderDiagnostic, type RenderOptions, type RenderReport, type RepairResult, type ReportInput, type ReportSeverity, type ResolvedEntrance, type ResolvedSeries, type ResolvedSketch, type Rng, type RoughContext, RoughPen, type RoughStyle, SKETCH_FONT_FAMILY, SKETCH_FONT_NAME, SLICER_TYPES, SPEC_ATTR, SR_ONLY_STYLE, type SankeySpec, type ScaleConfig, type ScaleType, type ScatterInsights, type ScatterSpec, type SearchSlicerSpec, type SelectConfig, type SelectionChangeListener, type SelectionDef, type SelectionListener, type SelectionParam, type SelectionStore, type SelectionValue, type SeriesInsights, type SetSelection, type SharedScales, type Size, type SketchConfig, type SlicerSpec, type SlicerType, type SlopeSpec, Surface, TICK_SIZE, TIME_UNITS, TRANSFORM_KINDS, TYPE_ATTR, type TableColumn, type TableSpec, type TextMetricsLite, type TextSelection, type ThemeColors, type ThemeFont, type ThemeInput, type ThemeTokens, type Tick, type TimeScaleOptions, type TimeUnit, type TimeUnitTransform, type TitleConfig, type TitleInput, Tooltip, type TooltipConfig, type TooltipContent, type TooltipRow, type Transform, type TreemapSpec, type TrendlineConfig, type UpdateContext, VERSION, type ValidationError, type ValidationResult, type ValueInsights, type ValueRef, type ValueRule, type WaterfallSpec, type WiredView, type XKind, type XModel, type YModel, aggregateValues, analyzeChart, animate, applyA11y, applyAggregate, applyBin, applyCalculate, applyFilter, applyFold, applyPatch, applyPick, applyTimeUnit, applyTransform, applyTransforms, arc, area, assertValidSpec, autoInsightAnnotations, backOut, bandScale, bounceOut, buildCartesianInteraction, buildCartesianModel, buildComboModel, buildDataTableFallback, buildFacetModels, buildHistogramModel, buildRenderReport, cartesianInteractionBuilders, cartesianRenderers, categorical, categoricalSchemes, chartTitleText, chartTypeLabel, checkExpression, clamp01, clamp255, compileExpression, compilePredicate, computeBackingSize, computeBins, computeFrame, computeSeriesInsights, contrastRatio, createDiv, createInspector, createRoughPen, createSelectionStore, cubicIn, cubicInOut, cubicOut, curveCatmullRom, curveLinear, curveMonotoneX, curveStep, curveStepAfter, curveStepBefore, customRenderers, darkTheme, decimate, defaultSpan, dependentParams, diverging, divergingColorScale, divergingSchemes, drawAnnotationLabels, drawAnnotations, drawAxesUnderlay, drawFacet, drawLegend, drawOverlay, drawTitle, drawTrendlineLabels, drawTrendlines, easings, elasticOut, ellipsize, ensureSketchFont, expoInOut, expoOut, facetReport, fillParentStyle, filterRows, fontString, formatCountUp, formatDate, formatNumber, formatValue, getDevicePixelRatio, groupBy, hashString, inferFieldType, inferFieldTypes, inferValueType, inheritInto, interpolateArray, interpolateNumber, interpolateNumberArray, interpolateObject, interpolateOklab, interpolateRgb, isBrowser, isEmptyValue, isFaceted, isParamClause, isSlicerType, keyFields, legendSwatchWidth, lightTheme, line, linear, linearRegression, linearScale, linearToSrgb, lintSpec, literalToValue, logScale, lttbRun, makeMatcher, matchesValue, measureText, monotoneXTangents, mulberry32, niceDomain, oklabToOklch, oklabToRgb, oklchToOklab, ordinalColorScale, overlayTextToCanvasCmd, paintCanvasText, paintLegendSwatch, parseColor, parseNumberFormat, pivot, placeViews, pointScale, polygonHachureLines, prefersReducedMotion, prettyDate, profileColumns, quadIn, quadInOut, quadOut, rampFromStops, readableTextColor, recommendChart, relativeLuminance, render, renderDashboard, renderToContext, repairReport, repairSpec, resolveCurve, resolveDashboardLayout, resolveDashboardSections, resolveEmphasis, resolveEntrance, resolveFilterValues, resolveInsightOptions, resolveSketch, resolveTheme, resolveUpdate, resolveValueRef, rgbToOklab, rgbaToCss, rotatePoint, roundedRect, sampleArc, sequential, sequentialColorScale, sequentialSchemes, serializeSpec, setMeasureContext, setStyle, sinInOut, slicerParamName, smartDate, specFields, srgbToLinear, stripData, summarize, summarizeChart, themes, tickIncrement, tickStep, ticks, timeScale, timeTickFormat, timeTicks, toHex, toPointer, tooltipEnabled, truncateTo, validateDashboard, validateSpec, wireViews, withAlpha, withSketchFont };
4427
+ export { type AggOp, type AggregateOp, type AggregateTransform, type AnimateOptions, type AnimationConfig, type AnimationHandle, type Annotation, type AnySpec, type AppliedRepair, type ArcOptions, type AreaOptions, type AreaPoint, type AreaSpec, type AxesConfig, type AxisConfig, type AxisInput, type BackingSize, type BandScale, type BandScaleOptions, type BarSpec, type BaseSlicerSpec, type BaseSpec, type BinLayout, type BinTransform, type BoxSpec, type BuildOptions, type BulletSpec, CARTESIAN_TYPES, CHART_TYPES, type CalculateTransform, type CalendarHeatmapSpec, CanvasLayer, type CanvasPillStyle, type CanvasTextCmd, type CartesianChartSpec, type CartesianInteractionBuilder, type CartesianModel, type CartesianRenderer, type CategoryInsights, type ChartInsights, type ChartInstance, type ChartSpec, type ChartSummary, type ChartType, type ChartTypeInfo, type ChoroplethSpec, type ColorScale, type ColumnProfile, type ComboAxisModel, type ComboLayer, type ComboLayerModel, type ComboMark, type ComboModel, type ComboSide, type ComboSpec, type Comparable, type ConditionalFormat, type ContinuousScale, type ControllerSelect, type Curve, type CurveType, type CustomRenderer, DEFAULT_ENTRANCE_DURATION, DEFAULT_ROUGH_STYLE, DEFAULT_UPDATE_DURATION, DIM_ALPHA, type DashboardCell, type DashboardInstance, type DashboardLayout, type DashboardResponsiveSpan, type DashboardSection, type DashboardSpec, type DashboardView, type DateRangeSlicerSpec, type Datum, type DebugConfig, type DebugSection, type DebugViewDeps, type DebugViewResult, type DecimateOptions, type Dimensions, type DraftOptions, type DraftResult, type DropdownSlicerSpec, type DroppedChrome, type DumbbellSpec, type EasingFunction, type Emphasis, type Encoding, type EntranceContext, ExpressionError, type Extent, FACETABLE_TYPES, FUNCTION_NAMES, type FacetConfig, type FacetLayout, type FacetPanel, type FieldDef, type FieldType, type FieldValue, type FillStyle, type FilterClause, type FilterPredicate, type FilterTransform, type FoldTransform, type Frame, type FrameDensity, type FrameInput, type FunnelSpec, type GaugeSpec, type GeoFeature, type GeoFeatureCollection, type GeoGeometry, type GeoMultiPolygon, type GeoPolygon, type GeoPosition, type GroupedMap, type HachureSegment, type HeadlessTarget, type HeatmapSpec, type HighlightConfig, type HistogramBin, type HistogramBinDatum, type HistogramModel, type HistogramSpec, type Hover, type IconRule, type Insets, type InsightFamily, type InsightOptions, type Inspector, type InspectorOptions, InteractionController, type InteractionLink, type InteractionModel, type Interpolator, type JsonPatchOp, type KpiComparison, type KpiSpec, LabelLedger, type LabelRecord, type LabelRole, type LegendConfig, type LegendHitRegion, type LegendItem, type LegendPosition, type LegendSymbol, type LineOptions, type LineSpec, type LinearScaleOptions, type LintFinding, type ListSlicerSpec, type LiteralPredicate, type LogScaleOptions, MIN_VIABLE_PLOT_SIZE, type MapProjection, type MarkOptions, type MatrixSpec, type MatrixValueDef, NO_PADDING, type NumberFormatSpec, type OKLCH, type OKLab, type OverlayTextOpts, type PathSink, type PieLabels, type PieSpec, type PivotCell, type PivotFlatRow, type PivotHeaderNode, type PivotOptions, type PivotResult, type PivotValueDef, type Point, type PointRef, type PointScale, type PointScaleOptions, type PointSelection, type PositionedLegendItem, type RGBA, type RangeSelection, type RangeSlicerSpec, type RecommendOptions, type RecommendedChart, type Rect, type RegressionFit, type RenderContext, type RenderDashboardOptions, type RenderDiagnostic, type RenderOptions, type RenderReport, type RepairOptions, type RepairResult, type ReportInput, type ReportSeverity, type ResolvedEntrance, type ResolvedSeries, type ResolvedSketch, type ResolvedTheme, type Rng, type RoughContext, RoughPen, type RoughStyle, SKETCH_FONT_FAMILY, SKETCH_FONT_NAME, SLICER_TYPES, SPEC_ATTR, SR_ONLY_STYLE, type SankeySpec, type ScaleConfig, type ScaleType, type ScatterInsights, type ScatterSpec, type SearchSlicerSpec, type SelectConfig, type SelectionChangeListener, type SelectionDef, type SelectionListener, type SelectionParam, type SelectionStore, type SelectionValue, type SeriesInsights, type SetSelection, type SharedScales, type Size, type SketchConfig, type SlicerSpec, type SlicerType, type SlopeSpec, Surface, TICK_SIZE, TIME_UNITS, TRANSFORM_KINDS, TYPE_ATTR, type TableColumn, type TableSpec, type TextMetricsLite, type TextSelection, type ThemeColors, type ThemeFont, type ThemeInput, type ThemeTokens, type ThemeWarning, type Tick, type TimeScaleOptions, type TimeUnit, type TimeUnitTransform, type TitleConfig, type TitleInput, Tooltip, type TooltipConfig, type TooltipContent, type TooltipRow, type Transform, type TreemapSpec, type TrendlineConfig, type UpdateContext, VERSION, type ValidationError, type ValidationResult, type ValueInsights, type ValueRef, type ValueRule, type WaterfallSpec, type WiredView, type XKind, type XModel, type YModel, adaptPaletteForDarkBackground, aggregateValues, analyzeChart, animate, applyA11y, applyAggregate, applyBin, applyCalculate, applyFilter, applyFold, applyPatch, applyPick, applyTimeUnit, applyTransform, applyTransforms, arc, area, assertValidSpec, autoInsightAnnotations, backOut, bandScale, bounceOut, boxesOverlap, buildCartesianInteraction, buildCartesianModel, buildComboModel, buildDataTableFallback, buildFacetModels, buildHistogramModel, buildRenderReport, cartesianInteractionBuilders, cartesianRenderers, categorical, categoricalSchemes, chartTitleText, chartTypeLabel, checkExpression, clamp01, clamp255, compileExpression, compilePredicate, computeBackingSize, computeBins, computeFrame, computeSeriesInsights, contrastRatio, createDiv, createInspector, createRoughPen, createSelectionStore, cubicIn, cubicInOut, cubicOut, curveCatmullRom, curveLinear, curveMonotoneX, curveStep, curveStepAfter, curveStepBefore, customRenderers, darkTheme, decimate, defaultSpan, dependentParams, diverging, divergingColorScale, divergingSchemes, draft, drawAnnotationLabels, drawAnnotations, drawAxesUnderlay, drawDebugCanvas, drawFacet, drawLegend, drawOverlay, drawTitle, drawTrendlineLabels, drawTrendlines, easings, elasticOut, ellipsize, ensureSketchFont, expoInOut, expoOut, facetReport, fillParentStyle, filterRows, fitLabel, fontString, formatCountUp, formatDate, formatNumber, formatValue, getDevicePixelRatio, groupBy, hashString, inferFieldType, inferFieldTypes, inferValueType, inheritInto, interpolateArray, interpolateNumber, interpolateNumberArray, interpolateObject, interpolateOklab, interpolateRgb, isBrowser, isEmptyValue, isFaceted, isParamClause, isSlicerType, keyFields, labelBox, legendSwatchWidth, lightTheme, line, linear, linearRegression, linearScale, linearToSrgb, lintSpec, listChartTypes, literalToValue, logScale, lttbRun, makeMatcher, matchesValue, measureText, monotoneXTangents, mulberry32, niceDomain, oklabToOklch, oklabToRgb, oklchToOklab, ordinalColorScale, overlayTextToCanvasCmd, paintCanvasText, paintLegendSwatch, parseColor, parseNumberFormat, pivot, placeViews, pointScale, polygonHachureLines, prefersReducedMotion, prettyDate, profileColumns, quadIn, quadInOut, quadOut, rampFromStops, readableTextColor, recommendChart, recordLabel, relativeLuminance, render, renderDashboard, renderDebugView, renderToContext, repairReport, repairSpec, resolveCurve, resolveDashboardLayout, resolveDashboardSections, resolveEmphasis, resolveEntrance, resolveFilterValues, resolveInsightOptions, resolveSketch, resolveTheme, resolveThemeChecked, resolveUpdate, resolveValueRef, rgbToOklab, rgbaToCss, rotatePoint, roundedRect, sampleArc, sequential, sequentialColorScale, sequentialSchemes, serializeSpec, setMeasureContext, setStyle, sinInOut, slicerParamName, smartDate, specFields, srgbToLinear, starterSpec, stripData, summarize, summarizeChart, themes, tickIncrement, tickStep, ticks, timeScale, timeTickFormat, timeTicks, toHex, toPointer, tooltipEnabled, truncateTo, validateDashboard, validateSpec, wireViews, withAlpha, withSketchFont };