@matthieumordrel/chart-studio 0.3.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -378
- package/dist/_internal.d.mts +9 -0
- package/dist/_internal.mjs +9 -0
- package/dist/core/chart-builder-controls.mjs +141 -0
- package/dist/core/chart-capabilities.d.mts +5 -0
- package/dist/core/chart-capabilities.mjs +9 -0
- package/dist/core/config-utils.mjs +2 -1
- package/dist/core/dashboard.types.d.mts +220 -0
- package/dist/core/data-label-defaults.d.mts +92 -0
- package/dist/core/data-label-defaults.mjs +78 -0
- package/dist/core/data-model.types.d.mts +196 -0
- package/dist/core/dataset-builder.types.d.mts +51 -0
- package/dist/core/dataset-chart-metadata.d.mts +8 -0
- package/dist/core/dataset-chart-metadata.mjs +4 -0
- package/dist/core/date-range-presets.d.mts +43 -1
- package/dist/core/date-range-presets.mjs +2 -2
- package/dist/core/date-utils.d.mts +26 -0
- package/dist/core/define-dashboard.d.mts +8 -0
- package/dist/core/define-dashboard.mjs +156 -0
- package/dist/core/define-data-model.d.mts +11 -0
- package/dist/core/define-data-model.mjs +327 -0
- package/dist/core/define-dataset.d.mts +13 -0
- package/dist/core/define-dataset.mjs +111 -0
- package/dist/core/formatting.d.mts +49 -0
- package/dist/core/formatting.mjs +32 -10
- package/dist/core/index.d.mts +19 -0
- package/dist/core/infer-columns.mjs +28 -2
- package/dist/core/materialized-view.mjs +580 -0
- package/dist/core/materialized-view.types.d.mts +223 -0
- package/dist/core/metric-utils.d.mts +18 -2
- package/dist/core/metric-utils.mjs +1 -1
- package/dist/core/model-chart.mjs +242 -0
- package/dist/core/model-chart.types.d.mts +199 -0
- package/dist/core/model-inference.mjs +169 -0
- package/dist/core/model-inference.types.d.mts +71 -0
- package/dist/core/pipeline.mjs +32 -1
- package/dist/core/schema-builder.mjs +28 -158
- package/dist/core/schema-builder.types.d.mts +2 -49
- package/dist/core/types.d.mts +61 -10
- package/dist/core/use-chart-options.d.mts +35 -8
- package/dist/core/use-chart-resolvers.mjs +13 -3
- package/dist/core/use-chart.d.mts +16 -12
- package/dist/core/use-chart.mjs +137 -35
- package/dist/core/use-dashboard.d.mts +190 -0
- package/dist/core/use-dashboard.mjs +551 -0
- package/dist/index.d.mts +14 -4
- package/dist/index.mjs +8 -2
- package/package.json +10 -41
- package/LICENSE +0 -21
- package/dist/core/define-chart-schema.d.mts +0 -38
- package/dist/core/define-chart-schema.mjs +0 -39
- package/dist/ui/chart-axis-ticks.mjs +0 -65
- package/dist/ui/chart-canvas.d.mts +0 -33
- package/dist/ui/chart-canvas.mjs +0 -779
- package/dist/ui/chart-context.d.mts +0 -99
- package/dist/ui/chart-context.mjs +0 -115
- package/dist/ui/chart-date-range-badge.d.mts +0 -20
- package/dist/ui/chart-date-range-badge.mjs +0 -49
- package/dist/ui/chart-date-range-panel.d.mts +0 -18
- package/dist/ui/chart-date-range-panel.mjs +0 -126
- package/dist/ui/chart-date-range.d.mts +0 -20
- package/dist/ui/chart-date-range.mjs +0 -67
- package/dist/ui/chart-debug.d.mts +0 -21
- package/dist/ui/chart-debug.mjs +0 -173
- package/dist/ui/chart-dropdown.mjs +0 -92
- package/dist/ui/chart-filters-panel.d.mts +0 -26
- package/dist/ui/chart-filters-panel.mjs +0 -132
- package/dist/ui/chart-filters.d.mts +0 -18
- package/dist/ui/chart-filters.mjs +0 -48
- package/dist/ui/chart-group-by-selector.d.mts +0 -16
- package/dist/ui/chart-group-by-selector.mjs +0 -32
- package/dist/ui/chart-metric-panel.d.mts +0 -25
- package/dist/ui/chart-metric-panel.mjs +0 -172
- package/dist/ui/chart-metric-selector.d.mts +0 -16
- package/dist/ui/chart-metric-selector.mjs +0 -50
- package/dist/ui/chart-select.mjs +0 -61
- package/dist/ui/chart-source-switcher.d.mts +0 -24
- package/dist/ui/chart-source-switcher.mjs +0 -56
- package/dist/ui/chart-time-bucket-selector.d.mts +0 -17
- package/dist/ui/chart-time-bucket-selector.mjs +0 -37
- package/dist/ui/chart-toolbar-overflow.d.mts +0 -28
- package/dist/ui/chart-toolbar-overflow.mjs +0 -231
- package/dist/ui/chart-toolbar.d.mts +0 -33
- package/dist/ui/chart-toolbar.mjs +0 -60
- package/dist/ui/chart-type-selector.d.mts +0 -19
- package/dist/ui/chart-type-selector.mjs +0 -168
- package/dist/ui/chart-x-axis-selector.d.mts +0 -16
- package/dist/ui/chart-x-axis-selector.mjs +0 -28
- package/dist/ui/index.d.mts +0 -19
- package/dist/ui/index.mjs +0 -18
- package/dist/ui/percent-stacked.mjs +0 -36
- package/dist/ui/theme.css +0 -67
- package/dist/ui/toolbar-types.d.mts +0 -7
- package/dist/ui/toolbar-types.mjs +0 -83
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DatasetBuilder, DatasetDefinition, ResolvedDatasetFromDefinition } from "./dataset-builder.types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/define-dataset.d.ts
|
|
4
|
+
declare function validateDatasetData<TDataset extends DatasetDefinition<any, any, any>>(dataset: TDataset, rows: Parameters<ResolvedDatasetFromDefinition<TDataset>['validateData']>[0], datasetLabel?: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Define one reusable dataset contract for columns, derived fields, and row identity.
|
|
7
|
+
*
|
|
8
|
+
* Dataset-owned `.columns(...)` is the canonical reusable meaning.
|
|
9
|
+
* Use `.chart(...)` to derive chart definitions from that shared contract.
|
|
10
|
+
*/
|
|
11
|
+
declare function defineDataset<TRow>(): DatasetBuilder<TRow, undefined, undefined>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { defineDataset, validateDatasetData };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { COLUMN_HELPER, assertColumnEntries, buildColumnsMap, createDatasetChartBuilder } from "./schema-builder.mjs";
|
|
2
|
+
//#region src/core/define-dataset.ts
|
|
3
|
+
function normalizeDatasetKey(key) {
|
|
4
|
+
return Array.isArray(key) ? key : [key];
|
|
5
|
+
}
|
|
6
|
+
function formatKeyValue(value) {
|
|
7
|
+
return value.length === 1 ? String(value[0]) : `[${value.map((part) => String(part)).join(", ")}]`;
|
|
8
|
+
}
|
|
9
|
+
function buildKeyFingerprint(parts) {
|
|
10
|
+
return JSON.stringify(parts.map((part) => {
|
|
11
|
+
if (part instanceof Date) return {
|
|
12
|
+
type: "date",
|
|
13
|
+
value: part.toISOString()
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
type: typeof part,
|
|
17
|
+
value: part
|
|
18
|
+
};
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
function validateDatasetRows(key, rows, datasetLabel) {
|
|
22
|
+
if (!key || key.length === 0) return;
|
|
23
|
+
const seen = /* @__PURE__ */ new Map();
|
|
24
|
+
rows.forEach((row, index) => {
|
|
25
|
+
const parts = key.map((keyId) => row[keyId]);
|
|
26
|
+
const missingKeyId = parts.findIndex((part) => part == null);
|
|
27
|
+
if (missingKeyId >= 0) throw new Error(`Dataset "${datasetLabel}" key "${key.join(", ")}" is missing a value at row ${index} for "${key[missingKeyId]}".`);
|
|
28
|
+
const fingerprint = buildKeyFingerprint(parts);
|
|
29
|
+
if (seen.get(fingerprint)) throw new Error(`Dataset "${datasetLabel}" key "${key.join(", ")}" must be unique. Duplicate value: ${formatKeyValue(parts)}.`);
|
|
30
|
+
seen.set(fingerprint, parts);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function resolveDatasetDefinition(dataset) {
|
|
34
|
+
return dataset.build();
|
|
35
|
+
}
|
|
36
|
+
function validateDatasetData(dataset, rows, datasetLabel = "dataset") {
|
|
37
|
+
validateDatasetRows(resolveDatasetDefinition(dataset).key, rows, datasetLabel);
|
|
38
|
+
}
|
|
39
|
+
function createDefinedDataset(state) {
|
|
40
|
+
let cachedDataset;
|
|
41
|
+
const build = () => {
|
|
42
|
+
if (cachedDataset) return cachedDataset;
|
|
43
|
+
const definedDataset = {
|
|
44
|
+
...state.key !== void 0 ? { key: state.key } : {},
|
|
45
|
+
...state.columns !== void 0 ? { columns: state.columns } : {},
|
|
46
|
+
chart(id) {
|
|
47
|
+
return createDatasetChartBuilder({ ...state.columns !== void 0 ? { columns: state.columns } : {} }, {
|
|
48
|
+
dataset: definedDataset,
|
|
49
|
+
chartId: id
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
validateData(data) {
|
|
53
|
+
validateDatasetRows(state.key, data, "dataset");
|
|
54
|
+
},
|
|
55
|
+
build() {
|
|
56
|
+
return definedDataset;
|
|
57
|
+
},
|
|
58
|
+
__datasetBrand: "dataset-definition"
|
|
59
|
+
};
|
|
60
|
+
cachedDataset = definedDataset;
|
|
61
|
+
return definedDataset;
|
|
62
|
+
};
|
|
63
|
+
return build();
|
|
64
|
+
}
|
|
65
|
+
function createDatasetBuilder(state = {}) {
|
|
66
|
+
let cachedDataset;
|
|
67
|
+
const getOrBuildDataset = () => {
|
|
68
|
+
if (cachedDataset) return cachedDataset;
|
|
69
|
+
cachedDataset = createDefinedDataset(state);
|
|
70
|
+
return cachedDataset;
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
key(keyOrKeys) {
|
|
74
|
+
return createDatasetBuilder({
|
|
75
|
+
...state,
|
|
76
|
+
key: normalizeDatasetKey(keyOrKeys)
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
columns(defineColumns) {
|
|
80
|
+
const entries = defineColumns(COLUMN_HELPER);
|
|
81
|
+
assertColumnEntries(entries, "defineDataset");
|
|
82
|
+
return createDatasetBuilder({
|
|
83
|
+
...state,
|
|
84
|
+
columns: buildColumnsMap(entries)
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
chart(id) {
|
|
88
|
+
return createDatasetChartBuilder({ ...state.columns !== void 0 ? { columns: state.columns } : {} }, {
|
|
89
|
+
dataset: getOrBuildDataset(),
|
|
90
|
+
chartId: id
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
validateData(data) {
|
|
94
|
+
validateDatasetRows(state.key, data, "dataset");
|
|
95
|
+
},
|
|
96
|
+
build() {
|
|
97
|
+
return getOrBuildDataset();
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Define one reusable dataset contract for columns, derived fields, and row identity.
|
|
103
|
+
*
|
|
104
|
+
* Dataset-owned `.columns(...)` is the canonical reusable meaning.
|
|
105
|
+
* Use `.chart(...)` to derive chart definitions from that shared contract.
|
|
106
|
+
*/
|
|
107
|
+
function defineDataset() {
|
|
108
|
+
return createDatasetBuilder();
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { defineDataset, resolveDatasetDefinition, validateDatasetData };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ChartColumn, ColumnFormat, TimeBucket } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/formatting.d.ts
|
|
4
|
+
/** Formatting surfaces exposed by the chart UI. */
|
|
5
|
+
type ChartValueSurface = 'axis' | 'tooltip' | 'data-label' | 'table-cell' | 'raw';
|
|
6
|
+
/** Numeric extent used to choose sensible default precision. */
|
|
7
|
+
type NumericRange = {
|
|
8
|
+
min: number;
|
|
9
|
+
max: number;
|
|
10
|
+
};
|
|
11
|
+
type FormatColumnLike<T> = {
|
|
12
|
+
type: ChartColumn<T>['type'];
|
|
13
|
+
format?: ColumnFormat;
|
|
14
|
+
formatter?: ChartColumn<T>['formatter'];
|
|
15
|
+
trueLabel?: string;
|
|
16
|
+
falseLabel?: string;
|
|
17
|
+
};
|
|
18
|
+
type FormatValueOptions<T> = {
|
|
19
|
+
column: FormatColumnLike<T>;
|
|
20
|
+
surface: ChartValueSurface;
|
|
21
|
+
timeBucket?: TimeBucket;
|
|
22
|
+
numericRange?: NumericRange | null;
|
|
23
|
+
locale?: string;
|
|
24
|
+
item?: T;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Build a numeric range from chart values.
|
|
28
|
+
*/
|
|
29
|
+
declare function createNumericRange(values: readonly number[]): NumericRange | null;
|
|
30
|
+
/**
|
|
31
|
+
* Decide whether an axis should keep decimal ticks for the current visible
|
|
32
|
+
* numeric values.
|
|
33
|
+
*/
|
|
34
|
+
declare function shouldAllowDecimalTicks(values: readonly number[]): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Format one chart value for a specific UI surface.
|
|
37
|
+
*/
|
|
38
|
+
declare function formatChartValue<T>(value: string | number | boolean | Date | null | undefined, options: FormatValueOptions<T>): string;
|
|
39
|
+
/**
|
|
40
|
+
* Format a date bucket label from the machine-friendly pipeline key.
|
|
41
|
+
*/
|
|
42
|
+
declare function formatTimeBucketLabel(key: string, bucket: TimeBucket, surface: ChartValueSurface, locale?: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Format the Y-axis or label width estimate with the same surface rules used in
|
|
45
|
+
* the visible chart.
|
|
46
|
+
*/
|
|
47
|
+
declare function formatNumericSurfaceValue(value: number, surface: ChartValueSurface, numericRange?: NumericRange | null, format?: ColumnFormat, formatter?: ChartColumn<unknown>['formatter'], locale?: string): string;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { ChartValueSurface, NumericRange, createNumericRange, formatChartValue, formatNumericSurfaceValue, formatTimeBucketLabel, shouldAllowDecimalTicks };
|
package/dist/core/formatting.mjs
CHANGED
|
@@ -54,7 +54,7 @@ function formatTimeBucketLabel(key, bucket, surface, locale = "en-US") {
|
|
|
54
54
|
case "day": return formatDateWithOptions(parseBucketDate(key), locale, getBucketDayOptions(surface));
|
|
55
55
|
case "week": {
|
|
56
56
|
const date = parseBucketDate(key);
|
|
57
|
-
return `${surface
|
|
57
|
+
return `${isFullPrecisionSurface(surface) ? "Week of " : "Wk of "}${formatDateWithOptions(date, locale, getBucketWeekOptions(surface))}`;
|
|
58
58
|
}
|
|
59
59
|
case "month": return formatDateWithOptions(parseBucketMonth(key), locale, {
|
|
60
60
|
month: "short",
|
|
@@ -68,6 +68,22 @@ function formatTimeBucketLabel(key, bucket, surface, locale = "en-US") {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
|
+
* Format the Y-axis or label width estimate with the same surface rules used in
|
|
72
|
+
* the visible chart.
|
|
73
|
+
*/
|
|
74
|
+
function formatNumericSurfaceValue(value, surface, numericRange, format, formatter, locale = "en-US") {
|
|
75
|
+
return formatChartValue(value, {
|
|
76
|
+
column: {
|
|
77
|
+
type: "number",
|
|
78
|
+
format,
|
|
79
|
+
formatter
|
|
80
|
+
},
|
|
81
|
+
surface,
|
|
82
|
+
numericRange,
|
|
83
|
+
locale
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
71
87
|
* Resolve the boolean labels while keeping null handling in the shared entry
|
|
72
88
|
* point above.
|
|
73
89
|
*/
|
|
@@ -176,17 +192,23 @@ function formatDateWithOptions(value, locale, options) {
|
|
|
176
192
|
/**
|
|
177
193
|
* Decide which number family should power the current surface.
|
|
178
194
|
*/
|
|
195
|
+
/**
|
|
196
|
+
* Surfaces that show full-precision values (not compacted).
|
|
197
|
+
*/
|
|
198
|
+
function isFullPrecisionSurface(surface) {
|
|
199
|
+
return surface === "tooltip" || surface === "table-cell";
|
|
200
|
+
}
|
|
179
201
|
function resolveNumberFormatMode(format, surface, numericRange, value) {
|
|
180
202
|
if (typeof format === "string") switch (format) {
|
|
181
|
-
case "currency": return surface
|
|
203
|
+
case "currency": return isFullPrecisionSurface(surface) ? "currency" : "compact-currency";
|
|
182
204
|
case "compact-number": return "compact-number";
|
|
183
205
|
case "percent": return "percent";
|
|
184
206
|
case "number":
|
|
185
207
|
case "date":
|
|
186
|
-
case "datetime": return surface
|
|
208
|
+
case "datetime": return isFullPrecisionSurface(surface) ? "number" : shouldUseCompactNumber(numericRange, value) ? "compact-number" : "number";
|
|
187
209
|
}
|
|
188
210
|
if (shouldUsePercentByDefault(numericRange)) return "percent";
|
|
189
|
-
if (surface
|
|
211
|
+
if (!isFullPrecisionSurface(surface) && shouldUseCompactNumber(numericRange, value)) return "compact-number";
|
|
190
212
|
return "number";
|
|
191
213
|
}
|
|
192
214
|
/**
|
|
@@ -239,7 +261,7 @@ function getNumberFormatOptions(mode, surface, numericRange, value) {
|
|
|
239
261
|
};
|
|
240
262
|
case "percent": return {
|
|
241
263
|
style: "percent",
|
|
242
|
-
maximumFractionDigits: surface
|
|
264
|
+
maximumFractionDigits: isFullPrecisionSurface(surface) ? 2 : 1
|
|
243
265
|
};
|
|
244
266
|
case "number": return { maximumFractionDigits: getStandardFractionDigits(surface, numericRange, value) };
|
|
245
267
|
}
|
|
@@ -249,7 +271,7 @@ function getNumberFormatOptions(mode, surface, numericRange, value) {
|
|
|
249
271
|
*/
|
|
250
272
|
function getStandardFractionDigits(surface, numericRange, value) {
|
|
251
273
|
const span = numericRange ? Math.abs(numericRange.max - numericRange.min) : Math.abs(value);
|
|
252
|
-
if (surface
|
|
274
|
+
if (isFullPrecisionSurface(surface)) {
|
|
253
275
|
if (span < 1) return 3;
|
|
254
276
|
if (span < 10) return 2;
|
|
255
277
|
if (span < 100) return 1;
|
|
@@ -263,7 +285,7 @@ function getStandardFractionDigits(surface, numericRange, value) {
|
|
|
263
285
|
* Match raw date values to a clear default display.
|
|
264
286
|
*/
|
|
265
287
|
function getDateValueOptions(mode, surface) {
|
|
266
|
-
if (mode === "datetime") return surface
|
|
288
|
+
if (mode === "datetime") return isFullPrecisionSurface(surface) ? {
|
|
267
289
|
dateStyle: "medium",
|
|
268
290
|
timeStyle: "short"
|
|
269
291
|
} : {
|
|
@@ -300,7 +322,7 @@ function getBucketDateOptions(bucket, surface) {
|
|
|
300
322
|
* Keep day buckets short on axes and clearer in tooltips.
|
|
301
323
|
*/
|
|
302
324
|
function getBucketDayOptions(surface) {
|
|
303
|
-
return surface
|
|
325
|
+
return isFullPrecisionSurface(surface) ? {
|
|
304
326
|
month: "short",
|
|
305
327
|
day: "numeric",
|
|
306
328
|
year: "2-digit"
|
|
@@ -313,7 +335,7 @@ function getBucketDayOptions(surface) {
|
|
|
313
335
|
* Keep week buckets short on axes and clearer in tooltips.
|
|
314
336
|
*/
|
|
315
337
|
function getBucketWeekOptions(surface) {
|
|
316
|
-
return surface
|
|
338
|
+
return isFullPrecisionSurface(surface) ? {
|
|
317
339
|
month: "short",
|
|
318
340
|
day: "numeric",
|
|
319
341
|
year: "2-digit"
|
|
@@ -346,4 +368,4 @@ function parseQuarterKey(key) {
|
|
|
346
368
|
};
|
|
347
369
|
}
|
|
348
370
|
//#endregion
|
|
349
|
-
export { createNumericRange, formatChartValue, formatTimeBucketLabel, shouldAllowDecimalTicks };
|
|
371
|
+
export { createNumericRange, formatChartValue, formatNumericSurfaceValue, formatTimeBucketLabel, shouldAllowDecimalTicks };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { DATE_RANGE_PRESETS, DateRangePreset, DateRangePresetId, autoFilterForBucket, getPresetLabel, resolvePresetFilter } from "./date-range-presets.mjs";
|
|
2
|
+
import { AggregateFunction, AggregateMetric, AggregateMetricAllowance, AvailableFilter, BooleanColumn, CategoricalChartType, CategoryColumn, ChartColumn, ChartColumnType, ChartControlMode, ChartDataScopeControlState, ChartDataScopeInputs, ChartDataScopeInputsFromSchemaDefinition, ChartDateRangeSelection, ChartInstance, ChartInstanceFromSchema, ChartInstanceFromSchemaDefinition, ChartSchema, ChartSchemaDefinition, ChartSeries, ChartSourceOptions, ChartType, ChartTypeConfig, ColumnFormat, ColumnFormatPreset, CountMetric, DateColumn, DateColumnFormat, DateRange, DateRangeFilter, DefinedChartSchema, DerivedBooleanColumnSchema, DerivedCategoryColumnSchema, DerivedColumnSchema, DerivedDateColumnSchema, DerivedNumberColumnSchema, DurationColumnFormat, DurationInputUnit, FilterState, FiltersConfig, GroupByConfig, InferableFieldKey, Metric, MetricAllowance, MetricConfig, MultiSourceChartDataScopeInputs, MultiSourceChartInstance, NumberColumn, NumberColumnFormat, NumericAggregateFunction, NumericAggregateSelection, RawColumnSchemaFor, RawColumnSchemaMap, ResolvedColumnIdFromSchema, ResolvedDateColumnIdFromSchema, ResolvedFilterColumnIdFromSchema, ResolvedGroupByColumnIdFromSchema, ResolvedMetricColumnIdFromSchema, ResolvedXAxisColumnIdFromSchema, RestrictedChartTypeFromSchema, RestrictedFilterColumnIdFromSchema, RestrictedGroupByColumnIdFromSchema, RestrictedMetricFromSchema, RestrictedTimeBucketFromSchema, RestrictedXAxisColumnIdFromSchema, SelectableControlConfig, SortConfig, SortDirection, TimeBucket, TimeBucketConfig, TimeSeriesChartType, TransformedDataPoint, ValidatedChartSchema, XAxisConfig } from "./types.mjs";
|
|
3
|
+
import { CHART_TYPE_CONFIG, ChartAxisType, ChartTypeCapabilities } from "./chart-capabilities.mjs";
|
|
4
|
+
import { buildColorMap, getSeriesColor } from "./colors.mjs";
|
|
5
|
+
import { DATA_LABEL_DEFAULTS, DataLabelDefaults, DataLabelPosition, DataLabelStyle, resolveShowDataLabels } from "./data-label-defaults.mjs";
|
|
6
|
+
import { computeDateRange, filterByDateRange } from "./date-utils.mjs";
|
|
7
|
+
import { buildAvailableMetrics, getMetricLabel } from "./metric-utils.mjs";
|
|
8
|
+
import { PipelineInput, PipelineOutput, applyFilters, extractAvailableFilters, runPipeline } from "./pipeline.mjs";
|
|
9
|
+
import { DatasetBuilder, DatasetChartBuilder, DatasetChartDefinition, DatasetDefinition, DatasetKey, DatasetRow, DefinedDataset, DefinedDatasetChartSchema, SingleDatasetKeyId } from "./dataset-builder.types.mjs";
|
|
10
|
+
import { DefinedMaterializedView, MaterializedProjectableColumnId, MaterializedViewDefinition, MaterializedViewMetadata, MaterializedViewStepMetadata, ModelMaterializationBuilder, ModelMaterializationStartBuilder } from "./materialized-view.types.mjs";
|
|
11
|
+
import { DataModelBuilder, DataModelDefinition, DefinedDataModel, KeyedDatasetDefinition, ModelAssociationDefinition, ModelAttributeDefinition, ModelDataInput, ModelDatasetId, ModelRelationshipDefinition, ResolvedDataModelFromDefinition, SelectAttributeConfig } from "./data-model.types.mjs";
|
|
12
|
+
import { defineDataModel } from "./define-data-model.mjs";
|
|
13
|
+
import { DashboardBuilder, DashboardChartIdFromDefinition, DashboardChartInstanceFromDefinition, DashboardDataInputFromDefinition, DashboardDatasetIdFromDefinition, DashboardDatasetRowsFromDefinition, DashboardDateRangeSelection, DashboardDefinition, DashboardLocalSharedSelectFilterConfig, DashboardResolvedChart, DashboardResolvedChartOwnership, DashboardRuntime, DashboardSharedDateRangeFilterConfig, DashboardSharedDateRangeFilterDefinition, DashboardSharedDateRangeFilterRuntime, DashboardSharedDateRangePresetId, DashboardSharedDateRangeTarget, DashboardSharedFilterDefinition, DashboardSharedFilterIdFromDefinition, DashboardSharedFilterRuntime, DashboardSharedFilterRuntimeFromDefinition, DashboardSharedFilters, DashboardSharedSelectFilterRuntime, DashboardSharedSelectTarget, DefinedDashboard, ResolvedDashboardFromDefinition } from "./dashboard.types.mjs";
|
|
14
|
+
import { defineDashboard, resolveDashboardDefinition } from "./define-dashboard.mjs";
|
|
15
|
+
import { defineDataset, validateDatasetData } from "./define-dataset.mjs";
|
|
16
|
+
import { inferColumnsFromData } from "./infer-columns.mjs";
|
|
17
|
+
import { DashboardProvider, useDashboard, useDashboardChart, useDashboardContext, useDashboardDataset, useDashboardSharedFilter } from "./use-dashboard.mjs";
|
|
18
|
+
import { UseChartOptions } from "./use-chart-options.mjs";
|
|
19
|
+
import { useChart } from "./use-chart.mjs";
|
|
@@ -215,7 +215,7 @@ function detectStringDateSignal(key, samples) {
|
|
|
215
215
|
return {
|
|
216
216
|
type: "category",
|
|
217
217
|
confidence: parseRatio >= .8 ? "medium" : "low",
|
|
218
|
-
looksDateLike: parseRatio >= .8
|
|
218
|
+
looksDateLike: strongPatternRatio >= .8 || parseRatio >= .8 && hasDateKeySignal
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
221
|
/**
|
|
@@ -461,6 +461,32 @@ function sortResolvedColumns(columns) {
|
|
|
461
461
|
});
|
|
462
462
|
}
|
|
463
463
|
/**
|
|
464
|
+
* Reorder resolved columns so that schema-declared columns maintain their
|
|
465
|
+
* declaration order while inferred-only columns keep their default sorted
|
|
466
|
+
* positions.
|
|
467
|
+
*
|
|
468
|
+
* The algorithm first sorts all columns with the default heuristic, then
|
|
469
|
+
* replaces the positions occupied by declared columns with those same
|
|
470
|
+
* columns in schema declaration order. This preserves type-rank placement
|
|
471
|
+
* for inferred columns while honouring the author's intent for explicitly
|
|
472
|
+
* declared ones.
|
|
473
|
+
*
|
|
474
|
+
* When no schema columns are declared, all columns are sorted using the
|
|
475
|
+
* default heuristic.
|
|
476
|
+
*/
|
|
477
|
+
function orderResolvedColumns(columns, schemaColumnOrder) {
|
|
478
|
+
const sorted = sortResolvedColumns(columns);
|
|
479
|
+
if (!schemaColumnOrder || schemaColumnOrder.length === 0) return sorted;
|
|
480
|
+
const declaredIds = new Set(schemaColumnOrder);
|
|
481
|
+
const declaredPositions = [];
|
|
482
|
+
for (let i = 0; i < sorted.length; i++) if (declaredIds.has(sorted[i].id)) declaredPositions.push(i);
|
|
483
|
+
const schemaOrderIndex = new Map(schemaColumnOrder.map((id, index) => [id, index]));
|
|
484
|
+
const declaredInSchemaOrder = sorted.filter((column) => declaredIds.has(column.id)).sort((a, b) => schemaOrderIndex.get(a.id) - schemaOrderIndex.get(b.id));
|
|
485
|
+
const result = [...sorted];
|
|
486
|
+
for (let i = 0; i < declaredPositions.length; i++) result[declaredPositions[i]] = declaredInSchemaOrder[i];
|
|
487
|
+
return result;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
464
490
|
* Resolve chart columns directly from raw data and an optional explicit schema.
|
|
465
491
|
*/
|
|
466
492
|
function inferColumnsFromData(data, schema) {
|
|
@@ -477,7 +503,7 @@ function inferColumnsFromData(data, schema) {
|
|
|
477
503
|
}
|
|
478
504
|
for (const [key, columnSchema] of getDerivedColumnSchemas(resolvedSchema, rawFieldIds)) resolvedColumns.push(buildDerivedColumn(key, columnSchema));
|
|
479
505
|
if (resolvedColumns.length === 0) warn("No inferable or explicit chart columns were found. Provide non-empty data or schema.columns.");
|
|
480
|
-
return finalizeResolvedColumns(
|
|
506
|
+
return finalizeResolvedColumns(orderResolvedColumns(resolvedColumns, resolvedSchema?.columns ? Object.keys(resolvedSchema.columns) : null));
|
|
481
507
|
}
|
|
482
508
|
//#endregion
|
|
483
509
|
export { inferColumnsFromData };
|