@fluentui/react-charts 9.3.12 → 9.3.13

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 (35) hide show
  1. package/CHANGELOG.md +13 -2
  2. package/dist/index.d.ts +852 -0
  3. package/lib/VegaDeclarativeChart.js +1 -0
  4. package/lib/VegaDeclarativeChart.js.map +1 -0
  5. package/lib/components/VegaDeclarativeChart/VegaDeclarativeChart.js +386 -0
  6. package/lib/components/VegaDeclarativeChart/VegaDeclarativeChart.js.map +1 -0
  7. package/lib/components/VegaDeclarativeChart/VegaDeclarativeChartHooks.js +20 -0
  8. package/lib/components/VegaDeclarativeChart/VegaDeclarativeChartHooks.js.map +1 -0
  9. package/lib/components/VegaDeclarativeChart/VegaLiteColorAdapter.js +415 -0
  10. package/lib/components/VegaDeclarativeChart/VegaLiteColorAdapter.js.map +1 -0
  11. package/lib/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.js +3284 -0
  12. package/lib/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.js.map +1 -0
  13. package/lib/components/VegaDeclarativeChart/VegaLiteTypes.js +28 -0
  14. package/lib/components/VegaDeclarativeChart/VegaLiteTypes.js.map +1 -0
  15. package/lib/components/VegaDeclarativeChart/index.js +1 -0
  16. package/lib/components/VegaDeclarativeChart/index.js.map +1 -0
  17. package/lib/index.js +1 -0
  18. package/lib/index.js.map +1 -1
  19. package/lib-commonjs/VegaDeclarativeChart.js +6 -0
  20. package/lib-commonjs/VegaDeclarativeChart.js.map +1 -0
  21. package/lib-commonjs/components/VegaDeclarativeChart/VegaDeclarativeChart.js +255 -0
  22. package/lib-commonjs/components/VegaDeclarativeChart/VegaDeclarativeChart.js.map +1 -0
  23. package/lib-commonjs/components/VegaDeclarativeChart/VegaDeclarativeChartHooks.js +35 -0
  24. package/lib-commonjs/components/VegaDeclarativeChart/VegaDeclarativeChartHooks.js.map +1 -0
  25. package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteColorAdapter.js +412 -0
  26. package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteColorAdapter.js.map +1 -0
  27. package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.js +3219 -0
  28. package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.js.map +1 -0
  29. package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteTypes.js +31 -0
  30. package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteTypes.js.map +1 -0
  31. package/lib-commonjs/components/VegaDeclarativeChart/index.js +6 -0
  32. package/lib-commonjs/components/VegaDeclarativeChart/index.js.map +1 -0
  33. package/lib-commonjs/index.js +1 -0
  34. package/lib-commonjs/index.js.map +1 -1
  35. package/package.json +3 -3
