@matthieumordrel/chart-studio 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +371 -0
  3. package/dist/core/chart-capabilities.d.ts +60 -0
  4. package/dist/core/chart-capabilities.d.ts.map +1 -0
  5. package/dist/core/chart-capabilities.js +55 -0
  6. package/dist/core/chart-capabilities.js.map +1 -0
  7. package/dist/core/colors.d.ts +25 -0
  8. package/dist/core/colors.d.ts.map +1 -0
  9. package/dist/core/colors.js +55 -0
  10. package/dist/core/colors.js.map +1 -0
  11. package/dist/core/config-utils.d.ts +43 -0
  12. package/dist/core/config-utils.d.ts.map +1 -0
  13. package/dist/core/config-utils.js +81 -0
  14. package/dist/core/config-utils.js.map +1 -0
  15. package/dist/core/date-utils.d.ts +29 -0
  16. package/dist/core/date-utils.d.ts.map +1 -0
  17. package/dist/core/date-utils.js +59 -0
  18. package/dist/core/date-utils.js.map +1 -0
  19. package/dist/core/define-chart-schema.d.ts +105 -0
  20. package/dist/core/define-chart-schema.d.ts.map +1 -0
  21. package/dist/core/define-chart-schema.js +45 -0
  22. package/dist/core/define-chart-schema.js.map +1 -0
  23. package/dist/core/formatting.d.ts +47 -0
  24. package/dist/core/formatting.d.ts.map +1 -0
  25. package/dist/core/formatting.js +397 -0
  26. package/dist/core/formatting.js.map +1 -0
  27. package/dist/core/index.d.ts +17 -0
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +13 -0
  30. package/dist/core/index.js.map +1 -0
  31. package/dist/core/infer-columns.d.ts +6 -0
  32. package/dist/core/infer-columns.d.ts.map +1 -0
  33. package/dist/core/infer-columns.js +513 -0
  34. package/dist/core/infer-columns.js.map +1 -0
  35. package/dist/core/metric-utils.d.ts +43 -0
  36. package/dist/core/metric-utils.d.ts.map +1 -0
  37. package/dist/core/metric-utils.js +142 -0
  38. package/dist/core/metric-utils.js.map +1 -0
  39. package/dist/core/pipeline-data-points.d.ts +23 -0
  40. package/dist/core/pipeline-data-points.d.ts.map +1 -0
  41. package/dist/core/pipeline-data-points.js +236 -0
  42. package/dist/core/pipeline-data-points.js.map +1 -0
  43. package/dist/core/pipeline-helpers.d.ts +38 -0
  44. package/dist/core/pipeline-helpers.d.ts.map +1 -0
  45. package/dist/core/pipeline-helpers.js +98 -0
  46. package/dist/core/pipeline-helpers.js.map +1 -0
  47. package/dist/core/pipeline.d.ts +70 -0
  48. package/dist/core/pipeline.d.ts.map +1 -0
  49. package/dist/core/pipeline.js +157 -0
  50. package/dist/core/pipeline.js.map +1 -0
  51. package/dist/core/types.d.ts +1109 -0
  52. package/dist/core/types.d.ts.map +1 -0
  53. package/dist/core/types.js +15 -0
  54. package/dist/core/types.js.map +1 -0
  55. package/dist/core/use-chart-options.d.ts +66 -0
  56. package/dist/core/use-chart-options.d.ts.map +1 -0
  57. package/dist/core/use-chart-options.js +5 -0
  58. package/dist/core/use-chart-options.js.map +1 -0
  59. package/dist/core/use-chart-resolvers.d.ts +14 -0
  60. package/dist/core/use-chart-resolvers.d.ts.map +1 -0
  61. package/dist/core/use-chart-resolvers.js +42 -0
  62. package/dist/core/use-chart-resolvers.js.map +1 -0
  63. package/dist/core/use-chart.d.ts +47 -0
  64. package/dist/core/use-chart.d.ts.map +1 -0
  65. package/dist/core/use-chart.js +266 -0
  66. package/dist/core/use-chart.js.map +1 -0
  67. package/dist/index.d.ts +36 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +36 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/ui/chart-axis-ticks.d.ts +35 -0
  72. package/dist/ui/chart-axis-ticks.d.ts.map +1 -0
  73. package/dist/ui/chart-axis-ticks.js +80 -0
  74. package/dist/ui/chart-axis-ticks.js.map +1 -0
  75. package/dist/ui/chart-canvas.d.ts +22 -0
  76. package/dist/ui/chart-canvas.d.ts.map +1 -0
  77. package/dist/ui/chart-canvas.js +338 -0
  78. package/dist/ui/chart-canvas.js.map +1 -0
  79. package/dist/ui/chart-context.d.ts +89 -0
  80. package/dist/ui/chart-context.d.ts.map +1 -0
  81. package/dist/ui/chart-context.js +129 -0
  82. package/dist/ui/chart-context.js.map +1 -0
  83. package/dist/ui/chart-date-range-badge.d.ts +14 -0
  84. package/dist/ui/chart-date-range-badge.d.ts.map +1 -0
  85. package/dist/ui/chart-date-range-badge.js +31 -0
  86. package/dist/ui/chart-date-range-badge.js.map +1 -0
  87. package/dist/ui/chart-date-range-panel.d.ts +25 -0
  88. package/dist/ui/chart-date-range-panel.d.ts.map +1 -0
  89. package/dist/ui/chart-date-range-panel.js +126 -0
  90. package/dist/ui/chart-date-range-panel.js.map +1 -0
  91. package/dist/ui/chart-date-range.d.ts +14 -0
  92. package/dist/ui/chart-date-range.d.ts.map +1 -0
  93. package/dist/ui/chart-date-range.js +38 -0
  94. package/dist/ui/chart-date-range.js.map +1 -0
  95. package/dist/ui/chart-debug.d.ts +10 -0
  96. package/dist/ui/chart-debug.d.ts.map +1 -0
  97. package/dist/ui/chart-debug.js +127 -0
  98. package/dist/ui/chart-debug.js.map +1 -0
  99. package/dist/ui/chart-dropdown.d.ts +35 -0
  100. package/dist/ui/chart-dropdown.d.ts.map +1 -0
  101. package/dist/ui/chart-dropdown.js +77 -0
  102. package/dist/ui/chart-dropdown.js.map +1 -0
  103. package/dist/ui/chart-filters-panel.d.ts +19 -0
  104. package/dist/ui/chart-filters-panel.d.ts.map +1 -0
  105. package/dist/ui/chart-filters-panel.js +47 -0
  106. package/dist/ui/chart-filters-panel.js.map +1 -0
  107. package/dist/ui/chart-filters.d.ts +12 -0
  108. package/dist/ui/chart-filters.d.ts.map +1 -0
  109. package/dist/ui/chart-filters.js +27 -0
  110. package/dist/ui/chart-filters.js.map +1 -0
  111. package/dist/ui/chart-group-by-selector.d.ts +8 -0
  112. package/dist/ui/chart-group-by-selector.d.ts.map +1 -0
  113. package/dist/ui/chart-group-by-selector.js +20 -0
  114. package/dist/ui/chart-group-by-selector.js.map +1 -0
  115. package/dist/ui/chart-metric-panel.d.ts +18 -0
  116. package/dist/ui/chart-metric-panel.d.ts.map +1 -0
  117. package/dist/ui/chart-metric-panel.js +119 -0
  118. package/dist/ui/chart-metric-panel.js.map +1 -0
  119. package/dist/ui/chart-metric-selector.d.ts +10 -0
  120. package/dist/ui/chart-metric-selector.d.ts.map +1 -0
  121. package/dist/ui/chart-metric-selector.js +28 -0
  122. package/dist/ui/chart-metric-selector.js.map +1 -0
  123. package/dist/ui/chart-select.d.ts +25 -0
  124. package/dist/ui/chart-select.d.ts.map +1 -0
  125. package/dist/ui/chart-select.js +36 -0
  126. package/dist/ui/chart-select.js.map +1 -0
  127. package/dist/ui/chart-source-switcher.d.ts +16 -0
  128. package/dist/ui/chart-source-switcher.d.ts.map +1 -0
  129. package/dist/ui/chart-source-switcher.js +32 -0
  130. package/dist/ui/chart-source-switcher.js.map +1 -0
  131. package/dist/ui/chart-time-bucket-selector.d.ts +9 -0
  132. package/dist/ui/chart-time-bucket-selector.d.ts.map +1 -0
  133. package/dist/ui/chart-time-bucket-selector.js +26 -0
  134. package/dist/ui/chart-time-bucket-selector.js.map +1 -0
  135. package/dist/ui/chart-toolbar-overflow.d.ts +29 -0
  136. package/dist/ui/chart-toolbar-overflow.d.ts.map +1 -0
  137. package/dist/ui/chart-toolbar-overflow.js +110 -0
  138. package/dist/ui/chart-toolbar-overflow.js.map +1 -0
  139. package/dist/ui/chart-toolbar.d.ts +45 -0
  140. package/dist/ui/chart-toolbar.d.ts.map +1 -0
  141. package/dist/ui/chart-toolbar.js +45 -0
  142. package/dist/ui/chart-toolbar.js.map +1 -0
  143. package/dist/ui/chart-type-selector.d.ts +8 -0
  144. package/dist/ui/chart-type-selector.d.ts.map +1 -0
  145. package/dist/ui/chart-type-selector.js +23 -0
  146. package/dist/ui/chart-type-selector.js.map +1 -0
  147. package/dist/ui/chart-x-axis-selector.d.ts +8 -0
  148. package/dist/ui/chart-x-axis-selector.d.ts.map +1 -0
  149. package/dist/ui/chart-x-axis-selector.js +15 -0
  150. package/dist/ui/chart-x-axis-selector.js.map +1 -0
  151. package/dist/ui/index.d.ts +25 -0
  152. package/dist/ui/index.d.ts.map +1 -0
  153. package/dist/ui/index.js +24 -0
  154. package/dist/ui/index.js.map +1 -0
  155. package/dist/ui/theme.css +62 -0
  156. package/dist/ui/toolbar-types.d.ts +43 -0
  157. package/dist/ui/toolbar-types.d.ts.map +1 -0
  158. package/dist/ui/toolbar-types.js +51 -0
  159. package/dist/ui/toolbar-types.js.map +1 -0
  160. package/package.json +76 -0
