@opendata-ai/openchart-core 8.0.0-rc.9 → 8.1.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.
Files changed (83) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +403 -45
  3. package/dist/index.js +50 -18
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/dist/styles.css.map +1 -1
  7. package/package.json +1 -2
  8. package/schema/chart.schema.json +375 -69
  9. package/schema/table.schema.json +35 -1
  10. package/schema/vizspec.schema.json +992 -171
  11. package/src/accessibility/__tests__/alt-text.test.ts +0 -110
  12. package/src/accessibility/__tests__/aria.test.ts +0 -125
  13. package/src/accessibility/alt-text.ts +0 -155
  14. package/src/accessibility/aria.ts +0 -75
  15. package/src/accessibility/index.ts +0 -6
  16. package/src/colors/__tests__/colorblind.test.ts +0 -75
  17. package/src/colors/__tests__/contrast.test.ts +0 -119
  18. package/src/colors/__tests__/palettes.test.ts +0 -74
  19. package/src/colors/colorblind.ts +0 -131
  20. package/src/colors/contrast.ts +0 -143
  21. package/src/colors/index.ts +0 -36
  22. package/src/colors/palettes.ts +0 -206
  23. package/src/helpers/__tests__/deep-merge.test.ts +0 -54
  24. package/src/helpers/__tests__/spec-builders.test.ts +0 -338
  25. package/src/helpers/deep-merge.ts +0 -29
  26. package/src/helpers/spec-builders.ts +0 -479
  27. package/src/index.ts +0 -215
  28. package/src/labels/__tests__/collision.test.ts +0 -310
  29. package/src/labels/collision.ts +0 -249
  30. package/src/labels/index.ts +0 -13
  31. package/src/layout/__tests__/chrome.test.ts +0 -208
  32. package/src/layout/__tests__/text-measure.test.ts +0 -57
  33. package/src/layout/chrome.ts +0 -470
  34. package/src/layout/index.ts +0 -18
  35. package/src/layout/text-measure.ts +0 -404
  36. package/src/layout/text-wrap.ts +0 -93
  37. package/src/locale/__tests__/format.test.ts +0 -606
  38. package/src/locale/format.ts +0 -459
  39. package/src/locale/index.ts +0 -21
  40. package/src/responsive/__tests__/breakpoints.test.ts +0 -146
  41. package/src/responsive/__tests__/metrics.test.ts +0 -52
  42. package/src/responsive/breakpoints.ts +0 -177
  43. package/src/responsive/index.ts +0 -53
  44. package/src/responsive/metrics.ts +0 -299
  45. package/src/schema/__tests__/generated-artifacts.test.ts +0 -42
  46. package/src/schema/__tests__/schema.test.ts +0 -179
  47. package/src/styles/__tests__/reduced-motion-selectors.test.ts +0 -28
  48. package/src/styles/animation.css +0 -213
  49. package/src/styles/base.css +0 -102
  50. package/src/styles/chrome.css +0 -174
  51. package/src/styles/dark.css +0 -44
  52. package/src/styles/graph.css +0 -135
  53. package/src/styles/index.css +0 -28
  54. package/src/styles/keyframes.css +0 -151
  55. package/src/styles/legend.css +0 -18
  56. package/src/styles/reduced-motion.css +0 -67
  57. package/src/styles/series-search.css +0 -153
  58. package/src/styles/sparkline.css +0 -16
  59. package/src/styles/table-animation.css +0 -93
  60. package/src/styles/table.css +0 -398
  61. package/src/styles/token-definitions.ts +0 -199
  62. package/src/styles/tokens.css +0 -156
  63. package/src/styles/tooltip.css +0 -126
  64. package/src/styles/you-draw-it.css +0 -126
  65. package/src/theme/__tests__/dark-mode.test.ts +0 -232
  66. package/src/theme/__tests__/defaults.test.ts +0 -73
  67. package/src/theme/__tests__/resolve.test.ts +0 -277
  68. package/src/theme/dark-mode.ts +0 -258
  69. package/src/theme/defaults.ts +0 -110
  70. package/src/theme/index.ts +0 -8
  71. package/src/theme/presets.ts +0 -64
  72. package/src/theme/resolve.ts +0 -312
  73. package/src/types/__tests__/encoding.test.ts +0 -368
  74. package/src/types/__tests__/gradient.test.ts +0 -95
  75. package/src/types/__tests__/spec.test.ts +0 -499
  76. package/src/types/encoding.ts +0 -280
  77. package/src/types/events.ts +0 -236
  78. package/src/types/index.ts +0 -290
  79. package/src/types/layout.ts +0 -2024
  80. package/src/types/schema-roots.ts +0 -32
  81. package/src/types/spec.ts +0 -2925
  82. package/src/types/table.ts +0 -108
  83. package/src/types/theme.ts +0 -209