@@ -0,0 +1,3219 @@
1
+ // Using custom VegaLiteTypes for internal adapter logic
2
+ // For public API, VegaDeclarativeChart accepts vega-lite's TopLevelSpec
3
+ "use strict";
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ function _export(target, all) {
8
+ for(var name in all)Object.defineProperty(target, name, {
9
+ enumerable: true,
10
+ get: all[name]
11
+ });
12
+ }
13
+ _export(exports, {
14
+ autoCorrectEncodingTypes: function() {
15
+ return autoCorrectEncodingTypes;
16
+ },
17
+ getChartType: function() {
18
+ return getChartType;
19
+ },
20
+ getMarkType: function() {
21
+ return getMarkType;
22
+ },
23
+ getVegaLiteLegendsProps: function() {
24
+ return getVegaLiteLegendsProps;
25
+ },
26
+ getVegaLiteTitles: function() {
27
+ return getVegaLiteTitles;
28
+ },
29
+ transformVegaLiteToAreaChartProps: function() {
30
+ return transformVegaLiteToAreaChartProps;
31
+ },
32
+ transformVegaLiteToDonutChartProps: function() {
33
+ return transformVegaLiteToDonutChartProps;
34
+ },
35
+ transformVegaLiteToGroupedVerticalBarChartProps: function() {
36
+ return transformVegaLiteToGroupedVerticalBarChartProps;
37
+ },
38
+ transformVegaLiteToHeatMapChartProps: function() {
39
+ return transformVegaLiteToHeatMapChartProps;
40
+ },
41
+ transformVegaLiteToHistogramProps: function() {
42
+ return transformVegaLiteToHistogramProps;
43
+ },
44
+ transformVegaLiteToHorizontalBarChartProps: function() {
45
+ return transformVegaLiteToHorizontalBarChartProps;
46
+ },
47
+ transformVegaLiteToLineChartProps: function() {
48
+ return transformVegaLiteToLineChartProps;
49
+ },
50
+ transformVegaLiteToPolarChartProps: function() {
51
+ return transformVegaLiteToPolarChartProps;
52
+ },
53
+ transformVegaLiteToScatterChartProps: function() {
54
+ return transformVegaLiteToScatterChartProps;
55
+ },
56
+ transformVegaLiteToVerticalBarChartProps: function() {
57
+ return transformVegaLiteToVerticalBarChartProps;
58
+ },
59
+ transformVegaLiteToVerticalStackedBarChartProps: function() {
60
+ return transformVegaLiteToVerticalStackedBarChartProps;
61
+ }
62
+ });
63
+ const _VegaLiteColorAdapter = require("./VegaLiteColorAdapter");
64
+ const _d3array = require("d3-array");
65
+ const _d3format = require("d3-format");
66
+ const _chartutilities = require("@fluentui/chart-utilities");
67
+ /**
68
+ * Vega-Lite to Fluent Charts adapter for line/point charts.
69
+ *
70
+ * Transforms Vega-Lite JSON specifications into Fluent LineChart props.
71
+ * Supports basic line charts with temporal/quantitative axes and color-encoded series.
72
+ *
73
+ * TODO: Future enhancements
74
+ * - Multi-view layouts (facet, concat, repeat)
75
+ * - Selection interactions
76
+ * - Remote data loading (url)
77
+ * - Transform pipeline (filter, aggregate, calculate)
78
+ * - Conditional encodings
79
+ * - Additional mark types (area, bar, etc.)
80
+ * - Tooltip customization
81
+ */ /**
82
+ * Default configuration values for VegaLite charts
83
+ */ const DEFAULT_CHART_HEIGHT = 350;
84
+ const DEFAULT_MAX_BAR_WIDTH = 50;
85
+ const DEFAULT_TRUNCATE_CHARS = 20;
86
+ /**
87
+ * Determines if a spec is a layered specification
88
+ */ function isLayerSpec(spec) {
89
+ return Array.isArray(spec.layer) && spec.layer.length > 0;
90
+ }
91
+ /**
92
+ * Determines if a spec is a single unit specification
93
+ */ function isUnitSpec(spec) {
94
+ return spec.mark !== undefined && spec.encoding !== undefined;
95
+ }
96
+ function getMarkType(mark) {
97
+ if (!mark) {
98
+ return undefined;
99
+ }
100
+ return typeof mark === 'string' ? mark : mark.type;
101
+ }
102
+ /**
103
+ * Resolves the color for a legend label using the priority chain:
104
+ * 1. Explicit color value from encoding
105
+ * 2. Mark-level color
106
+ * 3. Cached color from the shared color map
107
+ * 4. New color via local index for deterministic per-chart assignment
108
+ */ function resolveColor(legend, index, colorValue, markColor, colorMap, colorScheme, colorRange, isDarkTheme) {
109
+ var _colorMap_current, _colorMap_current1;
110
+ if (colorValue) {
111
+ return colorValue;
112
+ }
113
+ if (markColor) {
114
+ return markColor;
115
+ }
116
+ // Check colorMap cache first for cross-chart consistency
117
+ if ((_colorMap_current = colorMap.current) === null || _colorMap_current === void 0 ? void 0 : _colorMap_current.has(legend)) {
118
+ return colorMap.current.get(legend);
119
+ }
120
+ // Use local index (not colorMap.size) for deterministic per-chart color assignment
121
+ const color = (0, _VegaLiteColorAdapter.getVegaColor)(index, colorScheme, colorRange, isDarkTheme);
122
+ (_colorMap_current1 = colorMap.current) === null || _colorMap_current1 === void 0 ? void 0 : _colorMap_current1.set(legend, color);
123
+ return color;
124
+ }
125
+ /**
126
+ * Extracts inline data values from a Vega-Lite data specification
127
+ * TODO: Add support for URL-based data loading
128
+ * TODO: Add support for named dataset resolution
129
+ * TODO: Add support for data format parsing (csv, tsv)
130
+ */ function extractDataValues(data) {
131
+ if (!data) {
132
+ return [];
133
+ }
134
+ if (data.values && Array.isArray(data.values)) {
135
+ return data.values;
136
+ }
137
+ // TODO: Handle data.url - load remote data
138
+ if (data.url) {
139
+ // Remote data URLs are not yet supported
140
+ return [];
141
+ }
142
+ // TODO: Handle data.name - resolve named datasets
143
+ if (data.name) {
144
+ // Named datasets are not yet supported
145
+ return [];
146
+ }
147
+ return [];
148
+ }
149
+ /**
150
+ * Applies a fold transform to convert wide-format data to long-format
151
+ * The fold transform unpivots specified fields into key-value pairs
152
+ *
153
+ * @param data - Array of data records in wide format
154
+ * @param foldFields - Array of field names to fold
155
+ * @param asFields - [keyName, valueName] for the new columns (defaults to ['key', 'value'])
156
+ * @returns Array of data records in long format
157
+ */ function applyFoldTransform(data, foldFields, asFields = [
158
+ 'key',
159
+ 'value'
160
+ ]) {
161
+ const [keyField, valueField] = asFields;
162
+ const result = [];
163
+ for (const row of data){
164
+ // Create a base row without the fields being folded
165
+ const baseRow = {};
166
+ for (const [key, value] of Object.entries(row)){
167
+ if (!foldFields.includes(key)) {
168
+ baseRow[key] = value;
169
+ }
170
+ }
171
+ // Create a new row for each folded field
172
+ for (const field of foldFields){
173
+ if (field in row) {
174
+ result.push({
175
+ ...baseRow,
176
+ [keyField]: field,
177
+ [valueField]: row[field]
178
+ });
179
+ }
180
+ }
181
+ }
182
+ return result;
183
+ }
184
+ /**
185
+ * Applies transforms from a Vega-Lite spec to data
186
+ * Currently supports: fold transform
187
+ *
188
+ * @param data - Array of data records
189
+ * @param transforms - Array of Vega-Lite transform specifications
190
+ * @returns Transformed data array
191
+ */ function applyTransforms(data, transforms) {
192
+ if (!transforms || transforms.length === 0) {
193
+ return data;
194
+ }
195
+ let result = data;
196
+ for (const transform of transforms){
197
+ // Handle fold transform
198
+ if ('fold' in transform && Array.isArray(transform.fold)) {
199
+ const foldFields = transform.fold;
200
+ const asFields = transform.as || [
201
+ 'key',
202
+ 'value'
203
+ ];
204
+ result = applyFoldTransform(result, foldFields, asFields);
205
+ }
206
+ // Handle filter transform
207
+ if ('filter' in transform) {
208
+ const filterExpr = transform.filter;
209
+ if (typeof filterExpr === 'string') {
210
+ result = result.filter((row)=>{
211
+ try {
212
+ const datum = row;
213
+ // eslint-disable-next-line no-new-func
214
+ return new Function('datum', `return ${filterExpr}`)(datum);
215
+ } catch {
216
+ return true;
217
+ }
218
+ });
219
+ }
220
+ }
221
+ // Handle calculate transform
222
+ if ('calculate' in transform && 'as' in transform) {
223
+ const expr = transform.calculate;
224
+ const asField = transform.as;
225
+ result = result.map((row)=>{
226
+ try {
227
+ const datum = row;
228
+ // eslint-disable-next-line no-new-func
229
+ const value = new Function('datum', `return ${expr}`)(datum);
230
+ return {
231
+ ...row,
232
+ [asField]: value
233
+ };
234
+ } catch {
235
+ return row;
236
+ }
237
+ });
238
+ }
239
+ // Handle aggregate transform
240
+ if ('aggregate' in transform && Array.isArray(transform.aggregate)) {
241
+ const aggSpecs = transform.aggregate;
242
+ const groupby = transform.groupby || [];
243
+ const groups = new Map();
244
+ result.forEach((row)=>{
245
+ const key = groupby.map((g)=>String(row[g])).join('|');
246
+ if (!groups.has(key)) {
247
+ groups.set(key, []);
248
+ }
249
+ groups.get(key).push(row);
250
+ });
251
+ result = Array.from(groups.entries()).map(([key, rows])=>{
252
+ const baseRow = {};
253
+ groupby.forEach((g, i)=>{
254
+ baseRow[g] = rows[0][g];
255
+ });
256
+ aggSpecs.forEach((spec)=>{
257
+ const values = spec.field ? rows.map((r)=>Number(r[spec.field])).filter((v)=>!isNaN(v)) : [];
258
+ switch(spec.op){
259
+ case 'count':
260
+ baseRow[spec.as] = rows.length;
261
+ break;
262
+ case 'sum':
263
+ baseRow[spec.as] = (0, _d3array.sum)(values);
264
+ break;
265
+ case 'mean':
266
+ case 'average':
267
+ var _d3Mean;
268
+ baseRow[spec.as] = (_d3Mean = (0, _d3array.mean)(values)) !== null && _d3Mean !== void 0 ? _d3Mean : 0;
269
+ break;
270
+ case 'min':
271
+ var _d3Min;
272
+ baseRow[spec.as] = (_d3Min = (0, _d3array.min)(values)) !== null && _d3Min !== void 0 ? _d3Min : 0;
273
+ break;
274
+ case 'max':
275
+ var _d3Max;
276
+ baseRow[spec.as] = (_d3Max = (0, _d3array.max)(values)) !== null && _d3Max !== void 0 ? _d3Max : 0;
277
+ break;
278
+ default:
279
+ baseRow[spec.as] = rows.length;
280
+ }
281
+ });
282
+ return baseRow;
283
+ });
284
+ }
285
+ // Handle window transform
286
+ if ('window' in transform && Array.isArray(transform.window)) {
287
+ const windowOps = transform.window;
288
+ const sortFields = transform.sort || [];
289
+ const groupby = transform.groupby || [];
290
+ // Group data
291
+ const groups = new Map();
292
+ result.forEach((row)=>{
293
+ const key = groupby.length > 0 ? groupby.map((g)=>String(row[g])).join('|') : '__all__';
294
+ if (!groups.has(key)) {
295
+ groups.set(key, []);
296
+ }
297
+ groups.get(key).push(row);
298
+ });
299
+ const newResult = [];
300
+ groups.forEach((rows)=>{
301
+ // Sort within group
302
+ if (sortFields.length > 0) {
303
+ rows.sort((a, b)=>{
304
+ for (const sf of sortFields){
305
+ const va = Number(a[sf.field]) || 0;
306
+ const vb = Number(b[sf.field]) || 0;
307
+ const cmp = sf.order === 'descending' ? vb - va : va - vb;
308
+ if (cmp !== 0) {
309
+ return cmp;
310
+ }
311
+ }
312
+ return 0;
313
+ });
314
+ }
315
+ let runningSum = 0;
316
+ rows.forEach((row, idx)=>{
317
+ const newRow = {
318
+ ...row
319
+ };
320
+ windowOps.forEach((op)=>{
321
+ switch(op.op){
322
+ case 'sum':
323
+ runningSum += Number(row[op.field]) || 0;
324
+ newRow[op.as] = runningSum;
325
+ break;
326
+ case 'rank':
327
+ newRow[op.as] = idx + 1;
328
+ break;
329
+ case 'row_number':
330
+ newRow[op.as] = idx + 1;
331
+ break;
332
+ case 'count':
333
+ newRow[op.as] = idx + 1;
334
+ break;
335
+ default:
336
+ newRow[op.as] = idx + 1;
337
+ }
338
+ });
339
+ newResult.push(newRow);
340
+ });
341
+ });
342
+ result = newResult;
343
+ }
344
+ // Handle joinaggregate transform
345
+ if ('joinaggregate' in transform && Array.isArray(transform.joinaggregate)) {
346
+ const aggSpecs = transform.joinaggregate;
347
+ const groupby = transform.groupby || [];
348
+ // Compute aggregates
349
+ const groups = new Map();
350
+ result.forEach((row)=>{
351
+ const key = groupby.length > 0 ? groupby.map((g)=>String(row[g])).join('|') : '__all__';
352
+ if (!groups.has(key)) {
353
+ groups.set(key, []);
354
+ }
355
+ groups.get(key).push(row);
356
+ });
357
+ const aggResults = new Map();
358
+ groups.forEach((rows, key)=>{
359
+ const aggs = {};
360
+ aggSpecs.forEach((spec)=>{
361
+ const values = spec.field ? rows.map((r)=>Number(r[spec.field])).filter((v)=>!isNaN(v)) : [];
362
+ switch(spec.op){
363
+ case 'mean':
364
+ case 'average':
365
+ var _d3Mean;
366
+ aggs[spec.as] = (_d3Mean = (0, _d3array.mean)(values)) !== null && _d3Mean !== void 0 ? _d3Mean : 0;
367
+ break;
368
+ case 'sum':
369
+ aggs[spec.as] = (0, _d3array.sum)(values);
370
+ break;
371
+ case 'count':
372
+ aggs[spec.as] = rows.length;
373
+ break;
374
+ case 'min':
375
+ var _d3Min;
376
+ aggs[spec.as] = (_d3Min = (0, _d3array.min)(values)) !== null && _d3Min !== void 0 ? _d3Min : 0;
377
+ break;
378
+ case 'max':
379
+ var _d3Max;
380
+ aggs[spec.as] = (_d3Max = (0, _d3array.max)(values)) !== null && _d3Max !== void 0 ? _d3Max : 0;
381
+ break;
382
+ default:
383
+ aggs[spec.as] = rows.length;
384
+ }
385
+ });
386
+ aggResults.set(key, aggs);
387
+ });
388
+ // Join back: add aggregate values to each row
389
+ result = result.map((row)=>{
390
+ const key = groupby.length > 0 ? groupby.map((g)=>String(row[g])).join('|') : '__all__';
391
+ return {
392
+ ...row,
393
+ ...aggResults.get(key) || {}
394
+ };
395
+ });
396
+ }
397
+ // Handle regression transform (simple linear regression)
398
+ if ('regression' in transform && 'on' in transform) {
399
+ const yField = transform.regression;
400
+ const xField = transform.on;
401
+ const points = result.map((r)=>({
402
+ x: Number(r[xField]),
403
+ y: Number(r[yField])
404
+ })).filter((p)=>!isNaN(p.x) && !isNaN(p.y));
405
+ if (points.length >= 2) {
406
+ const n = points.length;
407
+ const sumX = (0, _d3array.sum)(points.map((p)=>p.x));
408
+ const sumY = (0, _d3array.sum)(points.map((p)=>p.y));
409
+ const sumXY = (0, _d3array.sum)(points.map((p)=>p.x * p.y));
410
+ const sumX2 = (0, _d3array.sum)(points.map((p)=>p.x * p.x));
411
+ const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
412
+ const intercept = (sumY - slope * sumX) / n;
413
+ var _d3Min;
414
+ const xMin = (_d3Min = (0, _d3array.min)(points.map((p)=>p.x))) !== null && _d3Min !== void 0 ? _d3Min : 0;
415
+ var _d3Max;
416
+ const xMax = (_d3Max = (0, _d3array.max)(points.map((p)=>p.x))) !== null && _d3Max !== void 0 ? _d3Max : 0;
417
+ result = [
418
+ {
419
+ [xField]: xMin,
420
+ [yField]: slope * xMin + intercept
421
+ },
422
+ {
423
+ [xField]: xMax,
424
+ [yField]: slope * xMax + intercept
425
+ }
426
+ ];
427
+ }
428
+ }
429
+ // Handle loess transform (simplified: moving average approximation)
430
+ if ('loess' in transform && 'on' in transform) {
431
+ const yField = transform.loess;
432
+ const xField = transform.on;
433
+ const sorted = [
434
+ ...result
435
+ ].filter((r)=>!isNaN(Number(r[xField])) && !isNaN(Number(r[yField]))).sort((a, b)=>Number(a[xField]) - Number(b[xField]));
436
+ const windowSize = Math.max(3, Math.floor(sorted.length / 4));
437
+ result = sorted.map((row, i)=>{
438
+ const start = Math.max(0, i - Math.floor(windowSize / 2));
439
+ const end = Math.min(sorted.length, start + windowSize);
440
+ const windowSlice = sorted.slice(start, end);
441
+ var _d3Mean;
442
+ const avgY = (_d3Mean = (0, _d3array.mean)(windowSlice.map((r)=>Number(r[yField])))) !== null && _d3Mean !== void 0 ? _d3Mean : Number(row[yField]);
443
+ return {
444
+ [xField]: row[xField],
445
+ [yField]: avgY
446
+ };
447
+ });
448
+ }
449
+ // Handle density transform (simplified: histogram-based density estimation)
450
+ if ('density' in transform) {
451
+ const field = transform.density;
452
+ const groupby = transform.groupby || [];
453
+ const groups = new Map();
454
+ result.forEach((row)=>{
455
+ const key = groupby.length > 0 ? groupby.map((g)=>String(row[g])).join('|') : '__all__';
456
+ if (!groups.has(key)) {
457
+ groups.set(key, []);
458
+ }
459
+ groups.get(key).push(Number(row[field]));
460
+ });
461
+ const densityResult = [];
462
+ groups.forEach((values, key)=>{
463
+ var _d3Min;
464
+ const min = (_d3Min = (0, _d3array.min)(values)) !== null && _d3Min !== void 0 ? _d3Min : 0;
465
+ var _d3Max;
466
+ const max = (_d3Max = (0, _d3array.max)(values)) !== null && _d3Max !== void 0 ? _d3Max : 0;
467
+ const range = max - min || 1;
468
+ const bins = 20;
469
+ const bandwidth = range / bins;
470
+ const groupFields = {};
471
+ if (groupby.length > 0) {
472
+ const sampleRow = result.find((r)=>groupby.map((g)=>String(r[g])).join('|') === key);
473
+ groupby.forEach((g)=>{
474
+ groupFields[g] = sampleRow === null || sampleRow === void 0 ? void 0 : sampleRow[g];
475
+ });
476
+ }
477
+ for(let i = 0; i <= bins; i++){
478
+ const x = min + i / bins * range;
479
+ const count = values.filter((v)=>Math.abs(v - x) < bandwidth).length;
480
+ const density = count / (values.length * bandwidth);
481
+ densityResult.push({
482
+ value: x,
483
+ density,
484
+ ...groupFields
485
+ });
486
+ }
487
+ });
488
+ result = densityResult;
489
+ }
490
+ // Handle quantile transform
491
+ if ('quantile' in transform) {
492
+ const field = transform.quantile;
493
+ const probs = transform.probs || [
494
+ 0.25,
495
+ 0.5,
496
+ 0.75
497
+ ];
498
+ const values = result.map((r)=>Number(r[field])).filter((v)=>!isNaN(v)).sort((a, b)=>a - b);
499
+ if (values.length > 0) {
500
+ result = probs.map((p)=>{
501
+ const idx = Math.min(Math.floor(p * values.length), values.length - 1);
502
+ return {
503
+ prob: String(p),
504
+ value: values[idx]
505
+ };
506
+ });
507
+ }
508
+ }
509
+ // Handle impute transform (fill missing values)
510
+ if ('impute' in transform && 'key' in transform) {
511
+ const field = transform.impute;
512
+ const keyField = transform.key;
513
+ const method = transform.method || 'value';
514
+ var _transform_value;
515
+ const fillValue = (_transform_value = transform.value) !== null && _transform_value !== void 0 ? _transform_value : 0;
516
+ const existingKeys = new Set(result.map((r)=>r[keyField]));
517
+ const allKeyValues = result.map((r)=>Number(r[keyField])).filter((v)=>!isNaN(v));
518
+ if (allKeyValues.length > 0) {
519
+ var _d3Min1;
520
+ const minKey = (_d3Min1 = (0, _d3array.min)(allKeyValues)) !== null && _d3Min1 !== void 0 ? _d3Min1 : 0;
521
+ var _d3Max1;
522
+ const maxKey = (_d3Max1 = (0, _d3array.max)(allKeyValues)) !== null && _d3Max1 !== void 0 ? _d3Max1 : 0;
523
+ for(let k = minKey; k <= maxKey; k++){
524
+ if (!existingKeys.has(k)) {
525
+ const imputed = {
526
+ [keyField]: k
527
+ };
528
+ imputed[field] = method === 'value' ? fillValue : 0;
529
+ result.push(imputed);
530
+ }
531
+ }
532
+ result.sort((a, b)=>Number(a[keyField]) - Number(b[keyField]));
533
+ }
534
+ }
535
+ // Handle lookup transform (join with secondary dataset)
536
+ if ('lookup' in transform && 'from' in transform) {
537
+ var _fromSpec_data;
538
+ const lookupField = transform.lookup;
539
+ const fromSpec = transform.from;
540
+ if (((_fromSpec_data = fromSpec.data) === null || _fromSpec_data === void 0 ? void 0 : _fromSpec_data.values) && fromSpec.key && fromSpec.fields) {
541
+ const lookupMap = new Map();
542
+ fromSpec.data.values.forEach((row)=>{
543
+ lookupMap.set(String(row[fromSpec.key]), row);
544
+ });
545
+ result = result.map((row)=>{
546
+ const lookupRow = lookupMap.get(String(row[lookupField]));
547
+ if (lookupRow) {
548
+ const extra = {};
549
+ fromSpec.fields.forEach((f)=>{
550
+ extra[f] = lookupRow[f];
551
+ });
552
+ return {
553
+ ...row,
554
+ ...extra
555
+ };
556
+ }
557
+ return row;
558
+ });
559
+ }
560
+ }
561
+ }
562
+ return result;
563
+ }
564
+ /**
565
+ * Normalizes a Vega-Lite spec into an array of unit specs with resolved data and encoding
566
+ * Handles both single-view and layered specifications
567
+ */ function normalizeSpec(spec) {
568
+ if (isLayerSpec(spec)) {
569
+ // Layered spec: merge shared data and encoding with each layer
570
+ const sharedData = spec.data;
571
+ const sharedEncoding = spec.encoding;
572
+ return spec.layer.map((layer)=>({
573
+ ...layer,
574
+ data: layer.data || sharedData,
575
+ encoding: {
576
+ ...sharedEncoding,
577
+ ...layer.encoding
578
+ }
579
+ }));
580
+ }
581
+ if (isUnitSpec(spec)) {
582
+ // Single unit spec
583
+ return [
584
+ {
585
+ mark: spec.mark,
586
+ encoding: spec.encoding,
587
+ data: spec.data
588
+ }
589
+ ];
590
+ }
591
+ // Unsupported spec structure
592
+ return [];
593
+ }
594
+ /**
595
+ * Parses a value to a Date if it's temporal, otherwise returns as number or string
596
+ */ function parseValue(value, isTemporalType) {
597
+ if (value === null || value === undefined) {
598
+ return '';
599
+ }
600
+ if (isTemporalType) {
601
+ // Try parsing as date
602
+ const dateValue = new Date(value);
603
+ if (!isNaN(dateValue.getTime())) {
604
+ return dateValue;
605
+ }
606
+ }
607
+ if (typeof value === 'number') {
608
+ return value;
609
+ }
610
+ return String(value);
611
+ }
612
+ /**
613
+ * Maps Vega-Lite interpolate to Fluent curve options
614
+ * Note: Only maps to curve types supported by LineChartLineOptions
615
+ */ function mapInterpolateToCurve(interpolate) {
616
+ if (!interpolate) {
617
+ return undefined;
618
+ }
619
+ switch(interpolate){
620
+ case 'linear':
621
+ case 'linear-closed':
622
+ return 'linear';
623
+ case 'step':
624
+ return 'step';
625
+ case 'step-before':
626
+ return 'stepBefore';
627
+ case 'step-after':
628
+ return 'stepAfter';
629
+ case 'natural':
630
+ return 'natural';
631
+ case 'monotone':
632
+ return 'linear';
633
+ // Note: basis, cardinal, catmull-rom are not supported by LineChartLineOptions
634
+ default:
635
+ return 'linear';
636
+ }
637
+ }
638
+ /**
639
+ * Extracts mark properties from VegaLiteMarkDef
640
+ */ function getMarkProperties(mark) {
641
+ if (typeof mark === 'string') {
642
+ return {};
643
+ }
644
+ return {
645
+ color: mark.color,
646
+ interpolate: mark.interpolate,
647
+ strokeWidth: mark.strokeWidth,
648
+ strokeDash: mark.strokeDash,
649
+ point: mark.point
650
+ };
651
+ }
652
+ /**
653
+ * Extracts annotations from Vega-Lite layers with text or rule marks
654
+ * Text marks become text annotations, rule marks become reference lines
655
+ */ function extractAnnotations(spec) {
656
+ const annotations = [];
657
+ if (!spec.layer || !Array.isArray(spec.layer)) {
658
+ return annotations;
659
+ }
660
+ spec.layer.forEach((layer, index)=>{
661
+ const mark = getMarkType(layer.mark);
662
+ const encoding = layer.encoding || {};
663
+ // Text marks become annotations
664
+ if (mark === 'text' && encoding.x && encoding.y) {
665
+ var _encoding_text, _encoding_text1, _encoding_text2;
666
+ const textValue = ((_encoding_text = encoding.text) === null || _encoding_text === void 0 ? void 0 : _encoding_text.datum) || ((_encoding_text1 = encoding.text) === null || _encoding_text1 === void 0 ? void 0 : _encoding_text1.value) || ((_encoding_text2 = encoding.text) === null || _encoding_text2 === void 0 ? void 0 : _encoding_text2.field) || '';
667
+ const xValue = encoding.x.datum || encoding.x.value || encoding.x.field;
668
+ const yValue = encoding.y.datum || encoding.y.value || encoding.y.field;
669
+ if (textValue && (xValue !== undefined || encoding.x.datum !== undefined) && (yValue !== undefined || encoding.y.datum !== undefined)) {
670
+ annotations.push({
671
+ id: `text-annotation-${index}`,
672
+ text: String(textValue),
673
+ coordinates: {
674
+ type: 'data',
675
+ x: encoding.x.datum || xValue || 0,
676
+ y: encoding.y.datum || yValue || 0
677
+ },
678
+ style: {
679
+ textColor: typeof layer.mark === 'object' ? layer.mark.color : undefined
680
+ }
681
+ });
682
+ }
683
+ }
684
+ // Rule marks can become reference lines (horizontal or vertical)
685
+ if (mark === 'rule') {
686
+ const markColor = typeof layer.mark === 'object' ? layer.mark.color : '#000';
687
+ const markStrokeWidth = typeof layer.mark === 'object' ? layer.mark.strokeWidth || 1 : 1;
688
+ const markStrokeDash = typeof layer.mark === 'object' ? layer.mark.strokeDash : undefined;
689
+ // Horizontal rule (y value constant)
690
+ if (encoding.y && (encoding.y.value !== undefined || encoding.y.datum !== undefined)) {
691
+ var _spec_layer, _companionText_encoding_text, _companionText_encoding, _companionText_encoding_text1, _companionText_encoding1;
692
+ var _encoding_y_value;
693
+ const yValue = (_encoding_y_value = encoding.y.value) !== null && _encoding_y_value !== void 0 ? _encoding_y_value : encoding.y.datum;
694
+ // Look for a companion text annotation at the same y-value
695
+ const companionText = (_spec_layer = spec.layer) === null || _spec_layer === void 0 ? void 0 : _spec_layer.find((l, i)=>{
696
+ var _l_encoding;
697
+ if (i === index) {
698
+ return false;
699
+ }
700
+ const m = getMarkType(l.mark);
701
+ var _l_encoding_y_datum;
702
+ return m === 'text' && ((_l_encoding = l.encoding) === null || _l_encoding === void 0 ? void 0 : _l_encoding.y) && ((_l_encoding_y_datum = l.encoding.y.datum) !== null && _l_encoding_y_datum !== void 0 ? _l_encoding_y_datum : l.encoding.y.value) === yValue;
703
+ });
704
+ const ruleText = companionText ? String(((_companionText_encoding = companionText.encoding) === null || _companionText_encoding === void 0 ? void 0 : (_companionText_encoding_text = _companionText_encoding.text) === null || _companionText_encoding_text === void 0 ? void 0 : _companionText_encoding_text.datum) || ((_companionText_encoding1 = companionText.encoding) === null || _companionText_encoding1 === void 0 ? void 0 : (_companionText_encoding_text1 = _companionText_encoding1.text) === null || _companionText_encoding_text1 === void 0 ? void 0 : _companionText_encoding_text1.value) || yValue) : String(yValue);
705
+ annotations.push({
706
+ id: `rule-h-${index}`,
707
+ text: ruleText,
708
+ coordinates: {
709
+ type: 'data',
710
+ x: 0,
711
+ y: yValue
712
+ },
713
+ style: {
714
+ textColor: markColor,
715
+ borderColor: markColor,
716
+ borderWidth: markStrokeWidth,
717
+ ...markStrokeDash && Array.isArray(markStrokeDash) ? {
718
+ borderRadius: 0
719
+ } // Indicate dashed style
720
+ : {}
721
+ }
722
+ });
723
+ } else if (encoding.x && (encoding.x.value !== undefined || encoding.x.datum !== undefined)) {
724
+ var _encoding_x_value;
725
+ const xValue = (_encoding_x_value = encoding.x.value) !== null && _encoding_x_value !== void 0 ? _encoding_x_value : encoding.x.datum;
726
+ annotations.push({
727
+ id: `rule-v-${index}`,
728
+ text: String(xValue),
729
+ coordinates: {
730
+ type: 'data',
731
+ x: xValue,
732
+ y: 0
733
+ },
734
+ style: {
735
+ textColor: markColor,
736
+ borderColor: markColor,
737
+ borderWidth: markStrokeWidth
738
+ }
739
+ });
740
+ }
741
+ }
742
+ });
743
+ return annotations;
744
+ }
745
+ /**
746
+ * Extracts color fill bars (background regions) from rect marks with x/x2 or y/y2 encodings
747
+ */ function extractColorFillBars(spec, colorMap, isDarkTheme) {
748
+ const colorFillBars = [];
749
+ if (!spec.layer || !Array.isArray(spec.layer)) {
750
+ return colorFillBars;
751
+ }
752
+ // Detect if x-axis is temporal by checking the primary data layer (non-rect layer)
753
+ const isXTemporal = spec.layer.some((layer)=>{
754
+ var _layer_encoding_x, _layer_encoding;
755
+ const layerMark = getMarkType(layer.mark);
756
+ // Skip rect layers, look at line/point/area layers
757
+ if (layerMark === 'rect') {
758
+ return false;
759
+ }
760
+ return ((_layer_encoding = layer.encoding) === null || _layer_encoding === void 0 ? void 0 : (_layer_encoding_x = _layer_encoding.x) === null || _layer_encoding_x === void 0 ? void 0 : _layer_encoding_x.type) === 'temporal';
761
+ });
762
+ spec.layer.forEach((layer, index)=>{
763
+ const mark = getMarkType(layer.mark);
764
+ const encoding = layer.encoding || {};
765
+ // Rect marks with x and x2 become color fill bars (vertical regions)
766
+ if (mark === 'rect' && encoding.x && encoding.x2) {
767
+ const legend = `region-${index}`;
768
+ const color = typeof layer.mark === 'object' && layer.mark.color ? layer.mark.color : (0, _VegaLiteColorAdapter.getVegaColorFromMap)(legend, colorMap, undefined, undefined, isDarkTheme);
769
+ // Extract start and end x values
770
+ const rawStartX = encoding.x.datum || encoding.x.value;
771
+ const rawEndX = encoding.x2.datum || encoding.x2.value;
772
+ if (rawStartX !== undefined && rawEndX !== undefined) {
773
+ // Convert to Date if x-axis is temporal and values are date-like strings
774
+ let startX = rawStartX;
775
+ let endX = rawEndX;
776
+ if (isXTemporal) {
777
+ const parsedStart = new Date(rawStartX);
778
+ const parsedEnd = new Date(rawEndX);
779
+ if (!isNaN(parsedStart.getTime())) {
780
+ startX = parsedStart;
781
+ }
782
+ if (!isNaN(parsedEnd.getTime())) {
783
+ endX = parsedEnd;
784
+ }
785
+ }
786
+ colorFillBars.push({
787
+ legend,
788
+ color,
789
+ data: [
790
+ {
791
+ startX,
792
+ endX
793
+ }
794
+ ],
795
+ applyPattern: false
796
+ });
797
+ }
798
+ }
799
+ });
800
+ return colorFillBars;
801
+ }
802
+ /**
803
+ * Extracts tick configuration from axis properties
804
+ */ function extractTickConfig(spec) {
805
+ var _encoding_x, _encoding_y;
806
+ const config = {};
807
+ const encoding = spec.encoding || {};
808
+ if ((_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.axis) {
809
+ if (encoding.x.axis.values) {
810
+ config.tickValues = encoding.x.axis.values;
811
+ }
812
+ if (encoding.x.axis.tickCount) {
813
+ config.xAxisTickCount = encoding.x.axis.tickCount;
814
+ }
815
+ }
816
+ if ((_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.axis) {
817
+ if (encoding.y.axis.tickCount) {
818
+ config.yAxisTickCount = encoding.y.axis.tickCount;
819
+ }
820
+ }
821
+ return config;
822
+ }
823
+ /**
824
+ * Validates that data array is not empty and contains valid values for the specified field
825
+ * @param data - Array of data objects
826
+ * @param field - Field name to validate
827
+ * @param chartType - Chart type for error message context
828
+ * @throws Error if data is empty or field has no valid values
829
+ */ function validateDataArray(data, field, chartType) {
830
+ if (!data || data.length === 0) {
831
+ throw new Error(`VegaLiteSchemaAdapter: Empty data array for ${chartType}`);
832
+ }
833
+ const hasValidValues = data.some((row)=>row[field] !== undefined && row[field] !== null);
834
+ if (!hasValidValues) {
835
+ throw new Error(`VegaLiteSchemaAdapter: No valid values found for field '${field}' in ${chartType}`);
836
+ }
837
+ }
838
+ /**
839
+ * Validates that nested arrays are not present in the data field (unsupported)
840
+ * @param data - Array of data objects
841
+ * @param field - Field name to validate
842
+ * @throws Error if nested arrays are detected
843
+ */ function validateNoNestedArrays(data, field) {
844
+ const hasNestedArrays = data.some((row)=>Array.isArray(row[field]));
845
+ if (hasNestedArrays) {
846
+ throw new Error(`VegaLiteSchemaAdapter: Nested arrays not supported for field '${field}'. ` + `Use flat data structures only.`);
847
+ }
848
+ }
849
+ /**
850
+ * Validates data type compatibility with encoding type
851
+ * @param data - Array of data objects
852
+ * @param field - Field name to validate
853
+ * @param expectedType - Expected Vega-Lite type (quantitative, temporal, nominal, ordinal)
854
+ * @throws Error if data type doesn't match encoding type
855
+ */ /**
856
+ * Validates and potentially auto-corrects encoding types based on actual data
857
+ * Returns the corrected type if auto-correction was applied
858
+ *
859
+ * @param data - Array of data values
860
+ * @param field - Field name to validate
861
+ * @param expectedType - Expected Vega-Lite type from schema
862
+ * @param encoding - Encoding object to potentially modify
863
+ * @param channelName - Name of encoding channel (x, y, etc.) for auto-correction
864
+ * @returns Corrected type if auto-correction was applied, otherwise undefined
865
+ */ function validateEncodingType(data, field, expectedType, encoding, channelName) {
866
+ if (!expectedType || expectedType === 'nominal' || expectedType === 'ordinal' || expectedType === 'geojson') {
867
+ return; // Nominal, ordinal, and geojson accept any type
868
+ }
869
+ // Find first non-null value to check type
870
+ const sampleValue = data.map((row)=>row[field]).find((v)=>v !== null && v !== undefined);
871
+ if (!sampleValue) {
872
+ return; // No values to validate
873
+ }
874
+ if (expectedType === 'quantitative') {
875
+ if (typeof sampleValue !== 'number' && !isFinite(Number(sampleValue))) {
876
+ // Type mismatch: quantitative declared but data is not numeric
877
+ const actualType = typeof sampleValue;
878
+ if (actualType === 'string') {
879
+ // Auto-correct: treat as nominal for categorical string data
880
+ // This matches Plotly behavior - render as categorical chart
881
+ // Modify encoding to use nominal type
882
+ if (encoding && channelName && encoding[channelName]) {
883
+ encoding[channelName].type = 'nominal';
884
+ }
885
+ return 'nominal';
886
+ }
887
+ // For non-string types, still throw error (truly invalid)
888
+ throw new Error(`VegaLiteSchemaAdapter: Field '${field}' marked as quantitative but contains non-numeric values (${actualType}).`);
889
+ }
890
+ } else if (expectedType === 'temporal') {
891
+ const isValidDate = sampleValue instanceof Date || typeof sampleValue === 'string' && !isNaN(Date.parse(sampleValue));
892
+ if (!isValidDate) {
893
+ let suggestion = '';
894
+ if (typeof sampleValue === 'number') {
895
+ suggestion = ' The data contains numbers. Change the type to "quantitative" instead.';
896
+ } else if (typeof sampleValue === 'string') {
897
+ suggestion = ` The data contains strings that are not valid dates (e.g., "${sampleValue}"). Ensure dates are in ISO format (YYYY-MM-DD) or valid date strings.`;
898
+ }
899
+ throw new Error(`VegaLiteSchemaAdapter: Field '${field}' marked as temporal but contains invalid date values.${suggestion}`);
900
+ }
901
+ }
902
+ return undefined;
903
+ }
904
+ /**
905
+ * Validates X and Y encodings for charts requiring both axes
906
+ * Performs comprehensive validation including data array, nested arrays, and encoding types
907
+ * Can auto-correct type mismatches (e.g., quantitative with string data → nominal)
908
+ *
909
+ * @param data - Array of data objects
910
+ * @param xField - X field name
911
+ * @param yField - Y field name
912
+ * @param xType - Expected X encoding type
913
+ * @param yType - Expected Y encoding type
914
+ * @param chartType - Chart type for error message context
915
+ * @param encoding - Encoding object (optional, for auto-correction)
916
+ * @throws Error if validation fails
917
+ */ function validateXYEncodings(data, xField, yField, xType, yType, chartType, encoding) {
918
+ validateDataArray(data, xField, chartType);
919
+ validateDataArray(data, yField, chartType);
920
+ validateNoNestedArrays(data, xField);
921
+ validateNoNestedArrays(data, yField);
922
+ // Validate types with auto-correction support
923
+ validateEncodingType(data, xField, xType, encoding, 'x');
924
+ validateEncodingType(data, yField, yType, encoding, 'y');
925
+ }
926
+ /**
927
+ * Extracts Y-axis scale type from encoding
928
+ * Returns 'log' if logarithmic scale is specified, undefined otherwise
929
+ */ function extractYAxisType(encoding) {
930
+ var _encoding_y;
931
+ const yScale = encoding === null || encoding === void 0 ? void 0 : (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.scale;
932
+ return (yScale === null || yScale === void 0 ? void 0 : yScale.type) === 'log' ? 'log' : undefined;
933
+ }
934
+ /**
935
+ * Extracts y-axis min/max considering both scale.domain and scale.zero.
936
+ * When scale.zero is false and no explicit domain, yMinValue is computed from data.
937
+ */ function extractYMinMax(encoding, dataValues) {
938
+ var _encoding_y;
939
+ const yScale = encoding === null || encoding === void 0 ? void 0 : (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.scale;
940
+ const domain = yScale === null || yScale === void 0 ? void 0 : yScale.domain;
941
+ // Explicit domain takes priority
942
+ if (Array.isArray(domain)) {
943
+ return {
944
+ yMinValue: domain[0],
945
+ yMaxValue: domain[1]
946
+ };
947
+ }
948
+ // When zero is explicitly false, compute min from data so y-axis doesn't start at 0
949
+ if ((yScale === null || yScale === void 0 ? void 0 : yScale.zero) === false) {
950
+ var _encoding_y1;
951
+ const yField = encoding === null || encoding === void 0 ? void 0 : (_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.field;
952
+ if (yField) {
953
+ const yValues = dataValues.map((row)=>Number(row[yField])).filter((v)=>!isNaN(v));
954
+ if (yValues.length > 0) {
955
+ var _d3Min;
956
+ const dataMin = (_d3Min = (0, _d3array.min)(yValues)) !== null && _d3Min !== void 0 ? _d3Min : 0;
957
+ var _d3Max;
958
+ const dataMax = (_d3Max = (0, _d3array.max)(yValues)) !== null && _d3Max !== void 0 ? _d3Max : 0;
959
+ const padding = (dataMax - dataMin) * 0.05;
960
+ return {
961
+ yMinValue: dataMin - padding
962
+ };
963
+ }
964
+ }
965
+ }
966
+ return {};
967
+ }
968
+ /**
969
+ * Creates a value formatter from a d3-format specifier string.
970
+ * Returns undefined if no format is specified or if the format is invalid.
971
+ */ function createValueFormatter(formatSpec) {
972
+ if (!formatSpec) {
973
+ return undefined;
974
+ }
975
+ try {
976
+ const formatter = (0, _d3format.format)(formatSpec);
977
+ return formatter;
978
+ } catch {
979
+ return undefined;
980
+ }
981
+ }
982
+ /**
983
+ * Converts Vega-Lite sort specification to Fluent Charts AxisCategoryOrder
984
+ * Supports: 'ascending', 'descending', null, array, or object with op/order
985
+ * @param sort - Vega-Lite sort specification
986
+ * @returns AxisCategoryOrder compatible value
987
+ */ function convertVegaSortToAxisCategoryOrder(sort) {
988
+ if (!sort) {
989
+ return undefined;
990
+ }
991
+ // Handle string sorts: 'ascending' | 'descending'
992
+ if (typeof sort === 'string') {
993
+ if (sort === 'ascending') {
994
+ return 'category ascending';
995
+ }
996
+ if (sort === 'descending') {
997
+ return 'category descending';
998
+ }
999
+ return undefined;
1000
+ }
1001
+ // Handle array sort (explicit ordering)
1002
+ if (Array.isArray(sort)) {
1003
+ return sort;
1004
+ }
1005
+ // Handle object sort with op and order
1006
+ if (typeof sort === 'object' && sort.op && sort.order) {
1007
+ const op = sort.op === 'average' ? 'mean' : sort.op; // Map 'average' to 'mean'
1008
+ const order = sort.order === 'ascending' ? 'ascending' : 'descending';
1009
+ return `${op} ${order}`;
1010
+ }
1011
+ return undefined;
1012
+ }
1013
+ /**
1014
+ * Extracts axis category ordering from Vega-Lite encoding
1015
+ * Returns props for xAxisCategoryOrder and yAxisCategoryOrder
1016
+ */ function extractAxisCategoryOrderProps(encoding) {
1017
+ var _encoding_x, _encoding_y;
1018
+ const result = {};
1019
+ if (encoding === null || encoding === void 0 ? void 0 : (_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.sort) {
1020
+ const xOrder = convertVegaSortToAxisCategoryOrder(encoding.x.sort);
1021
+ if (xOrder) {
1022
+ result.xAxisCategoryOrder = xOrder;
1023
+ }
1024
+ }
1025
+ if (encoding === null || encoding === void 0 ? void 0 : (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.sort) {
1026
+ const yOrder = convertVegaSortToAxisCategoryOrder(encoding.y.sort);
1027
+ if (yOrder) {
1028
+ result.yAxisCategoryOrder = yOrder;
1029
+ }
1030
+ }
1031
+ return result;
1032
+ }
1033
+ /**
1034
+ * Initializes the transformation context by normalizing spec and extracting common data
1035
+ * This reduces boilerplate across all transformer functions
1036
+ *
1037
+ * @param spec - Vega-Lite specification
1038
+ * @returns Normalized context with unit specs, data values, encoding, and mark properties
1039
+ */ function initializeTransformContext(spec) {
1040
+ var _colorEnc_condition, _encoding_x, _encoding_x1;
1041
+ const unitSpecs = normalizeSpec(spec);
1042
+ if (unitSpecs.length === 0) {
1043
+ throw new Error('VegaLiteSchemaAdapter: No valid unit specs found in specification');
1044
+ }
1045
+ const primarySpec = unitSpecs[0];
1046
+ const rawDataValues = extractDataValues(primarySpec.data);
1047
+ // Apply any transforms from both top-level spec and primary unit spec
1048
+ let dataValues = applyTransforms(rawDataValues, spec.transform);
1049
+ dataValues = applyTransforms(dataValues, primarySpec.transform);
1050
+ const encoding = primarySpec.encoding || {};
1051
+ // Handle conditional color encoding — evaluate test expressions and materialize color values
1052
+ const colorEnc = encoding.color;
1053
+ if ((colorEnc === null || colorEnc === void 0 ? void 0 : colorEnc.condition) && typeof ((_colorEnc_condition = colorEnc.condition) === null || _colorEnc_condition === void 0 ? void 0 : _colorEnc_condition.test) === 'string') {
1054
+ const condition = colorEnc.condition;
1055
+ const elseValue = colorEnc.value || '#999';
1056
+ const colorField = '__conditional_color__';
1057
+ dataValues.forEach((row)=>{
1058
+ try {
1059
+ const datum = row;
1060
+ // eslint-disable-next-line no-new-func
1061
+ const result = new Function('datum', `return ${condition.test}`)(datum);
1062
+ row[colorField] = result ? condition.value : elseValue;
1063
+ } catch {
1064
+ row[colorField] = elseValue;
1065
+ }
1066
+ });
1067
+ // Replace conditional color with a field-based color encoding using the materialized values
1068
+ encoding.color = {
1069
+ field: colorField,
1070
+ type: 'nominal',
1071
+ scale: {
1072
+ domain: [
1073
+ condition.value,
1074
+ elseValue
1075
+ ],
1076
+ range: [
1077
+ condition.value,
1078
+ elseValue
1079
+ ]
1080
+ },
1081
+ legend: null
1082
+ };
1083
+ }
1084
+ // Handle timeUnit on x/y encodings — aggregate data by time unit
1085
+ if (((_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.timeUnit) && ((_encoding_x1 = encoding.x) === null || _encoding_x1 === void 0 ? void 0 : _encoding_x1.field)) {
1086
+ var _encoding_y, _encoding_y1, _encoding_y2;
1087
+ const field = encoding.x.field;
1088
+ const unit = encoding.x.timeUnit;
1089
+ const yField = (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.field;
1090
+ const yAgg = ((_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.aggregate) || (yField ? 'mean' : 'count');
1091
+ const groups = new Map();
1092
+ dataValues.forEach((row)=>{
1093
+ const dateVal = new Date(row[field]);
1094
+ if (isNaN(dateVal.getTime())) {
1095
+ return;
1096
+ }
1097
+ let key;
1098
+ switch(unit){
1099
+ case 'year':
1100
+ key = String(dateVal.getFullYear());
1101
+ break;
1102
+ case 'quarter':
1103
+ key = `Q${Math.floor(dateVal.getMonth() / 3) + 1}`;
1104
+ break;
1105
+ case 'month':
1106
+ key = dateVal.toLocaleString('en', {
1107
+ month: 'short'
1108
+ });
1109
+ break;
1110
+ case 'day':
1111
+ key = String(dateVal.getDate());
1112
+ break;
1113
+ case 'hours':
1114
+ key = String(dateVal.getHours());
1115
+ break;
1116
+ default:
1117
+ key = String(dateVal);
1118
+ }
1119
+ if (!groups.has(key)) {
1120
+ groups.set(key, []);
1121
+ }
1122
+ groups.get(key).push(row);
1123
+ });
1124
+ dataValues = Array.from(groups.entries()).map(([key, rows])=>{
1125
+ const result = {
1126
+ [field]: key
1127
+ };
1128
+ if (yField && yAgg !== 'count') {
1129
+ const vals = rows.map((r)=>Number(r[yField])).filter((v)=>!isNaN(v));
1130
+ var _d3Mean;
1131
+ result[yField] = yAgg === 'sum' ? (0, _d3array.sum)(vals) : (_d3Mean = (0, _d3array.mean)(vals)) !== null && _d3Mean !== void 0 ? _d3Mean : 0;
1132
+ } else {
1133
+ result[yField || '__count'] = rows.length;
1134
+ }
1135
+ return result;
1136
+ });
1137
+ // Switch x from temporal to ordinal since we've aggregated
1138
+ encoding.x.type = 'ordinal';
1139
+ delete encoding.x.timeUnit;
1140
+ if ((_encoding_y2 = encoding.y) === null || _encoding_y2 === void 0 ? void 0 : _encoding_y2.aggregate) {
1141
+ delete encoding.y.aggregate;
1142
+ }
1143
+ }
1144
+ const markProps = getMarkProperties(primarySpec.mark);
1145
+ return {
1146
+ unitSpecs,
1147
+ primarySpec,
1148
+ dataValues,
1149
+ encoding,
1150
+ markProps
1151
+ };
1152
+ }
1153
+ /**
1154
+ * Extracts common encoding fields and aggregates from Vega-Lite encoding
1155
+ *
1156
+ * @param encoding - Vega-Lite encoding specification
1157
+ * @returns Object containing extracted field names and aggregates
1158
+ */ function extractEncodingFields(encoding) {
1159
+ var _encoding_x, _encoding_y, _encoding_x2, _encoding_color, _encoding_size, _encoding_theta, _encoding_radius, _encoding_x1, _encoding_y1;
1160
+ return {
1161
+ xField: (_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.field,
1162
+ yField: (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.field,
1163
+ x2Field: (_encoding_x2 = encoding.x2) === null || _encoding_x2 === void 0 ? void 0 : _encoding_x2.field,
1164
+ colorField: (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.field,
1165
+ sizeField: (_encoding_size = encoding.size) === null || _encoding_size === void 0 ? void 0 : _encoding_size.field,
1166
+ thetaField: (_encoding_theta = encoding.theta) === null || _encoding_theta === void 0 ? void 0 : _encoding_theta.field,
1167
+ radiusField: (_encoding_radius = encoding.radius) === null || _encoding_radius === void 0 ? void 0 : _encoding_radius.field,
1168
+ xAggregate: (_encoding_x1 = encoding.x) === null || _encoding_x1 === void 0 ? void 0 : _encoding_x1.aggregate,
1169
+ yAggregate: (_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.aggregate
1170
+ };
1171
+ }
1172
+ /**
1173
+ * Computes aggregate values for bar charts
1174
+ * Supports count, sum, mean, min, max aggregations
1175
+ *
1176
+ * @param data - Array of data values
1177
+ * @param groupField - Field to group by (x-axis field)
1178
+ * @param valueField - Field to aggregate (y-axis field, optional for count)
1179
+ * @param aggregate - Aggregate function (count, sum, mean, min, max)
1180
+ * @returns Array of {category, value} objects
1181
+ */ function computeAggregateData(data, groupField, valueField, aggregate) {
1182
+ // Group data by category
1183
+ const groups = new Map();
1184
+ data.forEach((row)=>{
1185
+ const category = String(row[groupField]);
1186
+ if (aggregate === 'count') {
1187
+ // For count, just track the count
1188
+ if (!groups.has(category)) {
1189
+ groups.set(category, []);
1190
+ }
1191
+ groups.get(category).push(1);
1192
+ } else if (valueField && row[valueField] !== undefined && row[valueField] !== null) {
1193
+ // For other aggregates, collect values
1194
+ const value = Number(row[valueField]);
1195
+ if (!isNaN(value)) {
1196
+ if (!groups.has(category)) {
1197
+ groups.set(category, []);
1198
+ }
1199
+ groups.get(category).push(value);
1200
+ }
1201
+ }
1202
+ });
1203
+ // Compute aggregate for each group
1204
+ const result = [];
1205
+ groups.forEach((values, category)=>{
1206
+ let aggregatedValue;
1207
+ switch(aggregate){
1208
+ case 'count':
1209
+ aggregatedValue = values.length;
1210
+ break;
1211
+ case 'sum':
1212
+ aggregatedValue = values.reduce((a, b)=>a + b, 0);
1213
+ break;
1214
+ case 'mean':
1215
+ case 'average':
1216
+ aggregatedValue = values.reduce((a, b)=>a + b, 0) / values.length;
1217
+ break;
1218
+ case 'min':
1219
+ var _d3Min;
1220
+ aggregatedValue = (_d3Min = (0, _d3array.min)(values)) !== null && _d3Min !== void 0 ? _d3Min : 0;
1221
+ break;
1222
+ case 'max':
1223
+ var _d3Max;
1224
+ aggregatedValue = (_d3Max = (0, _d3array.max)(values)) !== null && _d3Max !== void 0 ? _d3Max : 0;
1225
+ break;
1226
+ default:
1227
+ aggregatedValue = values.length; // Default to count
1228
+ }
1229
+ result.push({
1230
+ category,
1231
+ value: aggregatedValue
1232
+ });
1233
+ });
1234
+ return result;
1235
+ }
1236
+ /**
1237
+ * Counts rows per x-category, optionally grouped by a secondary (color) field.
1238
+ * Returns a Map<xKey, Map<legend, count>>.
1239
+ */ function countByCategory(dataValues, xField, colorField, defaultLegend) {
1240
+ const countMap = new Map();
1241
+ dataValues.forEach((row)=>{
1242
+ const xValue = row[xField];
1243
+ if (xValue === undefined) {
1244
+ return;
1245
+ }
1246
+ const xKey = String(xValue);
1247
+ const legend = colorField && row[colorField] !== undefined ? String(row[colorField]) : defaultLegend;
1248
+ if (!countMap.has(xKey)) {
1249
+ countMap.set(xKey, new Map());
1250
+ }
1251
+ const legendMap = countMap.get(xKey);
1252
+ legendMap.set(legend, (legendMap.get(legend) || 0) + 1);
1253
+ });
1254
+ return countMap;
1255
+ }
1256
+ /**
1257
+ * Extracts color configuration from Vega-Lite encoding
1258
+ *
1259
+ * @param encoding - Vega-Lite encoding specification
1260
+ * @returns Color scheme and range configuration
1261
+ */ function extractColorConfig(encoding) {
1262
+ var _encoding_color_scale, _encoding_color, _encoding_color_scale1, _encoding_color1;
1263
+ return {
1264
+ colorScheme: (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : (_encoding_color_scale = _encoding_color.scale) === null || _encoding_color_scale === void 0 ? void 0 : _encoding_color_scale.scheme,
1265
+ colorRange: (_encoding_color1 = encoding.color) === null || _encoding_color1 === void 0 ? void 0 : (_encoding_color_scale1 = _encoding_color1.scale) === null || _encoding_color_scale1 === void 0 ? void 0 : _encoding_color_scale1.range
1266
+ };
1267
+ }
1268
+ /**
1269
+ * Groups data rows into series based on color encoding field
1270
+ * Returns a map of series name to data points and ordinal mapping for categorical x-axis
1271
+ */ function groupDataBySeries(dataValues, xField, yField, colorField, isXTemporal, isYTemporal, xType, sizeField, yType) {
1272
+ const seriesMap = new Map();
1273
+ if (!xField || !yField) {
1274
+ return {
1275
+ seriesMap
1276
+ };
1277
+ }
1278
+ // Check if x-axis is ordinal/nominal (categorical)
1279
+ const isXOrdinal = xType === 'ordinal' || xType === 'nominal';
1280
+ const ordinalMapping = isXOrdinal ? new Map() : undefined;
1281
+ const ordinalLabels = [];
1282
+ // Check if y-axis is ordinal/nominal (categorical)
1283
+ const isYOrdinal = yType === 'ordinal' || yType === 'nominal';
1284
+ const yOrdinalMapping = isYOrdinal ? new Map() : undefined;
1285
+ const yOrdinalLabels = [];
1286
+ dataValues.forEach((row)=>{
1287
+ const xValue = parseValue(row[xField], isXTemporal);
1288
+ const yValue = parseValue(row[yField], isYTemporal);
1289
+ // Skip invalid values using chart-utilities validation
1290
+ if ((0, _chartutilities.isInvalidValue)(xValue) || (0, _chartutilities.isInvalidValue)(yValue)) {
1291
+ return;
1292
+ }
1293
+ // Skip if x or y is empty string (from null/undefined) or y is not a valid number/string
1294
+ if (xValue === '' || yValue === '' || typeof yValue !== 'number' && typeof yValue !== 'string') {
1295
+ return;
1296
+ }
1297
+ const seriesName = colorField && row[colorField] !== undefined ? String(row[colorField]) : 'default';
1298
+ if (!seriesMap.has(seriesName)) {
1299
+ seriesMap.set(seriesName, []);
1300
+ }
1301
+ // Handle x-value based on type
1302
+ let numericX;
1303
+ if (isXOrdinal && typeof xValue === 'string') {
1304
+ // For ordinal data, map each unique string to a sequential index
1305
+ if (!ordinalMapping.has(xValue)) {
1306
+ ordinalMapping.set(xValue, ordinalMapping.size);
1307
+ ordinalLabels.push(xValue);
1308
+ }
1309
+ numericX = ordinalMapping.get(xValue);
1310
+ } else if (typeof xValue === 'string') {
1311
+ // For non-ordinal strings, try to parse as float (fallback to 0)
1312
+ const parsed = parseFloat(xValue);
1313
+ if (isNaN(parsed)) {
1314
+ return;
1315
+ }
1316
+ numericX = parsed;
1317
+ } else {
1318
+ numericX = xValue;
1319
+ }
1320
+ const markerSize = sizeField && row[sizeField] !== undefined ? Number(row[sizeField]) : undefined;
1321
+ // Handle y-value: numeric or ordinal mapping
1322
+ let numericY;
1323
+ if (isYOrdinal && typeof yValue === 'string') {
1324
+ if (!yOrdinalMapping.has(yValue)) {
1325
+ yOrdinalMapping.set(yValue, yOrdinalMapping.size);
1326
+ yOrdinalLabels.push(yValue);
1327
+ }
1328
+ numericY = yOrdinalMapping.get(yValue);
1329
+ } else {
1330
+ numericY = typeof yValue === 'number' ? yValue : 0;
1331
+ }
1332
+ seriesMap.get(seriesName).push({
1333
+ x: numericX,
1334
+ y: numericY,
1335
+ ...markerSize !== undefined && !isNaN(markerSize) && {
1336
+ markerSize
1337
+ }
1338
+ });
1339
+ });
1340
+ return {
1341
+ seriesMap,
1342
+ ordinalMapping,
1343
+ ordinalLabels: ordinalLabels.length > 0 ? ordinalLabels : undefined,
1344
+ yOrdinalLabels: yOrdinalLabels.length > 0 ? yOrdinalLabels : undefined
1345
+ };
1346
+ }
1347
+ /**
1348
+ * Finds the primary data layer from unit specs for line/area charts
1349
+ * Skips rect layers (used for color fill bars) and finds the actual line/point/area layer
1350
+ *
1351
+ * @param unitSpecs - Array of normalized unit specs
1352
+ * @returns The primary spec containing the actual chart data, or undefined if not found
1353
+ */ function findPrimaryLineSpec(unitSpecs) {
1354
+ // First, try to find a line, point, or area layer
1355
+ const lineSpec = unitSpecs.find((spec)=>{
1356
+ const markType = getMarkType(spec.mark);
1357
+ return markType === 'line' || markType === 'point' || markType === 'area';
1358
+ });
1359
+ if (lineSpec) {
1360
+ return lineSpec;
1361
+ }
1362
+ // If no line/point/area layer, find first layer with actual field encodings (not just datum)
1363
+ const dataSpec = unitSpecs.find((spec)=>{
1364
+ var _encoding_x, _encoding_y;
1365
+ const encoding = spec.encoding || {};
1366
+ return ((_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.field) || ((_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.field);
1367
+ });
1368
+ return dataSpec || unitSpecs[0];
1369
+ }
1370
+ function autoCorrectEncodingTypes(spec) {
1371
+ var _encoding_x, _encoding_y;
1372
+ const unitSpec = spec.layer ? spec.layer[0] : spec;
1373
+ if (!unitSpec) {
1374
+ return;
1375
+ }
1376
+ const encoding = unitSpec.encoding;
1377
+ var _unitSpec_data;
1378
+ const data = extractDataValues((_unitSpec_data = unitSpec.data) !== null && _unitSpec_data !== void 0 ? _unitSpec_data : spec.data);
1379
+ if (!encoding || data.length === 0) {
1380
+ return;
1381
+ }
1382
+ // Check x encoding
1383
+ if ((_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.field) {
1384
+ const sample = data.map((row)=>row[encoding.x.field]).find((v)=>v !== null && v !== undefined);
1385
+ if (sample !== undefined) {
1386
+ if (encoding.x.type === 'quantitative') {
1387
+ if (typeof sample === 'string' && !isFinite(Number(sample))) {
1388
+ encoding.x.type = 'nominal';
1389
+ } else if (typeof sample === 'object') {
1390
+ encoding.x.type = 'nominal';
1391
+ }
1392
+ } else if (encoding.x.type === 'temporal') {
1393
+ const isValidDate = sample instanceof Date || typeof sample === 'string' && !isNaN(Date.parse(sample));
1394
+ if (!isValidDate) {
1395
+ encoding.x.type = typeof sample === 'number' ? 'quantitative' : 'nominal';
1396
+ }
1397
+ }
1398
+ }
1399
+ }
1400
+ // Check y encoding
1401
+ if ((_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.field) {
1402
+ const sample = data.map((row)=>row[encoding.y.field]).find((v)=>v !== null && v !== undefined);
1403
+ if (sample !== undefined) {
1404
+ if (encoding.y.type === 'quantitative') {
1405
+ if (typeof sample === 'string' && !isFinite(Number(sample))) {
1406
+ encoding.y.type = 'nominal';
1407
+ } else if (typeof sample === 'object' && sample !== null && !Array.isArray(sample) && !(sample instanceof Date)) {
1408
+ // Try to extract a numeric value from the object
1409
+ const numericKeys = Object.keys(sample).filter((k)=>typeof sample[k] === 'number');
1410
+ if (numericKeys.length === 1) {
1411
+ // Object has exactly one numeric property - use it as the value
1412
+ const numericKey = numericKeys[0];
1413
+ const yField = encoding.y.field;
1414
+ data.forEach((row)=>{
1415
+ const obj = row[yField];
1416
+ if (typeof obj === 'object' && obj !== null) {
1417
+ row[yField] = obj[numericKey];
1418
+ }
1419
+ });
1420
+ // Keep type as quantitative since we extracted numeric values
1421
+ } else {
1422
+ encoding.y.type = 'nominal';
1423
+ }
1424
+ } else if (typeof sample === 'object') {
1425
+ encoding.y.type = 'nominal';
1426
+ }
1427
+ } else if (encoding.y.type === 'temporal') {
1428
+ const isValidDate = sample instanceof Date || typeof sample === 'string' && !isNaN(Date.parse(sample));
1429
+ if (!isValidDate) {
1430
+ encoding.y.type = typeof sample === 'number' ? 'quantitative' : 'nominal';
1431
+ }
1432
+ }
1433
+ }
1434
+ }
1435
+ }
1436
+ function getChartType(spec) {
1437
+ var _spec_layer_, _spec_layer_1, _encoding_color, _encoding_x, _encoding_y, _encoding_color1;
1438
+ // Auto-correct encoding types based on actual data BEFORE chart type detection
1439
+ autoCorrectEncodingTypes(spec);
1440
+ // Handle layered specs - check if it's a bar+line combo for stacked bar with lines
1441
+ if (spec.layer && spec.layer.length > 1) {
1442
+ const marks = spec.layer.map((layer)=>getMarkType(layer.mark));
1443
+ const hasBar = marks.includes('bar');
1444
+ const hasLine = marks.includes('line') || marks.includes('point');
1445
+ // Bar + line combo should use stacked bar chart (which supports line overlays)
1446
+ if (hasBar && hasLine) {
1447
+ var _barLayer_encoding_color, _barLayer_encoding;
1448
+ const barLayer = spec.layer.find((layer)=>getMarkType(layer.mark) === 'bar');
1449
+ if (barLayer === null || barLayer === void 0 ? void 0 : (_barLayer_encoding = barLayer.encoding) === null || _barLayer_encoding === void 0 ? void 0 : (_barLayer_encoding_color = _barLayer_encoding.color) === null || _barLayer_encoding_color === void 0 ? void 0 : _barLayer_encoding_color.field) {
1450
+ return {
1451
+ type: 'stacked-bar',
1452
+ mark: 'bar'
1453
+ };
1454
+ }
1455
+ return {
1456
+ type: 'stacked-bar',
1457
+ mark: 'bar'
1458
+ };
1459
+ }
1460
+ }
1461
+ // Handle layered specs - use first layer's mark for other cases
1462
+ const mark = spec.layer ? (_spec_layer_ = spec.layer[0]) === null || _spec_layer_ === void 0 ? void 0 : _spec_layer_.mark : spec.mark;
1463
+ const markType = getMarkType(mark);
1464
+ const encoding = spec.layer ? (_spec_layer_1 = spec.layer[0]) === null || _spec_layer_1 === void 0 ? void 0 : _spec_layer_1.encoding : spec.encoding;
1465
+ const hasColorEncoding = !!(encoding === null || encoding === void 0 ? void 0 : (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.field);
1466
+ // Polar charts with arc marks: theta AND radius encodings
1467
+ if (markType === 'arc' && (encoding === null || encoding === void 0 ? void 0 : encoding.theta) && (encoding === null || encoding === void 0 ? void 0 : encoding.radius)) {
1468
+ return {
1469
+ type: 'polar',
1470
+ mark: markType
1471
+ };
1472
+ }
1473
+ // Arc marks for pie/donut charts (theta only, no radius)
1474
+ if (markType === 'arc' && (encoding === null || encoding === void 0 ? void 0 : encoding.theta)) {
1475
+ return {
1476
+ type: 'donut',
1477
+ mark: markType
1478
+ };
1479
+ }
1480
+ // Polar charts: non-arc marks with theta and radius encodings
1481
+ if ((encoding === null || encoding === void 0 ? void 0 : encoding.theta) && (encoding === null || encoding === void 0 ? void 0 : encoding.radius)) {
1482
+ return {
1483
+ type: 'polar',
1484
+ mark: markType
1485
+ };
1486
+ }
1487
+ // Rect marks for heatmaps (quantitative or nominal color)
1488
+ if (markType === 'rect' && (encoding === null || encoding === void 0 ? void 0 : (_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.field) && (encoding === null || encoding === void 0 ? void 0 : (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.field) && (encoding === null || encoding === void 0 ? void 0 : (_encoding_color1 = encoding.color) === null || _encoding_color1 === void 0 ? void 0 : _encoding_color1.field)) {
1489
+ return {
1490
+ type: 'heatmap',
1491
+ mark: markType
1492
+ };
1493
+ }
1494
+ // Bar charts
1495
+ if (markType === 'bar') {
1496
+ var _encoding_x1, _encoding_x2, _encoding_x3, _encoding_y1, _encoding_y2, _encoding_x4, _spec_data;
1497
+ if (encoding === null || encoding === void 0 ? void 0 : (_encoding_x1 = encoding.x) === null || _encoding_x1 === void 0 ? void 0 : _encoding_x1.bin) {
1498
+ return {
1499
+ type: 'histogram',
1500
+ mark: markType
1501
+ };
1502
+ }
1503
+ const isXNominal = (encoding === null || encoding === void 0 ? void 0 : (_encoding_x2 = encoding.x) === null || _encoding_x2 === void 0 ? void 0 : _encoding_x2.type) === 'nominal' || (encoding === null || encoding === void 0 ? void 0 : (_encoding_x3 = encoding.x) === null || _encoding_x3 === void 0 ? void 0 : _encoding_x3.type) === 'ordinal';
1504
+ const isYNominal = (encoding === null || encoding === void 0 ? void 0 : (_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.type) === 'nominal' || (encoding === null || encoding === void 0 ? void 0 : (_encoding_y2 = encoding.y) === null || _encoding_y2 === void 0 ? void 0 : _encoding_y2.type) === 'ordinal';
1505
+ if (isYNominal && !isXNominal) {
1506
+ return {
1507
+ type: 'horizontal-bar',
1508
+ mark: markType
1509
+ };
1510
+ }
1511
+ if (hasColorEncoding) {
1512
+ const hasXOffset = !!(encoding === null || encoding === void 0 ? void 0 : encoding.xOffset);
1513
+ if (hasXOffset) {
1514
+ return {
1515
+ type: 'grouped-bar',
1516
+ mark: markType
1517
+ };
1518
+ }
1519
+ return {
1520
+ type: 'stacked-bar',
1521
+ mark: markType
1522
+ };
1523
+ }
1524
+ const xField = encoding === null || encoding === void 0 ? void 0 : (_encoding_x4 = encoding.x) === null || _encoding_x4 === void 0 ? void 0 : _encoding_x4.field;
1525
+ const dataValues = (_spec_data = spec.data) === null || _spec_data === void 0 ? void 0 : _spec_data.values;
1526
+ if (xField && Array.isArray(dataValues) && dataValues.length > 0) {
1527
+ const xValues = dataValues.map((row)=>row[xField]);
1528
+ const uniqueXValues = new Set(xValues);
1529
+ if (uniqueXValues.size < xValues.length) {
1530
+ return {
1531
+ type: 'stacked-bar',
1532
+ mark: markType
1533
+ };
1534
+ }
1535
+ }
1536
+ return {
1537
+ type: 'bar',
1538
+ mark: markType
1539
+ };
1540
+ }
1541
+ if (markType === 'area') {
1542
+ return {
1543
+ type: 'area',
1544
+ mark: markType
1545
+ };
1546
+ }
1547
+ if (markType === 'point' || markType === 'circle' || markType === 'square' || markType === 'tick') {
1548
+ return {
1549
+ type: 'scatter',
1550
+ mark: markType
1551
+ };
1552
+ }
1553
+ // Trail marks rendered as line charts (size encoding as markerSize)
1554
+ if (markType === 'trail') {
1555
+ return {
1556
+ type: 'line',
1557
+ mark: 'line'
1558
+ };
1559
+ }
1560
+ // Error bar/band marks rendered as line charts
1561
+ if (markType === 'errorbar' || markType === 'errorband') {
1562
+ return {
1563
+ type: 'line',
1564
+ mark: 'line'
1565
+ };
1566
+ }
1567
+ return {
1568
+ type: 'line',
1569
+ mark: markType || 'line'
1570
+ };
1571
+ }
1572
+ function transformVegaLiteToLineChartProps(spec, colorMap, isDarkTheme) {
1573
+ var _encoding_x, _encoding_y, _encoding_x1, _encoding_y1, _encoding_x2, _encoding_y2, _spec_title, _encoding_x_axis, _encoding_x3, _encoding_y_axis, _encoding_y3, _encoding_x_axis1, _encoding_x4, _encoding_y_axis1, _encoding_y4, _encoding_x_axis2, _encoding_x5, _encoding_y_axis2, _encoding_y5, _encoding_color_legend, _encoding_color;
1574
+ // Initialize transformation context, but find the primary line/point layer for layered specs
1575
+ const unitSpecs = normalizeSpec(spec);
1576
+ if (unitSpecs.length === 0) {
1577
+ throw new Error('VegaLiteSchemaAdapter: No valid unit specs found in specification');
1578
+ }
1579
+ // For layered specs, find the actual line/point layer (not rect layers for color fill bars)
1580
+ const primarySpec = findPrimaryLineSpec(unitSpecs);
1581
+ if (!primarySpec) {
1582
+ throw new Error('VegaLiteSchemaAdapter: No valid line/point layer found in specification');
1583
+ }
1584
+ // Check if there's a point layer in addition to line layer (for line+point combo charts)
1585
+ const hasPointLayer = unitSpecs.some((unitSpec)=>getMarkType(unitSpec.mark) === 'point');
1586
+ const hasLineLayer = unitSpecs.some((unitSpec)=>getMarkType(unitSpec.mark) === 'line');
1587
+ const shouldShowPoints = hasPointLayer && hasLineLayer;
1588
+ const rawDataValues = extractDataValues(primarySpec.data);
1589
+ // Apply any transforms (fold, etc.) from the spec
1590
+ const dataValues = applyTransforms(rawDataValues, spec.transform);
1591
+ const encoding = primarySpec.encoding || {};
1592
+ const markProps = getMarkProperties(primarySpec.mark);
1593
+ // Extract field names
1594
+ const { xField, yField, colorField } = extractEncodingFields(encoding);
1595
+ // Check for size encoding from any layer (e.g., point layer with size in line+point combo)
1596
+ let sizeField;
1597
+ if (unitSpecs.length > 1) {
1598
+ for (const unitSpec of unitSpecs){
1599
+ var _unitEncoding_size;
1600
+ const unitEncoding = unitSpec.encoding || {};
1601
+ if ((_unitEncoding_size = unitEncoding.size) === null || _unitEncoding_size === void 0 ? void 0 : _unitEncoding_size.field) {
1602
+ sizeField = unitEncoding.size.field;
1603
+ break;
1604
+ }
1605
+ }
1606
+ } else {
1607
+ var _encoding_size;
1608
+ sizeField = (_encoding_size = encoding.size) === null || _encoding_size === void 0 ? void 0 : _encoding_size.field;
1609
+ }
1610
+ // Validate data and encodings
1611
+ if (!xField || !yField) {
1612
+ throw new Error('VegaLiteSchemaAdapter: Line chart requires both x and y encodings with field names');
1613
+ }
1614
+ validateXYEncodings(dataValues, xField, yField, (_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.type, (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.type, 'LineChart', encoding);
1615
+ const isXTemporal = ((_encoding_x1 = encoding.x) === null || _encoding_x1 === void 0 ? void 0 : _encoding_x1.type) === 'temporal';
1616
+ const isYTemporal = ((_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.type) === 'temporal';
1617
+ // Group data into series
1618
+ const { seriesMap, ordinalLabels, yOrdinalLabels } = groupDataBySeries(dataValues, xField, yField, colorField, isXTemporal, isYTemporal, (_encoding_x2 = encoding.x) === null || _encoding_x2 === void 0 ? void 0 : _encoding_x2.type, sizeField, (_encoding_y2 = encoding.y) === null || _encoding_y2 === void 0 ? void 0 : _encoding_y2.type);
1619
+ // Extract color configuration
1620
+ const { colorScheme, colorRange } = extractColorConfig(encoding);
1621
+ // Convert series map to LineChartPoints array
1622
+ const lineChartData = [];
1623
+ const colorIndex = new Map();
1624
+ let currentColorIndex = 0;
1625
+ seriesMap.forEach((dataPoints, seriesName)=>{
1626
+ if (!colorIndex.has(seriesName)) {
1627
+ colorIndex.set(seriesName, currentColorIndex++);
1628
+ }
1629
+ const color = resolveColor(seriesName, colorIndex.get(seriesName), undefined, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
1630
+ const curveOption = mapInterpolateToCurve(markProps.interpolate);
1631
+ // Build line options with curve, strokeDash, and strokeWidth
1632
+ const lineOptions = {};
1633
+ if (curveOption) {
1634
+ lineOptions.curve = curveOption;
1635
+ }
1636
+ if (markProps.strokeDash) {
1637
+ lineOptions.strokeDasharray = markProps.strokeDash.join(' ');
1638
+ }
1639
+ if (markProps.strokeWidth) {
1640
+ lineOptions.strokeWidth = markProps.strokeWidth;
1641
+ }
1642
+ lineChartData.push({
1643
+ legend: seriesName,
1644
+ data: dataPoints,
1645
+ color,
1646
+ hideNonActiveDots: !shouldShowPoints,
1647
+ ...Object.keys(lineOptions).length > 0 && {
1648
+ lineOptions
1649
+ }
1650
+ });
1651
+ });
1652
+ // Extract chart title
1653
+ const chartTitle = typeof spec.title === 'string' ? spec.title : (_spec_title = spec.title) === null || _spec_title === void 0 ? void 0 : _spec_title.text;
1654
+ var _encoding_x_axis_title;
1655
+ // Extract axis titles and formats
1656
+ const xAxisTitle = (_encoding_x_axis_title = (_encoding_x3 = encoding.x) === null || _encoding_x3 === void 0 ? void 0 : (_encoding_x_axis = _encoding_x3.axis) === null || _encoding_x_axis === void 0 ? void 0 : _encoding_x_axis.title) !== null && _encoding_x_axis_title !== void 0 ? _encoding_x_axis_title : undefined;
1657
+ var _encoding_y_axis_title;
1658
+ const yAxisTitle = (_encoding_y_axis_title = (_encoding_y3 = encoding.y) === null || _encoding_y3 === void 0 ? void 0 : (_encoding_y_axis = _encoding_y3.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.title) !== null && _encoding_y_axis_title !== void 0 ? _encoding_y_axis_title : undefined;
1659
+ const tickFormat = (_encoding_x4 = encoding.x) === null || _encoding_x4 === void 0 ? void 0 : (_encoding_x_axis1 = _encoding_x4.axis) === null || _encoding_x_axis1 === void 0 ? void 0 : _encoding_x_axis1.format;
1660
+ const yAxisTickFormat = (_encoding_y4 = encoding.y) === null || _encoding_y4 === void 0 ? void 0 : (_encoding_y_axis1 = _encoding_y4.axis) === null || _encoding_y_axis1 === void 0 ? void 0 : _encoding_y_axis1.format;
1661
+ // Extract tick values and counts
1662
+ // Use ordinalLabels for ordinal x-axis, otherwise use explicit values from spec
1663
+ const tickValues = ordinalLabels || ((_encoding_x5 = encoding.x) === null || _encoding_x5 === void 0 ? void 0 : (_encoding_x_axis2 = _encoding_x5.axis) === null || _encoding_x_axis2 === void 0 ? void 0 : _encoding_x_axis2.values);
1664
+ const yAxisTickCount = (_encoding_y5 = encoding.y) === null || _encoding_y5 === void 0 ? void 0 : (_encoding_y_axis2 = _encoding_y5.axis) === null || _encoding_y_axis2 === void 0 ? void 0 : _encoding_y_axis2.tickCount;
1665
+ // Extract domain/range for min/max values
1666
+ const { yMinValue, yMaxValue } = extractYMinMax(encoding, dataValues);
1667
+ // Extract annotations and color fill bars from layers
1668
+ const annotations = extractAnnotations(spec);
1669
+ const colorFillBars = extractColorFillBars(spec, colorMap, isDarkTheme);
1670
+ // Convert rule marks in layered specs to reference line series
1671
+ // Each horizontal rule becomes a 2-point line at constant y spanning the data x-range
1672
+ if (spec.layer && Array.isArray(spec.layer) && lineChartData.length > 0) {
1673
+ const allXValues = lineChartData.flatMap((series)=>series.data.map((p)=>p.x));
1674
+ const xMin = allXValues.length > 0 ? allXValues.reduce((a, b)=>a < b ? a : b) : 0;
1675
+ const xMax = allXValues.length > 0 ? allXValues.reduce((a, b)=>a > b ? a : b) : 0;
1676
+ spec.layer.forEach((layer, layerIndex)=>{
1677
+ var _ruleEncoding_y, _ruleEncoding_y1, _textLayer_encoding_text, _textLayer_encoding, _textLayer_encoding_text1, _textLayer_encoding1;
1678
+ const layerMark = getMarkType(layer.mark);
1679
+ if (layerMark !== 'rule') {
1680
+ return;
1681
+ }
1682
+ const ruleEncoding = layer.encoding || {};
1683
+ var _ruleEncoding_y_datum;
1684
+ const yDatum = (_ruleEncoding_y_datum = (_ruleEncoding_y = ruleEncoding.y) === null || _ruleEncoding_y === void 0 ? void 0 : _ruleEncoding_y.datum) !== null && _ruleEncoding_y_datum !== void 0 ? _ruleEncoding_y_datum : (_ruleEncoding_y1 = ruleEncoding.y) === null || _ruleEncoding_y1 === void 0 ? void 0 : _ruleEncoding_y1.value;
1685
+ if (yDatum === undefined) {
1686
+ return;
1687
+ }
1688
+ const ruleMarkProps = getMarkProperties(layer.mark);
1689
+ const ruleColor = ruleMarkProps.color || '#d62728';
1690
+ // Find companion text annotation for legend name
1691
+ const textLayer = spec.layer.find((l)=>{
1692
+ var _l_encoding;
1693
+ const m = getMarkType(l.mark);
1694
+ var _l_encoding_y_datum;
1695
+ return m === 'text' && ((_l_encoding = l.encoding) === null || _l_encoding === void 0 ? void 0 : _l_encoding.y) && ((_l_encoding_y_datum = l.encoding.y.datum) !== null && _l_encoding_y_datum !== void 0 ? _l_encoding_y_datum : l.encoding.y.value) === yDatum;
1696
+ });
1697
+ const ruleLegend = textLayer ? String(((_textLayer_encoding = textLayer.encoding) === null || _textLayer_encoding === void 0 ? void 0 : (_textLayer_encoding_text = _textLayer_encoding.text) === null || _textLayer_encoding_text === void 0 ? void 0 : _textLayer_encoding_text.datum) || ((_textLayer_encoding1 = textLayer.encoding) === null || _textLayer_encoding1 === void 0 ? void 0 : (_textLayer_encoding_text1 = _textLayer_encoding1.text) === null || _textLayer_encoding_text1 === void 0 ? void 0 : _textLayer_encoding_text1.value) || `y=${yDatum}`) : `y=${yDatum}`;
1698
+ const ruleLineOptions = {};
1699
+ if (ruleMarkProps.strokeDash) {
1700
+ ruleLineOptions.strokeDasharray = ruleMarkProps.strokeDash.join(' ');
1701
+ }
1702
+ if (ruleMarkProps.strokeWidth) {
1703
+ ruleLineOptions.strokeWidth = ruleMarkProps.strokeWidth;
1704
+ }
1705
+ lineChartData.push({
1706
+ legend: ruleLegend,
1707
+ data: [
1708
+ {
1709
+ x: xMin,
1710
+ y: yDatum
1711
+ },
1712
+ {
1713
+ x: xMax,
1714
+ y: yDatum
1715
+ }
1716
+ ],
1717
+ color: ruleColor,
1718
+ hideNonActiveDots: true,
1719
+ ...Object.keys(ruleLineOptions).length > 0 && {
1720
+ lineOptions: ruleLineOptions
1721
+ }
1722
+ });
1723
+ });
1724
+ }
1725
+ // Check for log scale on Y-axis
1726
+ const yAxisType = extractYAxisType(encoding);
1727
+ // Extract axis category ordering
1728
+ const categoryOrderProps = extractAxisCategoryOrderProps(encoding);
1729
+ // Build LineChartProps
1730
+ const chartProps = {
1731
+ lineChartData,
1732
+ ...chartTitle && {
1733
+ chartTitle
1734
+ }
1735
+ };
1736
+ var _encoding_color_legend_disable;
1737
+ return {
1738
+ data: chartProps,
1739
+ width: typeof spec.width === 'number' ? spec.width : undefined,
1740
+ height: typeof spec.height === 'number' ? spec.height : undefined,
1741
+ ...xAxisTitle && {
1742
+ chartTitle: xAxisTitle
1743
+ },
1744
+ ...yAxisTitle && {
1745
+ yAxisTitle
1746
+ },
1747
+ ...tickFormat && {
1748
+ tickFormat
1749
+ },
1750
+ ...yAxisTickFormat && {
1751
+ yAxisTickFormat
1752
+ },
1753
+ ...tickValues && {
1754
+ tickValues
1755
+ },
1756
+ ...yAxisTickCount && {
1757
+ yAxisTickCount
1758
+ },
1759
+ ...yMinValue !== undefined && {
1760
+ yMinValue
1761
+ },
1762
+ ...yMaxValue !== undefined && {
1763
+ yMaxValue
1764
+ },
1765
+ ...annotations.length > 0 && {
1766
+ annotations
1767
+ },
1768
+ ...colorFillBars.length > 0 && {
1769
+ colorFillBars
1770
+ },
1771
+ ...yAxisType && {
1772
+ yScaleType: yAxisType
1773
+ },
1774
+ // For nominal y-axis, provide tick values and labels
1775
+ ...yOrdinalLabels && yOrdinalLabels.length > 0 && {
1776
+ yAxisTickValues: Array.from({
1777
+ length: yOrdinalLabels.length
1778
+ }, (_, i)=>i),
1779
+ yAxisTickFormat: (val)=>{
1780
+ var _yOrdinalLabels_val;
1781
+ return (_yOrdinalLabels_val = yOrdinalLabels[val]) !== null && _yOrdinalLabels_val !== void 0 ? _yOrdinalLabels_val : String(val);
1782
+ },
1783
+ yMinValue: -0.5,
1784
+ yMaxValue: yOrdinalLabels.length - 0.5
1785
+ },
1786
+ ...categoryOrderProps,
1787
+ hideLegend: (_encoding_color_legend_disable = (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : (_encoding_color_legend = _encoding_color.legend) === null || _encoding_color_legend === void 0 ? void 0 : _encoding_color_legend.disable) !== null && _encoding_color_legend_disable !== void 0 ? _encoding_color_legend_disable : false
1788
+ };
1789
+ }
1790
+ function getVegaLiteLegendsProps(spec, colorMap, isDarkTheme) {
1791
+ var _encoding_color;
1792
+ const unitSpecs = normalizeSpec(spec);
1793
+ const legends = [];
1794
+ if (unitSpecs.length === 0) {
1795
+ return {
1796
+ legends,
1797
+ centerLegends: true,
1798
+ enabledWrapLines: true,
1799
+ canSelectMultipleLegends: true
1800
+ };
1801
+ }
1802
+ const primarySpec = unitSpecs[0];
1803
+ const dataValues = extractDataValues(primarySpec.data);
1804
+ const encoding = primarySpec.encoding || {};
1805
+ const colorField = (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.field;
1806
+ if (!colorField) {
1807
+ return {
1808
+ legends,
1809
+ centerLegends: true,
1810
+ enabledWrapLines: true,
1811
+ canSelectMultipleLegends: true
1812
+ };
1813
+ }
1814
+ // Extract unique series names
1815
+ const seriesNames = new Set();
1816
+ dataValues.forEach((row)=>{
1817
+ if (row[colorField] !== undefined) {
1818
+ seriesNames.add(String(row[colorField]));
1819
+ }
1820
+ });
1821
+ // Generate legends
1822
+ seriesNames.forEach((seriesName)=>{
1823
+ const color = (0, _VegaLiteColorAdapter.getVegaColorFromMap)(seriesName, colorMap, undefined, undefined, isDarkTheme);
1824
+ legends.push({
1825
+ title: seriesName,
1826
+ color
1827
+ });
1828
+ });
1829
+ return {
1830
+ legends,
1831
+ centerLegends: true,
1832
+ enabledWrapLines: true,
1833
+ canSelectMultipleLegends: true
1834
+ };
1835
+ }
1836
+ function getVegaLiteTitles(spec) {
1837
+ var _spec_title, _encoding_x, _encoding_x_axis, _encoding_x1, _encoding_y, _encoding_y_axis, _encoding_y1;
1838
+ const unitSpecs = normalizeSpec(spec);
1839
+ if (unitSpecs.length === 0) {
1840
+ return {};
1841
+ }
1842
+ const primarySpec = unitSpecs[0];
1843
+ const encoding = primarySpec.encoding || {};
1844
+ // Extract chart title
1845
+ const chartTitle = typeof spec.title === 'string' ? spec.title : (_spec_title = spec.title) === null || _spec_title === void 0 ? void 0 : _spec_title.text;
1846
+ // Extract title styles if title is an object
1847
+ let titleStyles;
1848
+ if (typeof spec.title === 'object' && spec.title !== null) {
1849
+ const titleObj = spec.title;
1850
+ // Build titleFont object if any font properties are present
1851
+ const titleFont = {};
1852
+ if (titleObj.font) {
1853
+ titleFont.family = titleObj.font;
1854
+ }
1855
+ if (titleObj.fontSize) {
1856
+ titleFont.size = titleObj.fontSize;
1857
+ }
1858
+ if (titleObj.fontWeight) {
1859
+ // Convert string weights to numbers (Font interface expects number)
1860
+ const weight = titleObj.fontWeight;
1861
+ if (typeof weight === 'string') {
1862
+ const weightMap = {
1863
+ normal: 400,
1864
+ bold: 700,
1865
+ lighter: 300,
1866
+ bolder: 600
1867
+ };
1868
+ titleFont.weight = weightMap[weight.toLowerCase()] || 400;
1869
+ } else {
1870
+ titleFont.weight = weight;
1871
+ }
1872
+ }
1873
+ if (titleObj.color) {
1874
+ titleFont.color = titleObj.color;
1875
+ }
1876
+ // Map Vega-Lite anchor values to TitleStyles anchor values
1877
+ const anchorMap = {
1878
+ start: 'left',
1879
+ middle: 'center',
1880
+ end: 'right'
1881
+ };
1882
+ titleStyles = {
1883
+ ...Object.keys(titleFont).length > 0 ? {
1884
+ titleFont
1885
+ } : {},
1886
+ ...titleObj.anchor && anchorMap[titleObj.anchor] ? {
1887
+ titleXAnchor: anchorMap[titleObj.anchor]
1888
+ } : {},
1889
+ ...titleObj.offset !== undefined || titleObj.subtitlePadding !== undefined ? {
1890
+ titlePad: {
1891
+ t: titleObj.offset,
1892
+ b: titleObj.subtitlePadding
1893
+ }
1894
+ } : {}
1895
+ };
1896
+ // Only include titleStyles if it has properties
1897
+ if (Object.keys(titleStyles).length === 0) {
1898
+ titleStyles = undefined;
1899
+ }
1900
+ }
1901
+ var _encoding_x_title, _ref, _encoding_y_title, _ref1;
1902
+ return {
1903
+ chartTitle,
1904
+ xAxisTitle: (_ref = (_encoding_x_title = (_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.title) !== null && _encoding_x_title !== void 0 ? _encoding_x_title : (_encoding_x1 = encoding.x) === null || _encoding_x1 === void 0 ? void 0 : (_encoding_x_axis = _encoding_x1.axis) === null || _encoding_x_axis === void 0 ? void 0 : _encoding_x_axis.title) !== null && _ref !== void 0 ? _ref : undefined,
1905
+ yAxisTitle: (_ref1 = (_encoding_y_title = (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.title) !== null && _encoding_y_title !== void 0 ? _encoding_y_title : (_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : (_encoding_y_axis = _encoding_y1.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.title) !== null && _ref1 !== void 0 ? _ref1 : undefined,
1906
+ ...titleStyles ? {
1907
+ titleStyles
1908
+ } : {}
1909
+ };
1910
+ }
1911
+ function transformVegaLiteToVerticalBarChartProps(spec, colorMap, isDarkTheme) {
1912
+ var _encoding_color, _encoding_y_axis, _encoding_y, _barData_, _encoding_color_legend, _encoding_color1;
1913
+ // Initialize transformation context
1914
+ const { dataValues, encoding, markProps } = initializeTransformContext(spec);
1915
+ // Extract field names and aggregates
1916
+ const { xField, yField, colorField, yAggregate } = extractEncodingFields(encoding);
1917
+ // Check if this is an aggregate bar chart
1918
+ // Aggregate can be: count (no field needed) or sum/mean/etc (with field)
1919
+ const isAggregate = !!yAggregate;
1920
+ if (!xField && !isAggregate) {
1921
+ throw new Error('VegaLiteSchemaAdapter: x encoding is required for bar charts');
1922
+ }
1923
+ // For aggregate charts, compute aggregated data
1924
+ let aggregatedData;
1925
+ if (isAggregate && xField) {
1926
+ aggregatedData = computeAggregateData(dataValues, xField, yField, yAggregate);
1927
+ }
1928
+ // Validate data and encodings (skip for aggregate charts)
1929
+ if (!isAggregate && xField && yField) {
1930
+ var _encoding_x, _encoding_y1;
1931
+ validateXYEncodings(dataValues, xField, yField, (_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.type, (_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.type, 'VerticalBarChart', encoding);
1932
+ }
1933
+ // Extract color configuration
1934
+ const { colorScheme, colorRange } = extractColorConfig(encoding);
1935
+ const colorValue = (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.value;
1936
+ const barData = [];
1937
+ const colorIndex = new Map();
1938
+ let currentColorIndex = 0;
1939
+ // When there's no color field, all bars share a single legend
1940
+ const useSingleLegendForAggregate = !colorField;
1941
+ if (aggregatedData) {
1942
+ // Use aggregated data
1943
+ aggregatedData.forEach(({ category, value })=>{
1944
+ const legend = useSingleLegendForAggregate ? 'Bar' : String(category);
1945
+ if (!colorIndex.has(legend)) {
1946
+ colorIndex.set(legend, currentColorIndex++);
1947
+ }
1948
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
1949
+ barData.push({
1950
+ x: category,
1951
+ y: value,
1952
+ legend,
1953
+ color
1954
+ });
1955
+ });
1956
+ } else if (xField && yField) {
1957
+ var _dataValues_find;
1958
+ // Check if y values are numeric; if not, fall back to count aggregation
1959
+ const firstYValue = (_dataValues_find = dataValues.find((r)=>r[yField] !== undefined)) === null || _dataValues_find === void 0 ? void 0 : _dataValues_find[yField];
1960
+ const yIsNumeric = typeof firstYValue === 'number';
1961
+ if (!yIsNumeric) {
1962
+ // y values are non-numeric: compute count per x category
1963
+ const counts = countByCategory(dataValues, xField, undefined, '');
1964
+ counts.forEach((legendMap, xKey)=>{
1965
+ // No color grouping - each xKey gets one bar; use xKey as legend
1966
+ const totalCount = Array.from(legendMap.values()).reduce((a, b)=>a + b, 0);
1967
+ const legend = xKey;
1968
+ if (!colorIndex.has(legend)) {
1969
+ colorIndex.set(legend, currentColorIndex++);
1970
+ }
1971
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
1972
+ barData.push({
1973
+ x: xKey,
1974
+ y: totalCount,
1975
+ legend,
1976
+ color
1977
+ });
1978
+ });
1979
+ } else {
1980
+ var _encoding_y_axis1, _encoding_y2;
1981
+ // When there's no color field encoding, use a single legend name for all bars
1982
+ // This ensures: uniform bar color, single legend entry, no tooltip duplication
1983
+ const useSingleLegend = !colorField;
1984
+ // Create value formatter for bar data labels
1985
+ const yFormatter = createValueFormatter((_encoding_y2 = encoding.y) === null || _encoding_y2 === void 0 ? void 0 : (_encoding_y_axis1 = _encoding_y2.axis) === null || _encoding_y_axis1 === void 0 ? void 0 : _encoding_y_axis1.format);
1986
+ // Use raw data (normal numeric y values)
1987
+ dataValues.forEach((row)=>{
1988
+ const xValue = row[xField];
1989
+ const yValue = row[yField];
1990
+ // Use chart-utilities validation
1991
+ if ((0, _chartutilities.isInvalidValue)(xValue) || (0, _chartutilities.isInvalidValue)(yValue) || typeof yValue !== 'number') {
1992
+ return;
1993
+ }
1994
+ const legend = colorField && row[colorField] !== undefined ? String(row[colorField]) : useSingleLegend ? 'Bar' : String(xValue);
1995
+ if (!colorIndex.has(legend)) {
1996
+ colorIndex.set(legend, currentColorIndex++);
1997
+ }
1998
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
1999
+ // For bar charts, x-axis values are treated as categories (even if numeric)
2000
+ // Convert to string to ensure consistent categorical positioning
2001
+ const xCategory = typeof xValue === 'number' ? String(xValue) : xValue;
2002
+ barData.push({
2003
+ x: xCategory,
2004
+ y: yValue,
2005
+ legend,
2006
+ color,
2007
+ ...yFormatter && {
2008
+ yAxisCalloutData: yFormatter(yValue),
2009
+ barLabel: yFormatter(yValue)
2010
+ }
2011
+ });
2012
+ });
2013
+ }
2014
+ }
2015
+ const titles = getVegaLiteTitles(spec);
2016
+ // Extract axis category ordering
2017
+ const categoryOrderProps = extractAxisCategoryOrderProps(encoding);
2018
+ // Extract tick configuration
2019
+ const tickConfig = extractTickConfig(spec);
2020
+ // Extract y-axis formatting and scale props
2021
+ const yAxisTickFormat = (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : (_encoding_y_axis = _encoding_y.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.format;
2022
+ const { yMinValue, yMaxValue } = extractYMinMax(encoding, dataValues);
2023
+ const yAxisType = extractYAxisType(encoding);
2024
+ // Compute truncation based on number of unique x-axis categories
2025
+ const uniqueXCount = new Set(barData.map((d)=>String(d.x))).size;
2026
+ const barTruncateChars = uniqueXCount > 20 ? 6 : uniqueXCount > 10 ? 10 : DEFAULT_TRUNCATE_CHARS;
2027
+ var _encoding_color_legend_disable;
2028
+ const result = {
2029
+ data: barData,
2030
+ chartTitle: titles.chartTitle,
2031
+ xAxisTitle: titles.xAxisTitle,
2032
+ yAxisTitle: titles.yAxisTitle,
2033
+ ...titles.titleStyles ? titles.titleStyles : {},
2034
+ roundCorners: true,
2035
+ wrapXAxisLables: typeof ((_barData_ = barData[0]) === null || _barData_ === void 0 ? void 0 : _barData_.x) === 'string',
2036
+ hideTickOverlap: true,
2037
+ noOfCharsToTruncate: barTruncateChars,
2038
+ xAxis: {
2039
+ tickLayout: 'auto'
2040
+ },
2041
+ ...yAxisTickFormat && {
2042
+ yAxisTickFormat
2043
+ },
2044
+ ...yMinValue !== undefined && {
2045
+ yMinValue
2046
+ },
2047
+ ...yMaxValue !== undefined && {
2048
+ yMaxValue
2049
+ },
2050
+ ...yAxisType && {
2051
+ yScaleType: yAxisType
2052
+ },
2053
+ ...categoryOrderProps,
2054
+ // Hide legend for single-series bar charts (no color encoding) to avoid showing "Bar" legend
2055
+ hideLegend: !colorField ? true : (_encoding_color_legend_disable = (_encoding_color1 = encoding.color) === null || _encoding_color1 === void 0 ? void 0 : (_encoding_color_legend = _encoding_color1.legend) === null || _encoding_color_legend === void 0 ? void 0 : _encoding_color_legend.disable) !== null && _encoding_color_legend_disable !== void 0 ? _encoding_color_legend_disable : false
2056
+ };
2057
+ if (tickConfig.tickValues) {
2058
+ result.tickValues = tickConfig.tickValues;
2059
+ }
2060
+ if (tickConfig.xAxisTickCount) {
2061
+ result.xAxisTickCount = tickConfig.xAxisTickCount;
2062
+ }
2063
+ return result;
2064
+ }
2065
+ function transformVegaLiteToVerticalStackedBarChartProps(spec, colorMap, isDarkTheme) {
2066
+ var _encoding_color, _encoding_y_axis, _encoding_y, _encoding_color_legend, _encoding_color1, _chartData_;
2067
+ // Initialize transformation context (skip warnings as we handle layered spec differently)
2068
+ const { unitSpecs } = initializeTransformContext(spec);
2069
+ // Separate bar, line, and rule specs from layered specifications
2070
+ const barSpecs = unitSpecs.filter((s)=>getMarkType(s.mark) === 'bar');
2071
+ const lineSpecs = unitSpecs.filter((s)=>{
2072
+ const mark = getMarkType(s.mark);
2073
+ return mark === 'line' || mark === 'point';
2074
+ });
2075
+ const ruleSpecs = unitSpecs.filter((s)=>getMarkType(s.mark) === 'rule');
2076
+ // Use bar specs if available, otherwise fall back to first unit spec
2077
+ const primarySpec = barSpecs.length > 0 ? barSpecs[0] : unitSpecs[0];
2078
+ const rawDataValues = extractDataValues(primarySpec.data);
2079
+ // Apply transforms from both top-level spec and primary spec
2080
+ let dataValues = applyTransforms(rawDataValues, spec.transform);
2081
+ dataValues = applyTransforms(dataValues, primarySpec.transform);
2082
+ const encoding = primarySpec.encoding || {};
2083
+ const markProps = getMarkProperties(primarySpec.mark);
2084
+ // Extract field names and aggregates
2085
+ const { xField, yField, colorField, yAggregate } = extractEncodingFields(encoding);
2086
+ const colorValue = (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.value; // Static color value
2087
+ // Support aggregate encodings (e.g., count, sum)
2088
+ const isAggregate = !!yAggregate;
2089
+ if (!xField) {
2090
+ throw new Error('VegaLiteSchemaAdapter: x encoding is required for stacked bar charts');
2091
+ }
2092
+ // For aggregate charts, compute aggregated data
2093
+ let aggregatedData;
2094
+ if (isAggregate) {
2095
+ aggregatedData = computeAggregateData(dataValues, xField, yField, yAggregate);
2096
+ } else if (!yField) {
2097
+ throw new Error('VegaLiteSchemaAdapter: y encoding is required for stacked bar charts');
2098
+ }
2099
+ // Extract color configuration
2100
+ const { colorScheme, colorRange } = extractColorConfig(encoding);
2101
+ // Group data by x value, then by color (stack)
2102
+ const mapXToDataPoints = {};
2103
+ const colorIndex = new Map();
2104
+ let currentColorIndex = 0;
2105
+ if (aggregatedData) {
2106
+ // Use aggregated data
2107
+ aggregatedData.forEach(({ category, value })=>{
2108
+ const xKey = String(category);
2109
+ const legend = 'Bar';
2110
+ if (!mapXToDataPoints[xKey]) {
2111
+ mapXToDataPoints[xKey] = {
2112
+ xAxisPoint: category,
2113
+ chartData: [],
2114
+ lineData: []
2115
+ };
2116
+ }
2117
+ if (!colorIndex.has(legend)) {
2118
+ colorIndex.set(legend, currentColorIndex++);
2119
+ }
2120
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
2121
+ mapXToDataPoints[xKey].chartData.push({
2122
+ legend,
2123
+ data: value,
2124
+ color
2125
+ });
2126
+ });
2127
+ } else {
2128
+ var _dataValues_find;
2129
+ // Check if y values are actually numeric; if not, fall back to count aggregation
2130
+ const firstYValue = (_dataValues_find = dataValues.find((r)=>r[yField] !== undefined)) === null || _dataValues_find === void 0 ? void 0 : _dataValues_find[yField];
2131
+ const yIsNumeric = typeof firstYValue === 'number';
2132
+ if (!yIsNumeric && yField) {
2133
+ // y values are non-numeric (e.g., strings after auto-correction from quantitative to nominal)
2134
+ // Fall back to count aggregation: count rows per x category and color
2135
+ const counts = countByCategory(dataValues, xField, colorField, 'Bar');
2136
+ counts.forEach((legendMap, xKey)=>{
2137
+ mapXToDataPoints[xKey] = {
2138
+ xAxisPoint: xKey,
2139
+ chartData: [],
2140
+ lineData: []
2141
+ };
2142
+ legendMap.forEach((count, legend)=>{
2143
+ if (!colorIndex.has(legend)) {
2144
+ colorIndex.set(legend, currentColorIndex++);
2145
+ }
2146
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
2147
+ mapXToDataPoints[xKey].chartData.push({
2148
+ legend,
2149
+ data: count,
2150
+ color
2151
+ });
2152
+ });
2153
+ });
2154
+ } else {
2155
+ // Process bar data (normal numeric y values)
2156
+ dataValues.forEach((row)=>{
2157
+ var _encoding_y_axis, _encoding_y;
2158
+ const xValue = row[xField];
2159
+ const yValue = row[yField];
2160
+ const stackValue = colorField ? row[colorField] : 'Bar'; // Default legend if no color field
2161
+ if ((0, _chartutilities.isInvalidValue)(xValue) || (0, _chartutilities.isInvalidValue)(yValue) || typeof yValue !== 'number') {
2162
+ return;
2163
+ }
2164
+ const xKey = String(xValue);
2165
+ const legend = stackValue !== undefined ? String(stackValue) : 'Bar';
2166
+ if (!mapXToDataPoints[xKey]) {
2167
+ // For bar charts, x-axis values are treated as categories (even if numeric)
2168
+ const xCategory = typeof xValue === 'number' ? String(xValue) : xValue;
2169
+ mapXToDataPoints[xKey] = {
2170
+ xAxisPoint: xCategory,
2171
+ chartData: [],
2172
+ lineData: []
2173
+ };
2174
+ }
2175
+ if (!colorIndex.has(legend)) {
2176
+ colorIndex.set(legend, currentColorIndex++);
2177
+ }
2178
+ // Use static color if provided, otherwise use color scheme/scale
2179
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
2180
+ const stackYFormatter = createValueFormatter((_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : (_encoding_y_axis = _encoding_y.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.format);
2181
+ mapXToDataPoints[xKey].chartData.push({
2182
+ legend,
2183
+ data: yValue,
2184
+ color,
2185
+ ...stackYFormatter && {
2186
+ yAxisCalloutData: stackYFormatter(yValue),
2187
+ barLabel: stackYFormatter(yValue)
2188
+ }
2189
+ });
2190
+ });
2191
+ }
2192
+ } // end else (non-aggregate)
2193
+ // Process line data from additional layers (if any)
2194
+ lineSpecs.forEach((lineSpec, lineIndex)=>{
2195
+ var _lineEncoding_x, _lineEncoding_y, _lineEncoding_color;
2196
+ let lineDataValues = extractDataValues(lineSpec.data);
2197
+ // Apply transforms from both top-level spec and line spec
2198
+ lineDataValues = applyTransforms(lineDataValues, spec.transform);
2199
+ lineDataValues = applyTransforms(lineDataValues, lineSpec.transform);
2200
+ const lineEncoding = lineSpec.encoding || {};
2201
+ const lineMarkProps = getMarkProperties(lineSpec.mark);
2202
+ const lineXField = (_lineEncoding_x = lineEncoding.x) === null || _lineEncoding_x === void 0 ? void 0 : _lineEncoding_x.field;
2203
+ const lineYField = (_lineEncoding_y = lineEncoding.y) === null || _lineEncoding_y === void 0 ? void 0 : _lineEncoding_y.field;
2204
+ const lineColorField = (_lineEncoding_color = lineEncoding.color) === null || _lineEncoding_color === void 0 ? void 0 : _lineEncoding_color.field;
2205
+ if (!lineXField || !lineYField) {
2206
+ return; // Skip if required fields are missing
2207
+ }
2208
+ const lineLegendBase = lineColorField ? 'Line' : `Line ${lineIndex + 1}`;
2209
+ lineDataValues.forEach((row)=>{
2210
+ var _spec_resolve_scale, _spec_resolve;
2211
+ const xValue = row[lineXField];
2212
+ const yValue = row[lineYField];
2213
+ if ((0, _chartutilities.isInvalidValue)(xValue) || (0, _chartutilities.isInvalidValue)(yValue)) {
2214
+ return;
2215
+ }
2216
+ const xKey = String(xValue);
2217
+ const lineLegend = lineColorField && row[lineColorField] !== undefined ? String(row[lineColorField]) : lineLegendBase;
2218
+ // Ensure x-axis point exists
2219
+ if (!mapXToDataPoints[xKey]) {
2220
+ mapXToDataPoints[xKey] = {
2221
+ xAxisPoint: xValue,
2222
+ chartData: [],
2223
+ lineData: []
2224
+ };
2225
+ }
2226
+ // Determine line color
2227
+ if (!colorIndex.has(lineLegend)) {
2228
+ colorIndex.set(lineLegend, currentColorIndex++);
2229
+ }
2230
+ let lineColor;
2231
+ if (lineMarkProps.color) {
2232
+ lineColor = lineMarkProps.color;
2233
+ } else {
2234
+ // Use lineLegend for consistent color assignment
2235
+ lineColor = resolveColor(lineLegend, colorIndex.get(lineLegend), undefined, undefined, colorMap, undefined, undefined, isDarkTheme);
2236
+ }
2237
+ // Determine if this line should use secondary Y-axis
2238
+ // Check if spec has independent Y scales AND line uses different Y field than bars
2239
+ const hasIndependentYScales = ((_spec_resolve = spec.resolve) === null || _spec_resolve === void 0 ? void 0 : (_spec_resolve_scale = _spec_resolve.scale) === null || _spec_resolve_scale === void 0 ? void 0 : _spec_resolve_scale.y) === 'independent';
2240
+ const useSecondaryYScale = hasIndependentYScales && lineYField !== yField;
2241
+ const lineData = {
2242
+ y: yValue,
2243
+ color: lineColor,
2244
+ legend: lineLegend,
2245
+ legendShape: 'triangle',
2246
+ data: typeof yValue === 'number' ? yValue : undefined,
2247
+ useSecondaryYScale
2248
+ };
2249
+ // Add line options if available
2250
+ if (lineMarkProps.strokeWidth || lineMarkProps.strokeDash) {
2251
+ lineData.lineOptions = {
2252
+ ...lineMarkProps.strokeWidth && {
2253
+ strokeWidth: lineMarkProps.strokeWidth
2254
+ },
2255
+ ...lineMarkProps.strokeDash && {
2256
+ strokeDasharray: lineMarkProps.strokeDash.join(' ')
2257
+ }
2258
+ };
2259
+ }
2260
+ mapXToDataPoints[xKey].lineData.push(lineData);
2261
+ });
2262
+ });
2263
+ // Process rule specs as horizontal reference lines
2264
+ // Each rule with a constant y-value becomes a flat line across all x-axis points
2265
+ ruleSpecs.forEach((ruleSpec, ruleIndex)=>{
2266
+ var _ruleEncoding_y, _ruleEncoding_y1;
2267
+ const ruleEncoding = ruleSpec.encoding || {};
2268
+ const ruleMarkProps = getMarkProperties(ruleSpec.mark);
2269
+ var _ruleEncoding_y_datum;
2270
+ const yDatum = (_ruleEncoding_y_datum = (_ruleEncoding_y = ruleEncoding.y) === null || _ruleEncoding_y === void 0 ? void 0 : _ruleEncoding_y.datum) !== null && _ruleEncoding_y_datum !== void 0 ? _ruleEncoding_y_datum : (_ruleEncoding_y1 = ruleEncoding.y) === null || _ruleEncoding_y1 === void 0 ? void 0 : _ruleEncoding_y1.value;
2271
+ if (yDatum !== undefined) {
2272
+ var _textSpec_encoding_text, _textSpec_encoding, _textSpec_encoding_text1, _textSpec_encoding1;
2273
+ const ruleLegend = `Reference_${ruleIndex}`;
2274
+ const ruleColor = ruleMarkProps.color || '#d62728';
2275
+ if (!colorIndex.has(ruleLegend)) {
2276
+ colorIndex.set(ruleLegend, currentColorIndex++);
2277
+ }
2278
+ const lineOptions = {};
2279
+ if (ruleMarkProps.strokeDash) {
2280
+ lineOptions.strokeDasharray = ruleMarkProps.strokeDash.join(' ');
2281
+ }
2282
+ if (ruleMarkProps.strokeWidth) {
2283
+ lineOptions.strokeWidth = ruleMarkProps.strokeWidth;
2284
+ }
2285
+ // Look for companion text annotation at the same y-value
2286
+ const textSpec = unitSpecs.find((s, i)=>{
2287
+ var _s_encoding;
2288
+ var _s_encoding_y_datum;
2289
+ return getMarkType(s.mark) === 'text' && ((_s_encoding = s.encoding) === null || _s_encoding === void 0 ? void 0 : _s_encoding.y) && ((_s_encoding_y_datum = s.encoding.y.datum) !== null && _s_encoding_y_datum !== void 0 ? _s_encoding_y_datum : s.encoding.y.value) === yDatum;
2290
+ });
2291
+ const ruleText = textSpec ? String(((_textSpec_encoding = textSpec.encoding) === null || _textSpec_encoding === void 0 ? void 0 : (_textSpec_encoding_text = _textSpec_encoding.text) === null || _textSpec_encoding_text === void 0 ? void 0 : _textSpec_encoding_text.datum) || ((_textSpec_encoding1 = textSpec.encoding) === null || _textSpec_encoding1 === void 0 ? void 0 : (_textSpec_encoding_text1 = _textSpec_encoding1.text) === null || _textSpec_encoding_text1 === void 0 ? void 0 : _textSpec_encoding_text1.value) || yDatum) : String(yDatum);
2292
+ // Add the constant y-value line to every x-axis point
2293
+ Object.keys(mapXToDataPoints).forEach((xKey)=>{
2294
+ mapXToDataPoints[xKey].lineData.push({
2295
+ y: yDatum,
2296
+ legend: ruleText,
2297
+ color: ruleColor,
2298
+ ...Object.keys(lineOptions).length > 0 && {
2299
+ lineOptions
2300
+ },
2301
+ useSecondaryYScale: false
2302
+ });
2303
+ });
2304
+ }
2305
+ });
2306
+ const chartData = Object.values(mapXToDataPoints);
2307
+ const titles = getVegaLiteTitles(spec);
2308
+ // Check if we have secondary Y-axis data
2309
+ const hasSecondaryYAxis = chartData.some((point)=>{
2310
+ var _point_lineData;
2311
+ return (_point_lineData = point.lineData) === null || _point_lineData === void 0 ? void 0 : _point_lineData.some((line)=>line.useSecondaryYScale);
2312
+ });
2313
+ // Extract secondary Y-axis properties from line layers
2314
+ let secondaryYAxisProps = {};
2315
+ if (hasSecondaryYAxis && lineSpecs.length > 0) {
2316
+ var _lineEncoding_y;
2317
+ const lineSpec = lineSpecs[0];
2318
+ const lineEncoding = lineSpec.encoding || {};
2319
+ const lineYAxis = (_lineEncoding_y = lineEncoding.y) === null || _lineEncoding_y === void 0 ? void 0 : _lineEncoding_y.axis;
2320
+ if (lineYAxis === null || lineYAxis === void 0 ? void 0 : lineYAxis.title) {
2321
+ secondaryYAxisProps.secondaryYAxistitle = lineYAxis.title;
2322
+ }
2323
+ // Compute secondary Y scale domain from line data values
2324
+ const allLineYValues = [];
2325
+ chartData.forEach((point)=>{
2326
+ var _point_lineData;
2327
+ (_point_lineData = point.lineData) === null || _point_lineData === void 0 ? void 0 : _point_lineData.forEach((line)=>{
2328
+ if (line.useSecondaryYScale && typeof line.y === 'number') {
2329
+ allLineYValues.push(line.y);
2330
+ }
2331
+ });
2332
+ });
2333
+ if (allLineYValues.length > 0) {
2334
+ var _lineEncoding_y_scale, _lineEncoding_y1;
2335
+ // Use explicit domain from line encoding if available, otherwise compute from data
2336
+ const lineDomain = (_lineEncoding_y1 = lineEncoding.y) === null || _lineEncoding_y1 === void 0 ? void 0 : (_lineEncoding_y_scale = _lineEncoding_y1.scale) === null || _lineEncoding_y_scale === void 0 ? void 0 : _lineEncoding_y_scale.domain;
2337
+ var _d3Min;
2338
+ const secYMin = Array.isArray(lineDomain) ? lineDomain[0] : (_d3Min = (0, _d3array.min)(allLineYValues)) !== null && _d3Min !== void 0 ? _d3Min : 0;
2339
+ var _d3Max;
2340
+ const secYMax = Array.isArray(lineDomain) ? lineDomain[1] : (_d3Max = (0, _d3array.max)(allLineYValues)) !== null && _d3Max !== void 0 ? _d3Max : 0;
2341
+ secondaryYAxisProps.secondaryYScaleOptions = {
2342
+ yMinValue: secYMin,
2343
+ yMaxValue: secYMax
2344
+ };
2345
+ }
2346
+ }
2347
+ // Check for log scale on primary Y-axis
2348
+ const yAxisType = extractYAxisType(encoding);
2349
+ // Extract y-axis formatting and domain props
2350
+ const yAxisTickFormat = (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : (_encoding_y_axis = _encoding_y.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.format;
2351
+ const { yMinValue, yMaxValue } = extractYMinMax(encoding, dataValues);
2352
+ // Extract axis category ordering
2353
+ const categoryOrderProps = extractAxisCategoryOrderProps(encoding);
2354
+ var _spec_height, _encoding_color_legend_disable;
2355
+ return {
2356
+ data: chartData,
2357
+ chartTitle: titles.chartTitle,
2358
+ xAxisTitle: titles.xAxisTitle,
2359
+ yAxisTitle: titles.yAxisTitle,
2360
+ ...titles.titleStyles ? titles.titleStyles : {},
2361
+ width: spec.width,
2362
+ height: (_spec_height = spec.height) !== null && _spec_height !== void 0 ? _spec_height : DEFAULT_CHART_HEIGHT,
2363
+ hideLegend: (_encoding_color_legend_disable = (_encoding_color1 = encoding.color) === null || _encoding_color1 === void 0 ? void 0 : (_encoding_color_legend = _encoding_color1.legend) === null || _encoding_color_legend === void 0 ? void 0 : _encoding_color_legend.disable) !== null && _encoding_color_legend_disable !== void 0 ? _encoding_color_legend_disable : false,
2364
+ showYAxisLables: true,
2365
+ roundCorners: true,
2366
+ hideTickOverlap: true,
2367
+ barGapMax: 2,
2368
+ noOfCharsToTruncate: DEFAULT_TRUNCATE_CHARS,
2369
+ showYAxisLablesTooltip: true,
2370
+ wrapXAxisLables: typeof ((_chartData_ = chartData[0]) === null || _chartData_ === void 0 ? void 0 : _chartData_.xAxisPoint) === 'string',
2371
+ xAxis: {
2372
+ tickLayout: 'auto'
2373
+ },
2374
+ ...yAxisTickFormat && {
2375
+ yAxisTickFormat
2376
+ },
2377
+ ...yMinValue !== undefined && {
2378
+ yMinValue
2379
+ },
2380
+ ...yMaxValue !== undefined && {
2381
+ yMaxValue
2382
+ },
2383
+ ...yAxisType && {
2384
+ yScaleType: yAxisType
2385
+ },
2386
+ ...secondaryYAxisProps,
2387
+ ...categoryOrderProps
2388
+ };
2389
+ }
2390
+ function transformVegaLiteToGroupedVerticalBarChartProps(spec, colorMap, isDarkTheme) {
2391
+ var _encoding_y_axis, _encoding_y;
2392
+ // Initialize transformation context
2393
+ const { dataValues, encoding } = initializeTransformContext(spec);
2394
+ // Extract field names
2395
+ const { xField, yField, colorField } = extractEncodingFields(encoding);
2396
+ if (!xField || !yField || !colorField) {
2397
+ throw new Error('VegaLiteSchemaAdapter: x, y, and color encodings are required for grouped bar charts');
2398
+ }
2399
+ // Extract color configuration
2400
+ const { colorScheme, colorRange } = extractColorConfig(encoding);
2401
+ // Group data by x value (name), then by color (series)
2402
+ const groupedData = {};
2403
+ const colorIndex = new Map();
2404
+ let currentColorIndex = 0;
2405
+ dataValues.forEach((row)=>{
2406
+ const xValue = row[xField];
2407
+ const yValue = row[yField];
2408
+ const groupValue = row[colorField];
2409
+ if ((0, _chartutilities.isInvalidValue)(xValue) || (0, _chartutilities.isInvalidValue)(yValue) || typeof yValue !== 'number' || (0, _chartutilities.isInvalidValue)(groupValue)) {
2410
+ return;
2411
+ }
2412
+ const xKey = String(xValue);
2413
+ const legend = String(groupValue);
2414
+ if (!groupedData[xKey]) {
2415
+ groupedData[xKey] = {};
2416
+ }
2417
+ groupedData[xKey][legend] = yValue;
2418
+ if (!colorIndex.has(legend)) {
2419
+ colorIndex.set(legend, currentColorIndex++);
2420
+ }
2421
+ });
2422
+ // Convert to GroupedVerticalBarChartData format
2423
+ const chartData = Object.keys(groupedData).map((name)=>{
2424
+ const series = Object.keys(groupedData[name]).map((legend)=>({
2425
+ key: legend,
2426
+ data: groupedData[name][legend],
2427
+ legend,
2428
+ color: resolveColor(legend, colorIndex.get(legend), undefined, undefined, colorMap, colorScheme, colorRange, isDarkTheme)
2429
+ }));
2430
+ return {
2431
+ name,
2432
+ series
2433
+ };
2434
+ });
2435
+ const titles = getVegaLiteTitles(spec);
2436
+ // Extract y-axis formatting and scale props
2437
+ const yAxisTickFormat = (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : (_encoding_y_axis = _encoding_y.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.format;
2438
+ const { yMinValue, yMaxValue } = extractYMinMax(encoding, dataValues);
2439
+ const yAxisType = extractYAxisType(encoding);
2440
+ return {
2441
+ data: chartData,
2442
+ chartTitle: titles.chartTitle,
2443
+ xAxisTitle: titles.xAxisTitle,
2444
+ yAxisTitle: titles.yAxisTitle,
2445
+ ...titles.titleStyles ? titles.titleStyles : {},
2446
+ ...yAxisTickFormat && {
2447
+ yAxisTickFormat
2448
+ },
2449
+ ...yMinValue !== undefined && {
2450
+ yMinValue
2451
+ },
2452
+ ...yMaxValue !== undefined && {
2453
+ yMaxValue
2454
+ },
2455
+ ...yAxisType && {
2456
+ yScaleType: yAxisType
2457
+ }
2458
+ };
2459
+ }
2460
+ function transformVegaLiteToHorizontalBarChartProps(spec, colorMap, isDarkTheme) {
2461
+ var _encoding_color, _encoding_color_legend, _encoding_color1;
2462
+ // Initialize transformation context
2463
+ const { dataValues, encoding, markProps } = initializeTransformContext(spec);
2464
+ // Extract field names and aggregates
2465
+ const { xField, yField, colorField, xAggregate, x2Field } = extractEncodingFields(encoding);
2466
+ // Check if this is an aggregate bar chart
2467
+ // Aggregate can be: count (no field needed) or sum/mean/etc (with field)
2468
+ const isAggregate = !!xAggregate;
2469
+ if (!yField && !isAggregate) {
2470
+ throw new Error('VegaLiteSchemaAdapter: y encoding is required for horizontal bar charts');
2471
+ }
2472
+ // For aggregate charts, compute aggregated data
2473
+ let aggregatedData;
2474
+ if (isAggregate && yField) {
2475
+ aggregatedData = computeAggregateData(dataValues, yField, xField, xAggregate);
2476
+ }
2477
+ const colorValue = (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.value;
2478
+ const barData = [];
2479
+ const colorIndex = new Map();
2480
+ let currentColorIndex = 0;
2481
+ if (aggregatedData) {
2482
+ // Use aggregated data
2483
+ aggregatedData.forEach(({ category, value })=>{
2484
+ const legend = String(category);
2485
+ if (!colorIndex.has(legend)) {
2486
+ colorIndex.set(legend, currentColorIndex++);
2487
+ }
2488
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, undefined, undefined, isDarkTheme);
2489
+ barData.push({
2490
+ x: value,
2491
+ y: category,
2492
+ legend,
2493
+ color
2494
+ });
2495
+ });
2496
+ } else if (x2Field && xField && yField) {
2497
+ var _encoding_x;
2498
+ // Gantt chart: bar mark with x/x2 temporal range encoding
2499
+ const isXTemporal = ((_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.type) === 'temporal';
2500
+ dataValues.forEach((row)=>{
2501
+ const startVal = row[xField];
2502
+ const endVal = row[x2Field];
2503
+ const yValue = row[yField];
2504
+ if (startVal === undefined || endVal === undefined || yValue === undefined) {
2505
+ return;
2506
+ }
2507
+ let xNumeric;
2508
+ if (isXTemporal) {
2509
+ const startDate = new Date(startVal);
2510
+ const endDate = new Date(endVal);
2511
+ if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
2512
+ return;
2513
+ }
2514
+ xNumeric = Math.round((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
2515
+ } else {
2516
+ xNumeric = Number(endVal) - Number(startVal);
2517
+ if (isNaN(xNumeric)) {
2518
+ return;
2519
+ }
2520
+ }
2521
+ const legend = colorField && row[colorField] !== undefined ? String(row[colorField]) : String(yValue);
2522
+ if (!colorIndex.has(legend)) {
2523
+ colorIndex.set(legend, currentColorIndex++);
2524
+ }
2525
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, undefined, undefined, isDarkTheme);
2526
+ barData.push({
2527
+ x: xNumeric,
2528
+ y: yValue,
2529
+ legend,
2530
+ color
2531
+ });
2532
+ });
2533
+ } else if (xField && yField) {
2534
+ // Use raw data
2535
+ dataValues.forEach((row)=>{
2536
+ const xValue = row[xField];
2537
+ const yValue = row[yField];
2538
+ if ((0, _chartutilities.isInvalidValue)(xValue) || (0, _chartutilities.isInvalidValue)(yValue) || typeof xValue !== 'number') {
2539
+ return;
2540
+ }
2541
+ // When no color field, use single legend to avoid tooltip duplication with y-axis labels
2542
+ const legend = colorField && row[colorField] !== undefined ? String(row[colorField]) : !colorField ? 'Bar' : String(yValue);
2543
+ if (!colorIndex.has(legend)) {
2544
+ colorIndex.set(legend, currentColorIndex++);
2545
+ }
2546
+ const color = resolveColor(legend, colorIndex.get(legend), colorValue, markProps.color, colorMap, undefined, undefined, isDarkTheme);
2547
+ barData.push({
2548
+ x: xValue,
2549
+ y: yValue,
2550
+ legend,
2551
+ color
2552
+ });
2553
+ });
2554
+ }
2555
+ const titles = getVegaLiteTitles(spec);
2556
+ const annotations = extractAnnotations(spec);
2557
+ const tickConfig = extractTickConfig(spec);
2558
+ var _encoding_color_legend_disable;
2559
+ const result = {
2560
+ data: barData,
2561
+ chartTitle: titles.chartTitle,
2562
+ xAxisTitle: titles.xAxisTitle,
2563
+ yAxisTitle: titles.yAxisTitle,
2564
+ ...titles.titleStyles ? titles.titleStyles : {},
2565
+ // Hide legend for single-series horizontal bars (no color encoding)
2566
+ hideLegend: !colorField ? true : (_encoding_color_legend_disable = (_encoding_color1 = encoding.color) === null || _encoding_color1 === void 0 ? void 0 : (_encoding_color_legend = _encoding_color1.legend) === null || _encoding_color_legend === void 0 ? void 0 : _encoding_color_legend.disable) !== null && _encoding_color_legend_disable !== void 0 ? _encoding_color_legend_disable : false
2567
+ };
2568
+ if (annotations.length > 0) {
2569
+ result.annotations = annotations;
2570
+ }
2571
+ if (tickConfig.tickValues) {
2572
+ result.tickValues = tickConfig.tickValues;
2573
+ }
2574
+ if (tickConfig.xAxisTickCount) {
2575
+ result.xAxisTickCount = tickConfig.xAxisTickCount;
2576
+ }
2577
+ if (tickConfig.yAxisTickCount) {
2578
+ result.yAxisTickCount = tickConfig.yAxisTickCount;
2579
+ }
2580
+ return result;
2581
+ }
2582
+ function transformVegaLiteToAreaChartProps(spec, colorMap, isDarkTheme) {
2583
+ var _encoding_color, _encoding_y;
2584
+ // Area charts use the same structure as line charts in Fluent Charts
2585
+ // The only difference is the component renders with filled areas
2586
+ const lineChartProps = transformVegaLiteToLineChartProps(spec, colorMap, isDarkTheme);
2587
+ // Determine stacking mode based on Vega-Lite spec
2588
+ const unitSpecs = normalizeSpec(spec);
2589
+ // Use findPrimaryLineSpec to skip auxiliary layers (like rect for color fill bars)
2590
+ const primarySpec = findPrimaryLineSpec(unitSpecs);
2591
+ const encoding = (primarySpec === null || primarySpec === void 0 ? void 0 : primarySpec.encoding) || {};
2592
+ // Check if stacking is enabled
2593
+ // In Vega-Lite, area charts stack by default when color encoding is present
2594
+ // stack can be explicitly set to null to disable stacking
2595
+ const hasColorEncoding = !!((_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.field);
2596
+ const stackConfig = (_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.stack;
2597
+ const isStacked = stackConfig !== null && (stackConfig === 'zero' || hasColorEncoding);
2598
+ // Set mode: 'tozeroy' for single series, 'tonexty' for stacked
2599
+ const mode = isStacked ? 'tonexty' : 'tozeroy';
2600
+ return {
2601
+ ...lineChartProps,
2602
+ mode
2603
+ };
2604
+ }
2605
+ function transformVegaLiteToScatterChartProps(spec, colorMap, isDarkTheme) {
2606
+ var _encoding_x, _encoding_y, _encoding_y1, _encoding_y2, _encoding_y_axis, _encoding_y3, _encoding_color_legend, _encoding_color;
2607
+ // Initialize transformation context
2608
+ const { dataValues, encoding, markProps } = initializeTransformContext(spec);
2609
+ // Extract field names
2610
+ const { xField, yField, colorField, sizeField } = extractEncodingFields(encoding);
2611
+ if (!xField || !yField) {
2612
+ throw new Error('VegaLiteSchemaAdapter: Both x and y encodings are required for scatter charts');
2613
+ }
2614
+ const isXTemporal = ((_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.type) === 'temporal';
2615
+ const isYTemporal = ((_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.type) === 'temporal';
2616
+ // Check if y-values are strings (nominal/ordinal) and build ordinal mapping
2617
+ const yIsNominal = ((_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.type) === 'nominal' || ((_encoding_y2 = encoding.y) === null || _encoding_y2 === void 0 ? void 0 : _encoding_y2.type) === 'ordinal';
2618
+ const yOrdinalMap = new Map();
2619
+ const yOrdinalLabels = [];
2620
+ if (yIsNominal) {
2621
+ // Collect unique y-values in order
2622
+ dataValues.forEach((row)=>{
2623
+ const yVal = row[yField];
2624
+ if (yVal !== undefined) {
2625
+ const key = String(yVal);
2626
+ if (!yOrdinalMap.has(key)) {
2627
+ yOrdinalMap.set(key, yOrdinalMap.size);
2628
+ yOrdinalLabels.push(key);
2629
+ }
2630
+ }
2631
+ });
2632
+ }
2633
+ // Group data by series (color encoding)
2634
+ const groupedData = {};
2635
+ dataValues.forEach((row)=>{
2636
+ const seriesName = colorField && row[colorField] !== undefined ? String(row[colorField]) : 'default';
2637
+ if (!groupedData[seriesName]) {
2638
+ groupedData[seriesName] = [];
2639
+ }
2640
+ groupedData[seriesName].push(row);
2641
+ });
2642
+ const seriesNames = Object.keys(groupedData);
2643
+ const colorIndex = new Map();
2644
+ let currentColorIndex = 0;
2645
+ const chartData = seriesNames.map((seriesName, index)=>{
2646
+ var _encoding_color_scale, _encoding_color;
2647
+ if (!colorIndex.has(seriesName)) {
2648
+ colorIndex.set(seriesName, currentColorIndex++);
2649
+ }
2650
+ const seriesData = groupedData[seriesName];
2651
+ const points = seriesData.map((row)=>{
2652
+ const xValue = parseValue(row[xField], isXTemporal);
2653
+ const yValue = parseValue(row[yField], isYTemporal);
2654
+ const markerSize = sizeField && row[sizeField] !== undefined ? Number(row[sizeField]) : undefined;
2655
+ // Map nominal y-values to numeric indices
2656
+ let numericY;
2657
+ if (yIsNominal && typeof yValue === 'string') {
2658
+ var _yOrdinalMap_get;
2659
+ numericY = (_yOrdinalMap_get = yOrdinalMap.get(yValue)) !== null && _yOrdinalMap_get !== void 0 ? _yOrdinalMap_get : 0;
2660
+ } else {
2661
+ numericY = typeof yValue === 'number' ? yValue : 0;
2662
+ }
2663
+ return {
2664
+ x: typeof xValue === 'number' || xValue instanceof Date ? xValue : String(xValue),
2665
+ y: numericY,
2666
+ ...markerSize !== undefined && {
2667
+ markerSize
2668
+ }
2669
+ };
2670
+ });
2671
+ // Get color for this series
2672
+ const colorValue = colorField && ((_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : (_encoding_color_scale = _encoding_color.scale) === null || _encoding_color_scale === void 0 ? void 0 : _encoding_color_scale.range) && Array.isArray(encoding.color.scale.range) ? encoding.color.scale.range[index] : markProps.color;
2673
+ const color = typeof colorValue === 'string' ? colorValue : resolveColor(seriesName, colorIndex.get(seriesName), undefined, undefined, colorMap, undefined, undefined, isDarkTheme);
2674
+ return {
2675
+ legend: seriesName,
2676
+ data: points,
2677
+ color,
2678
+ legendShape: 'circle'
2679
+ };
2680
+ });
2681
+ const titles = getVegaLiteTitles(spec);
2682
+ const annotations = extractAnnotations(spec);
2683
+ const tickConfig = extractTickConfig(spec);
2684
+ // Check for log scale on Y-axis
2685
+ const yAxisType = extractYAxisType(encoding);
2686
+ // Extract y-axis formatting and domain props
2687
+ const yAxisTickFormat = (_encoding_y3 = encoding.y) === null || _encoding_y3 === void 0 ? void 0 : (_encoding_y_axis = _encoding_y3.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.format;
2688
+ const { yMinValue, yMaxValue } = extractYMinMax(encoding, dataValues);
2689
+ // Extract axis category ordering
2690
+ const categoryOrderProps = extractAxisCategoryOrderProps(encoding);
2691
+ var _encoding_color_legend_disable;
2692
+ const result = {
2693
+ data: {
2694
+ chartTitle: titles.chartTitle,
2695
+ scatterChartData: chartData
2696
+ },
2697
+ xAxisTitle: titles.xAxisTitle,
2698
+ yAxisTitle: titles.yAxisTitle,
2699
+ ...titles.titleStyles ? titles.titleStyles : {},
2700
+ ...yAxisTickFormat && {
2701
+ yAxisTickFormat
2702
+ },
2703
+ ...yMinValue !== undefined && {
2704
+ yMinValue
2705
+ },
2706
+ ...yMaxValue !== undefined && {
2707
+ yMaxValue
2708
+ },
2709
+ ...yAxisType && {
2710
+ yScaleType: yAxisType
2711
+ },
2712
+ // For nominal y-axis, provide tick values and labels
2713
+ ...yIsNominal && yOrdinalLabels.length > 0 && {
2714
+ yAxisTickValues: Array.from({
2715
+ length: yOrdinalLabels.length
2716
+ }, (_, i)=>i),
2717
+ yAxisTickFormat: (val)=>{
2718
+ var _yOrdinalLabels_val;
2719
+ return (_yOrdinalLabels_val = yOrdinalLabels[val]) !== null && _yOrdinalLabels_val !== void 0 ? _yOrdinalLabels_val : String(val);
2720
+ },
2721
+ yMinValue: -0.5,
2722
+ yMaxValue: yOrdinalLabels.length - 0.5
2723
+ },
2724
+ ...categoryOrderProps,
2725
+ hideLegend: (_encoding_color_legend_disable = (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : (_encoding_color_legend = _encoding_color.legend) === null || _encoding_color_legend === void 0 ? void 0 : _encoding_color_legend.disable) !== null && _encoding_color_legend_disable !== void 0 ? _encoding_color_legend_disable : false
2726
+ };
2727
+ if (annotations.length > 0) {
2728
+ result.annotations = annotations;
2729
+ }
2730
+ if (tickConfig.tickValues) {
2731
+ result.tickValues = tickConfig.tickValues;
2732
+ }
2733
+ if (tickConfig.xAxisTickCount) {
2734
+ result.xAxisTickCount = tickConfig.xAxisTickCount;
2735
+ }
2736
+ if (tickConfig.yAxisTickCount) {
2737
+ result.yAxisTickCount = tickConfig.yAxisTickCount;
2738
+ }
2739
+ return result;
2740
+ }
2741
+ function transformVegaLiteToDonutChartProps(spec, colorMap, isDarkTheme) {
2742
+ // Initialize transformation context
2743
+ const { dataValues, encoding, primarySpec } = initializeTransformContext(spec);
2744
+ // Extract field names
2745
+ const { thetaField, colorField } = extractEncodingFields(encoding);
2746
+ if (!thetaField) {
2747
+ throw new Error('VegaLiteSchemaAdapter: Theta encoding is required for donut charts');
2748
+ }
2749
+ // Extract color configuration
2750
+ const { colorScheme, colorRange } = extractColorConfig(encoding);
2751
+ // Extract innerRadius from mark properties if available
2752
+ const mark = primarySpec.mark;
2753
+ const innerRadius = typeof mark === 'object' && (mark === null || mark === void 0 ? void 0 : mark.innerRadius) !== undefined ? mark.innerRadius : 0;
2754
+ const chartData = [];
2755
+ const colorIndex = new Map();
2756
+ let currentColorIndex = 0;
2757
+ dataValues.forEach((row)=>{
2758
+ const value = row[thetaField];
2759
+ const legend = colorField && row[colorField] !== undefined ? String(row[colorField]) : String(value);
2760
+ if (value === undefined || typeof value !== 'number') {
2761
+ return;
2762
+ }
2763
+ if (!colorIndex.has(legend)) {
2764
+ colorIndex.set(legend, currentColorIndex++);
2765
+ }
2766
+ chartData.push({
2767
+ legend,
2768
+ data: value,
2769
+ color: resolveColor(legend, colorIndex.get(legend), undefined, undefined, colorMap, colorScheme, colorRange, isDarkTheme)
2770
+ });
2771
+ });
2772
+ const titles = getVegaLiteTitles(spec);
2773
+ return {
2774
+ data: {
2775
+ chartTitle: titles.chartTitle,
2776
+ chartData
2777
+ },
2778
+ innerRadius,
2779
+ width: typeof spec.width === 'number' ? spec.width : undefined,
2780
+ height: typeof spec.height === 'number' ? spec.height : undefined,
2781
+ ...titles.titleStyles ? titles.titleStyles : {}
2782
+ };
2783
+ }
2784
+ function transformVegaLiteToHeatMapChartProps(spec, colorMap, isDarkTheme) {
2785
+ var _encoding_color, _encoding_color1, _encoding_x, _encoding_x1, _encoding_color_scale, _encoding_color2, _encoding_color_scale1, _encoding_color3;
2786
+ // Initialize transformation context
2787
+ const { dataValues, encoding } = initializeTransformContext(spec);
2788
+ // Extract field names
2789
+ const { xField, yField, colorField } = extractEncodingFields(encoding);
2790
+ if (!xField || !yField || !colorField) {
2791
+ throw new Error('VegaLiteSchemaAdapter: x, y, and color encodings are required for heatmap charts');
2792
+ }
2793
+ const heatmapDataPoints = [];
2794
+ let minValue = Number.POSITIVE_INFINITY;
2795
+ let maxValue = Number.NEGATIVE_INFINITY;
2796
+ // Check if color values are nominal (strings) rather than quantitative (numbers)
2797
+ const isNominalColor = ((_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.type) === 'nominal' || ((_encoding_color1 = encoding.color) === null || _encoding_color1 === void 0 ? void 0 : _encoding_color1.type) === 'ordinal' || dataValues.some((row)=>row[colorField] !== undefined && typeof row[colorField] !== 'number');
2798
+ const nominalColorMap = new Map();
2799
+ dataValues.forEach((row)=>{
2800
+ const xValue = row[xField];
2801
+ const yValue = row[yField];
2802
+ const colorValue = row[colorField];
2803
+ if ((0, _chartutilities.isInvalidValue)(xValue) || (0, _chartutilities.isInvalidValue)(yValue) || (0, _chartutilities.isInvalidValue)(colorValue)) {
2804
+ return;
2805
+ }
2806
+ let value;
2807
+ if (isNominalColor) {
2808
+ // Map nominal color values to sequential numeric indices
2809
+ const key = String(colorValue);
2810
+ if (!nominalColorMap.has(key)) {
2811
+ nominalColorMap.set(key, nominalColorMap.size);
2812
+ }
2813
+ value = nominalColorMap.get(key);
2814
+ } else {
2815
+ value = typeof colorValue === 'number' ? colorValue : 0;
2816
+ }
2817
+ minValue = Math.min(minValue, value);
2818
+ maxValue = Math.max(maxValue, value);
2819
+ heatmapDataPoints.push({
2820
+ x: xValue,
2821
+ y: yValue,
2822
+ value,
2823
+ rectText: isNominalColor ? String(colorValue) : value
2824
+ });
2825
+ });
2826
+ // Validate that we have complete grid data
2827
+ if (heatmapDataPoints.length === 0) {
2828
+ throw new Error('VegaLiteSchemaAdapter: Heatmap requires data points with x, y, and color values');
2829
+ }
2830
+ // Extract unique x and y values and create complete grid
2831
+ const uniqueXValues = new Set(heatmapDataPoints.map((p)=>String(p.x)));
2832
+ const uniqueYValues = new Set(heatmapDataPoints.map((p)=>String(p.y)));
2833
+ // Build a map of existing data points for quick lookup
2834
+ const dataPointMap = new Map();
2835
+ const rectTextMap = new Map();
2836
+ heatmapDataPoints.forEach((point)=>{
2837
+ const key = `${String(point.x)}|${String(point.y)}`;
2838
+ dataPointMap.set(key, point.value);
2839
+ var _point_rectText;
2840
+ rectTextMap.set(key, (_point_rectText = point.rectText) !== null && _point_rectText !== void 0 ? _point_rectText : point.value);
2841
+ });
2842
+ // Generate complete grid - fill missing cells with 0
2843
+ const completeGridDataPoints = [];
2844
+ let xValuesArray = Array.from(uniqueXValues);
2845
+ const yValuesArray = Array.from(uniqueYValues);
2846
+ // Sort x-values chronologically if they appear to be dates
2847
+ const isXTemporal = ((_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.type) === 'temporal' || ((_encoding_x1 = encoding.x) === null || _encoding_x1 === void 0 ? void 0 : _encoding_x1.type) === 'ordinal';
2848
+ if (isXTemporal) {
2849
+ const firstX = xValuesArray[0];
2850
+ const parsedDate = new Date(firstX);
2851
+ if (!isNaN(parsedDate.getTime())) {
2852
+ // Values are parseable as dates — sort chronologically
2853
+ xValuesArray = xValuesArray.sort((a, b)=>new Date(a).getTime() - new Date(b).getTime());
2854
+ }
2855
+ }
2856
+ yValuesArray.forEach((yVal)=>{
2857
+ xValuesArray.forEach((xVal)=>{
2858
+ const key = `${xVal}|${yVal}`;
2859
+ var _dataPointMap_get;
2860
+ const value = (_dataPointMap_get = dataPointMap.get(key)) !== null && _dataPointMap_get !== void 0 ? _dataPointMap_get : 0; // Use 0 for missing cells
2861
+ // Update min/max to include filled values
2862
+ if (value !== 0 || dataPointMap.has(key)) {
2863
+ minValue = Math.min(minValue, value);
2864
+ maxValue = Math.max(maxValue, value);
2865
+ }
2866
+ var _rectTextMap_get;
2867
+ completeGridDataPoints.push({
2868
+ x: xVal,
2869
+ y: yVal,
2870
+ value,
2871
+ rectText: (_rectTextMap_get = rectTextMap.get(key)) !== null && _rectTextMap_get !== void 0 ? _rectTextMap_get : value
2872
+ });
2873
+ });
2874
+ });
2875
+ const heatmapData = {
2876
+ legend: '',
2877
+ data: completeGridDataPoints,
2878
+ value: 0
2879
+ };
2880
+ const titles = getVegaLiteTitles(spec);
2881
+ // Create color scale domain and range
2882
+ let domainValues = [];
2883
+ let rangeValues = [];
2884
+ // Check for named color scheme or custom range from encoding
2885
+ const colorScheme = (_encoding_color2 = encoding.color) === null || _encoding_color2 === void 0 ? void 0 : (_encoding_color_scale = _encoding_color2.scale) === null || _encoding_color_scale === void 0 ? void 0 : _encoding_color_scale.scheme;
2886
+ const customRange = (_encoding_color3 = encoding.color) === null || _encoding_color3 === void 0 ? void 0 : (_encoding_color_scale1 = _encoding_color3.scale) === null || _encoding_color_scale1 === void 0 ? void 0 : _encoding_color_scale1.range;
2887
+ if (isNominalColor && nominalColorMap.size > 0) {
2888
+ // For nominal colors, use categorical color scale
2889
+ const numCategories = nominalColorMap.size;
2890
+ domainValues = Array.from({
2891
+ length: numCategories
2892
+ }, (_, i)=>i);
2893
+ if (customRange && customRange.length >= numCategories) {
2894
+ rangeValues = customRange.slice(0, numCategories);
2895
+ } else {
2896
+ // Use distinct categorical colors for each category
2897
+ for(let i = 0; i < numCategories; i++){
2898
+ rangeValues.push((0, _VegaLiteColorAdapter.getVegaColor)(i, colorScheme, customRange, isDarkTheme !== null && isDarkTheme !== void 0 ? isDarkTheme : false));
2899
+ }
2900
+ }
2901
+ } else {
2902
+ // Quantitative color scale
2903
+ const steps = 5;
2904
+ for(let i = 0; i < steps; i++){
2905
+ const t = i / (steps - 1);
2906
+ domainValues.push(minValue + (maxValue - minValue) * t);
2907
+ }
2908
+ if (customRange && customRange.length > 0) {
2909
+ rangeValues = customRange.length >= steps ? customRange.slice(0, steps) : customRange;
2910
+ } else if (colorScheme) {
2911
+ const schemeColors = (0, _VegaLiteColorAdapter.getSequentialSchemeColors)(colorScheme, steps);
2912
+ if (schemeColors) {
2913
+ var _encoding_color4, _encoding_color_scale2, _encoding_color5;
2914
+ const isReversed = ((_encoding_color4 = encoding.color) === null || _encoding_color4 === void 0 ? void 0 : _encoding_color4.sort) === 'descending' || ((_encoding_color5 = encoding.color) === null || _encoding_color5 === void 0 ? void 0 : (_encoding_color_scale2 = _encoding_color5.scale) === null || _encoding_color_scale2 === void 0 ? void 0 : _encoding_color_scale2.reverse) === true;
2915
+ rangeValues = isReversed ? schemeColors.reverse() : schemeColors;
2916
+ }
2917
+ }
2918
+ // Fall back to default blue-to-red gradient if no scheme matched
2919
+ if (rangeValues.length === 0) {
2920
+ for(let i = 0; i < steps; i++){
2921
+ const t = i / (steps - 1);
2922
+ if (isDarkTheme) {
2923
+ const r = Math.round(0 + 255 * t);
2924
+ const g = Math.round(100 + (165 - 100) * t);
2925
+ const b = Math.round(255 - 255 * t);
2926
+ rangeValues.push(`rgb(${r}, ${g}, ${b})`);
2927
+ } else {
2928
+ const r = Math.round(0 + 255 * t);
2929
+ const g = Math.round(150 - 150 * t);
2930
+ const b = Math.round(255 - 255 * t);
2931
+ rangeValues.push(`rgb(${r}, ${g}, ${b})`);
2932
+ }
2933
+ }
2934
+ }
2935
+ }
2936
+ var _spec_height;
2937
+ return {
2938
+ chartTitle: titles.chartTitle,
2939
+ data: [
2940
+ heatmapData
2941
+ ],
2942
+ domainValuesForColorScale: domainValues,
2943
+ rangeValuesForColorScale: rangeValues,
2944
+ xAxisTitle: titles.xAxisTitle,
2945
+ yAxisTitle: titles.yAxisTitle,
2946
+ ...titles.titleStyles ? titles.titleStyles : {},
2947
+ width: spec.width,
2948
+ height: (_spec_height = spec.height) !== null && _spec_height !== void 0 ? _spec_height : DEFAULT_CHART_HEIGHT,
2949
+ hideLegend: true,
2950
+ showYAxisLables: true,
2951
+ sortOrder: 'none',
2952
+ hideTickOverlap: true,
2953
+ noOfCharsToTruncate: xValuesArray.length > 20 ? 6 : xValuesArray.length > 10 ? 10 : DEFAULT_TRUNCATE_CHARS,
2954
+ showYAxisLablesTooltip: true,
2955
+ wrapXAxisLables: true
2956
+ };
2957
+ }
2958
+ /**
2959
+ * Helper function to get bin center for display
2960
+ */ function getBinCenter(bin) {
2961
+ return (bin.x0 + bin.x1) / 2;
2962
+ }
2963
+ /**
2964
+ * Helper function to calculate histogram aggregation function
2965
+ *
2966
+ * @param aggregate - Aggregation type (count, sum, mean, min, max)
2967
+ * @param bin - Binned data values
2968
+ * @returns Aggregated value
2969
+ */ function calculateHistogramAggregate(aggregate, bin) {
2970
+ switch(aggregate){
2971
+ case 'sum':
2972
+ return (0, _d3array.sum)(bin);
2973
+ case 'mean':
2974
+ case 'average':
2975
+ var _d3Mean;
2976
+ return bin.length === 0 ? 0 : (_d3Mean = (0, _d3array.mean)(bin)) !== null && _d3Mean !== void 0 ? _d3Mean : 0;
2977
+ case 'min':
2978
+ var _d3Min;
2979
+ return (_d3Min = (0, _d3array.min)(bin)) !== null && _d3Min !== void 0 ? _d3Min : 0;
2980
+ case 'max':
2981
+ var _d3Max;
2982
+ return (_d3Max = (0, _d3array.max)(bin)) !== null && _d3Max !== void 0 ? _d3Max : 0;
2983
+ case 'count':
2984
+ default:
2985
+ return bin.length;
2986
+ }
2987
+ }
2988
+ function transformVegaLiteToHistogramProps(spec, colorMap, isDarkTheme) {
2989
+ var _encoding_y, _encoding_x, _encoding_color, _dataValues_, _encoding_y1, _encoding_y_axis, _encoding_y2;
2990
+ // Initialize transformation context
2991
+ const { dataValues, encoding } = initializeTransformContext(spec);
2992
+ // Extract field names
2993
+ const { xField } = extractEncodingFields(encoding);
2994
+ const yAggregate = ((_encoding_y = encoding.y) === null || _encoding_y === void 0 ? void 0 : _encoding_y.aggregate) || 'count';
2995
+ const binConfig = (_encoding_x = encoding.x) === null || _encoding_x === void 0 ? void 0 : _encoding_x.bin;
2996
+ if (!xField || !binConfig) {
2997
+ throw new Error('VegaLiteSchemaAdapter: Histogram requires x encoding with bin property');
2998
+ }
2999
+ // Validate data
3000
+ validateDataArray(dataValues, xField, 'Histogram');
3001
+ validateNoNestedArrays(dataValues, xField);
3002
+ // Extract numeric values from the field
3003
+ const allValues = dataValues.map((row)=>row[xField]).filter((val)=>!(0, _chartutilities.isInvalidValue)(val));
3004
+ const values = allValues.filter((val)=>typeof val === 'number');
3005
+ if (values.length === 0) {
3006
+ // Provide helpful error message based on actual data type
3007
+ const sampleValue = allValues[0];
3008
+ const actualType = typeof sampleValue;
3009
+ let suggestion = '';
3010
+ if (actualType === 'string') {
3011
+ // Check if strings contain numbers
3012
+ const hasEmbeddedNumbers = allValues.some((val)=>typeof val === 'string' && /\d/.test(val));
3013
+ if (hasEmbeddedNumbers) {
3014
+ suggestion = ' The data contains strings with embedded numbers (e.g., "40 salads"). ' + 'Consider extracting the numeric values first, or change the encoding type to "nominal" or "ordinal" for a categorical bar chart.';
3015
+ } else {
3016
+ suggestion = ` The data contains categorical strings (e.g., "${sampleValue}"). ` + 'Change the x encoding type to "nominal" or "ordinal" for a categorical bar chart, ' + 'or remove bin: true to create a simple bar chart.';
3017
+ }
3018
+ } else if (actualType === 'undefined') {
3019
+ suggestion = ' The field may not exist in the data.';
3020
+ }
3021
+ throw new Error(`VegaLiteSchemaAdapter: No numeric values found for histogram binning on field "${xField}". ` + `Found ${actualType} values instead.${suggestion}`);
3022
+ }
3023
+ // Create bins using d3
3024
+ const [minVal, maxVal] = (0, _d3array.extent)(values);
3025
+ const binGenerator = (0, _d3array.bin)().domain([
3026
+ minVal,
3027
+ maxVal
3028
+ ]);
3029
+ // Apply bin configuration
3030
+ if (typeof binConfig === 'object') {
3031
+ if (binConfig.maxbins) {
3032
+ binGenerator.thresholds(binConfig.maxbins);
3033
+ }
3034
+ if (binConfig.extent) {
3035
+ binGenerator.domain(binConfig.extent);
3036
+ }
3037
+ }
3038
+ const bins = binGenerator(values);
3039
+ // Calculate histogram data points
3040
+ const legend = ((_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : _encoding_color.field) ? String((_dataValues_ = dataValues[0]) === null || _dataValues_ === void 0 ? void 0 : _dataValues_[encoding.color.field]) : 'Frequency';
3041
+ const color = resolveColor(legend, 0, undefined, undefined, colorMap, undefined, undefined, isDarkTheme);
3042
+ const yField = (_encoding_y1 = encoding.y) === null || _encoding_y1 === void 0 ? void 0 : _encoding_y1.field;
3043
+ const histogramData = bins.map((bin)=>{
3044
+ const x = getBinCenter(bin);
3045
+ let y;
3046
+ if (yAggregate !== 'count' && yField) {
3047
+ // For non-count aggregates, collect y-field values for rows whose x-value falls in this bin
3048
+ const yValues = dataValues.filter((row)=>{
3049
+ const xVal = Number(row[xField]);
3050
+ return !isNaN(xVal) && xVal >= bin.x0 && xVal < bin.x1;
3051
+ }).map((row)=>Number(row[yField])).filter((v)=>!isNaN(v));
3052
+ // Include the last bin's upper bound (x1 is inclusive for the last bin)
3053
+ if (bin === bins[bins.length - 1]) {
3054
+ const extraRows = dataValues.filter((row)=>Number(row[xField]) === bin.x1).map((row)=>Number(row[yField])).filter((v)=>!isNaN(v));
3055
+ yValues.push(...extraRows);
3056
+ }
3057
+ y = calculateHistogramAggregate(yAggregate, yValues);
3058
+ } else {
3059
+ y = calculateHistogramAggregate(yAggregate, bin);
3060
+ }
3061
+ const xAxisCalloutData = `[${bin.x0} - ${bin.x1})`;
3062
+ return {
3063
+ x,
3064
+ y,
3065
+ legend,
3066
+ color,
3067
+ xAxisCalloutData
3068
+ };
3069
+ });
3070
+ const titles = getVegaLiteTitles(spec);
3071
+ const annotations = extractAnnotations(spec);
3072
+ const yAxisTickFormat = (_encoding_y2 = encoding.y) === null || _encoding_y2 === void 0 ? void 0 : (_encoding_y_axis = _encoding_y2.axis) === null || _encoding_y_axis === void 0 ? void 0 : _encoding_y_axis.format;
3073
+ return {
3074
+ data: histogramData,
3075
+ chartTitle: titles.chartTitle,
3076
+ xAxisTitle: titles.xAxisTitle || xField,
3077
+ yAxisTitle: titles.yAxisTitle || yAggregate,
3078
+ ...titles.titleStyles ? titles.titleStyles : {},
3079
+ roundCorners: true,
3080
+ hideTickOverlap: true,
3081
+ maxBarWidth: DEFAULT_MAX_BAR_WIDTH,
3082
+ ...annotations.length > 0 && {
3083
+ annotations
3084
+ },
3085
+ ...yAxisTickFormat && {
3086
+ yAxisTickFormat
3087
+ },
3088
+ mode: 'histogram'
3089
+ };
3090
+ }
3091
+ function transformVegaLiteToPolarChartProps(spec, colorMap, isDarkTheme) {
3092
+ var _encoding_theta, _encoding_color_legend, _encoding_color;
3093
+ // Initialize transformation context
3094
+ const { dataValues, encoding, markProps, primarySpec } = initializeTransformContext(spec);
3095
+ // Extract field names
3096
+ const { thetaField, radiusField, colorField } = extractEncodingFields(encoding);
3097
+ // Validate polar encodings
3098
+ if (!thetaField || !radiusField) {
3099
+ throw new Error('VegaLiteSchemaAdapter: Both theta and radius encodings are required for polar charts');
3100
+ }
3101
+ validateDataArray(dataValues, thetaField, 'PolarChart');
3102
+ validateDataArray(dataValues, radiusField, 'PolarChart');
3103
+ // Determine mark type for polar chart series type
3104
+ const mark = primarySpec.mark;
3105
+ const markType = typeof mark === 'string' ? mark : mark === null || mark === void 0 ? void 0 : mark.type;
3106
+ // Arc marks with theta+radius should be treated as area polar (radial/rose charts)
3107
+ const isAreaMark = markType === 'area' || markType === 'arc';
3108
+ const isLineMark = markType === 'line';
3109
+ // Extract color configuration
3110
+ const { colorScheme, colorRange } = extractColorConfig(encoding);
3111
+ // Group data by series (color field)
3112
+ const seriesMap = new Map();
3113
+ const colorIndex = new Map();
3114
+ let currentColorIndex = 0;
3115
+ dataValues.forEach((row)=>{
3116
+ const thetaValue = row[thetaField];
3117
+ const radiusValue = row[radiusField];
3118
+ // Skip invalid values
3119
+ if ((0, _chartutilities.isInvalidValue)(thetaValue) || (0, _chartutilities.isInvalidValue)(radiusValue)) {
3120
+ return;
3121
+ }
3122
+ const seriesName = colorField && row[colorField] !== undefined ? String(row[colorField]) : 'default';
3123
+ if (!colorIndex.has(seriesName)) {
3124
+ colorIndex.set(seriesName, currentColorIndex++);
3125
+ }
3126
+ if (!seriesMap.has(seriesName)) {
3127
+ seriesMap.set(seriesName, []);
3128
+ }
3129
+ // Convert theta value - handle different types
3130
+ let theta;
3131
+ if (typeof thetaValue === 'number') {
3132
+ // Numeric theta - assume degrees
3133
+ theta = thetaValue;
3134
+ } else {
3135
+ // Categorical theta
3136
+ theta = String(thetaValue);
3137
+ }
3138
+ // Convert radius value
3139
+ const r = typeof radiusValue === 'number' ? radiusValue : Number(radiusValue);
3140
+ seriesMap.get(seriesName).push({
3141
+ theta,
3142
+ r
3143
+ });
3144
+ });
3145
+ // Convert series map to polar chart data array
3146
+ const polarData = [];
3147
+ seriesMap.forEach((dataPoints, seriesName)=>{
3148
+ const color = resolveColor(seriesName, colorIndex.get(seriesName), undefined, markProps.color, colorMap, colorScheme, colorRange, isDarkTheme);
3149
+ const curveOption = mapInterpolateToCurve(markProps.interpolate);
3150
+ // Build line options with curve, strokeDash, and strokeWidth
3151
+ const lineOptions = {};
3152
+ if (curveOption) {
3153
+ lineOptions.curve = curveOption;
3154
+ }
3155
+ if (markProps.strokeDash) {
3156
+ lineOptions.strokeDasharray = markProps.strokeDash.join(' ');
3157
+ }
3158
+ if (markProps.strokeWidth) {
3159
+ lineOptions.strokeWidth = markProps.strokeWidth;
3160
+ }
3161
+ if (isAreaMark) {
3162
+ const series = {
3163
+ type: 'areapolar',
3164
+ legend: seriesName,
3165
+ color,
3166
+ data: dataPoints,
3167
+ ...Object.keys(lineOptions).length > 0 && {
3168
+ lineOptions
3169
+ }
3170
+ };
3171
+ polarData.push(series);
3172
+ } else if (isLineMark) {
3173
+ const series = {
3174
+ type: 'linepolar',
3175
+ legend: seriesName,
3176
+ color,
3177
+ data: dataPoints,
3178
+ ...Object.keys(lineOptions).length > 0 && {
3179
+ lineOptions
3180
+ }
3181
+ };
3182
+ polarData.push(series);
3183
+ } else {
3184
+ // Default to scatter polar for point marks
3185
+ const series = {
3186
+ type: 'scatterpolar',
3187
+ legend: seriesName,
3188
+ color,
3189
+ data: dataPoints
3190
+ };
3191
+ polarData.push(series);
3192
+ }
3193
+ });
3194
+ // Extract chart titles
3195
+ const titles = getVegaLiteTitles(spec);
3196
+ // Build axis props from encoding
3197
+ const radialAxis = {};
3198
+ const angularAxis = {};
3199
+ // Determine angular axis category order if theta is categorical
3200
+ const thetaType = (_encoding_theta = encoding.theta) === null || _encoding_theta === void 0 ? void 0 : _encoding_theta.type;
3201
+ if (thetaType === 'nominal' || thetaType === 'ordinal') {
3202
+ // Get unique theta values in order for category order
3203
+ const thetaValues = Array.from(new Set(dataValues.map((row)=>String(row[thetaField]))));
3204
+ angularAxis.categoryOrder = thetaValues;
3205
+ }
3206
+ var _encoding_color_legend_disable;
3207
+ return {
3208
+ data: polarData,
3209
+ ...titles.chartTitle && {
3210
+ chartTitle: titles.chartTitle
3211
+ },
3212
+ ...titles.titleStyles ? titles.titleStyles : {},
3213
+ width: typeof spec.width === 'number' ? spec.width : undefined,
3214
+ height: typeof spec.height === 'number' ? spec.height : 400,
3215
+ hideLegend: (_encoding_color_legend_disable = (_encoding_color = encoding.color) === null || _encoding_color === void 0 ? void 0 : (_encoding_color_legend = _encoding_color.legend) === null || _encoding_color_legend === void 0 ? void 0 : _encoding_color_legend.disable) !== null && _encoding_color_legend_disable !== void 0 ? _encoding_color_legend_disable : false,
3216
+ radialAxis,
3217
+ angularAxis
3218
+ };
3219
+ }