@@ -0,0 +1,513 @@
1
+ const MAX_SAMPLE_COUNT = 50;
2
+ const DATE_KEY_PATTERN = /(date|time|timestamp|created|updated|start|end|deadline|due|scheduled|posted|published|at)$/i;
3
+ const DATETIME_VALUE_PATTERN = /^\d{4}-\d{2}-\d{2}[t\s]\d{2}:\d{2}/i;
4
+ const DATE_VALUE_PATTERN = /^\d{4}-\d{2}(-\d{2})?(?:[t\s].+)?$/i;
5
+ /**
6
+ * Humanize an object key into a UI label.
7
+ */
8
+ function humanizeKey(key) {
9
+ return key
10
+ .replace(/[_-]+/g, ' ')
11
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
12
+ .trim()
13
+ .split(/\s+/)
14
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
15
+ .join(' ');
16
+ }
17
+ /**
18
+ * Return true when development warnings should be shown.
19
+ */
20
+ function shouldWarn() {
21
+ return typeof process !== 'undefined' ? process.env['NODE_ENV'] !== 'production' : true;
22
+ }
23
+ /**
24
+ * Emit a namespaced development warning.
25
+ */
26
+ function warn(message) {
27
+ if (!shouldWarn())
28
+ return;
29
+ console.warn(`[chart-studio] ${message}`);
30
+ }
31
+ /**
32
+ * Read a raw field value from an item.
33
+ */
34
+ function getFieldValue(item, key) {
35
+ return item[key];
36
+ }
37
+ /**
38
+ * Create an accessor that returns the raw field value.
39
+ */
40
+ function createAccessor(key) {
41
+ return (item) => getFieldValue(item, key);
42
+ }
43
+ /**
44
+ * Treat one runtime string key as an inferable top-level field key.
45
+ *
46
+ * `collectFieldKeys()` only emits keys from the raw data objects and from the
47
+ * raw-field section of `schema.columns`, so this cast is the narrow boundary between runtime
48
+ * string discovery and the strongly typed inference pipeline.
49
+ */
50
+ function toInferableFieldKey(key) {
51
+ return key;
52
+ }
53
+ /**
54
+ * Adapt a strongly typed field formatter to the looser runtime formatter shape.
55
+ *
56
+ * The runtime inference layer does not know the exact field value type after a
57
+ * hint is selected, so the formatter is widened once here instead of repeating
58
+ * casts across each column builder.
59
+ */
60
+ function toRuntimeFormatter(formatter) {
61
+ if (!formatter) {
62
+ return undefined;
63
+ }
64
+ return (value, item) => formatter(value, item);
65
+ }
66
+ /**
67
+ * Normalize one raw-field schema override into the runtime shape used by the inference layer.
68
+ *
69
+ * Schema formatters are intentionally more specific than the runtime pipeline can
70
+ * express, so this helper contains the one widening step that keeps the rest of
71
+ * the implementation free of repeated formatter casts.
72
+ */
73
+ function toRuntimeColumnSchema(columnSchema) {
74
+ if (!columnSchema || columnSchema === false) {
75
+ return undefined;
76
+ }
77
+ return {
78
+ ...columnSchema,
79
+ formatter: toRuntimeFormatter(columnSchema.formatter),
80
+ };
81
+ }
82
+ /**
83
+ * Extract raw-field schema entries from the full schema object.
84
+ */
85
+ function getRawColumnSchemaMap(schema) {
86
+ if (!schema?.columns) {
87
+ return undefined;
88
+ }
89
+ const rawColumns = {};
90
+ for (const [key, value] of Object.entries(schema.columns)) {
91
+ if (value !== false && typeof value === 'object' && value !== null && 'kind' in value && value.kind === 'derived') {
92
+ continue;
93
+ }
94
+ rawColumns[key] = value;
95
+ }
96
+ return rawColumns;
97
+ }
98
+ /**
99
+ * Extract derived column definitions from the full schema object.
100
+ *
101
+ * Derived ids are additive-only. If callers attempt to reuse a raw field id,
102
+ * the explicit derived definition is ignored so runtime behavior stays aligned
103
+ * with the public contract even in untyped JavaScript or unsafe casts.
104
+ */
105
+ function getDerivedColumnSchemas(schema, rawFieldIds) {
106
+ if (!schema?.columns) {
107
+ return [];
108
+ }
109
+ return Object.entries(schema.columns).flatMap(([key, value]) => {
110
+ if (typeof value === 'object' && value !== null && 'kind' in value && value.kind === 'derived') {
111
+ const derivedColumn = value;
112
+ if (rawFieldIds.has(key)) {
113
+ warn(`schema.columns.${key} cannot be derived because derived columns must use a new id instead of replacing a raw field.`);
114
+ return [];
115
+ }
116
+ if (derivedColumn.label.trim().length === 0) {
117
+ warn(`schema.columns.${key} should declare a non-empty label so derived columns stay intentional in the UI.`);
118
+ }
119
+ return [[key, derivedColumn]];
120
+ }
121
+ return [];
122
+ });
123
+ }
124
+ /**
125
+ * Extract only string samples after runtime classification has selected the
126
+ * string/category path.
127
+ */
128
+ function getStringSamples(samples) {
129
+ return samples.filter((value) => typeof value === 'string');
130
+ }
131
+ /**
132
+ * Extract only numeric samples after runtime classification has selected the
133
+ * numeric path.
134
+ */
135
+ function getNumberSamples(samples) {
136
+ return samples.filter((value) => typeof value === 'number');
137
+ }
138
+ /**
139
+ * Narrow the final inferred columns array back to the literal column-id union
140
+ * derived from the caller's hints.
141
+ *
142
+ * Inference happens over runtime strings, but every column in this array was
143
+ * constructed from keys collected by `collectFieldKeys()` and filtered through
144
+ * `buildColumn()`. This cast is therefore the final boundary between runtime
145
+ * discovery and the exported literal-id API.
146
+ */
147
+ function finalizeResolvedColumns(columns) {
148
+ return columns;
149
+ }
150
+ /**
151
+ * Check whether a runtime value can participate in automatic column inference.
152
+ */
153
+ function isPrimitiveSample(value) {
154
+ return (typeof value === 'string' ||
155
+ typeof value === 'number' ||
156
+ typeof value === 'boolean' ||
157
+ value instanceof Date);
158
+ }
159
+ /**
160
+ * Collect a bounded set of non-null samples for one field.
161
+ */
162
+ function collectSamples(data, key) {
163
+ const samples = [];
164
+ for (const item of data) {
165
+ const value = getFieldValue(item, key);
166
+ if (value == null)
167
+ continue;
168
+ if (!isPrimitiveSample(value))
169
+ continue;
170
+ samples.push(value);
171
+ if (samples.length >= MAX_SAMPLE_COUNT) {
172
+ break;
173
+ }
174
+ }
175
+ return samples;
176
+ }
177
+ /**
178
+ * Gather all top-level raw field keys present in data or raw schema overrides.
179
+ */
180
+ function collectFieldKeys(data, rawColumnSchema) {
181
+ const keys = new Set();
182
+ for (const item of data) {
183
+ for (const key of Object.keys(item)) {
184
+ keys.add(key);
185
+ }
186
+ }
187
+ for (const key of Object.keys(rawColumnSchema ?? {})) {
188
+ keys.add(key);
189
+ }
190
+ return [...keys];
191
+ }
192
+ /**
193
+ * Classify the dominant runtime kind for a field.
194
+ */
195
+ function classifyRuntimeField(samples) {
196
+ if (samples.length === 0) {
197
+ return 'empty';
198
+ }
199
+ const kinds = new Set();
200
+ for (const value of samples) {
201
+ if (value instanceof Date) {
202
+ kinds.add('date');
203
+ continue;
204
+ }
205
+ switch (typeof value) {
206
+ case 'string':
207
+ kinds.add('category');
208
+ break;
209
+ case 'number':
210
+ kinds.add('number');
211
+ break;
212
+ case 'boolean':
213
+ kinds.add('boolean');
214
+ break;
215
+ default:
216
+ kinds.add('unsupported');
217
+ break;
218
+ }
219
+ }
220
+ if (kinds.size > 1) {
221
+ return 'mixed';
222
+ }
223
+ return kinds.values().next().value ?? 'unsupported';
224
+ }
225
+ /**
226
+ * Detect whether string samples should be treated as dates.
227
+ */
228
+ function detectStringDateSignal(key, samples) {
229
+ if (samples.length === 0) {
230
+ return { type: 'category', confidence: 'low', looksDateLike: false };
231
+ }
232
+ const parseableCount = samples.filter((value) => !Number.isNaN(Date.parse(value))).length;
233
+ const strongDatePatternCount = samples.filter((value) => DATE_VALUE_PATTERN.test(value) || DATETIME_VALUE_PATTERN.test(value)).length;
234
+ const parseRatio = parseableCount / samples.length;
235
+ const strongPatternRatio = strongDatePatternCount / samples.length;
236
+ const hasDateKeySignal = DATE_KEY_PATTERN.test(key);
237
+ if (strongPatternRatio >= 0.8 || (parseRatio === 1 && hasDateKeySignal)) {
238
+ return { type: 'date', confidence: 'high', looksDateLike: true };
239
+ }
240
+ if (parseRatio >= 0.8 && hasDateKeySignal) {
241
+ return { type: 'date', confidence: 'medium', looksDateLike: true };
242
+ }
243
+ return {
244
+ type: 'category',
245
+ confidence: parseRatio >= 0.8 ? 'medium' : 'low',
246
+ looksDateLike: parseRatio >= 0.8,
247
+ };
248
+ }
249
+ /**
250
+ * Detect whether numeric samples should be treated as timestamps.
251
+ */
252
+ function detectNumericDateSignal(key, samples) {
253
+ if (!DATE_KEY_PATTERN.test(key) || samples.length === 0) {
254
+ return { type: 'number', confidence: 'high', looksDateLike: false };
255
+ }
256
+ const plausibleTimestampCount = samples.filter((value) => {
257
+ if (!Number.isFinite(value))
258
+ return false;
259
+ const milliseconds = value > 1e12 ? value : value * 1000;
260
+ return milliseconds >= Date.UTC(2000, 0, 1) && milliseconds <= Date.UTC(2100, 0, 1);
261
+ }).length;
262
+ const ratio = plausibleTimestampCount / samples.length;
263
+ if (ratio === 1) {
264
+ return { type: 'date', confidence: 'high', looksDateLike: true };
265
+ }
266
+ if (ratio >= 0.8) {
267
+ return { type: 'date', confidence: 'medium', looksDateLike: true };
268
+ }
269
+ return { type: 'number', confidence: 'high', looksDateLike: false };
270
+ }
271
+ /**
272
+ * Infer the best-fit column type for one field.
273
+ */
274
+ function inferColumnType(key, samples) {
275
+ const runtimeKind = classifyRuntimeField(samples);
276
+ switch (runtimeKind) {
277
+ case 'boolean':
278
+ return { type: 'boolean', confidence: 'high', looksDateLike: false };
279
+ case 'date':
280
+ return { type: 'date', confidence: 'high', looksDateLike: true };
281
+ case 'number': {
282
+ const signal = detectNumericDateSignal(key, getNumberSamples(samples));
283
+ return { type: signal.type, confidence: signal.confidence, looksDateLike: signal.looksDateLike };
284
+ }
285
+ case 'category': {
286
+ const signal = detectStringDateSignal(key, getStringSamples(samples));
287
+ return { type: signal.type, confidence: signal.confidence, looksDateLike: signal.looksDateLike };
288
+ }
289
+ case 'empty':
290
+ return { type: null, confidence: 'low', looksDateLike: false };
291
+ default:
292
+ return { type: null, confidence: 'low', looksDateLike: false };
293
+ }
294
+ }
295
+ /**
296
+ * Keep inferred columns neutral unless the caller opts into a specific format.
297
+ */
298
+ function inferDefaultFormat(_key, _type) {
299
+ return undefined;
300
+ }
301
+ /**
302
+ * Build reusable debug metadata for one resolved column.
303
+ */
304
+ function createInferenceMetadata(detectedType, confidence, hinted) {
305
+ return { detectedType, confidence, hinted };
306
+ }
307
+ /**
308
+ * Normalize numeric timestamps so second-based Unix values also behave like dates.
309
+ */
310
+ function normalizeDateValue(value) {
311
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
312
+ return value;
313
+ }
314
+ if (value >= 1e9 && value < 1e12) {
315
+ return value * 1000;
316
+ }
317
+ return value;
318
+ }
319
+ /**
320
+ * Build a date column for one field.
321
+ */
322
+ function createDateColumn(key, hint, confidence, hinted) {
323
+ const accessor = createAccessor(key);
324
+ return {
325
+ id: key,
326
+ type: 'date',
327
+ label: typeof hint === 'object' && hint?.label ? hint.label : humanizeKey(key),
328
+ format: typeof hint === 'object' && hint?.format ? hint.format : inferDefaultFormat(key, 'date'),
329
+ formatter: hint?.formatter,
330
+ inference: createInferenceMetadata('date', confidence, hinted),
331
+ accessor: (item) => {
332
+ const value = accessor(item);
333
+ return value instanceof Date || typeof value === 'string' || typeof value === 'number'
334
+ ? normalizeDateValue(value)
335
+ : null;
336
+ },
337
+ };
338
+ }
339
+ /**
340
+ * Build a category column for one field.
341
+ */
342
+ function createCategoryColumn(key, hint, confidence, hinted) {
343
+ const accessor = createAccessor(key);
344
+ return {
345
+ id: key,
346
+ type: 'category',
347
+ label: typeof hint === 'object' && hint?.label ? hint.label : humanizeKey(key),
348
+ format: typeof hint === 'object' ? hint.format : undefined,
349
+ formatter: hint?.formatter,
350
+ inference: createInferenceMetadata('category', confidence, hinted),
351
+ accessor: (item) => {
352
+ const value = accessor(item);
353
+ return value == null ? null : String(value);
354
+ },
355
+ };
356
+ }
357
+ /**
358
+ * Build a boolean column for one field.
359
+ */
360
+ function createBooleanColumn(key, hint, confidence, hinted) {
361
+ const accessor = createAccessor(key);
362
+ const trueLabel = typeof hint === 'object' && 'trueLabel' in hint && hint.trueLabel ? hint.trueLabel : 'True';
363
+ const falseLabel = typeof hint === 'object' && 'falseLabel' in hint && hint.falseLabel ? hint.falseLabel : 'False';
364
+ return {
365
+ id: key,
366
+ type: 'boolean',
367
+ label: typeof hint === 'object' && hint?.label ? hint.label : humanizeKey(key),
368
+ format: typeof hint === 'object' ? hint.format : undefined,
369
+ formatter: hint?.formatter,
370
+ inference: createInferenceMetadata('boolean', confidence, hinted),
371
+ trueLabel,
372
+ falseLabel,
373
+ accessor: (item) => {
374
+ const value = accessor(item);
375
+ return typeof value === 'boolean' ? value : null;
376
+ },
377
+ };
378
+ }
379
+ /**
380
+ * Build a number column for one field.
381
+ */
382
+ function createNumberColumn(key, hint, confidence, hinted) {
383
+ const accessor = createAccessor(key);
384
+ return {
385
+ id: key,
386
+ type: 'number',
387
+ label: typeof hint === 'object' && hint?.label ? hint.label : humanizeKey(key),
388
+ format: typeof hint === 'object' && hint?.format ? hint.format : inferDefaultFormat(key, 'number'),
389
+ formatter: hint?.formatter,
390
+ inference: createInferenceMetadata('number', confidence, hinted),
391
+ accessor: (item) => {
392
+ const value = accessor(item);
393
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
394
+ },
395
+ };
396
+ }
397
+ /**
398
+ * Build one resolved column from data samples and optional hint overrides.
399
+ */
400
+ function buildRawColumn(key, samples, columnSchema) {
401
+ if (columnSchema === false) {
402
+ return null;
403
+ }
404
+ const runtimeSchema = toRuntimeColumnSchema(columnSchema);
405
+ const inferred = inferColumnType(key, samples);
406
+ const hintedType = runtimeSchema?.type;
407
+ const resolvedType = hintedType ?? inferred.type;
408
+ if (!resolvedType) {
409
+ return null;
410
+ }
411
+ if (hintedType && inferred.type && hintedType !== inferred.type) {
412
+ warn(`schema.columns.${key} overrides inferred type "${inferred.type}" with "${hintedType}".`);
413
+ }
414
+ if (inferred.looksDateLike && inferred.type !== 'date' && !hintedType) {
415
+ warn(`Field "${key}" looks date-like but was inferred as category. Add schema.columns.${key}.type = 'date' if that is intentional.`);
416
+ }
417
+ const confidence = hintedType ? 'high' : inferred.confidence;
418
+ switch (resolvedType) {
419
+ case 'date':
420
+ return createDateColumn(key, runtimeSchema, confidence, hintedType != null);
421
+ case 'category':
422
+ return createCategoryColumn(key, runtimeSchema, confidence, hintedType != null);
423
+ case 'boolean':
424
+ return createBooleanColumn(key, runtimeSchema, confidence, hintedType != null);
425
+ case 'number':
426
+ return createNumberColumn(key, runtimeSchema, confidence, hintedType != null);
427
+ }
428
+ }
429
+ /**
430
+ * Adapt one explicit derived column definition into the shared runtime shape.
431
+ */
432
+ function toRuntimeDerivedSchema(columnSchema) {
433
+ return {
434
+ ...columnSchema,
435
+ formatter: toRuntimeFormatter(columnSchema.formatter),
436
+ };
437
+ }
438
+ /**
439
+ * Build one resolved derived column from the explicit schema.
440
+ */
441
+ function buildDerivedColumn(key, columnSchema) {
442
+ const runtimeSchema = toRuntimeDerivedSchema(columnSchema);
443
+ switch (columnSchema.type) {
444
+ case 'date':
445
+ return {
446
+ ...createDateColumn(key, runtimeSchema, 'high', true),
447
+ accessor: columnSchema.accessor,
448
+ };
449
+ case 'category':
450
+ return {
451
+ ...createCategoryColumn(key, runtimeSchema, 'high', true),
452
+ accessor: columnSchema.accessor,
453
+ };
454
+ case 'boolean':
455
+ return {
456
+ ...createBooleanColumn(key, runtimeSchema, 'high', true),
457
+ accessor: columnSchema.accessor,
458
+ };
459
+ case 'number':
460
+ return {
461
+ ...createNumberColumn(key, runtimeSchema, 'high', true),
462
+ accessor: columnSchema.accessor,
463
+ };
464
+ }
465
+ }
466
+ /**
467
+ * Order resolved columns so the best default chart choices appear first.
468
+ */
469
+ function sortResolvedColumns(columns) {
470
+ const typeRank = {
471
+ date: 0,
472
+ category: 1,
473
+ boolean: 2,
474
+ number: 3,
475
+ };
476
+ return [...columns].sort((left, right) => {
477
+ const byType = typeRank[left.type] - typeRank[right.type];
478
+ if (byType !== 0) {
479
+ return byType;
480
+ }
481
+ const leftIdLike = /(^id$|id$|uuid|slug|token|hash)/i.test(left.id);
482
+ const rightIdLike = /(^id$|id$|uuid|slug|token|hash)/i.test(right.id);
483
+ if (leftIdLike !== rightIdLike) {
484
+ return leftIdLike ? 1 : -1;
485
+ }
486
+ return left.label.localeCompare(right.label);
487
+ });
488
+ }
489
+ /**
490
+ * Resolve chart columns directly from raw data and an optional explicit schema.
491
+ */
492
+ export function inferColumnsFromData(data, schema) {
493
+ const rawColumnSchema = getRawColumnSchemaMap(schema);
494
+ const fields = collectFieldKeys(data, rawColumnSchema);
495
+ const rawFieldIds = new Set(fields);
496
+ const resolvedColumns = [];
497
+ for (const field of fields) {
498
+ const samples = collectSamples(data, field);
499
+ const typedField = toInferableFieldKey(field);
500
+ const column = buildRawColumn(typedField, samples, rawColumnSchema?.[typedField]);
501
+ if (column) {
502
+ resolvedColumns.push(column);
503
+ }
504
+ }
505
+ for (const [key, columnSchema] of getDerivedColumnSchemas(schema, rawFieldIds)) {
506
+ resolvedColumns.push(buildDerivedColumn(key, columnSchema));
507
+ }
508
+ if (resolvedColumns.length === 0) {
509
+ warn('No inferable or explicit chart columns were found. Provide non-empty data or schema.columns.');
510
+ }
511
+ return finalizeResolvedColumns(sortResolvedColumns(resolvedColumns));
512
+ }
513
+ //# sourceMappingURL=infer-columns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer-columns.js","sourceRoot":"","sources":["../../src/core/infer-columns.ts"],"names":[],"mappings":"AAqBA,MAAM,gBAAgB,GAAG,EAAE,CAAA;AAC3B,MAAM,gBAAgB,GAAG,8FAA8F,CAAA;AACvH,MAAM,sBAAsB,GAAG,qCAAqC,CAAA;AACpE,MAAM,kBAAkB,GAAG,qCAAqC,CAAA;AAoBhE;;GAEG;AACH,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG;SACP,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED;;GAEG;AACH,SAAS,UAAU;IACjB,OAAO,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA;AACzF,CAAC;AAED;;GAEG;AACH,SAAS,IAAI,CAAC,OAAe;IAC3B,IAAI,CAAC,UAAU,EAAE;QAAE,OAAM;IACzB,OAAO,CAAC,IAAI,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAA;AAC3C,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAI,IAAO,EAAE,GAAW;IAC5C,OAAO,IAAI,CAAC,GAAc,CAAC,CAAA;AAC7B,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAI,GAAW;IACpC,OAAO,CAAC,IAAO,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAI,GAAW;IACzC,OAAO,GAA2B,CAAA;AACpC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CACzB,SAAqB;IAErB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,KAA0C,EAAE,IAAI,CAAC,CAAA;AACrF,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAC5B,YAAoD;IAEpD,IAAI,CAAC,YAAY,IAAI,YAAY,KAAK,KAAK,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO;QACL,GAAG,YAAY;QACf,SAAS,EAAE,kBAAkB,CAAC,YAAY,CAAC,SAAS,CAAC;KACtD,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAC5B,MAAuC;IAEvC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QACrB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,UAAU,GAA0B,EAAE,CAAA;IAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1D,IAAI,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAClH,SAAQ;QACV,CAAC;QAED,UAAU,CAAC,GAA2B,CAAC,GAAG,KAAoD,CAAA;IAChG,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,uBAAuB,CAC9B,MAAuC,EACvC,WAAgC;IAEhC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QACrB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC7D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/F,MAAM,aAAa,GAAG,KAA+B,CAAA;YAErD,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC,kBAAkB,GAAG,gGAAgG,CAAC,CAAA;gBAC3H,OAAO,EAAE,CAAA;YACX,CAAC;YAED,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,kBAAkB,GAAG,kFAAkF,CAAC,CAAA;YAC/G,CAAC;YAED,OAAO,CAAC,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAA;QAC/B,CAAC;QAED,OAAO,EAAE,CAAA;IACX,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAAmC;IAC3D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAA;AAC9E,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAAmC;IAC3D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAA;AAC9E,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,uBAAuB,CAI9B,OAA0C;IAE1C,OAAO,OAAuF,CAAA;AAChG,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,KAAc;IACvC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAO,KAAK,KAAK,SAAS;QAC1B,KAAK,YAAY,IAAI,CACtB,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAI,IAAkB,EAAE,GAAW;IACxD,MAAM,OAAO,GAAsB,EAAE,CAAA;IAErC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACtC,IAAI,KAAK,IAAI,IAAI;YAAE,SAAQ;QAC3B,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;YAAE,SAAQ;QACvC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnB,IAAI,OAAO,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;YACvC,MAAK;QACP,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CACvB,IAAkB,EAClB,eAAkD;IAElD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAE9B,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAA+B,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACf,CAAC;IACH,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACf,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,OAAmC;IAC/D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAA;IACzC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YAC1B,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACjB,SAAQ;QACV,CAAC;QAED,QAAQ,OAAO,KAAK,EAAE,CAAC;YACrB,KAAK,QAAQ;gBACX,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;gBACrB,MAAK;YACP,KAAK,QAAQ;gBACX,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;gBACnB,MAAK;YACP,KAAK,SAAS;gBACZ,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;gBACpB,MAAK;YACP;gBACE,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;gBACxB,MAAK;QACT,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,aAAa,CAAA;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,GAAW,EAAE,OAA0B;IACrE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAC,CAAA;IACpE,CAAC;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACzF,MAAM,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAC3C,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAChF,CAAC,MAAM,CAAA;IACR,MAAM,UAAU,GAAG,cAAc,GAAG,OAAO,CAAC,MAAM,CAAA;IAClD,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAA;IAClE,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAEnD,IAAI,kBAAkB,IAAI,GAAG,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,gBAAgB,CAAC,EAAE,CAAC;QACxE,OAAO,EAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAC,CAAA;IAChE,CAAC;IAED,IAAI,UAAU,IAAI,GAAG,IAAI,gBAAgB,EAAE,CAAC;QAC1C,OAAO,EAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAC,CAAA;IAClE,CAAC;IAED,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,UAAU,EAAE,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK;QAChD,aAAa,EAAE,UAAU,IAAI,GAAG;KACjC,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,GAAW,EAAE,OAA0B;IACtE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAC,CAAA;IACnE,CAAC;IAED,MAAM,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAA;QACzC,MAAM,YAAY,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAA;QACxD,OAAO,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACrF,CAAC,CAAC,CAAC,MAAM,CAAA;IAET,MAAM,KAAK,GAAG,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAA;IACtD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,EAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAC,CAAA;IAChE,CAAC;IAED,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;QACjB,OAAO,EAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAC,CAAA;IAClE,CAAC;IAED,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAC,CAAA;AACnE,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CACtB,GAAW,EACX,OAAmC;IAEnC,MAAM,WAAW,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAA;IACjD,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,EAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAC,CAAA;QACpE,KAAK,MAAM;YACT,OAAO,EAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAC,CAAA;QAChE,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;YACtE,OAAO,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAC,CAAA;QAChG,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,MAAM,GAAG,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;YACrE,OAAO,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAC,CAAA;QAChG,CAAC;QACD,KAAK,OAAO;YACV,OAAO,EAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAC,CAAA;QAC9D;YACE,OAAO,EAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAC,CAAA;IAChE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAsB;IAC9D,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC9B,YAA6B,EAC7B,UAA+B,EAC/B,MAAe;IAEf,OAAO,EAAC,YAAY,EAAE,UAAU,EAAE,MAAM,EAAC,CAAA;AAC3C,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,KAA6B;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;QACjC,OAAO,KAAK,GAAG,IAAI,CAAA;IACrB,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CACvB,GAAQ,EACR,IAAwC,EACxC,UAA+B,EAC/B,MAAe;IAEf,MAAM,QAAQ,GAAG,cAAc,CAAI,GAAG,CAAC,CAAA;IACvC,OAAO;QACL,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC;QAC9E,MAAM,EAAE,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC;QAChG,SAAS,EAAE,IAAI,EAAE,SAAS;QAC1B,SAAS,EAAE,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC;QAC9D,QAAQ,EAAE,CAAC,IAAO,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;YAC5B,OAAO,KAAK,YAAY,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;gBACpF,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC;gBAC3B,CAAC,CAAC,IAAI,CAAA;QACV,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,GAAQ,EACR,IAAwC,EACxC,UAA+B,EAC/B,MAAe;IAEf,MAAM,QAAQ,GAAG,cAAc,CAAI,GAAG,CAAC,CAAA;IACvC,OAAO;QACL,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC;QAC9E,MAAM,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC1D,SAAS,EAAE,IAAI,EAAE,SAAS;QAC1B,SAAS,EAAE,uBAAuB,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC;QAClE,QAAQ,EAAE,CAAC,IAAO,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;YAC5B,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC7C,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAC1B,GAAQ,EACR,IAAwC,EACxC,UAA+B,EAC/B,MAAe;IAEf,MAAM,QAAQ,GAAG,cAAc,CAAI,GAAG,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,WAAW,IAAI,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAA;IAC7G,MAAM,UAAU,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,YAAY,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAA;IAElH,OAAO;QACL,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC;QAC9E,MAAM,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC1D,SAAS,EAAE,IAAI,EAAE,SAAS;QAC1B,SAAS,EAAE,uBAAuB,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC;QACjE,SAAS;QACT,UAAU;QACV,QAAQ,EAAE,CAAC,IAAO,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;YAC5B,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;QAClD,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,GAAQ,EACR,IAAwC,EACxC,UAA+B,EAC/B,MAAe;IAEf,MAAM,QAAQ,GAAG,cAAc,CAAI,GAAG,CAAC,CAAA;IACvC,OAAO;QACL,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC;QAC9E,MAAM,EAAE,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,QAAQ,CAAC;QAClG,SAAS,EAAE,IAAI,EAAE,SAAS;QAC1B,SAAS,EAAE,uBAAuB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC;QAChE,QAAQ,EAAE,CAAC,IAAO,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;YAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;QAC3E,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,GAAQ,EACR,OAAmC,EACnC,YAAoD;IAEpD,IAAI,YAAY,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,aAAa,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACzD,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAC9C,MAAM,UAAU,GAAG,aAAa,EAAE,IAAI,CAAA;IACtC,MAAM,YAAY,GAAG,UAAU,IAAI,QAAQ,CAAC,IAAI,CAAA;IAChD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,UAAU,IAAI,QAAQ,CAAC,IAAI,IAAI,UAAU,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,kBAAkB,GAAG,6BAA6B,QAAQ,CAAC,IAAI,WAAW,UAAU,IAAI,CAAC,CAAA;IAChG,CAAC;IAED,IAAI,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACtE,IAAI,CAAC,UAAU,GAAG,sEAAsE,GAAG,wCAAwC,CAAC,CAAA;IACtI,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAA;IAC5D,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,MAAM;YACT,OAAO,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,IAAI,IAAI,CAAC,CAAA;QAC7E,KAAK,UAAU;YACb,OAAO,oBAAoB,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,IAAI,IAAI,CAAC,CAAA;QACjF,KAAK,SAAS;YACZ,OAAO,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,IAAI,IAAI,CAAC,CAAA;QAChF,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,IAAI,IAAI,CAAC,CAAA;IACjF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAI,YAAoC;IACrE,OAAO;QACL,GAAG,YAAY;QACf,SAAS,EAAE,kBAAkB,CAAC,YAAY,CAAC,SAAS,CAAC;KACtD,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,GAAW,EACX,YAIgC;IAEhC,MAAM,aAAa,GAAG,sBAAsB,CAAC,YAAY,CAAC,CAAA;IAC1D,QAAQ,YAAY,CAAC,IAAI,EAAE,CAAC;QAC1B,KAAK,MAAM;YACT,OAAO;gBACL,GAAG,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC;gBACrD,QAAQ,EAAE,YAAY,CAAC,QAAQ;aAChC,CAAA;QACH,KAAK,UAAU;YACb,OAAO;gBACL,GAAG,oBAAoB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC;gBACzD,QAAQ,EAAE,YAAY,CAAC,QAAQ;aAChC,CAAA;QACH,KAAK,SAAS;YACZ,OAAO;gBACL,GAAG,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC;gBACxD,QAAQ,EAAE,YAAY,CAAC,QAAQ;aAChC,CAAA;QACH,KAAK,QAAQ;YACX,OAAO;gBACL,GAAG,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC;gBACvD,QAAQ,EAAE,YAAY,CAAC,QAAQ;aAChC,CAAA;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAC1B,OAA0C;IAE1C,MAAM,QAAQ,GAAoC;QAChD,IAAI,EAAE,CAAC;QACP,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,CAAC;KACV,CAAA;IAED,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACzD,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO,MAAM,CAAA;QACf,CAAC;QAED,MAAM,UAAU,GAAG,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACnE,MAAM,WAAW,GAAG,kCAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACrE,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;YAC/B,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5B,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAkB,EAClB,MAAgB;IAEhB,MAAM,eAAe,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACrD,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAA;IACtD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAA;IACnC,MAAM,eAAe,GAA6B,EAAE,CAAA;IAEpD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC3C,MAAM,UAAU,GAAG,mBAAmB,CAAI,KAAK,CAAC,CAAA;QAChD,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,UAAU,CAAC,CAAC,CAAA;QACjF,IAAI,MAAM,EAAE,CAAC;YACX,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,uBAAuB,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC;QAC/E,eAAe,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAA;IAC7D,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,8FAA8F,CAAC,CAAA;IACtG,CAAC;IAED,OAAO,uBAAuB,CAAa,mBAAmB,CAAC,eAAe,CAAC,CAAC,CAAA;AAClF,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { AggregateMetric, CountMetric, ChartColumn, Metric, MetricAllowance, MetricConfig, NumericAggregateFunction } from './types.js';
2
+ /**
3
+ * Default metric used when no numeric aggregation is selected.
4
+ */
5
+ export declare const DEFAULT_METRIC: CountMetric;
6
+ /**
7
+ * Type guard for aggregate metrics.
8
+ */
9
+ export declare function isAggregateMetric<TColumnId extends string>(metric: Metric<TColumnId>): metric is AggregateMetric<TColumnId>;
10
+ /**
11
+ * Compare two metric definitions for semantic equality.
12
+ */
13
+ export declare function isSameMetric<TColumnId extends string>(left: Metric<TColumnId>, right: Metric<TColumnId>): boolean;
14
+ /**
15
+ * Human-readable label for a numeric aggregate.
16
+ */
17
+ export declare function getAggregateMetricLabel(columnLabel: string, aggregate: NumericAggregateFunction): string;
18
+ /**
19
+ * Human-readable label for a metric.
20
+ */
21
+ export declare function getMetricLabel<T, TColumnId extends string>(metric: Metric<TColumnId>, columns: readonly ChartColumn<T, TColumnId>[]): string;
22
+ /**
23
+ * Build the metric options available for a set of columns.
24
+ */
25
+ export declare function buildAvailableMetrics<T, TColumnId extends string>(columns: readonly ChartColumn<T, TColumnId>[]): Metric<TColumnId>[];
26
+ /**
27
+ * Expand declarative metric restriction entries into the normalized metric list
28
+ * used by the runtime and typed chart state.
29
+ */
30
+ export declare function normalizeMetricAllowances<TColumnId extends string>(allowedMetrics?: readonly MetricAllowance<TColumnId>[]): Metric<TColumnId>[] | undefined;
31
+ /**
32
+ * Apply a declarative metric whitelist to the inferred metric options.
33
+ *
34
+ * Metrics are matched structurally so callers can safely pass fresh object
35
+ * literals in `config.metric.allowed`. The final order follows the declarative
36
+ * restriction list, so the first allowed metric becomes the default.
37
+ */
38
+ export declare function restrictAvailableMetrics<TColumnId extends string>(metrics: readonly Metric<TColumnId>[], config?: MetricConfig<TColumnId>): Metric<TColumnId>[];
39
+ /**
40
+ * Validate a metric against the active source.
41
+ */
42
+ export declare function resolveMetric<T, TColumnId extends string>(metric: Metric<TColumnId>, columns: readonly ChartColumn<T, TColumnId>[], availableMetrics?: readonly Metric<TColumnId>[], configuredDefaultMetric?: Metric<TColumnId>): Metric<TColumnId>;
43
+ //# sourceMappingURL=metric-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metric-utils.d.ts","sourceRoot":"","sources":["../../src/core/metric-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,WAAW,EACX,MAAM,EACN,eAAe,EACf,YAAY,EAEZ,wBAAwB,EACzB,MAAM,YAAY,CAAA;AAEnB;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,WAA6B,CAAA;AAE1D;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,SAAS,MAAM,EACxD,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,GACxB,MAAM,IAAI,eAAe,CAAC,SAAS,CAAC,CAEtC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,SAAS,MAAM,EACnD,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,EACvB,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,GACvB,OAAO,CAeT;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,wBAAwB,GAClC,MAAM,CAWR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,EACxD,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,EACzB,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,GAC5C,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,EAC/D,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,GAC5C,MAAM,CAAC,SAAS,CAAC,EAAE,CAgBrB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,SAAS,MAAM,EAChE,cAAc,CAAC,EAAE,SAAS,eAAe,CAAC,SAAS,CAAC,EAAE,GACrD,MAAM,CAAC,SAAS,CAAC,EAAE,GAAG,SAAS,CA4BjC;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,SAAS,MAAM,EAC/D,OAAO,EAAE,SAAS,MAAM,CAAC,SAAS,CAAC,EAAE,EACrC,MAAM,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,GAC/B,MAAM,CAAC,SAAS,CAAC,EAAE,CA4BrB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,EACvD,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,EACzB,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,EAC7C,gBAAgB,CAAC,EAAE,SAAS,MAAM,CAAC,SAAS,CAAC,EAAE,EAC/C,uBAAuB,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,GAC1C,MAAM,CAAC,SAAS,CAAC,CA4BnB"}