@pixerate/editor 0.45.0 → 0.46.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.
@@ -0,0 +1,646 @@
1
+ import { H as HistoryManager } from '../HistoryManager-DeQQMBCj.cjs';
2
+ import { C as CommandSpec } from '../registry-vz6HOiiy.cjs';
3
+ import '../types-DsiXGmjo.cjs';
4
+ import '../schema-Di0CS6Pe.cjs';
5
+
6
+ /** Chart kinds. `bar`, `line`, `area` and `scatter` are cartesian; series may mix them (a combo chart). */
7
+ type ChartType = 'bar' | 'line' | 'area' | 'scatter' | 'pie' | 'donut';
8
+ /** How a series is drawn in a cartesian chart. */
9
+ type ChartSeriesType = 'bar' | 'line' | 'area' | 'scatter';
10
+ /** One data value; `null` is a gap (missing value). */
11
+ type ChartValue = number | null;
12
+ interface ChartSeries {
13
+ /** Stable id (unique within the chart). */
14
+ id: string;
15
+ name: string;
16
+ /** One value per category. */
17
+ values: ChartValue[];
18
+ /** CSS colour (default: the palette colour for the series' position). */
19
+ color?: string;
20
+ /** Overrides the chart type for this series (cartesian charts only). */
21
+ type?: ChartSeriesType;
22
+ /** Hidden series keep their data but are not drawn or scaled. */
23
+ hidden?: boolean;
24
+ }
25
+ interface ChartNumberFormat {
26
+ /** `number` (default), `percent` (0.25 → 25%), `currency` or `compact` (1.2K). */
27
+ style?: 'number' | 'percent' | 'currency' | 'compact';
28
+ /** Fixed decimals (default: as many as the ticks need, up to 2). */
29
+ decimals?: number;
30
+ /** ISO currency code for `currency` (default `USD`). */
31
+ currency?: string;
32
+ prefix?: string;
33
+ suffix?: string;
34
+ }
35
+ interface ChartAxis {
36
+ /** Draw the axis line, ticks and labels (default `true`). */
37
+ show: boolean;
38
+ title: string;
39
+ /** Fixed lower bound (default: from the data, including 0 for bars and areas). */
40
+ min: number | null;
41
+ /** Fixed upper bound (default: from the data). */
42
+ max: number | null;
43
+ /** Grid lines at each tick (default: on for the value axis). */
44
+ gridlines: boolean;
45
+ /** How tick and data labels are written (value axis only). */
46
+ format: ChartNumberFormat;
47
+ }
48
+ type ChartLegendPosition = 'top' | 'bottom' | 'left' | 'right';
49
+ interface ChartLegend {
50
+ show: boolean;
51
+ position: ChartLegendPosition;
52
+ }
53
+ type ChartStacking = 'none' | 'stacked' | 'percent';
54
+ type ChartOrientation = 'vertical' | 'horizontal';
55
+ type ChartCurve = 'linear' | 'smooth' | 'step';
56
+ /** A whole chart: data plus presentation. Plain JSON, safe to persist. */
57
+ interface ChartSpec {
58
+ version: 1;
59
+ type: ChartType;
60
+ title: string;
61
+ subtitle: string;
62
+ /** Category labels (the x axis, or pie slices). */
63
+ categories: string[];
64
+ series: ChartSeries[];
65
+ /** The category axis. */
66
+ xAxis: ChartAxis;
67
+ /** The value axis. */
68
+ yAxis: ChartAxis;
69
+ legend: ChartLegend;
70
+ /** Stack bars and areas (`percent` scales each category to 100%). */
71
+ stacking: ChartStacking;
72
+ /** `horizontal` draws bars sideways (bar charts only). */
73
+ orientation: ChartOrientation;
74
+ /** Line and area interpolation. */
75
+ curve: ChartCurve;
76
+ /** Dots on line and area series. */
77
+ points: boolean;
78
+ /** Value labels on bars, points and slices. */
79
+ dataLabels: boolean;
80
+ /** Series colours in order (cycled). */
81
+ palette: string[];
82
+ /** Donut hole as a fraction of the radius (0–0.9). */
83
+ innerRadius: number;
84
+ }
85
+ /** What a click selects. */
86
+ type ChartSelection = {
87
+ kind: 'chart';
88
+ } | {
89
+ kind: 'title';
90
+ } | {
91
+ kind: 'subtitle';
92
+ } | {
93
+ kind: 'legend';
94
+ } | {
95
+ kind: 'axis';
96
+ axis: 'x' | 'y';
97
+ } | {
98
+ kind: 'series';
99
+ seriesId: string;
100
+ } | {
101
+ kind: 'point';
102
+ seriesId: string;
103
+ index: number;
104
+ } | {
105
+ kind: 'category';
106
+ index: number;
107
+ };
108
+ /** Colours and type used to lay out a chart. Any CSS colour strings work. */
109
+ interface ChartTheme {
110
+ /** Fill behind the chart (`transparent` lets the page show through). */
111
+ background: string;
112
+ /** The page colour: slice separators and hollow points (set it when `background` is transparent). */
113
+ surface: string;
114
+ text: string;
115
+ mutedText: string;
116
+ grid: string;
117
+ axis: string;
118
+ /** Outline drawn around the selected mark. */
119
+ selection: string;
120
+ fontFamily: string;
121
+ fontSize: number;
122
+ titleSize: number;
123
+ }
124
+ interface ChartRect {
125
+ x: number;
126
+ y: number;
127
+ width: number;
128
+ height: number;
129
+ }
130
+ /** What a mark is, for styling and tests. */
131
+ type ChartMarkRole = 'background' | 'title' | 'subtitle' | 'grid' | 'axis' | 'tick' | 'tick-label' | 'axis-title' | 'bar' | 'line' | 'area' | 'point' | 'slice' | 'data-label' | 'legend-swatch' | 'legend-label' | 'selection' | 'empty';
132
+ interface ChartMarkBase {
133
+ /** Unique within the scene (a stable key for frameworks). */
134
+ key: string;
135
+ role: ChartMarkRole;
136
+ /** What clicking this mark selects (none: not clickable). */
137
+ target?: ChartSelection;
138
+ /** Mark belongs to the current selection. */
139
+ selected?: boolean;
140
+ opacity?: number;
141
+ }
142
+ interface ChartRectMark extends ChartMarkBase {
143
+ kind: 'rect';
144
+ x: number;
145
+ y: number;
146
+ width: number;
147
+ height: number;
148
+ fill: string;
149
+ stroke?: string;
150
+ strokeWidth?: number;
151
+ radius?: number;
152
+ }
153
+ interface ChartPathMark extends ChartMarkBase {
154
+ kind: 'path';
155
+ d: string;
156
+ fill?: string;
157
+ stroke?: string;
158
+ strokeWidth?: number;
159
+ dash?: string;
160
+ }
161
+ interface ChartCircleMark extends ChartMarkBase {
162
+ kind: 'circle';
163
+ cx: number;
164
+ cy: number;
165
+ r: number;
166
+ fill: string;
167
+ stroke?: string;
168
+ strokeWidth?: number;
169
+ }
170
+ interface ChartLineMark extends ChartMarkBase {
171
+ kind: 'line';
172
+ x1: number;
173
+ y1: number;
174
+ x2: number;
175
+ y2: number;
176
+ stroke: string;
177
+ strokeWidth?: number;
178
+ dash?: string;
179
+ }
180
+ interface ChartTextMark extends ChartMarkBase {
181
+ kind: 'text';
182
+ x: number;
183
+ y: number;
184
+ text: string;
185
+ anchor: 'start' | 'middle' | 'end';
186
+ /** Vertical alignment of the text box to `y`. */
187
+ baseline: 'top' | 'middle' | 'bottom';
188
+ size: number;
189
+ weight?: number;
190
+ fill: string;
191
+ /** Degrees, around (x, y). */
192
+ rotate?: number;
193
+ }
194
+ type ChartMark = ChartRectMark | ChartPathMark | ChartCircleMark | ChartLineMark | ChartTextMark;
195
+ /** Maps between data values and scene pixels along one axis of the plot. */
196
+ interface ChartValueScale {
197
+ /** `y` for vertical charts, `x` for horizontal bars. */
198
+ axis: 'x' | 'y';
199
+ domain: [number, number];
200
+ range: [number, number];
201
+ ticks: number[];
202
+ }
203
+ /** A laid-out chart: drawing primitives in scene pixels, ready for SVG, canvas or anything else. */
204
+ interface ChartScene {
205
+ width: number;
206
+ height: number;
207
+ /** The plot area (inside the axes). Empty for pies. */
208
+ plot: ChartRect;
209
+ /** Draw in order. */
210
+ marks: ChartMark[];
211
+ /** The value scale of a cartesian chart (absent for pies and empty charts). */
212
+ valueScale?: ChartValueScale;
213
+ /** Percent-stacked: values are shown as shares, so dragging is disabled. */
214
+ percent: boolean;
215
+ theme: ChartTheme;
216
+ }
217
+ interface ChartIssue {
218
+ path: string;
219
+ message: string;
220
+ }
221
+
222
+ declare const CHART_TYPES: readonly ChartType[];
223
+ declare const CHART_SERIES_TYPES: readonly ChartSeriesType[];
224
+ declare const CHART_STACKINGS: readonly ChartStacking[];
225
+ declare const CHART_CURVES: readonly ChartCurve[];
226
+ declare const CHART_ORIENTATIONS: readonly ChartOrientation[];
227
+ declare const CHART_LEGEND_POSITIONS: readonly ChartLegendPosition[];
228
+ declare const CHART_NUMBER_STYLES: readonly NonNullable<ChartNumberFormat['style']>[];
229
+ /** Labels for pickers, shared by the React and Svelte components. */
230
+ declare const CHART_TYPE_LABELS: Readonly<Record<ChartType, string>>;
231
+ /** A colour-blind-friendly categorical palette (Okabe–Ito order, tuned for light and dark backgrounds). */
232
+ declare const DEFAULT_CHART_PALETTE: readonly string[];
233
+ declare const DEFAULT_CHART_THEME: ChartTheme;
234
+ /**
235
+ * A theme that reads the page's `--background`, `--foreground`, `--muted-foreground`,
236
+ * `--border` and `--primary` colour variables (full colours, as the other components'
237
+ * inline styles use them), with light fallbacks. The React and Svelte canvases use it.
238
+ */
239
+ declare const CSS_VARIABLE_CHART_THEME: ChartTheme;
240
+ declare function isCartesianChart(type: ChartType): boolean;
241
+ declare function defaultChartAxis(value: boolean): ChartAxis;
242
+ /** A complete spec with every default filled in. */
243
+ declare function createChartSpec(partial?: Partial<ChartSpec>): ChartSpec;
244
+ /** The colour a series is drawn with. */
245
+ declare function chartSeriesColor(spec: Pick<ChartSpec, 'palette' | 'series'>, seriesIndex: number): string;
246
+ /** The colour a pie slice is drawn with (by category). */
247
+ declare function chartSliceColor(spec: Pick<ChartSpec, 'palette'>, index: number): string;
248
+ /** How a series is drawn in a cartesian chart. */
249
+ declare function chartSeriesType(spec: Pick<ChartSpec, 'type'>, series: ChartSeries): ChartSeriesType;
250
+ /** An id not used by any series (`series-1`, `series-2`, …). */
251
+ declare function uniqueChartSeriesId(series: readonly Pick<ChartSeries, 'id'>[], base?: string): string;
252
+ /**
253
+ * Reads a number the way people type it in a data grid: `1,234.5`, `12%` (→ 0.12),
254
+ * `$40`, `(3)` (→ -3). Blank → `null`. Returns `undefined` when it is not a number.
255
+ */
256
+ declare function parseChartValue(input: unknown): ChartValue | undefined;
257
+ declare function normalizeChartAxis(value: unknown, fallback: ChartAxis, path: string, issues?: ChartIssue[]): ChartAxis;
258
+ /** Values as numbers or nulls; bad entries become null and are reported. */
259
+ declare function normalizeChartValues(value: unknown, length: number | undefined, path: string, issues?: ChartIssue[]): ChartValue[];
260
+ /**
261
+ * Turns any input (a partial spec, saved JSON, an agent's arguments) into a complete,
262
+ * valid `ChartSpec`. Every value is checked; problems are reported as sentences in
263
+ * `issues` and replaced by defaults, so the result is always drawable. Series values are
264
+ * padded or trimmed to the number of categories.
265
+ */
266
+ declare function normalizeChartSpec(input: unknown): {
267
+ spec: ChartSpec;
268
+ issues: ChartIssue[];
269
+ };
270
+ /** A deep copy (specs are plain JSON). */
271
+ declare function cloneChartSpec(spec: ChartSpec): ChartSpec;
272
+ declare function cloneChartSeries(series: ChartSeries): ChartSeries;
273
+ interface ChartTableOptions {
274
+ /**
275
+ * `columns` (default): the first column holds categories and each other column is a
276
+ * series. `rows`: the first row holds categories and each other row is a series.
277
+ */
278
+ seriesIn?: 'columns' | 'rows';
279
+ /** The first row (or column for `rows`) holds series names (default `true`). */
280
+ header?: boolean;
281
+ }
282
+ interface ChartTableData {
283
+ categories: string[];
284
+ series: ChartSeries[];
285
+ issues: ChartIssue[];
286
+ }
287
+ /**
288
+ * Reads a grid of cells (from CSV, a spreadsheet range or the clipboard) as categories and
289
+ * series. Cells that are not numbers become gaps and are reported.
290
+ */
291
+ declare function chartDataFromTable(rows: ReadonlyArray<ReadonlyArray<unknown>>, options?: ChartTableOptions): ChartTableData;
292
+ /** The chart's data as a grid: a header row of series names, then one row per category. */
293
+ declare function chartDataToTable(spec: Pick<ChartSpec, 'categories' | 'series'>, options?: {
294
+ categoryHeader?: string;
295
+ }): (string | number | null)[][];
296
+ /** A colour input value (`#rrggbb`) for a CSS colour: `#abc` expands, non-hex colours show as black. */
297
+ declare function chartColorInputValue(color: string): string;
298
+
299
+ /** A "nice" step (1, 2, 2.5 or 5 × 10ⁿ) for about `count` intervals over `span`. */
300
+ declare function niceStep(span: number, count: number): number;
301
+ interface NiceScale {
302
+ min: number;
303
+ max: number;
304
+ step: number;
305
+ ticks: number[];
306
+ }
307
+ /**
308
+ * Extends `[min, max]` to round numbers and lists the ticks between them. Fixed ends
309
+ * (`fixedMin` / `fixedMax`) are kept exactly; ticks then start at the first nice value
310
+ * inside them.
311
+ */
312
+ declare function niceScale(min: number, max: number, count?: number, fixedMin?: number | null, fixedMax?: number | null): NiceScale;
313
+ /** Decimals needed to tell ticks `step` apart (at most 6). */
314
+ declare function stepDecimals(step: number): number;
315
+ /**
316
+ * Writes a number for a chart label. Locale-independent (so labels and tests are the same
317
+ * everywhere): `,` thousands, `.` decimals. `decimals` defaults to `fallbackDecimals`
318
+ * (e.g. from the tick step), else up to 2 trimmed.
319
+ */
320
+ declare function formatChartNumber(value: number | null | undefined, format?: ChartNumberFormat, fallbackDecimals?: number): string;
321
+ /** Linear map from `domain` to `range`. */
322
+ declare function linearMap(value: number, domain: readonly [number, number], range: readonly [number, number]): number;
323
+
324
+ type ChartTextMeasure = (text: string, size: number, weight?: number) => number;
325
+ interface ChartLayoutOptions {
326
+ width: number;
327
+ height: number;
328
+ theme?: Partial<ChartTheme>;
329
+ /** Highlighted in the scene (selection outlines, `selected` flags). */
330
+ selection?: ChartSelection | null;
331
+ /** Text width in pixels (default: an estimate from the character count). */
332
+ measureText?: ChartTextMeasure;
333
+ /** Shown when there is nothing to draw (default "No data"). */
334
+ emptyMessage?: string;
335
+ }
336
+ /** A DOM-free text width estimate (average glyph ≈ 0.56 em, bold ≈ 0.6 em). */
337
+ declare const estimateChartTextWidth: ChartTextMeasure;
338
+ /** Whether two selections point at the same thing. */
339
+ declare function sameChartSelection(a: ChartSelection | null | undefined, b: ChartSelection | null | undefined): boolean;
340
+ /**
341
+ * Lays a chart out as drawing primitives (rects, paths, circles, lines and text) in a
342
+ * `width × height` box. Pure and DOM-free: the React and Svelte canvases render the marks
343
+ * as SVG, `chartSceneToSvg` writes them as a string, and anything else (canvas, PDF) can
344
+ * draw them too. Clickable marks carry the `target` they select.
345
+ */
346
+ declare function layoutChart(spec: ChartSpec, options: ChartLayoutOptions): ChartScene;
347
+ /**
348
+ * The data value at a scene point along the value axis (for dragging a bar or point), or
349
+ * `undefined` when the scene has no value scale or is percent-stacked.
350
+ */
351
+ declare function chartValueAtPoint(scene: ChartScene, point: {
352
+ x: number;
353
+ y: number;
354
+ }): number | undefined;
355
+ /** The value a drag should store: snapped to a tenth of the tick step (or `step`) and kept finite. */
356
+ declare function snapChartValue(scene: ChartScene, value: number, step?: number): number;
357
+
358
+ /** SVG `dominant-baseline` for a text mark's baseline (shared by every renderer). */
359
+ declare function chartTextBaseline(baseline: ChartTextMark['baseline']): 'hanging' | 'central' | 'text-after-edge';
360
+ /** SVG `transform` for a rotated text mark, if any. */
361
+ declare function chartTextTransform(mark: ChartTextMark): string | undefined;
362
+ interface ChartSvgOptions {
363
+ /** Leave out selection outlines (default `true`: exports show the chart only). */
364
+ hideSelection?: boolean;
365
+ /** Accessible title (default: the chart title). */
366
+ ariaLabel?: string;
367
+ }
368
+ /** Writes a laid-out scene as a standalone SVG document string. */
369
+ declare function chartSceneToSvg(scene: ChartScene, options?: ChartSvgOptions): string;
370
+ /** Lays out and writes a chart as SVG, e.g. for export or server rendering. */
371
+ declare function chartToSvg(spec: ChartSpec, options: Omit<ChartLayoutOptions, 'selection'> & ChartSvgOptions): string;
372
+
373
+ interface ChartControllerOptions {
374
+ /** Starting chart (any partial or saved spec; problems are reported in `state.issues`). */
375
+ spec?: Partial<ChartSpec> | unknown;
376
+ /** History to record into, e.g. one shared with the rest of the app (default: a new one). */
377
+ history?: HistoryManager;
378
+ /** Called after the spec changes (edit, undo, redo, load). */
379
+ onChange?: (spec: Readonly<ChartSpec>) => void;
380
+ }
381
+ /** A snapshot of the controller. The same object is returned until something changes. */
382
+ interface ChartState {
383
+ spec: Readonly<ChartSpec>;
384
+ selection: ChartSelection | null;
385
+ /** The series the selection belongs to (a series or one of its points). */
386
+ selectedSeries: ChartSeries | null;
387
+ /** The category the selection belongs to (a category or a point). */
388
+ selectedIndex: number | null;
389
+ /** Problems from the last load or rejected edit, as sentences. */
390
+ issues: readonly ChartIssue[];
391
+ /** The gesture in progress (e.g. a bar drag), if any. */
392
+ gesture: string | null;
393
+ canUndo: boolean;
394
+ canRedo: boolean;
395
+ undoLabel: string;
396
+ redoLabel: string;
397
+ /** Bumped on every change. */
398
+ revision: number;
399
+ }
400
+ type ChartActionResult = {
401
+ ok: true;
402
+ } | {
403
+ ok: false;
404
+ message: string;
405
+ issues?: ChartIssue[];
406
+ };
407
+ /** Top-level fields with partial axes and legend. */
408
+ type ChartSpecPatch = Partial<Omit<ChartSpec, 'version' | 'xAxis' | 'yAxis' | 'legend'>> & {
409
+ xAxis?: Partial<ChartAxis>;
410
+ yAxis?: Partial<ChartAxis>;
411
+ legend?: Partial<ChartLegend>;
412
+ };
413
+ interface ChartSeriesInput {
414
+ id?: string;
415
+ name?: string;
416
+ values?: readonly unknown[];
417
+ color?: string;
418
+ type?: ChartSeriesType;
419
+ hidden?: boolean;
420
+ }
421
+ interface ChartSeriesPatch {
422
+ name?: string;
423
+ /** `null` goes back to the palette colour. */
424
+ color?: string | null;
425
+ /** `null` follows the chart type. */
426
+ type?: ChartSeriesType | null;
427
+ hidden?: boolean;
428
+ }
429
+ interface ChartEditOptions {
430
+ /** Undo step label. */
431
+ label?: string;
432
+ }
433
+ /**
434
+ * Headless state for a chart editor: a validated `ChartSpec`, a selection, and undoable
435
+ * edits to data (values, series, categories, pasted grids, CSV) and presentation (type,
436
+ * titles, axes, legend, stacking, …). Drags merge into one undo step (`beginGesture`).
437
+ * `getState()` returns the same object until something changes, so it works with
438
+ * `useSyncExternalStore` and Svelte runes alike.
439
+ */
440
+ declare class ChartController {
441
+ readonly history: HistoryManager;
442
+ private spec;
443
+ private selection;
444
+ private issues;
445
+ private gestureKey;
446
+ private gestureCount;
447
+ private revision;
448
+ private applying;
449
+ private readonly onChange?;
450
+ private readonly listeners;
451
+ private unsubscribeHistory?;
452
+ private state;
453
+ constructor(options?: ChartControllerOptions);
454
+ private connect;
455
+ /** The current snapshot (stable until the next change). */
456
+ getState: () => ChartState;
457
+ /** Calls `listener` after every change. Returns an unsubscribe function. */
458
+ subscribe: (listener: (state: ChartState) => void) => (() => void);
459
+ /** The current spec (do not mutate; edit through the controller). */
460
+ getSpec(): Readonly<ChartSpec>;
461
+ getSeries(id: string): ChartSeries | undefined;
462
+ private computeState;
463
+ private notify;
464
+ /** Drops a selection that no longer points at anything. */
465
+ private validSelection;
466
+ private applySpec;
467
+ private commit;
468
+ private reject;
469
+ /** A copy of the spec with `edit` applied (series and categories copied as needed). */
470
+ private edited;
471
+ private unknownSeries;
472
+ private badIndex;
473
+ /**
474
+ * Changes any presentation or data fields as one undo step. All-or-nothing: if anything
475
+ * is invalid, nothing changes and every problem is returned (and shown in `state.issues`).
476
+ */
477
+ update(patch: ChartSpecPatch, options?: ChartEditOptions): ChartActionResult;
478
+ setType(type: ChartType): ChartActionResult;
479
+ setTitle(title: string): ChartActionResult;
480
+ setSubtitle(subtitle: string): ChartActionResult;
481
+ /** Changes the category (`x`) or value (`y`) axis. */
482
+ setAxis(axis: 'x' | 'y', patch: Partial<ChartAxis>): ChartActionResult;
483
+ setLegend(patch: Partial<ChartLegend>): ChartActionResult;
484
+ /**
485
+ * Replaces categories and / or series as one undo step. Values are validated and padded
486
+ * to the categories; all-or-nothing like `update`.
487
+ */
488
+ setData(data: {
489
+ categories?: readonly unknown[];
490
+ series?: readonly ChartSeriesInput[];
491
+ }, options?: ChartEditOptions): ChartActionResult;
492
+ /**
493
+ * Sets one value (numbers, numeric text such as `1,200` or `12%`, or blank for a gap).
494
+ * One undo step, or part of the current gesture.
495
+ */
496
+ setValue(seriesId: string, index: number, value: unknown, options?: ChartEditOptions): ChartActionResult;
497
+ /** Several values as one undo step (all-or-nothing). */
498
+ setValues(cells: readonly {
499
+ seriesId: string;
500
+ index: number;
501
+ value: unknown;
502
+ }[], options?: ChartEditOptions): ChartActionResult;
503
+ /** Adds a series (values padded to the categories) and selects it. Returns its id. */
504
+ addSeries(input?: ChartSeriesInput, options?: {
505
+ at?: number;
506
+ }): {
507
+ ok: true;
508
+ id: string;
509
+ } | {
510
+ ok: false;
511
+ message: string;
512
+ issues?: ChartIssue[];
513
+ };
514
+ removeSeries(id: string): ChartActionResult;
515
+ updateSeries(id: string, patch: ChartSeriesPatch): ChartActionResult;
516
+ toggleSeries(id: string): ChartActionResult;
517
+ /** Moves a series to position `to` (drawing and legend order). */
518
+ moveSeries(id: string, to: number): ChartActionResult;
519
+ /** Inserts a category (with gaps in every series) at `at` (default: the end). Returns its index. */
520
+ addCategory(label?: string, options?: {
521
+ at?: number;
522
+ }): {
523
+ ok: true;
524
+ index: number;
525
+ };
526
+ removeCategory(index: number): ChartActionResult;
527
+ renameCategory(index: number, label: string): ChartActionResult;
528
+ moveCategory(from: number, to: number): ChartActionResult;
529
+ /**
530
+ * Pastes a block of cells (TSV / CSV text or rows) into the data grid with its top-left at
531
+ * `row` (category index) and `column` (series index; `-1` is the category column). The
532
+ * grid grows to fit. Non-numeric value cells become gaps and are reported in `issues`.
533
+ */
534
+ pasteCells(row: number, column: number, cells: string | ReadonlyArray<ReadonlyArray<unknown>>): ChartActionResult & {
535
+ issues?: ChartIssue[];
536
+ };
537
+ /**
538
+ * Replaces the data with a grid of cells (see `chartDataFromTable`): one undo step. Series
539
+ * colours and types are kept by name.
540
+ */
541
+ importTable(rows: ReadonlyArray<ReadonlyArray<unknown>>, options?: ChartTableOptions): ChartActionResult & {
542
+ issues?: ChartIssue[];
543
+ };
544
+ /** Imports CSV (or TSV, detected by tabs) text; see `importTable`. */
545
+ importCsv(text: string, options?: ChartTableOptions & {
546
+ delimiter?: string;
547
+ }): ChartActionResult & {
548
+ issues?: ChartIssue[];
549
+ };
550
+ /** Selects a chart element (view state; not an undo step). */
551
+ select(selection: ChartSelection | null): void;
552
+ /**
553
+ * Deletes what is selected: a series or category is removed, a point becomes a gap, a
554
+ * title is cleared, the legend or an axis is hidden.
555
+ */
556
+ deleteSelection(): ChartActionResult;
557
+ /** Adds `delta` to a value (a gap counts as 0). */
558
+ nudgeValue(seriesId: string, index: number, delta: number): ChartActionResult;
559
+ /** Starts a continuous edit (a drag): every change until `endGesture()` is one undo step. */
560
+ beginGesture(key: string): void;
561
+ endGesture(): void;
562
+ /** The spec, for saving (a copy). */
563
+ toJSON(): ChartSpec;
564
+ /**
565
+ * Replaces the chart without an undo step (e.g. when opening a document). Problems are
566
+ * fixed with defaults and reported in `state.issues` (and returned).
567
+ */
568
+ load(input: unknown, options?: {
569
+ clearHistory?: boolean;
570
+ }): ChartIssue[];
571
+ undo(): boolean;
572
+ redo(): boolean;
573
+ /** Stops listening to the history (reconnected by the next `subscribe`). */
574
+ destroy(): void;
575
+ }
576
+ declare function createChartController(options?: ChartControllerOptions): ChartController;
577
+
578
+ interface ChartCommandOptions {
579
+ /** Id prefix (default `chart.`); use one per chart when several are registered. */
580
+ prefix?: string;
581
+ /** Palette group (default `Chart`). */
582
+ group?: string;
583
+ /** Command scope. Omit for global commands. */
584
+ scope?: string;
585
+ }
586
+ /**
587
+ * Palette and agent commands for a chart: describe, update presentation, replace data, set
588
+ * values, add / remove series and categories, import CSV and export SVG. Register them in a
589
+ * `CommandRegistry` and agents get them through `createCommandToolProvider`. Failures throw
590
+ * sentences, which the registry returns as `{ ok: false, code: 'failed', message }`.
591
+ */
592
+ declare function createChartCommands(controller: ChartController, options?: ChartCommandOptions): CommandSpec[];
593
+
594
+ /** Scene coordinates of a pointer, given the rendered element's box (the scene is scaled to fit it). */
595
+ declare function chartClientToScene(scene: Pick<ChartScene, 'width' | 'height'>, box: {
596
+ left: number;
597
+ top: number;
598
+ width: number;
599
+ height: number;
600
+ }, clientX: number, clientY: number): {
601
+ x: number;
602
+ y: number;
603
+ };
604
+ /** Whether a point can be dragged to a new value in this scene (cartesian, not percent-stacked, not hidden). */
605
+ declare function canDragChartPoint(controller: ChartController, scene: ChartScene, target: ChartSelection | undefined): target is Extract<ChartSelection, {
606
+ kind: 'point';
607
+ }>;
608
+ interface ChartPointDrag {
609
+ /** Moves the value with the pointer (scene coordinates). */
610
+ move(point: {
611
+ x: number;
612
+ y: number;
613
+ }): void;
614
+ /** Ends the drag (one undo step for the whole drag). */
615
+ end(): void;
616
+ }
617
+ /**
618
+ * Starts dragging a bar or point: the value follows the pointer along the value axis,
619
+ * snapped to a tenth of the tick step (`step` overrides), and the whole drag is one undo
620
+ * step. Works for stacked bars too (the drag changes the segment by the distance moved).
621
+ * Returns `null` when the target cannot be dragged.
622
+ */
623
+ declare function startChartPointDrag(controller: ChartController, scene: ChartScene, target: ChartSelection | undefined, start: {
624
+ x: number;
625
+ y: number;
626
+ }, options?: {
627
+ step?: number;
628
+ }): ChartPointDrag | null;
629
+ interface ChartKeyInput {
630
+ key: string;
631
+ shiftKey?: boolean;
632
+ altKey?: boolean;
633
+ metaKey?: boolean;
634
+ ctrlKey?: boolean;
635
+ }
636
+ /**
637
+ * Keyboard editing on a focused chart: arrows move a point selection between categories
638
+ * (← →) and change its value (↑ ↓, a tenth of the tick step; Shift: a whole step), Delete /
639
+ * Backspace deletes the selection, Escape clears it. Returns `true` when the key was used
640
+ * (call `preventDefault`).
641
+ */
642
+ declare function handleChartKey(controller: ChartController, scene: ChartScene | null, event: ChartKeyInput): boolean;
643
+ /** A short description of the selection for an inspector heading or a screen reader. */
644
+ declare function describeChartSelection(controller: ChartController, selection?: ChartSelection | null): string;
645
+
646
+ export { CHART_CURVES, CHART_LEGEND_POSITIONS, CHART_NUMBER_STYLES, CHART_ORIENTATIONS, CHART_SERIES_TYPES, CHART_STACKINGS, CHART_TYPES, CHART_TYPE_LABELS, CSS_VARIABLE_CHART_THEME, type ChartActionResult, type ChartAxis, type ChartCircleMark, type ChartCommandOptions, ChartController, type ChartControllerOptions, type ChartCurve, type ChartEditOptions, type ChartIssue, type ChartKeyInput, type ChartLayoutOptions, type ChartLegend, type ChartLegendPosition, type ChartLineMark, type ChartMark, type ChartMarkRole, type ChartNumberFormat, type ChartOrientation, type ChartPathMark, type ChartPointDrag, type ChartRect, type ChartRectMark, type ChartScene, type ChartSelection, type ChartSeries, type ChartSeriesInput, type ChartSeriesPatch, type ChartSeriesType, type ChartSpec, type ChartSpecPatch, type ChartStacking, type ChartState, type ChartSvgOptions, type ChartTableData, type ChartTableOptions, type ChartTextMark, type ChartTextMeasure, type ChartTheme, type ChartType, type ChartValue, type ChartValueScale, DEFAULT_CHART_PALETTE, DEFAULT_CHART_THEME, type NiceScale, canDragChartPoint, chartClientToScene, chartColorInputValue, chartDataFromTable, chartDataToTable, chartSceneToSvg, chartSeriesColor, chartSeriesType, chartSliceColor, chartTextBaseline, chartTextTransform, chartToSvg, chartValueAtPoint, cloneChartSeries, cloneChartSpec, createChartCommands, createChartController, createChartSpec, defaultChartAxis, describeChartSelection, estimateChartTextWidth, formatChartNumber, handleChartKey, isCartesianChart, layoutChart, linearMap, niceScale, niceStep, normalizeChartAxis, normalizeChartSpec, normalizeChartValues, parseChartValue, sameChartSelection, snapChartValue, startChartPointDrag, stepDecimals, uniqueChartSeriesId };