semiotic 3.6.0 → 3.7.1
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/CLAUDE.md +192 -228
- package/README.md +70 -17
- package/ai/cli.js +41 -0
- package/ai/componentMetadata.cjs +11 -2
- package/ai/dist/mcp-server.js +625 -10
- package/ai/examples.md +98 -0
- package/ai/schema.json +581 -1
- package/ai/system-prompt.md +7 -4
- package/dist/components/AccessibleNavTree.d.ts +26 -0
- package/dist/components/Annotation.d.ts +41 -15
- package/dist/components/CategoryColors.d.ts +1 -1
- package/dist/components/ChartContainer.d.ts +32 -2
- package/dist/components/ChartGrid.d.ts +1 -1
- package/dist/components/ContextLayout.d.ts +1 -1
- package/dist/components/DataSummaryContext.d.ts +1 -1
- package/dist/components/DetailsPanel.d.ts +1 -1
- package/dist/components/Legend.d.ts +3 -2
- package/dist/components/LinkedCharts.d.ts +1 -1
- package/dist/components/ThemeProvider.d.ts +1 -1
- package/dist/components/Tooltip/FlippingTooltip.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +2 -2
- package/dist/components/ai/annotationProvenance.d.ts +349 -0
- package/dist/components/ai/audienceProfile.d.ts +60 -3
- package/dist/components/ai/chartCapabilityTypes.d.ts +60 -2
- package/dist/components/ai/chartRoles.d.ts +27 -0
- package/dist/components/ai/conversationArc.d.ts +379 -0
- package/dist/components/ai/dataScaleProfile.d.ts +320 -0
- package/dist/components/ai/describeChart.d.ts +114 -0
- package/dist/components/ai/navigationTree.d.ts +45 -0
- package/dist/components/ai/qualityScorecard.d.ts +11 -0
- package/dist/components/ai/readerGrounding.d.ts +70 -0
- package/dist/components/ai/suggestCharts.d.ts +34 -1
- package/dist/components/ai/useConversationArc.d.ts +89 -0
- package/dist/components/ai/useNavigationSync.d.ts +61 -0
- package/dist/components/ai/variantDiscovery.d.ts +168 -0
- package/dist/components/charts/geo/ChoroplethMap.d.ts +2 -1
- package/dist/components/charts/network/CirclePack.d.ts +2 -1
- package/dist/components/charts/network/OrbitDiagram.d.ts +1 -1
- package/dist/components/charts/network/TreeDiagram.d.ts +2 -1
- package/dist/components/charts/network/Treemap.d.ts +2 -1
- package/dist/components/charts/realtime/RealtimeHeatmap.d.ts +3 -0
- package/dist/components/charts/realtime/RealtimeHistogram.d.ts +4 -1
- package/dist/components/charts/realtime/RealtimeLineChart.d.ts +3 -0
- package/dist/components/charts/realtime/RealtimeSwarmChart.d.ts +3 -0
- package/dist/components/charts/realtime/RealtimeWaterfallChart.d.ts +3 -0
- package/dist/components/charts/shared/ChartError.d.ts +2 -1
- package/dist/components/charts/shared/annotationHierarchy.d.ts +42 -0
- package/dist/components/charts/shared/annotationResolvers.d.ts +3 -2
- package/dist/components/charts/shared/annotationRules.d.ts +16 -0
- package/dist/components/charts/shared/annotationTypes.d.ts +14 -0
- package/dist/components/charts/shared/auditAccessibility.d.ts +90 -0
- package/dist/components/charts/shared/chartSpecs.d.ts +2 -3
- package/dist/components/charts/shared/diagnoseConfig.d.ts +4 -6
- package/dist/components/charts/shared/selectionUtils.d.ts +5 -2
- package/dist/components/charts/shared/streamPropsHelpers.d.ts +2 -0
- package/dist/components/charts/shared/types.d.ts +5 -1
- package/dist/components/charts/shared/withChartWrapper.d.ts +1 -1
- package/dist/components/charts/value/BigNumber.capability.d.ts +13 -0
- package/dist/components/charts/value/BigNumber.d.ts +14 -0
- package/dist/components/charts/value/formatting.d.ts +40 -0
- package/dist/components/charts/value/thresholdSparkline.d.ts +40 -0
- package/dist/components/charts/value/types.d.ts +292 -0
- package/dist/components/charts/xy/MinimapChart.d.ts +2 -1
- package/dist/components/charts/xy/ScatterplotMatrix.d.ts +2 -1
- package/dist/components/realtime/lifecycleBands.d.ts +44 -0
- package/dist/components/realtime/types.d.ts +23 -8
- package/dist/components/recipes/annotationDensity.d.ts +69 -0
- package/dist/components/recipes/annotationLayout.d.ts +93 -0
- package/dist/components/semiotic-ai.d.ts +38 -15
- package/dist/components/semiotic-realtime.d.ts +2 -0
- package/dist/components/semiotic-recipes.d.ts +4 -0
- package/dist/components/semiotic-server.d.ts +2 -1
- package/dist/components/semiotic-utils.d.ts +8 -0
- package/dist/components/semiotic-value.d.ts +55 -0
- package/dist/components/semiotic.d.ts +7 -0
- package/dist/components/server/renderEvidence.d.ts +92 -0
- package/dist/components/server/renderToStaticSVG.d.ts +14 -1
- package/dist/components/server/staticAnnotations.d.ts +2 -0
- package/dist/components/stream/AccessibleDataTable.d.ts +15 -6
- package/dist/components/stream/FocusRing.d.ts +2 -1
- package/dist/components/stream/MarginalGraphics.d.ts +2 -1
- package/dist/components/stream/NetworkSVGOverlay.d.ts +13 -6
- package/dist/components/stream/OrdinalBrushOverlay.d.ts +19 -1
- package/dist/components/stream/OrdinalSVGOverlay.d.ts +4 -2
- package/dist/components/stream/SVGOverlay.d.ts +5 -2
- package/dist/components/stream/XYBrushOverlay.d.ts +21 -1
- package/dist/components/stream/geoTypes.d.ts +3 -0
- package/dist/components/stream/networkTypes.d.ts +2 -0
- package/dist/components/stream/ordinalTypes.d.ts +2 -0
- package/dist/components/stream/types.d.ts +2 -0
- package/dist/geo.min.js +1 -1
- package/dist/geo.module.min.js +1 -1
- package/dist/network.min.js +1 -1
- package/dist/network.module.min.js +1 -1
- package/dist/ordinal.min.js +1 -1
- package/dist/ordinal.module.min.js +1 -1
- package/dist/realtime.min.js +1 -1
- package/dist/realtime.module.min.js +1 -1
- package/dist/semiotic-ai.d.ts +38 -15
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-realtime.d.ts +2 -0
- package/dist/semiotic-recipes.d.ts +4 -0
- package/dist/semiotic-recipes.min.js +1 -1
- package/dist/semiotic-recipes.module.min.js +1 -1
- package/dist/semiotic-server.d.ts +2 -1
- package/dist/semiotic-themes.min.js +1 -1
- package/dist/semiotic-themes.module.min.js +1 -1
- package/dist/semiotic-utils.d.ts +8 -0
- package/dist/semiotic-utils.min.js +1 -1
- package/dist/semiotic-utils.module.min.js +1 -1
- package/dist/semiotic-value.d.ts +55 -0
- package/dist/semiotic-value.min.js +2 -0
- package/dist/semiotic-value.module.min.js +2 -0
- package/dist/semiotic.d.ts +7 -0
- package/dist/semiotic.min.js +1 -1
- package/dist/semiotic.module.min.js +1 -1
- package/dist/server.min.js +1 -1
- package/dist/server.module.min.js +1 -1
- package/dist/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +19 -5
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scale-aware suggestion overlay. The companion to AudienceProfile: where
|
|
3
|
+
* AudienceProfile describes *who* reads the chart, DataScaleProfile and
|
|
4
|
+
* DataQualityProfile describe *how big* and *how clean* the data actually is.
|
|
5
|
+
*
|
|
6
|
+
* Semiotic does not measure scale or quality from the data passed to it —
|
|
7
|
+
* the row data may be a sample, a future projection, or completely absent.
|
|
8
|
+
* Orgs declare these facts up front and the suggestion engine biases
|
|
9
|
+
* rankings accordingly. Identical philosophy to AudienceProfile.
|
|
10
|
+
*
|
|
11
|
+
* The two profiles compose additively with the audience overlay:
|
|
12
|
+
*
|
|
13
|
+
* composite = baseScore
|
|
14
|
+
* + scaleBias(scale, capability, profile)
|
|
15
|
+
* + qualityBias(quality, capability, profile)
|
|
16
|
+
* + audienceBias(audience, capability)
|
|
17
|
+
*
|
|
18
|
+
* Each layer can be omitted independently. Most adjust ranking only, but
|
|
19
|
+
* per-chart scale preferences can also hard-filter via `minBand`/`maxBand`
|
|
20
|
+
* exclusions in addition to `fits()`.
|
|
21
|
+
*/
|
|
22
|
+
import type { ChartCapability, ChartDataProfile } from "./chartCapabilityTypes";
|
|
23
|
+
/**
|
|
24
|
+
* Coarse row-count band. Used for grouping suggestions ("show me charts that
|
|
25
|
+
* work at small scale") and for surfacing scale-band on each suggestion.
|
|
26
|
+
*
|
|
27
|
+
* Defaults below are research-backed starting points — see DEFAULT_SCALE_THRESHOLDS.
|
|
28
|
+
*/
|
|
29
|
+
export type ScaleBand = "tiny" | "small" | "medium" | "large" | "huge";
|
|
30
|
+
/**
|
|
31
|
+
* Coarse cardinality band. A "low"-cardinality field is bar-chart-able;
|
|
32
|
+
* "high" almost always wants treemap, force layout, or aggregation.
|
|
33
|
+
*/
|
|
34
|
+
export type CardinalityBand = "low" | "medium" | "high";
|
|
35
|
+
/**
|
|
36
|
+
* Field-count band. "narrow" datasets need at most one mark per column;
|
|
37
|
+
* "wide" datasets typically need a matrix-style layout (parallel coords,
|
|
38
|
+
* scatterplot matrix, heatmap of fields).
|
|
39
|
+
*/
|
|
40
|
+
export type FieldBand = "narrow" | "typical" | "wide";
|
|
41
|
+
/**
|
|
42
|
+
* Research-backed default breakpoints. Treat as starting points — orgs override
|
|
43
|
+
* via `DataScaleProfile.thresholds`.
|
|
44
|
+
*
|
|
45
|
+
* Row thresholds:
|
|
46
|
+
* • tiny ≤ 3 — single-value territory; recommendation often "a value, not a chart"
|
|
47
|
+
* • small ≤ 25 — Miller's 7±2 plus a comfortable buffer; bar/pie/dot legible
|
|
48
|
+
* • medium ≤ 250 — line/scatter/area sweet spot (Cleveland-McGill, position channel)
|
|
49
|
+
* • large ≤ 5000 — dense scatter/heatmap/ridgeline (Munzner ch. 10 quantitative encoding)
|
|
50
|
+
* • huge > 5000 — aggregation, sampling, density reduction required (Few, "Now You See It")
|
|
51
|
+
*
|
|
52
|
+
* Cardinality (per categorical field):
|
|
53
|
+
* • low ≤ 7 — Miller (1956); robust bar chart
|
|
54
|
+
* • medium ≤ 25 — bar still legible with care; treemap competitive
|
|
55
|
+
* • high > 25 — treemap, packed force, or aggregation
|
|
56
|
+
*
|
|
57
|
+
* Field count:
|
|
58
|
+
* • narrow ≤ 3 — single-mark-per-row layouts dominate
|
|
59
|
+
* • typical ≤ 10 — standard catalog applies
|
|
60
|
+
* • wide > 10 — parallel coords / scatterplot matrix territory
|
|
61
|
+
*
|
|
62
|
+
* References:
|
|
63
|
+
* - Miller, G.A. (1956). "The Magical Number Seven, Plus or Minus Two."
|
|
64
|
+
* Psychological Review, 63(2), 81–97.
|
|
65
|
+
* - Cleveland, W.S. & McGill, R. (1984). "Graphical Perception: Theory,
|
|
66
|
+
* Experimentation, and Application to the Development of Graphical Methods."
|
|
67
|
+
* JASA, 79(387), 531–554.
|
|
68
|
+
* - Munzner, T. (2014). Visualization Analysis and Design, ch. 10.
|
|
69
|
+
* - Few, S. (2009). Now You See It: Simple Visualization Techniques for
|
|
70
|
+
* Quantitative Analysis.
|
|
71
|
+
*/
|
|
72
|
+
export declare const DEFAULT_SCALE_THRESHOLDS: {
|
|
73
|
+
readonly rows: {
|
|
74
|
+
readonly tiny: 3;
|
|
75
|
+
readonly small: 25;
|
|
76
|
+
readonly medium: 250;
|
|
77
|
+
readonly large: 5000;
|
|
78
|
+
};
|
|
79
|
+
readonly cardinality: {
|
|
80
|
+
readonly low: 7;
|
|
81
|
+
readonly medium: 25;
|
|
82
|
+
};
|
|
83
|
+
readonly fields: {
|
|
84
|
+
readonly narrow: 3;
|
|
85
|
+
readonly typical: 10;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
export interface ScaleThresholds {
|
|
89
|
+
rows?: {
|
|
90
|
+
tiny?: number;
|
|
91
|
+
small?: number;
|
|
92
|
+
medium?: number;
|
|
93
|
+
large?: number;
|
|
94
|
+
};
|
|
95
|
+
cardinality?: {
|
|
96
|
+
low?: number;
|
|
97
|
+
medium?: number;
|
|
98
|
+
};
|
|
99
|
+
fields?: {
|
|
100
|
+
narrow?: number;
|
|
101
|
+
typical?: number;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Per-chart scale preference — analogous to AudienceProfile.targets but scoped
|
|
106
|
+
* to scale fit. Lets orgs say "we'd rather not see Heatmap below 100 rows even
|
|
107
|
+
* when the engine thinks it's competitive."
|
|
108
|
+
*/
|
|
109
|
+
export interface ChartScalePreference {
|
|
110
|
+
/** Add this many points to the composite score for this chart. Range -3..+3. */
|
|
111
|
+
bias?: number;
|
|
112
|
+
/** Restrict suggestion of this chart to data with rows in this band or above. */
|
|
113
|
+
minBand?: ScaleBand;
|
|
114
|
+
/** Restrict suggestion of this chart to data with rows in this band or below. */
|
|
115
|
+
maxBand?: ScaleBand;
|
|
116
|
+
/** Human-readable rationale. Surfaces in suggestion.reasons when the rule fires. */
|
|
117
|
+
reason?: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Forward-looking declaration of how big the user's data actually is. The row
|
|
121
|
+
* data passed to suggestCharts may be a sample, a stub, or a future projection;
|
|
122
|
+
* DataScaleProfile is what the chart needs to actually handle at production.
|
|
123
|
+
*
|
|
124
|
+
* Every field is optional. Omitting a field falls back to what profileData()
|
|
125
|
+
* measured from the sample. Specifying a field overrides the measurement.
|
|
126
|
+
*/
|
|
127
|
+
export interface DataScaleProfile {
|
|
128
|
+
/**
|
|
129
|
+
* Production row count. May be larger than the sample passed to suggestCharts.
|
|
130
|
+
* Accepts a band string ("medium") for hand-waving estimates, or an exact number.
|
|
131
|
+
*/
|
|
132
|
+
rows?: number | ScaleBand;
|
|
133
|
+
/**
|
|
134
|
+
* Production field/column count. Affects parallel-coords / matrix recommendations.
|
|
135
|
+
*/
|
|
136
|
+
fields?: number | FieldBand;
|
|
137
|
+
/**
|
|
138
|
+
* Per-field cardinality. Use field name as key; value is distinct count or band.
|
|
139
|
+
* @example cardinality: { region: 12, status: "low" }
|
|
140
|
+
*/
|
|
141
|
+
cardinality?: Partial<Record<string, number | CardinalityBand>>;
|
|
142
|
+
/**
|
|
143
|
+
* Aggregate cardinality fallback when per-field isn't declared. The "typical"
|
|
144
|
+
* categorical field in this dataset has this much cardinality.
|
|
145
|
+
*/
|
|
146
|
+
typicalCardinality?: number | CardinalityBand;
|
|
147
|
+
/**
|
|
148
|
+
* How does this dataset grow?
|
|
149
|
+
* • "static" — fixed, or refreshed periodically as a whole
|
|
150
|
+
* • "appending" — grows by adding rows; old rows are stable
|
|
151
|
+
* • "windowed" — sliding window of recent data (e.g. last 7 days)
|
|
152
|
+
* Affects streaming recommendations and decay/staleness defaults.
|
|
153
|
+
*/
|
|
154
|
+
growth?: "static" | "appending" | "windowed";
|
|
155
|
+
/**
|
|
156
|
+
* Override the default scale thresholds for this profile. Orgs use this to
|
|
157
|
+
* encode their own definition of "small" / "medium" / "large" — e.g. a BI
|
|
158
|
+
* shop where 10k rows is "small" because dashboards typically run 100k+.
|
|
159
|
+
*/
|
|
160
|
+
thresholds?: ScaleThresholds;
|
|
161
|
+
/**
|
|
162
|
+
* Per-chart preferences. Like AudienceProfile.familiarity / .targets,
|
|
163
|
+
* orgs can override scale fit on a per-component basis.
|
|
164
|
+
* @example charts: { Heatmap: { minBand: "medium", reason: "below 50 rows the cells are dominant noise" } }
|
|
165
|
+
*/
|
|
166
|
+
charts?: Partial<Record<string, ChartScalePreference>>;
|
|
167
|
+
/** Display name. Surfaced in suggestion.reasons when scale bias fires. */
|
|
168
|
+
name?: string;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* User-declared data-quality profile. Quality issues affect *which treatment*
|
|
172
|
+
* of a chart is recommended (broken vs connected lines, log vs linear, with vs
|
|
173
|
+
* without regression overlay), and can add caveats. Quality biases score
|
|
174
|
+
* modestly but biases caveats heavily.
|
|
175
|
+
*/
|
|
176
|
+
export interface DataQualityProfile {
|
|
177
|
+
/**
|
|
178
|
+
* Fraction of non-null values (0..1). Map of field name → completeness, or
|
|
179
|
+
* a single aggregate. 1.0 = complete; 0.5 = half the values missing.
|
|
180
|
+
* @example completeness: { revenue: 0.98, cohort: 0.62 }
|
|
181
|
+
*/
|
|
182
|
+
completeness?: Partial<Record<string, number>> | number;
|
|
183
|
+
/**
|
|
184
|
+
* Fraction of values flagged as outliers (0..1). Affects recommendations
|
|
185
|
+
* for regression overlays, log scales, and outlier-detection intent.
|
|
186
|
+
* @example outliers: { revenue: 0.04 }
|
|
187
|
+
*/
|
|
188
|
+
outliers?: Partial<Record<string, number>> | number;
|
|
189
|
+
/**
|
|
190
|
+
* Fraction of values that don't match the dominant type for the field (0..1).
|
|
191
|
+
* Strings mixed into a numeric column, dates in arbitrary formats, etc.
|
|
192
|
+
* High heterogeneity → caveats and possibly reject from numeric-required charts.
|
|
193
|
+
*/
|
|
194
|
+
typeHeterogeneity?: Partial<Record<string, number>> | number;
|
|
195
|
+
/** Display name. Surfaced in suggestion.reasons when quality bias fires. */
|
|
196
|
+
name?: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Classify a row count into a ScaleBand using the profile's thresholds (or defaults).
|
|
200
|
+
*/
|
|
201
|
+
export declare function classifyRowBand(rows: number, scale?: DataScaleProfile): ScaleBand;
|
|
202
|
+
/**
|
|
203
|
+
* Classify cardinality. Per-field if the field is named; otherwise the aggregate.
|
|
204
|
+
*/
|
|
205
|
+
export declare function classifyCardinalityBand(count: number, scale?: DataScaleProfile): CardinalityBand;
|
|
206
|
+
/**
|
|
207
|
+
* Classify field count.
|
|
208
|
+
*/
|
|
209
|
+
export declare function classifyFieldBand(count: number, scale?: DataScaleProfile): FieldBand;
|
|
210
|
+
/**
|
|
211
|
+
* Compare two bands by order (tiny < small < medium < large < huge).
|
|
212
|
+
* Returns negative if a < b, zero if equal, positive if a > b.
|
|
213
|
+
*/
|
|
214
|
+
export declare function compareBands(a: ScaleBand, b: ScaleBand): number;
|
|
215
|
+
/**
|
|
216
|
+
* Resolve a declared `rows` value (number, band, or undefined) to an effective
|
|
217
|
+
* row count for bias calculations. Bands resolve to the midpoint of their range.
|
|
218
|
+
*
|
|
219
|
+
* When the user declares a number, we use it directly. When they declare a band,
|
|
220
|
+
* we use a representative point inside that band. When they declare nothing,
|
|
221
|
+
* we fall back to the profile's measured rowCount.
|
|
222
|
+
*/
|
|
223
|
+
export declare function resolveRowsToNumber(declared: number | ScaleBand | undefined, measuredRows: number, scale?: DataScaleProfile): number;
|
|
224
|
+
/**
|
|
225
|
+
* Resolve a declared cardinality value to a number.
|
|
226
|
+
*/
|
|
227
|
+
export declare function resolveCardinalityToNumber(declared: number | CardinalityBand | undefined, measured: number | undefined, scale?: DataScaleProfile): number | undefined;
|
|
228
|
+
/**
|
|
229
|
+
* The effective scale view the engine reasons over. Merges the declared
|
|
230
|
+
* DataScaleProfile with the profile's measured stats. Surfaced on each
|
|
231
|
+
* Suggestion so callers can detect threshold crossings ("you outgrew this
|
|
232
|
+
* chart") and so the conversational layer can narrate scale rationale.
|
|
233
|
+
*/
|
|
234
|
+
export interface EffectiveScale {
|
|
235
|
+
/** Effective row count after merging declared scale with measured profile. */
|
|
236
|
+
rows: number;
|
|
237
|
+
/** Band classification of the effective row count. */
|
|
238
|
+
rowBand: ScaleBand;
|
|
239
|
+
/** Effective field count. */
|
|
240
|
+
fields: number;
|
|
241
|
+
/** Band classification of the effective field count. */
|
|
242
|
+
fieldBand: FieldBand;
|
|
243
|
+
/** Typical-category cardinality, if known. */
|
|
244
|
+
typicalCardinality?: number;
|
|
245
|
+
/** Band of that cardinality. */
|
|
246
|
+
cardinalityBand?: CardinalityBand;
|
|
247
|
+
/** Pass-through of growth mode (defaults to "static"). */
|
|
248
|
+
growth: "static" | "appending" | "windowed";
|
|
249
|
+
/** Source of the rows number: "declared" if user provided, "measured" otherwise. */
|
|
250
|
+
rowsSource: "declared" | "measured";
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Compute the effective scale for a profile under the optional declared scale.
|
|
254
|
+
* When no scale is declared, the profile's measured stats define everything.
|
|
255
|
+
*/
|
|
256
|
+
export declare function computeEffectiveScale(profile: ChartDataProfile, scale?: DataScaleProfile): EffectiveScale;
|
|
257
|
+
export interface ScaleBiasResult {
|
|
258
|
+
/** Score delta to apply to the suggestion composite. */
|
|
259
|
+
delta: number;
|
|
260
|
+
/** Reasons to append to the suggestion.reasons[] array. */
|
|
261
|
+
reasons: string[];
|
|
262
|
+
/** Caveats to append (mostly from quality). */
|
|
263
|
+
caveats: string[];
|
|
264
|
+
/** True if a per-chart minBand/maxBand restriction excluded this chart. */
|
|
265
|
+
excluded: boolean;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Apply scale and quality bias to a chart's composite score.
|
|
269
|
+
*
|
|
270
|
+
* Two terms compose additively beyond the audience bias:
|
|
271
|
+
* • Capability scale-fit: each capability optionally declares a `scaleFit`
|
|
272
|
+
* function returning {delta, reason?, caveat?}. Range ±SCALE_BIAS_MAX.
|
|
273
|
+
* • Org per-chart preference: `DataScaleProfile.charts[component]` can
|
|
274
|
+
* pin a chart to a band range (excludes outside it) and add an
|
|
275
|
+
* org-defined bias. Range ±PREFERENCE_BIAS_MAX.
|
|
276
|
+
*
|
|
277
|
+
* Pure function — used by both `suggestCharts` and any caller that needs
|
|
278
|
+
* to reason about a single (capability × variant × scale) tuple.
|
|
279
|
+
*/
|
|
280
|
+
export declare function applyScaleBias(capability: ChartCapability, profile: ChartDataProfile, effectiveScale: EffectiveScale, scale: DataScaleProfile | undefined, quality: DataQualityProfile | undefined): ScaleBiasResult;
|
|
281
|
+
/**
|
|
282
|
+
* Declarative sugar for capability authors. Convert a hint object into a
|
|
283
|
+
* scaleFit function. The hint object expresses the sweet-spot row range and
|
|
284
|
+
* optional cardinality range; the engine derives a smooth bias curve.
|
|
285
|
+
*
|
|
286
|
+
* Use this when the chart's scale behavior is straightforward. For more
|
|
287
|
+
* sophisticated logic (e.g. "smoothing variant degrades faster at high cardinality"),
|
|
288
|
+
* write a scaleFit function directly.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* scaleFit: scaleHints({
|
|
292
|
+
* rows: { sweetSpot: [25, 1000], caveatAbove: 5000 },
|
|
293
|
+
* cardinality: { sweetSpot: [3, 15], caveatAbove: 30 },
|
|
294
|
+
* })
|
|
295
|
+
*/
|
|
296
|
+
export interface ScaleHintInput {
|
|
297
|
+
rows?: {
|
|
298
|
+
sweetSpot: [number, number];
|
|
299
|
+
caveatAbove?: number;
|
|
300
|
+
caveatBelow?: number;
|
|
301
|
+
};
|
|
302
|
+
cardinality?: {
|
|
303
|
+
sweetSpot: [number, number];
|
|
304
|
+
caveatAbove?: number;
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
export type ScaleFitFn = (profile: ChartDataProfile, effective: EffectiveScale, scale: DataScaleProfile | undefined) => ScaleFitResult | null;
|
|
308
|
+
export interface ScaleFitResult {
|
|
309
|
+
delta: number;
|
|
310
|
+
reason?: string;
|
|
311
|
+
caveats?: string[];
|
|
312
|
+
}
|
|
313
|
+
export type QualityFitFn = (profile: ChartDataProfile, quality: DataQualityProfile) => ScaleFitResult | null;
|
|
314
|
+
/**
|
|
315
|
+
* Build a scaleFit function from a declarative hint shape. Smooth bias —
|
|
316
|
+
* positive inside the sweet spot, decays toward zero, and tips negative
|
|
317
|
+
* past the caveat thresholds. The decay is gradual rather than a cliff
|
|
318
|
+
* so a chart isn't all-or-nothing at the boundary.
|
|
319
|
+
*/
|
|
320
|
+
export declare function scaleHints(hint: ScaleHintInput): ScaleFitFn;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Datum } from "../charts/shared/datumTypes";
|
|
2
|
+
import type { ChartCapability, ChartFamily } from "./chartCapabilityTypes";
|
|
3
|
+
import type { IntentId } from "./intents";
|
|
4
|
+
import type { AudienceProfile } from "./audienceProfile";
|
|
5
|
+
/**
|
|
6
|
+
* describeChart — generate a layered natural-language description of a chart
|
|
7
|
+
* from its `(component, props)` config, following Lundgard & Satyanarayan's
|
|
8
|
+
* four-level model of semantic content (IEEE VIS 2021):
|
|
9
|
+
*
|
|
10
|
+
* L1 (encoding) — chart type and what's mapped to which channel.
|
|
11
|
+
* L2 (statistics) — ranges, mean, extrema (the level blind/low-vision
|
|
12
|
+
* readers rank *most* useful, alongside L3).
|
|
13
|
+
* L3 (trends) — overall direction and notable shape over an ordered axis.
|
|
14
|
+
* L4 (intent) — the *illocutionary* sentence: what communicative act the
|
|
15
|
+
* chart performs and which feature it asks the reader to act
|
|
16
|
+
* on ("This is an alerting chart; the May spike warrants a
|
|
17
|
+
* closer look."). Opt-in — only emitted when the caller
|
|
18
|
+
* supplies the chart's capability descriptor (or an explicit
|
|
19
|
+
* communicative act). Without that intent metadata, the
|
|
20
|
+
* domain meaning stays the author's `summary` or an LLM's
|
|
21
|
+
* job, as before.
|
|
22
|
+
*
|
|
23
|
+
* Pure, SSR-safe, dependency-light (the new capability/audience inputs are
|
|
24
|
+
* type-only — no runtime registry pull). Wired into ChartContainer as an opt-in
|
|
25
|
+
* full-accessibility affordance (see ChartContainer's `describe` prop); also
|
|
26
|
+
* usable directly, surfaced by the accessibility audit, and composed by
|
|
27
|
+
* `buildReaderGrounding` into the agent-reader payload.
|
|
28
|
+
*/
|
|
29
|
+
export type DescribeLevel = "l1" | "l2" | "l3" | "l4";
|
|
30
|
+
/**
|
|
31
|
+
* The communicative act a chart performs — its illocutionary force, the verb
|
|
32
|
+
* behind "what is this chart *doing*?". Derived from the dominant intent (or
|
|
33
|
+
* the chart family as a fallback) and used to phrase the L4 sentence.
|
|
34
|
+
*/
|
|
35
|
+
export type CommunicativeAct = "alerting" | "tracking" | "comparing" | "ranking" | "apportioning" | "characterizing" | "relating" | "tracing" | "nesting" | "locating" | "presenting";
|
|
36
|
+
/**
|
|
37
|
+
* Lightweight intent context for the L4 sentence. Either hand `describeChart`
|
|
38
|
+
* a full {@link ChartCapability} (its static `intentScores` are read; function
|
|
39
|
+
* scorers are skipped since no data profile is in scope here) or this resolved
|
|
40
|
+
* shape — e.g. a `Suggestion`'s already-resolved `{ family, intentScores }`,
|
|
41
|
+
* which is the most precise source.
|
|
42
|
+
*/
|
|
43
|
+
export interface DescribeCapabilityContext {
|
|
44
|
+
/** Chart family — anchors the communicative act when intent scores are absent. */
|
|
45
|
+
family?: ChartFamily;
|
|
46
|
+
/** Per-intent scores (0..5), already resolved. The top-scoring intent picks the act. */
|
|
47
|
+
intentScores?: Partial<Record<IntentId, number>>;
|
|
48
|
+
/** Explicit override — skips intent/family inference entirely. */
|
|
49
|
+
act?: CommunicativeAct;
|
|
50
|
+
}
|
|
51
|
+
export interface DescribeChartResult {
|
|
52
|
+
/** The selected levels joined into one description (what you'd feed a summary). */
|
|
53
|
+
text: string;
|
|
54
|
+
/** Each level on its own, so callers can pick verbosity. */
|
|
55
|
+
levels: {
|
|
56
|
+
l1?: string;
|
|
57
|
+
l2?: string;
|
|
58
|
+
l3?: string;
|
|
59
|
+
l4?: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The author's marked features, as a sentence — present only when the chart
|
|
63
|
+
* carries `annotations`. An annotation is author intent in its purest form,
|
|
64
|
+
* so it leads `text` ahead of the auto-derived L1–L3: a non-visual or agent
|
|
65
|
+
* reader hears what the author chose to call out first. Provenance-aware —
|
|
66
|
+
* an AI- or watcher-authored note is qualified as such.
|
|
67
|
+
*/
|
|
68
|
+
annotations?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface DescribeChartOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Which semantic levels to include. Default ["l1","l2","l3"]. L4 is appended
|
|
73
|
+
* automatically when `capability` (or `capability.act`) is provided and
|
|
74
|
+
* `levels` is left at the default; pass `levels` explicitly to override.
|
|
75
|
+
*/
|
|
76
|
+
levels?: DescribeLevel[];
|
|
77
|
+
/** Locale for number formatting. Default "en". */
|
|
78
|
+
locale?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Intent context that powers the L4 illocutionary sentence — a chart's
|
|
81
|
+
* capability descriptor or a resolved {@link DescribeCapabilityContext}.
|
|
82
|
+
* Closes the L1–L3 → L4 gap by joining the *production*-side intent metadata
|
|
83
|
+
* (which already lives in each `*.capability.ts`) to the *reception*-side
|
|
84
|
+
* description.
|
|
85
|
+
*/
|
|
86
|
+
capability?: ChartCapability | DescribeCapabilityContext;
|
|
87
|
+
/**
|
|
88
|
+
* Audience profile — tunes the L4 sentence for reception. When the chart's
|
|
89
|
+
* familiarity for this audience is low, L4 appends a brief orienting nudge so
|
|
90
|
+
* an unfamiliar reader leans on the description.
|
|
91
|
+
*/
|
|
92
|
+
audience?: AudienceProfile;
|
|
93
|
+
}
|
|
94
|
+
/** The communicative act a built-in intent implies, or undefined if unknown. */
|
|
95
|
+
export declare function communicativeActForIntent(intent: IntentId): CommunicativeAct | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* Resolve the communicative act for a chart from (in priority order) an explicit
|
|
98
|
+
* act, the dominant resolved intent, the declared family, or the component's own
|
|
99
|
+
* family classification. Returns undefined only when nothing identifies it.
|
|
100
|
+
*/
|
|
101
|
+
export declare function resolveCommunicativeAct(component: string, context: ChartCapability | DescribeCapabilityContext | undefined): CommunicativeAct | undefined;
|
|
102
|
+
/** Build a number formatter — compact (6.5M) for large magnitudes, plain
|
|
103
|
+
* otherwise. Exported so the navigation tree formats values identically. */
|
|
104
|
+
export declare function chartValueFormatter(locale?: string): (n: number) => string;
|
|
105
|
+
/**
|
|
106
|
+
* One human phrase for a single annotation — its kind (provenance-qualified),
|
|
107
|
+
* plus its label if it has one: `an AI-suggested callout labeled "Peak"`.
|
|
108
|
+
* Exported so the navigation tree (`buildNavigationTree`) labels its annotation
|
|
109
|
+
* nodes with the same vocabulary the prose description uses — tree and prose
|
|
110
|
+
* speak the same language. Editorial status is *not* included here (it would
|
|
111
|
+
* change the prose sentence); callers that want it append it themselves.
|
|
112
|
+
*/
|
|
113
|
+
export declare function annotationPhrase(ann: Datum): string;
|
|
114
|
+
export declare function describeChart(component: string, props: Datum, options?: DescribeChartOptions): DescribeChartResult;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Datum } from "../charts/shared/datumTypes";
|
|
2
|
+
/**
|
|
3
|
+
* buildNavigationTree — turn a chart config into a structured, labeled
|
|
4
|
+
* navigation tree (chart → axes/series → data points), following the Olli /
|
|
5
|
+
* Data Navigator model: a navigable *structure*, uncoupled from how the chart
|
|
6
|
+
* is rendered (canvas, SVG, image). A screen-reader user descends the tree —
|
|
7
|
+
* "Series sales" → "point 3 of 9: March, 6,800" — with spoken structural
|
|
8
|
+
* context at each level, instead of wading through a flat point list.
|
|
9
|
+
*
|
|
10
|
+
* Pure and SSR-safe. Composes `describeChart()` for node labels so the tree and
|
|
11
|
+
* the prose description speak the same language. Rendered by `AccessibleNavTree`
|
|
12
|
+
* and surfaced as the opt-in ChartContainer `navigable` affordance.
|
|
13
|
+
*/
|
|
14
|
+
export type NavTreeRole = "chart" | "axis" | "series" | "datum" | "annotation";
|
|
15
|
+
export interface NavTreeNode {
|
|
16
|
+
/** Stable id within the tree. */
|
|
17
|
+
id: string;
|
|
18
|
+
role: NavTreeRole;
|
|
19
|
+
/** What assistive tech announces for this node. */
|
|
20
|
+
label: string;
|
|
21
|
+
/** 1-based depth (maps to aria-level). */
|
|
22
|
+
level: number;
|
|
23
|
+
/** Measure value, for datum leaves. */
|
|
24
|
+
value?: number;
|
|
25
|
+
/** Raw datum, for datum leaves. */
|
|
26
|
+
datum?: Datum | null;
|
|
27
|
+
children?: NavTreeNode[];
|
|
28
|
+
}
|
|
29
|
+
export interface BuildNavigationTreeOptions {
|
|
30
|
+
/** Cap leaves per branch (keeps a 50k-row chart from building a giant tree). Default 200. */
|
|
31
|
+
maxLeaves?: number;
|
|
32
|
+
locale?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build a structured navigation tree for a chart config. Full trees for XY,
|
|
36
|
+
* bar, part-to-whole, and distribution families; for everything else (network,
|
|
37
|
+
* hierarchy, geo, single value) it returns a root-only node with an L1 label
|
|
38
|
+
* rather than inventing a structure.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildNavigationTree(component: string, props: Datum, options?: BuildNavigationTreeOptions): NavTreeNode;
|
|
41
|
+
/** Flatten a tree to its visible nodes given a set of expanded node ids, in DFS
|
|
42
|
+
* order. Used by the renderer for roving-tabindex keyboard navigation. */
|
|
43
|
+
export declare function flattenVisible(root: NavTreeNode, expanded: Set<string>): NavTreeNode[];
|
|
44
|
+
/** Total descendant + self count — handy for tests and summaries. */
|
|
45
|
+
export declare function countNodes(root: NavTreeNode): number;
|
|
@@ -30,6 +30,8 @@ export interface PerCapabilityScore {
|
|
|
30
30
|
rejectedOn: number;
|
|
31
31
|
/** Number of fixtures where this capability appeared in the top-3 ranked suggestions. */
|
|
32
32
|
inTopThreeOn: number;
|
|
33
|
+
/** Number of fixtures where this capability was the #1 ranked suggestion. */
|
|
34
|
+
topPickOn: number;
|
|
33
35
|
/** Fixtures where the human expert picked this chart AND it was in top-3 ranking. */
|
|
34
36
|
expertAgreementCount: number;
|
|
35
37
|
/** Mean composite score across fixtures where it fit. */
|
|
@@ -58,6 +60,10 @@ export interface PerFixtureScore {
|
|
|
58
60
|
rejectedCount: number;
|
|
59
61
|
/** True if the top-3 ranking contained at least one expected component (when expected is provided). */
|
|
60
62
|
expertAgreement: boolean | null;
|
|
63
|
+
/** True if the #1 ranked suggestion was an expected component — the strict
|
|
64
|
+
* form of agreement. Reported alongside the lenient top-3 form so the
|
|
65
|
+
* scorecard can't flatter itself with close-second behavior. */
|
|
66
|
+
topPickAgreement: boolean | null;
|
|
61
67
|
/** Did the engine honor `expectsNoFit`? */
|
|
62
68
|
noFitHonored: boolean | null;
|
|
63
69
|
}
|
|
@@ -69,6 +75,11 @@ export interface ScorecardReport {
|
|
|
69
75
|
capabilityCount: number;
|
|
70
76
|
/** Fraction of expectation-bearing fixtures where the engine agreed with the expert. */
|
|
71
77
|
expertAgreementRate: number;
|
|
78
|
+
/** Strict agreement: fraction of expectation-bearing fixtures where the
|
|
79
|
+
* engine's #1 pick was an expert pick. Always reported next to the
|
|
80
|
+
* lenient top-3 rate — the gap between the two is the honest measure of
|
|
81
|
+
* how often the engine is merely "not completely wrong." */
|
|
82
|
+
top1AgreementRate: number;
|
|
72
83
|
/** Average caveat coverage across all suggestions. */
|
|
73
84
|
overallCaveatCoverage: number;
|
|
74
85
|
/** Average variant utilization across all suggestions. */
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Datum } from "../charts/shared/datumTypes";
|
|
2
|
+
import { type DescribeChartResult, type DescribeLevel, type DescribeCapabilityContext, type CommunicativeAct } from "./describeChart";
|
|
3
|
+
import { type NavTreeNode } from "./navigationTree";
|
|
4
|
+
import type { ChartCapability, ChartFamily } from "./chartCapabilityTypes";
|
|
5
|
+
import type { IntentId } from "./intents";
|
|
6
|
+
import type { AudienceProfile } from "./audienceProfile";
|
|
7
|
+
/**
|
|
8
|
+
* buildReaderGrounding — the single payload an AI agent reads to interpret a
|
|
9
|
+
* chart faithfully, without seeing the pixels. It composes the three reception
|
|
10
|
+
* artifacts the accessibility layer already builds:
|
|
11
|
+
*
|
|
12
|
+
* • {@link describeChart} L1–L3 — encoding, statistics, and trend.
|
|
13
|
+
* • the L4 *communicative act* — what the chart is asking the reader to do
|
|
14
|
+
* (the intent metadata that lives in each `*.capability.ts`).
|
|
15
|
+
* • {@link buildNavigationTree} — the structured chart → axes/series → datum
|
|
16
|
+
* tree the agent (or a screen reader) traverses.
|
|
17
|
+
*
|
|
18
|
+
* It's the reader-side complement to the author-side capability descriptor: the
|
|
19
|
+
* descriptor says how a chart *should* be used; this says how a given chart
|
|
20
|
+
* instance *reads*. Position it as the documented "render evidence" an LLM
|
|
21
|
+
* consumes — the non-visual reader and the AI reader are the same consumer.
|
|
22
|
+
*
|
|
23
|
+
* Pure and SSR-safe (the capability/audience inputs are type-only).
|
|
24
|
+
*/
|
|
25
|
+
export interface ChartReaderGroundingOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Intent context powering the L4 communicative-act sentence — a chart's
|
|
28
|
+
* capability descriptor or a resolved {@link DescribeCapabilityContext}
|
|
29
|
+
* (e.g. a `Suggestion`'s `{ family, intentScores }`). Optional: without it
|
|
30
|
+
* the act is inferred from the component's family, best-effort.
|
|
31
|
+
*/
|
|
32
|
+
capability?: ChartCapability | DescribeCapabilityContext;
|
|
33
|
+
/** Audience profile — tunes the L4 sentence for reception (low familiarity → orienting nudge). */
|
|
34
|
+
audience?: AudienceProfile;
|
|
35
|
+
/** Locale for number formatting. Default "en". */
|
|
36
|
+
locale?: string;
|
|
37
|
+
/** Levels for the prose description. Default ["l1","l2","l3"] (L4 is carried in `intent`). */
|
|
38
|
+
levels?: DescribeLevel[];
|
|
39
|
+
/** Cap navigation-tree leaves per branch. Forwarded to buildNavigationTree (default 200). */
|
|
40
|
+
maxLeaves?: number;
|
|
41
|
+
/** Skip the navigation structure (e.g. to save tokens). Default false. */
|
|
42
|
+
includeStructure?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface ChartReaderGroundingIntent {
|
|
45
|
+
/** The communicative act the chart performs. */
|
|
46
|
+
act: CommunicativeAct;
|
|
47
|
+
/** The L4 illocutionary sentence ("This is an alerting chart; …"). */
|
|
48
|
+
sentence: string;
|
|
49
|
+
/** Chart family, when known from the supplied context. */
|
|
50
|
+
family?: ChartFamily;
|
|
51
|
+
/** Resolved per-intent scores, when the caller passed them (not from a raw descriptor). */
|
|
52
|
+
intentScores?: Partial<Record<IntentId, number>>;
|
|
53
|
+
}
|
|
54
|
+
export interface ChartReaderGrounding {
|
|
55
|
+
component: string;
|
|
56
|
+
/** Layered L1–L3 description ({ text, levels }). */
|
|
57
|
+
description: DescribeChartResult;
|
|
58
|
+
/** Communicative act + L4 sentence, when an act could be resolved. */
|
|
59
|
+
intent?: ChartReaderGroundingIntent;
|
|
60
|
+
/** Structured navigation tree (chart → axes/series → datum). Omitted when `includeStructure: false`. */
|
|
61
|
+
structure?: NavTreeNode;
|
|
62
|
+
/** L1–L4 joined into one prose blob an LLM can read directly. */
|
|
63
|
+
text: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Build the combined reader-grounding payload for a chart config. See the
|
|
67
|
+
* module docstring; pass a `capability` (or a resolved context) for the most
|
|
68
|
+
* precise L4 act, an `audience` for reception tuning.
|
|
69
|
+
*/
|
|
70
|
+
export declare function buildReaderGrounding(component: string, props: Datum, options?: ChartReaderGroundingOptions): ChartReaderGrounding;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Datum } from "../charts/shared/datumTypes";
|
|
2
2
|
import { type ProfileDataOptions } from "./profileData";
|
|
3
|
-
import type { ChartCapability, ChartDataProfile, Suggestion } from "./chartCapabilityTypes";
|
|
3
|
+
import type { ChartCapability, ChartDataProfile, ScaledSuggestionGroups, Suggestion } from "./chartCapabilityTypes";
|
|
4
4
|
import type { IntentId } from "./intents";
|
|
5
5
|
import { type AudienceProfile } from "./audienceProfile";
|
|
6
|
+
import { type DataQualityProfile, type DataScaleProfile } from "./dataScaleProfile";
|
|
6
7
|
export interface SuggestChartsOptions extends ProfileDataOptions {
|
|
7
8
|
/** Ranking intent(s). When omitted, suggestions are ranked by mean intent score. */
|
|
8
9
|
intent?: IntentId | IntentId[];
|
|
@@ -25,6 +26,19 @@ export interface SuggestChartsOptions extends ProfileDataOptions {
|
|
|
25
26
|
* bias to the ranking. See `audienceProfile.ts`.
|
|
26
27
|
*/
|
|
27
28
|
audience?: AudienceProfile;
|
|
29
|
+
/**
|
|
30
|
+
* Forward-looking declaration of the dataset's scale (row count, cardinality,
|
|
31
|
+
* field count, growth mode). When provided, the engine biases recommendations
|
|
32
|
+
* toward charts that work at the declared scale rather than the sample size.
|
|
33
|
+
* See `dataScaleProfile.ts`.
|
|
34
|
+
*/
|
|
35
|
+
scale?: DataScaleProfile;
|
|
36
|
+
/**
|
|
37
|
+
* Declaration of the dataset's quality (completeness, outliers, type
|
|
38
|
+
* heterogeneity). Affects caveats and biases score modestly. See
|
|
39
|
+
* `dataScaleProfile.ts`.
|
|
40
|
+
*/
|
|
41
|
+
quality?: DataQualityProfile;
|
|
28
42
|
}
|
|
29
43
|
/**
|
|
30
44
|
* Suggest charts for a dataset, ranked by intent suitability.
|
|
@@ -74,3 +88,22 @@ export declare function scoreChart(component: string, data: ReadonlyArray<Datum>
|
|
|
74
88
|
}): Suggestion | {
|
|
75
89
|
reason: string;
|
|
76
90
|
};
|
|
91
|
+
/**
|
|
92
|
+
* Return suggestions grouped by scale band. The "graduation of views" surface:
|
|
93
|
+
* the same data + intent can produce different chart recommendations depending
|
|
94
|
+
* on the row band you optimize for. Useful for narratives like
|
|
95
|
+
* "now → at 10× → at 100×" or for picking the right chart for a sample vs the
|
|
96
|
+
* production dataset.
|
|
97
|
+
*
|
|
98
|
+
* Behavior: runs `suggestCharts` five times (once per band — tiny/small/medium/
|
|
99
|
+
* large/huge), pinning the row band on each pass while keeping all other
|
|
100
|
+
* options stable. Each band returns its own ranked list. The same chart can
|
|
101
|
+
* appear in multiple bands when its sweet spot spans them.
|
|
102
|
+
*
|
|
103
|
+
* The single `effective` value on the return is computed from the *original*
|
|
104
|
+
* options (declared scale or measured profile), so callers can detect which
|
|
105
|
+
* band the user's actual data lives in and highlight that tier.
|
|
106
|
+
*/
|
|
107
|
+
export declare function suggestChartsGrouped(data: ReadonlyArray<Datum> | null | undefined, options?: SuggestChartsOptions & {
|
|
108
|
+
maxPerBand?: number;
|
|
109
|
+
}): ScaledSuggestionGroups;
|