@@ -1,280 +0,0 @@
1
- /**
2
- * Per-mark-type encoding validation rules.
3
- *
4
- * Defines which encoding channels are required vs optional for each mark type.
5
- * The engine compiler uses these rules to validate specs at runtime (TypeScript
6
- * catches compile-time errors; these catch runtime JSON from Claude or APIs).
7
- */
8
-
9
- import type { FieldType, MarkType } from './spec';
10
-
11
- // ---------------------------------------------------------------------------
12
- // Encoding rule types
13
- // ---------------------------------------------------------------------------
14
-
15
- /** Constraint on what field types are valid for an encoding channel. */
16
- export interface ChannelRule {
17
- /** Whether this channel is required for the chart type. */
18
- required: boolean;
19
- /** Allowed field types. If empty, any field type is accepted. */
20
- allowedTypes: FieldType[];
21
- }
22
-
23
- /** Encoding rules for a single chart type: which channels are required/optional. */
24
- export interface EncodingRule {
25
- x: ChannelRule;
26
- y: ChannelRule;
27
- x2?: ChannelRule;
28
- y2?: ChannelRule;
29
- color: ChannelRule;
30
- size: ChannelRule;
31
- opacity?: ChannelRule;
32
- strokeDash?: ChannelRule;
33
- text?: ChannelRule;
34
- tooltip?: ChannelRule;
35
- theta?: ChannelRule;
36
- detail: ChannelRule;
37
- }
38
-
39
- // ---------------------------------------------------------------------------
40
- // Mark encoding rules
41
- // ---------------------------------------------------------------------------
42
-
43
- /** Helper to create a required channel rule. */
44
- function required(...types: FieldType[]): ChannelRule {
45
- return { required: true, allowedTypes: types };
46
- }
47
-
48
- /** Helper to create an optional channel rule. */
49
- function optional(...types: FieldType[]): ChannelRule {
50
- return { required: false, allowedTypes: types };
51
- }
52
-
53
- /**
54
- * Encoding rules per mark type.
55
- *
56
- * Defines which channels are required and what field types they accept.
57
- * The compiler uses this map to validate user specs at runtime.
58
- *
59
- * Key design decisions:
60
- * - line/area: x is temporal/ordinal (the axis), y is quantitative (the value)
61
- * - bar: covers both horizontal and vertical orientations, so both axes accept
62
- * all relevant types. The engine validates the combination later (one axis
63
- * must be quantitative).
64
- * - arc: no x axis; y is the value (quantitative), color is the category
65
- * - circle: y is the category, x is quantitative
66
- * - point: both axes are quantitative
67
- * - text/rule: fully optional positioning
68
- * - tick/rect: both axes required, any type
69
- * - beeswarm: both axes optional at the channel level; the compiler enforces
70
- * the combination (exactly one quantitative value axis, the other axis an
71
- * optional nominal/ordinal lane channel)
72
- * - waffle: no positional axes; y is the share value (quantitative, with
73
- * theta accepted as an alias like arc), color is the category
74
- * - calendar: x is the daily date (temporal), color the per-day value
75
- * (quantitative); no y channel (the calendar owns its own geometry)
76
- * - parliament: no positional axes; theta (aliased to y) is the seat count
77
- * (quantitative), color the party
78
- */
79
- export const MARK_ENCODING_RULES: Record<MarkType, EncodingRule> = {
80
- bar: {
81
- x: required('quantitative', 'nominal', 'ordinal', 'temporal'),
82
- y: required('quantitative', 'nominal', 'ordinal'),
83
- x2: optional('quantitative'),
84
- y2: optional('quantitative'),
85
- color: optional('nominal', 'ordinal', 'quantitative'),
86
- size: optional(),
87
- opacity: optional('quantitative'),
88
- tooltip: optional(),
89
- detail: optional('nominal'),
90
- },
91
- line: {
92
- x: required('temporal', 'ordinal'),
93
- y: required('quantitative'),
94
- color: optional('nominal', 'ordinal', 'quantitative'),
95
- size: optional(),
96
- opacity: optional('quantitative'),
97
- strokeDash: optional('nominal', 'ordinal'),
98
- tooltip: optional(),
99
- detail: optional('nominal'),
100
- },
101
- area: {
102
- x: required('temporal', 'ordinal'),
103
- y: required('quantitative'),
104
- y2: optional('quantitative'),
105
- color: optional('nominal', 'ordinal', 'quantitative'),
106
- size: optional(),
107
- opacity: optional('quantitative'),
108
- tooltip: optional(),
109
- detail: optional('nominal'),
110
- },
111
- point: {
112
- x: required('quantitative', 'temporal', 'nominal', 'ordinal'),
113
- y: required('quantitative', 'temporal', 'nominal', 'ordinal'),
114
- color: optional('nominal', 'ordinal', 'quantitative'),
115
- size: optional('quantitative'),
116
- opacity: optional('quantitative'),
117
- tooltip: optional(),
118
- detail: optional('nominal'),
119
- },
120
- circle: {
121
- x: required('quantitative'),
122
- y: required('nominal', 'ordinal'),
123
- color: optional('nominal', 'ordinal', 'quantitative'),
124
- size: optional('quantitative'),
125
- opacity: optional('quantitative'),
126
- tooltip: optional(),
127
- detail: optional('nominal'),
128
- },
129
- lollipop: {
130
- x: required('quantitative'),
131
- y: required('nominal', 'ordinal'),
132
- color: optional('nominal', 'ordinal', 'quantitative'),
133
- size: optional('quantitative'),
134
- opacity: optional('quantitative'),
135
- tooltip: optional(),
136
- detail: optional('nominal'),
137
- },
138
- beeswarm: {
139
- x: optional('quantitative', 'nominal', 'ordinal'),
140
- y: optional('quantitative', 'nominal', 'ordinal'),
141
- color: optional('nominal', 'ordinal', 'quantitative'),
142
- size: optional('quantitative'),
143
- opacity: optional('quantitative'),
144
- tooltip: optional(),
145
- detail: optional('nominal'),
146
- },
147
- // Range: x+x2 with nominal y (horizontal) or y+y2 with nominal x (vertical).
148
- // The orientation-dependent x2/y2 requirement is enforced by a dedicated
149
- // check in the validator; the static table can only mark them optional.
150
- range: {
151
- x: required('quantitative', 'nominal', 'ordinal'),
152
- y: required('quantitative', 'nominal', 'ordinal'),
153
- x2: optional('quantitative'),
154
- y2: optional('quantitative'),
155
- color: optional('nominal', 'ordinal'),
156
- size: optional(),
157
- opacity: optional('quantitative'),
158
- tooltip: optional(),
159
- detail: optional('nominal'),
160
- },
161
- arc: {
162
- x: optional(),
163
- y: optional('quantitative'),
164
- theta: required('quantitative'),
165
- color: required('nominal', 'ordinal'),
166
- size: optional(),
167
- opacity: optional('quantitative'),
168
- tooltip: optional(),
169
- detail: optional('nominal'),
170
- },
171
- waffle: {
172
- x: optional(),
173
- y: required('quantitative'),
174
- color: required('nominal', 'ordinal'),
175
- size: optional(),
176
- opacity: optional('quantitative'),
177
- tooltip: optional(),
178
- theta: optional('quantitative'),
179
- detail: optional('nominal'),
180
- },
181
- // parliament: hemicycle seat chart. Like arc/waffle, no positional axes;
182
- // color is the party (required), theta the seat count (aliased to y in the
183
- // sugar pass). y is accepted so the theta alias resolves before the rules
184
- // check runs.
185
- parliament: {
186
- x: optional(),
187
- y: required('quantitative'),
188
- color: required('nominal', 'ordinal'),
189
- size: optional(),
190
- opacity: optional('quantitative'),
191
- tooltip: optional(),
192
- theta: optional('quantitative'),
193
- detail: optional('nominal'),
194
- },
195
- text: {
196
- x: optional(),
197
- y: optional(),
198
- color: optional(),
199
- size: optional('quantitative'),
200
- opacity: optional('quantitative'),
201
- text: required(),
202
- tooltip: optional(),
203
- detail: optional('nominal'),
204
- },
205
- rule: {
206
- x: optional(),
207
- y: optional(),
208
- x2: optional(),
209
- y2: optional(),
210
- color: optional(),
211
- size: optional(),
212
- opacity: optional('quantitative'),
213
- strokeDash: optional('nominal', 'ordinal'),
214
- tooltip: optional(),
215
- detail: optional('nominal'),
216
- },
217
- tick: {
218
- x: required(),
219
- y: required(),
220
- color: optional(),
221
- size: optional(),
222
- opacity: optional('quantitative'),
223
- tooltip: optional(),
224
- detail: optional('nominal'),
225
- },
226
- rect: {
227
- x: required(),
228
- y: required(),
229
- x2: optional(),
230
- y2: optional(),
231
- color: optional(),
232
- size: optional(),
233
- opacity: optional('quantitative'),
234
- tooltip: optional(),
235
- detail: optional('nominal'),
236
- },
237
- // calendar: x is the daily date (temporal), color the per-day value
238
- // (quantitative). No y channel: the calendar computes its own
239
- // weeks-x-weekdays geometry, so y is left optional here and the dedicated
240
- // validator rejects it with a pointed message.
241
- calendar: {
242
- x: required('temporal'),
243
- y: optional(),
244
- color: required('quantitative'),
245
- size: optional(),
246
- opacity: optional('quantitative'),
247
- tooltip: optional(),
248
- detail: optional('nominal'),
249
- },
250
- };
251
-
252
- /** @deprecated Use MARK_ENCODING_RULES instead. */
253
- export const CHART_ENCODING_RULES = MARK_ENCODING_RULES;
254
-
255
- // ---------------------------------------------------------------------------
256
- // Graph encoding rules
257
- // ---------------------------------------------------------------------------
258
-
259
- /** Encoding rule for a single graph visual channel. */
260
- export interface GraphChannelRule {
261
- /** Whether this channel is required. */
262
- required: boolean;
263
- /** Allowed field types. Empty means any type. */
264
- allowedTypes: FieldType[];
265
- }
266
-
267
- /**
268
- * Encoding rules for graph visualizations.
269
- *
270
- * All graph encoding channels are optional since a graph can be rendered
271
- * with just nodes and edges (uniform appearance). Encoding channels add
272
- * visual differentiation based on data fields.
273
- */
274
- export const GRAPH_ENCODING_RULES: Record<string, GraphChannelRule> = {
275
- nodeColor: { required: false, allowedTypes: ['nominal', 'ordinal'] },
276
- nodeSize: { required: false, allowedTypes: ['quantitative'] },
277
- edgeColor: { required: false, allowedTypes: ['nominal', 'ordinal'] },
278
- edgeWidth: { required: false, allowedTypes: ['quantitative'] },
279
- nodeLabel: { required: false, allowedTypes: [] },
280
- };
@@ -1,236 +0,0 @@
1
- /**
2
- * Chart interaction event types.
3
- *
4
- * These types define the callback signatures for user interactions with
5
- * chart elements: clicking marks, hovering, legend toggles, and annotation clicks.
6
- *
7
- * Event handlers are optional and passed through MountOptions (vanilla) or
8
- * ChartProps (React). The vanilla adapter wires DOM event listeners to
9
- * mark elements and constructs these typed events from the raw browser events.
10
- */
11
-
12
- import type {
13
- Annotation,
14
- AnnotationOffset,
15
- DataRow,
16
- RangeAnnotation,
17
- RefLineAnnotation,
18
- TextAnnotation,
19
- } from './spec';
20
-
21
- // ---------------------------------------------------------------------------
22
- // Chrome key identifiers
23
- // ---------------------------------------------------------------------------
24
-
25
- /** Identifies a specific chrome text element (title, subtitle, source, byline, footer). */
26
- export type ChromeKey = 'title' | 'subtitle' | 'source' | 'byline' | 'footer';
27
-
28
- // ---------------------------------------------------------------------------
29
- // Element references (identity for selection/edit callbacks)
30
- // ---------------------------------------------------------------------------
31
-
32
- /**
33
- * Reference to an editable chart element.
34
- * Carries enough info to find the element in both the spec and the DOM.
35
- * The `annotation` variant uses two-tier identity: `id` (when the consumer provides one)
36
- * and `index` (always available, position in the spec's annotations array).
37
- */
38
- export type ElementRef =
39
- | {
40
- type: 'annotation';
41
- index: number;
42
- id?: string;
43
- /** RFC 6901 JSON Pointer to the edited property in the spec. */
44
- path?: string;
45
- }
46
- | {
47
- type: 'chrome';
48
- key: ChromeKey;
49
- /** RFC 6901 JSON Pointer to the edited property in the spec. */
50
- path?: string;
51
- }
52
- | {
53
- type: 'series-label';
54
- series: string;
55
- /** RFC 6901 JSON Pointer to the edited property in the spec. */
56
- path?: string;
57
- }
58
- | {
59
- type: 'legend';
60
- /** RFC 6901 JSON Pointer to the edited property in the spec. */
61
- path?: string;
62
- }
63
- | {
64
- type: 'legend-entry';
65
- series: string;
66
- index: number;
67
- /** RFC 6901 JSON Pointer to the edited property in the spec. */
68
- path?: string;
69
- };
70
-
71
- /** Helper constructors for ergonomic ElementRef creation. */
72
- export const elementRef = {
73
- annotation: (index: number, id?: string, path?: string): ElementRef => ({
74
- type: 'annotation',
75
- index,
76
- ...(id !== undefined ? { id } : {}),
77
- ...(path !== undefined ? { path } : {}),
78
- }),
79
- chrome: (key: ChromeKey, path?: string): ElementRef => ({
80
- type: 'chrome',
81
- key,
82
- ...(path !== undefined ? { path } : {}),
83
- }),
84
- seriesLabel: (series: string, path?: string): ElementRef => ({
85
- type: 'series-label',
86
- series,
87
- ...(path !== undefined ? { path } : {}),
88
- }),
89
- legend: (path?: string): ElementRef => ({
90
- type: 'legend',
91
- ...(path !== undefined ? { path } : {}),
92
- }),
93
- legendEntry: (series: string, index: number, path?: string): ElementRef => ({
94
- type: 'legend-entry',
95
- series,
96
- index,
97
- ...(path !== undefined ? { path } : {}),
98
- }),
99
- } as const;
100
-
101
- // ---------------------------------------------------------------------------
102
- // Element edit events
103
- // ---------------------------------------------------------------------------
104
-
105
- /**
106
- * Discriminated union of all element edit events.
107
- * Fired by the `onEdit` callback when any editable chart element is modified.
108
- * Covers repositioning (drag), deletion (Delete key), and text editing (double-click).
109
- * Selection events (onSelect/onDeselect) are separate callbacks, not part of this union.
110
- *
111
- * For the `annotation` variant:
112
- * - `annotation` is the ORIGINAL spec annotation (may have a stale or missing offset)
113
- * - `offset` is the NEW accumulated position after the drag completes
114
- * - To persist a drag edit back into your spec: `{ ...edit.annotation, offset: edit.offset }`
115
- */
116
- export type ElementEdit =
117
- | {
118
- type: 'annotation';
119
- element: ElementRef;
120
- annotation: TextAnnotation;
121
- offset: AnnotationOffset;
122
- }
123
- | {
124
- type: 'annotation-connector';
125
- element: ElementRef;
126
- annotation: TextAnnotation;
127
- endpoint: 'from' | 'to';
128
- offset: AnnotationOffset;
129
- }
130
- | {
131
- type: 'range-label';
132
- element: ElementRef;
133
- annotation: RangeAnnotation;
134
- labelOffset: AnnotationOffset;
135
- }
136
- | {
137
- type: 'refline-label';
138
- element: ElementRef;
139
- annotation: RefLineAnnotation;
140
- labelOffset: AnnotationOffset;
141
- }
142
- | {
143
- type: 'annotation-anchor';
144
- element: ElementRef;
145
- annotation: TextAnnotation;
146
- x: string | number;
147
- y: string | number;
148
- }
149
- | { type: 'chrome'; key: ChromeKey; text: string; offset: AnnotationOffset }
150
- | { type: 'series-label'; series: string; offset: AnnotationOffset }
151
- | { type: 'legend'; offset: AnnotationOffset }
152
- /**
153
- * Transient legend visibility toggle. Reports the same runtime show/hide
154
- * a reader triggers; not persisted by openchart. To author default-hidden
155
- * series, set `spec.hiddenSeries` directly. Hosts building spec
156
- * persistence should generally not write legend-toggle edits back into
157
- * the authored spec. `hidden: true` means the series was just hidden.
158
- */
159
- | { type: 'legend-toggle'; series: string; hidden: boolean }
160
- | { type: 'add'; annotation: TextAnnotation }
161
- | { type: 'delete'; element: ElementRef }
162
- | { type: 'text-edit'; element: ElementRef; oldText: string; newText: string };
163
-
164
- // ---------------------------------------------------------------------------
165
- // Mark events
166
- // ---------------------------------------------------------------------------
167
-
168
- /**
169
- * Event fired when a user interacts with a data mark (bar, point, line segment, etc.).
170
- *
171
- * Contains the underlying data row, the series it belongs to (if multi-series),
172
- * the position within the chart container, and the raw browser MouseEvent.
173
- */
174
- export interface MarkEvent {
175
- /** The data row associated with the mark that was interacted with. */
176
- datum: DataRow;
177
- /** Series identifier, if the chart has multiple series (e.g. multi-line). */
178
- series?: string;
179
- /** Position of the interaction relative to the chart container. */
180
- position: { x: number; y: number };
181
- /** The raw browser MouseEvent. */
182
- event: MouseEvent;
183
- }
184
-
185
- // ---------------------------------------------------------------------------
186
- // Chart event handler interface
187
- // ---------------------------------------------------------------------------
188
-
189
- /**
190
- * Event handler callbacks for chart interactions.
191
- *
192
- * All handlers are optional. Pass these through MountOptions (vanilla adapter)
193
- * or ChartProps (React component) to receive interaction callbacks.
194
- */
195
- export interface ChartEventHandlers {
196
- /**
197
- * Explicitly enable or disable edit interactions (drag, select, keyboard
198
- * delete/edit). When true, the interaction layer is wired even without
199
- * onEdit. When false, all edit interactions are suppressed even when
200
- * onEdit is provided. When omitted, each interaction block uses its
201
- * existing callback-presence gate.
202
- */
203
- editable?: boolean;
204
- /** Called when a data mark is clicked. */
205
- onMarkClick?: (event: MarkEvent) => void;
206
- /** Called when the mouse enters a data mark. */
207
- onMarkHover?: (event: MarkEvent) => void;
208
- /** Called when the mouse leaves a data mark. */
209
- onMarkLeave?: () => void;
210
- /** Called when a legend entry is toggled (clicked to show/hide a series). */
211
- onLegendToggle?: (series: string, visible: boolean) => void;
212
- /**
213
- * Called when the series search (`seriesSearch`) changes the highlight set.
214
- * Receives the full set of highlighted values after the change, including
215
- * the authored `encoding.color.highlight` baseline.
216
- */
217
- onHighlightChange?: (values: string[]) => void;
218
- /** Called when an annotation element is clicked. */
219
- onAnnotationClick?: (annotation: Annotation, event: MouseEvent) => void;
220
- /** Called when a text annotation label is dragged to a new position. */
221
- onAnnotationEdit?: (annotation: TextAnnotation, updatedOffset: AnnotationOffset) => void;
222
- /** Unified edit callback. Fires for any spec-modifying edit (repositioning, deletion, text editing). */
223
- onEdit?: (edit: ElementEdit) => void;
224
- /** Fired when an element is selected via click or programmatic select(). */
225
- onSelect?: (element: ElementRef) => void;
226
- /** Fired when the current element is deselected (click empty, Escape, or new selection replaces old). */
227
- onDeselect?: (element: ElementRef) => void;
228
- /** Fired when inline text editing commits. Also flows through onEdit as a 'text-edit' event. */
229
- onTextEdit?: (element: ElementRef, oldText: string, newText: string) => void;
230
- /**
231
- * Fired when a "you draw it" (`youDrawIt`) drawing is revealed (button click
232
- * or programmatic reveal), with the reader's guess in data coordinates,
233
- * ordered by x. For newsrooms aggregating reader guesses.
234
- */
235
- onReveal?: (guess: Array<{ x: string | number; y: number }>) => void;
236
- }