@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.
- package/LICENSE +21 -0
- package/README.md +371 -0
- package/dist/core/chart-capabilities.d.ts +60 -0
- package/dist/core/chart-capabilities.d.ts.map +1 -0
- package/dist/core/chart-capabilities.js +55 -0
- package/dist/core/chart-capabilities.js.map +1 -0
- package/dist/core/colors.d.ts +25 -0
- package/dist/core/colors.d.ts.map +1 -0
- package/dist/core/colors.js +55 -0
- package/dist/core/colors.js.map +1 -0
- package/dist/core/config-utils.d.ts +43 -0
- package/dist/core/config-utils.d.ts.map +1 -0
- package/dist/core/config-utils.js +81 -0
- package/dist/core/config-utils.js.map +1 -0
- package/dist/core/date-utils.d.ts +29 -0
- package/dist/core/date-utils.d.ts.map +1 -0
- package/dist/core/date-utils.js +59 -0
- package/dist/core/date-utils.js.map +1 -0
- package/dist/core/define-chart-schema.d.ts +105 -0
- package/dist/core/define-chart-schema.d.ts.map +1 -0
- package/dist/core/define-chart-schema.js +45 -0
- package/dist/core/define-chart-schema.js.map +1 -0
- package/dist/core/formatting.d.ts +47 -0
- package/dist/core/formatting.d.ts.map +1 -0
- package/dist/core/formatting.js +397 -0
- package/dist/core/formatting.js.map +1 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/infer-columns.d.ts +6 -0
- package/dist/core/infer-columns.d.ts.map +1 -0
- package/dist/core/infer-columns.js +513 -0
- package/dist/core/infer-columns.js.map +1 -0
- package/dist/core/metric-utils.d.ts +43 -0
- package/dist/core/metric-utils.d.ts.map +1 -0
- package/dist/core/metric-utils.js +142 -0
- package/dist/core/metric-utils.js.map +1 -0
- package/dist/core/pipeline-data-points.d.ts +23 -0
- package/dist/core/pipeline-data-points.d.ts.map +1 -0
- package/dist/core/pipeline-data-points.js +236 -0
- package/dist/core/pipeline-data-points.js.map +1 -0
- package/dist/core/pipeline-helpers.d.ts +38 -0
- package/dist/core/pipeline-helpers.d.ts.map +1 -0
- package/dist/core/pipeline-helpers.js +98 -0
- package/dist/core/pipeline-helpers.js.map +1 -0
- package/dist/core/pipeline.d.ts +70 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +157 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/types.d.ts +1109 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +15 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/use-chart-options.d.ts +66 -0
- package/dist/core/use-chart-options.d.ts.map +1 -0
- package/dist/core/use-chart-options.js +5 -0
- package/dist/core/use-chart-options.js.map +1 -0
- package/dist/core/use-chart-resolvers.d.ts +14 -0
- package/dist/core/use-chart-resolvers.d.ts.map +1 -0
- package/dist/core/use-chart-resolvers.js +42 -0
- package/dist/core/use-chart-resolvers.js.map +1 -0
- package/dist/core/use-chart.d.ts +47 -0
- package/dist/core/use-chart.d.ts.map +1 -0
- package/dist/core/use-chart.js +266 -0
- package/dist/core/use-chart.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/chart-axis-ticks.d.ts +35 -0
- package/dist/ui/chart-axis-ticks.d.ts.map +1 -0
- package/dist/ui/chart-axis-ticks.js +80 -0
- package/dist/ui/chart-axis-ticks.js.map +1 -0
- package/dist/ui/chart-canvas.d.ts +22 -0
- package/dist/ui/chart-canvas.d.ts.map +1 -0
- package/dist/ui/chart-canvas.js +338 -0
- package/dist/ui/chart-canvas.js.map +1 -0
- package/dist/ui/chart-context.d.ts +89 -0
- package/dist/ui/chart-context.d.ts.map +1 -0
- package/dist/ui/chart-context.js +129 -0
- package/dist/ui/chart-context.js.map +1 -0
- package/dist/ui/chart-date-range-badge.d.ts +14 -0
- package/dist/ui/chart-date-range-badge.d.ts.map +1 -0
- package/dist/ui/chart-date-range-badge.js +31 -0
- package/dist/ui/chart-date-range-badge.js.map +1 -0
- package/dist/ui/chart-date-range-panel.d.ts +25 -0
- package/dist/ui/chart-date-range-panel.d.ts.map +1 -0
- package/dist/ui/chart-date-range-panel.js +126 -0
- package/dist/ui/chart-date-range-panel.js.map +1 -0
- package/dist/ui/chart-date-range.d.ts +14 -0
- package/dist/ui/chart-date-range.d.ts.map +1 -0
- package/dist/ui/chart-date-range.js +38 -0
- package/dist/ui/chart-date-range.js.map +1 -0
- package/dist/ui/chart-debug.d.ts +10 -0
- package/dist/ui/chart-debug.d.ts.map +1 -0
- package/dist/ui/chart-debug.js +127 -0
- package/dist/ui/chart-debug.js.map +1 -0
- package/dist/ui/chart-dropdown.d.ts +35 -0
- package/dist/ui/chart-dropdown.d.ts.map +1 -0
- package/dist/ui/chart-dropdown.js +77 -0
- package/dist/ui/chart-dropdown.js.map +1 -0
- package/dist/ui/chart-filters-panel.d.ts +19 -0
- package/dist/ui/chart-filters-panel.d.ts.map +1 -0
- package/dist/ui/chart-filters-panel.js +47 -0
- package/dist/ui/chart-filters-panel.js.map +1 -0
- package/dist/ui/chart-filters.d.ts +12 -0
- package/dist/ui/chart-filters.d.ts.map +1 -0
- package/dist/ui/chart-filters.js +27 -0
- package/dist/ui/chart-filters.js.map +1 -0
- package/dist/ui/chart-group-by-selector.d.ts +8 -0
- package/dist/ui/chart-group-by-selector.d.ts.map +1 -0
- package/dist/ui/chart-group-by-selector.js +20 -0
- package/dist/ui/chart-group-by-selector.js.map +1 -0
- package/dist/ui/chart-metric-panel.d.ts +18 -0
- package/dist/ui/chart-metric-panel.d.ts.map +1 -0
- package/dist/ui/chart-metric-panel.js +119 -0
- package/dist/ui/chart-metric-panel.js.map +1 -0
- package/dist/ui/chart-metric-selector.d.ts +10 -0
- package/dist/ui/chart-metric-selector.d.ts.map +1 -0
- package/dist/ui/chart-metric-selector.js +28 -0
- package/dist/ui/chart-metric-selector.js.map +1 -0
- package/dist/ui/chart-select.d.ts +25 -0
- package/dist/ui/chart-select.d.ts.map +1 -0
- package/dist/ui/chart-select.js +36 -0
- package/dist/ui/chart-select.js.map +1 -0
- package/dist/ui/chart-source-switcher.d.ts +16 -0
- package/dist/ui/chart-source-switcher.d.ts.map +1 -0
- package/dist/ui/chart-source-switcher.js +32 -0
- package/dist/ui/chart-source-switcher.js.map +1 -0
- package/dist/ui/chart-time-bucket-selector.d.ts +9 -0
- package/dist/ui/chart-time-bucket-selector.d.ts.map +1 -0
- package/dist/ui/chart-time-bucket-selector.js +26 -0
- package/dist/ui/chart-time-bucket-selector.js.map +1 -0
- package/dist/ui/chart-toolbar-overflow.d.ts +29 -0
- package/dist/ui/chart-toolbar-overflow.d.ts.map +1 -0
- package/dist/ui/chart-toolbar-overflow.js +110 -0
- package/dist/ui/chart-toolbar-overflow.js.map +1 -0
- package/dist/ui/chart-toolbar.d.ts +45 -0
- package/dist/ui/chart-toolbar.d.ts.map +1 -0
- package/dist/ui/chart-toolbar.js +45 -0
- package/dist/ui/chart-toolbar.js.map +1 -0
- package/dist/ui/chart-type-selector.d.ts +8 -0
- package/dist/ui/chart-type-selector.d.ts.map +1 -0
- package/dist/ui/chart-type-selector.js +23 -0
- package/dist/ui/chart-type-selector.js.map +1 -0
- package/dist/ui/chart-x-axis-selector.d.ts +8 -0
- package/dist/ui/chart-x-axis-selector.d.ts.map +1 -0
- package/dist/ui/chart-x-axis-selector.js +15 -0
- package/dist/ui/chart-x-axis-selector.js.map +1 -0
- package/dist/ui/index.d.ts +25 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +24 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/theme.css +62 -0
- package/dist/ui/toolbar-types.d.ts +43 -0
- package/dist/ui/toolbar-types.d.ts.map +1 -0
- package/dist/ui/toolbar-types.js +51 -0
- package/dist/ui/toolbar-types.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default metric used when no numeric aggregation is selected.
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_METRIC = { kind: 'count' };
|
|
5
|
+
/**
|
|
6
|
+
* Type guard for aggregate metrics.
|
|
7
|
+
*/
|
|
8
|
+
export function isAggregateMetric(metric) {
|
|
9
|
+
return metric.kind === 'aggregate';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Compare two metric definitions for semantic equality.
|
|
13
|
+
*/
|
|
14
|
+
export function isSameMetric(left, right) {
|
|
15
|
+
if (left.kind !== right.kind) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (left.kind === 'count') {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return (right.kind === 'aggregate'
|
|
22
|
+
&& left.columnId === right.columnId
|
|
23
|
+
&& left.aggregate === right.aggregate
|
|
24
|
+
&& (left.includeZeros ?? true) === (right.includeZeros ?? true));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Human-readable label for a numeric aggregate.
|
|
28
|
+
*/
|
|
29
|
+
export function getAggregateMetricLabel(columnLabel, aggregate) {
|
|
30
|
+
switch (aggregate) {
|
|
31
|
+
case 'sum':
|
|
32
|
+
return `Sum of ${columnLabel}`;
|
|
33
|
+
case 'avg':
|
|
34
|
+
return `Avg ${columnLabel}`;
|
|
35
|
+
case 'min':
|
|
36
|
+
return `Min ${columnLabel}`;
|
|
37
|
+
case 'max':
|
|
38
|
+
return `Max ${columnLabel}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Human-readable label for a metric.
|
|
43
|
+
*/
|
|
44
|
+
export function getMetricLabel(metric, columns) {
|
|
45
|
+
if (!isAggregateMetric(metric)) {
|
|
46
|
+
return 'Count';
|
|
47
|
+
}
|
|
48
|
+
const column = columns.find((candidate) => candidate.type === 'number' && candidate.id === metric.columnId);
|
|
49
|
+
if (!column) {
|
|
50
|
+
return 'Count';
|
|
51
|
+
}
|
|
52
|
+
return getAggregateMetricLabel(column.label, metric.aggregate);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the metric options available for a set of columns.
|
|
56
|
+
*/
|
|
57
|
+
export function buildAvailableMetrics(columns) {
|
|
58
|
+
const metrics = [DEFAULT_METRIC];
|
|
59
|
+
const numberColumns = columns.filter((column) => column.type === 'number');
|
|
60
|
+
for (const column of numberColumns) {
|
|
61
|
+
metrics.push({ kind: 'aggregate', columnId: column.id, aggregate: 'sum' }, { kind: 'aggregate', columnId: column.id, aggregate: 'avg' }, { kind: 'aggregate', columnId: column.id, aggregate: 'min' }, { kind: 'aggregate', columnId: column.id, aggregate: 'max' });
|
|
62
|
+
}
|
|
63
|
+
return metrics;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Expand declarative metric restriction entries into the normalized metric list
|
|
67
|
+
* used by the runtime and typed chart state.
|
|
68
|
+
*/
|
|
69
|
+
export function normalizeMetricAllowances(allowedMetrics) {
|
|
70
|
+
if (!allowedMetrics) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const normalized = [];
|
|
74
|
+
for (const allowedMetric of allowedMetrics) {
|
|
75
|
+
if (allowedMetric.kind === 'count') {
|
|
76
|
+
normalized.push(allowedMetric);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const aggregates = Array.isArray(allowedMetric.aggregate)
|
|
80
|
+
? allowedMetric.aggregate
|
|
81
|
+
: [allowedMetric.aggregate];
|
|
82
|
+
for (const aggregate of aggregates) {
|
|
83
|
+
normalized.push({
|
|
84
|
+
kind: 'aggregate',
|
|
85
|
+
columnId: allowedMetric.columnId,
|
|
86
|
+
aggregate,
|
|
87
|
+
includeZeros: allowedMetric.includeZeros,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return normalized;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Apply a declarative metric whitelist to the inferred metric options.
|
|
95
|
+
*
|
|
96
|
+
* Metrics are matched structurally so callers can safely pass fresh object
|
|
97
|
+
* literals in `config.metric.allowed`. The final order follows the declarative
|
|
98
|
+
* restriction list, so the first allowed metric becomes the default.
|
|
99
|
+
*/
|
|
100
|
+
export function restrictAvailableMetrics(metrics, config) {
|
|
101
|
+
const normalizedAllowedMetrics = normalizeMetricAllowances(config?.allowed);
|
|
102
|
+
if (!normalizedAllowedMetrics) {
|
|
103
|
+
const hiddenMetrics = config?.hidden;
|
|
104
|
+
if (!hiddenMetrics || hiddenMetrics.length === 0) {
|
|
105
|
+
return [...metrics];
|
|
106
|
+
}
|
|
107
|
+
const visibleMetrics = metrics.filter(metric => hiddenMetrics.every(hiddenMetric => !isSameMetric(metric, hiddenMetric)));
|
|
108
|
+
return visibleMetrics.length > 0 ? visibleMetrics : [metrics[0] ?? DEFAULT_METRIC];
|
|
109
|
+
}
|
|
110
|
+
const allowedMetrics = normalizedAllowedMetrics.filter(allowedMetric => metrics.some(metric => isSameMetric(metric, allowedMetric)));
|
|
111
|
+
const hiddenMetrics = config?.hidden;
|
|
112
|
+
const restricted = !hiddenMetrics || hiddenMetrics.length === 0
|
|
113
|
+
? allowedMetrics
|
|
114
|
+
: allowedMetrics.filter(metric => hiddenMetrics.every(hiddenMetric => !isSameMetric(metric, hiddenMetric)));
|
|
115
|
+
// A chart always needs one active metric. Fall back to the inferred default if
|
|
116
|
+
// the whitelist ends up empty or does not match the active source.
|
|
117
|
+
return restricted.length > 0 ? restricted : [metrics[0] ?? DEFAULT_METRIC];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Validate a metric against the active source.
|
|
121
|
+
*/
|
|
122
|
+
export function resolveMetric(metric, columns, availableMetrics, configuredDefaultMetric) {
|
|
123
|
+
if (availableMetrics && availableMetrics.length > 0) {
|
|
124
|
+
const selectedMetric = availableMetrics.find(candidate => isSameMetric(candidate, metric));
|
|
125
|
+
if (selectedMetric) {
|
|
126
|
+
return selectedMetric;
|
|
127
|
+
}
|
|
128
|
+
const defaultMetric = configuredDefaultMetric
|
|
129
|
+
? availableMetrics.find(candidate => isSameMetric(candidate, configuredDefaultMetric))
|
|
130
|
+
: undefined;
|
|
131
|
+
return defaultMetric ?? availableMetrics[0];
|
|
132
|
+
}
|
|
133
|
+
if (!isAggregateMetric(metric)) {
|
|
134
|
+
return DEFAULT_METRIC;
|
|
135
|
+
}
|
|
136
|
+
const column = columns.find((candidate) => candidate.type === 'number' && candidate.id === metric.columnId);
|
|
137
|
+
if (!column) {
|
|
138
|
+
return DEFAULT_METRIC;
|
|
139
|
+
}
|
|
140
|
+
return metric;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=metric-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric-utils.js","sourceRoot":"","sources":["../../src/core/metric-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bucket and aggregation steps for the chart transformation pipeline.
|
|
3
|
+
*/
|
|
4
|
+
import type { ChartColumn, Metric, NumberColumn, TimeBucket, TransformedDataPoint } from './types.js';
|
|
5
|
+
type DataPointResult = {
|
|
6
|
+
data: TransformedDataPoint[];
|
|
7
|
+
groups: string[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Build chart-ready data points by bucketing the X-axis, pivoting groups, and
|
|
11
|
+
* aggregating the selected metric.
|
|
12
|
+
*
|
|
13
|
+
* @param items - Filtered source data
|
|
14
|
+
* @param xColumn - Active X-axis column
|
|
15
|
+
* @param groupByColumn - Optional group-by column
|
|
16
|
+
* @param metric - Selected metric configuration
|
|
17
|
+
* @param numberColumns - Number columns available for metric lookup
|
|
18
|
+
* @param timeBucket - Time bucket used for date X-axes
|
|
19
|
+
* @returns Aggregated chart data points and group labels
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildDataPoints<T, TColumnId extends string>(items: T[], xColumn: ChartColumn<T, TColumnId>, groupByColumn: ChartColumn<T, TColumnId> | null, metric: Metric<TColumnId>, numberColumns: NumberColumn<T, TColumnId>[], timeBucket: TimeBucket): DataPointResult;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=pipeline-data-points.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-data-points.d.ts","sourceRoot":"","sources":["../../src/core/pipeline-data-points.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,WAAW,EAEX,MAAM,EACN,YAAY,EACZ,UAAU,EACV,oBAAoB,EACrB,MAAM,YAAY,CAAA;AAOnB,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,oBAAoB,EAAE,CAAA;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,EACzD,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,EAClC,aAAa,EAAE,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,EAC/C,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,EACzB,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,EAC3C,UAAU,EAAE,UAAU,GACrB,eAAe,CAkBjB"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bucket and aggregation steps for the chart transformation pipeline.
|
|
3
|
+
*/
|
|
4
|
+
import { isAggregateMetric } from './metric-utils.js';
|
|
5
|
+
import { aggregate, dateBucketKey, dateBucketLabel, getStringValue } from './pipeline-helpers.js';
|
|
6
|
+
/**
|
|
7
|
+
* Build chart-ready data points by bucketing the X-axis, pivoting groups, and
|
|
8
|
+
* aggregating the selected metric.
|
|
9
|
+
*
|
|
10
|
+
* @param items - Filtered source data
|
|
11
|
+
* @param xColumn - Active X-axis column
|
|
12
|
+
* @param groupByColumn - Optional group-by column
|
|
13
|
+
* @param metric - Selected metric configuration
|
|
14
|
+
* @param numberColumns - Number columns available for metric lookup
|
|
15
|
+
* @param timeBucket - Time bucket used for date X-axes
|
|
16
|
+
* @returns Aggregated chart data points and group labels
|
|
17
|
+
*/
|
|
18
|
+
export function buildDataPoints(items, xColumn, groupByColumn, metric, numberColumns, timeBucket) {
|
|
19
|
+
const groupSet = new Set();
|
|
20
|
+
if (groupByColumn) {
|
|
21
|
+
for (const item of items) {
|
|
22
|
+
groupSet.add(getStringValue(item, groupByColumn));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const groups = groupByColumn ? [...groupSet].toSorted() : ['value'];
|
|
26
|
+
const metricColumn = isAggregateMetric(metric)
|
|
27
|
+
? (numberColumns.find((column) => column.id === metric.columnId) ?? null)
|
|
28
|
+
: null;
|
|
29
|
+
if (xColumn.type === 'date') {
|
|
30
|
+
return buildTimeBuckets(items, xColumn, groupByColumn, groups, metric, metricColumn, timeBucket);
|
|
31
|
+
}
|
|
32
|
+
return buildCategoryBuckets(items, xColumn, groupByColumn, groups, metric, metricColumn);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate a continuous sequence of date buckets from the minimum to maximum
|
|
36
|
+
* date found in the data.
|
|
37
|
+
*
|
|
38
|
+
* @param items - Filtered source data
|
|
39
|
+
* @param xColumn - Active date column
|
|
40
|
+
* @param bucket - Time bucket granularity
|
|
41
|
+
* @returns Every bucket between the first and last date in the dataset
|
|
42
|
+
*/
|
|
43
|
+
function generateBucketsFromData(items, xColumn, bucket) {
|
|
44
|
+
let min = null;
|
|
45
|
+
let max = null;
|
|
46
|
+
for (const item of items) {
|
|
47
|
+
const rawValue = xColumn.accessor(item);
|
|
48
|
+
if (rawValue == null)
|
|
49
|
+
continue;
|
|
50
|
+
const date = new Date(rawValue);
|
|
51
|
+
if (Number.isNaN(date.getTime()))
|
|
52
|
+
continue;
|
|
53
|
+
if (!min || date < min)
|
|
54
|
+
min = date;
|
|
55
|
+
if (!max || date > max)
|
|
56
|
+
max = date;
|
|
57
|
+
}
|
|
58
|
+
if (!min || !max)
|
|
59
|
+
return [];
|
|
60
|
+
const buckets = [];
|
|
61
|
+
const cursor = startOfBucket(min, bucket);
|
|
62
|
+
const seenKeys = new Set();
|
|
63
|
+
const maxBuckets = 500;
|
|
64
|
+
for (let bucketCount = 0; bucketCount < maxBuckets; bucketCount += 1) {
|
|
65
|
+
if (cursor > max)
|
|
66
|
+
break;
|
|
67
|
+
const key = dateBucketKey(cursor, bucket);
|
|
68
|
+
if (!seenKeys.has(key)) {
|
|
69
|
+
seenKeys.add(key);
|
|
70
|
+
buckets.push({ key, label: dateBucketLabel(key, bucket) });
|
|
71
|
+
}
|
|
72
|
+
advanceBucketCursor(cursor, bucket);
|
|
73
|
+
}
|
|
74
|
+
return buckets;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Normalize a date to the start of its containing bucket.
|
|
78
|
+
*
|
|
79
|
+
* @param date - Source date
|
|
80
|
+
* @param bucket - Time bucket granularity
|
|
81
|
+
* @returns Start boundary for the bucket containing the source date
|
|
82
|
+
*/
|
|
83
|
+
function startOfBucket(date, bucket) {
|
|
84
|
+
const normalized = new Date(date);
|
|
85
|
+
normalized.setHours(0, 0, 0, 0);
|
|
86
|
+
switch (bucket) {
|
|
87
|
+
case 'day':
|
|
88
|
+
return normalized;
|
|
89
|
+
case 'week': {
|
|
90
|
+
const day = normalized.getDay();
|
|
91
|
+
normalized.setDate(normalized.getDate() - ((day + 6) % 7));
|
|
92
|
+
return normalized;
|
|
93
|
+
}
|
|
94
|
+
case 'month':
|
|
95
|
+
normalized.setDate(1);
|
|
96
|
+
return normalized;
|
|
97
|
+
case 'quarter':
|
|
98
|
+
normalized.setMonth(Math.floor(normalized.getMonth() / 3) * 3, 1);
|
|
99
|
+
return normalized;
|
|
100
|
+
case 'year':
|
|
101
|
+
normalized.setMonth(0, 1);
|
|
102
|
+
return normalized;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Advance a mutable cursor by a single bucket interval.
|
|
107
|
+
*
|
|
108
|
+
* @param cursor - Current date cursor
|
|
109
|
+
* @param bucket - Time bucket granularity
|
|
110
|
+
*/
|
|
111
|
+
function advanceBucketCursor(cursor, bucket) {
|
|
112
|
+
switch (bucket) {
|
|
113
|
+
case 'day':
|
|
114
|
+
cursor.setDate(cursor.getDate() + 1);
|
|
115
|
+
break;
|
|
116
|
+
case 'week':
|
|
117
|
+
cursor.setDate(cursor.getDate() + 7);
|
|
118
|
+
break;
|
|
119
|
+
case 'month':
|
|
120
|
+
cursor.setMonth(cursor.getMonth() + 1);
|
|
121
|
+
break;
|
|
122
|
+
case 'quarter':
|
|
123
|
+
cursor.setMonth(cursor.getMonth() + 3);
|
|
124
|
+
break;
|
|
125
|
+
case 'year':
|
|
126
|
+
cursor.setFullYear(cursor.getFullYear() + 1);
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build data points for a date X-axis.
|
|
132
|
+
*
|
|
133
|
+
* @param items - Filtered source data
|
|
134
|
+
* @param xColumn - Active date column
|
|
135
|
+
* @param groupByColumn - Optional group-by column
|
|
136
|
+
* @param groups - Resolved group labels
|
|
137
|
+
* @param metric - Selected metric configuration
|
|
138
|
+
* @param metricColumn - Resolved numeric metric column
|
|
139
|
+
* @param timeBucket - Time bucket granularity
|
|
140
|
+
* @returns Aggregated date-bucketed data points
|
|
141
|
+
*/
|
|
142
|
+
function buildTimeBuckets(items, xColumn, groupByColumn, groups, metric, metricColumn, timeBucket) {
|
|
143
|
+
const allBuckets = generateBucketsFromData(items, xColumn, timeBucket);
|
|
144
|
+
const accumulator = new Map();
|
|
145
|
+
for (const { key } of allBuckets) {
|
|
146
|
+
const groupMap = new Map();
|
|
147
|
+
for (const group of groups) {
|
|
148
|
+
groupMap.set(group, []);
|
|
149
|
+
}
|
|
150
|
+
accumulator.set(key, groupMap);
|
|
151
|
+
}
|
|
152
|
+
for (const item of items) {
|
|
153
|
+
const rawValue = xColumn.accessor(item);
|
|
154
|
+
if (rawValue == null)
|
|
155
|
+
continue;
|
|
156
|
+
const date = new Date(rawValue);
|
|
157
|
+
const key = dateBucketKey(date, timeBucket);
|
|
158
|
+
const groupMap = accumulator.get(key);
|
|
159
|
+
if (!groupMap)
|
|
160
|
+
continue;
|
|
161
|
+
const group = groupByColumn ? getStringValue(item, groupByColumn) : 'value';
|
|
162
|
+
const values = groupMap.get(group);
|
|
163
|
+
if (!values)
|
|
164
|
+
continue;
|
|
165
|
+
if (metricColumn) {
|
|
166
|
+
const metricValue = metricColumn.accessor(item);
|
|
167
|
+
if (metricValue != null)
|
|
168
|
+
values.push(metricValue);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
values.push(1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const data = allBuckets.map(({ key, label }) => {
|
|
175
|
+
const point = { xLabel: label, xKey: key };
|
|
176
|
+
const groupMap = accumulator.get(key);
|
|
177
|
+
for (const group of groups) {
|
|
178
|
+
point[group] = aggregate(groupMap.get(group) ?? [], metric.kind === 'aggregate' ? metric.aggregate : 'count', metric.kind === 'aggregate' ? (metric.includeZeros ?? true) : true);
|
|
179
|
+
}
|
|
180
|
+
return point;
|
|
181
|
+
});
|
|
182
|
+
return { data, groups };
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Build data points for a categorical or boolean X-axis.
|
|
186
|
+
*
|
|
187
|
+
* @param items - Filtered source data
|
|
188
|
+
* @param xColumn - Active X-axis column
|
|
189
|
+
* @param groupByColumn - Optional group-by column
|
|
190
|
+
* @param groups - Resolved group labels
|
|
191
|
+
* @param metric - Selected metric configuration
|
|
192
|
+
* @param metricColumn - Resolved numeric metric column
|
|
193
|
+
* @returns Aggregated category-bucketed data points
|
|
194
|
+
*/
|
|
195
|
+
function buildCategoryBuckets(items, xColumn, groupByColumn, groups, metric, metricColumn) {
|
|
196
|
+
const xValues = new Set();
|
|
197
|
+
for (const item of items) {
|
|
198
|
+
xValues.add(getStringValue(item, xColumn));
|
|
199
|
+
}
|
|
200
|
+
const accumulator = new Map();
|
|
201
|
+
for (const xValue of xValues) {
|
|
202
|
+
const groupMap = new Map();
|
|
203
|
+
for (const group of groups) {
|
|
204
|
+
groupMap.set(group, []);
|
|
205
|
+
}
|
|
206
|
+
accumulator.set(xValue, groupMap);
|
|
207
|
+
}
|
|
208
|
+
for (const item of items) {
|
|
209
|
+
const xValue = getStringValue(item, xColumn);
|
|
210
|
+
const groupMap = accumulator.get(xValue);
|
|
211
|
+
if (!groupMap)
|
|
212
|
+
continue;
|
|
213
|
+
const group = groupByColumn ? getStringValue(item, groupByColumn) : 'value';
|
|
214
|
+
const values = groupMap.get(group);
|
|
215
|
+
if (!values)
|
|
216
|
+
continue;
|
|
217
|
+
if (metricColumn) {
|
|
218
|
+
const metricValue = metricColumn.accessor(item);
|
|
219
|
+
if (metricValue != null)
|
|
220
|
+
values.push(metricValue);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
values.push(1);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const data = [...xValues].map((xValue) => {
|
|
227
|
+
const point = { xLabel: xValue, xKey: xValue };
|
|
228
|
+
const groupMap = accumulator.get(xValue);
|
|
229
|
+
for (const group of groups) {
|
|
230
|
+
point[group] = aggregate(groupMap.get(group) ?? [], metric.kind === 'aggregate' ? metric.aggregate : 'count', metric.kind === 'aggregate' ? (metric.includeZeros ?? true) : true);
|
|
231
|
+
}
|
|
232
|
+
return point;
|
|
233
|
+
});
|
|
234
|
+
return { data, groups };
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=pipeline-data-points.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-data-points.js","sourceRoot":"","sources":["../../src/core/pipeline-data-points.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for the chart transformation pipeline.
|
|
3
|
+
*/
|
|
4
|
+
import type { AggregateFunction, ChartColumn, TimeBucket } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Format a stable key for a date bucket.
|
|
7
|
+
*
|
|
8
|
+
* @param date - Source date
|
|
9
|
+
* @param bucket - Time bucket granularity
|
|
10
|
+
* @returns Machine-friendly bucket key
|
|
11
|
+
*/
|
|
12
|
+
export declare function dateBucketKey(date: Date, bucket: TimeBucket): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format a bucket key into a human-readable label.
|
|
15
|
+
*
|
|
16
|
+
* @param key - Bucket key
|
|
17
|
+
* @param bucket - Time bucket granularity
|
|
18
|
+
* @returns Display label for the chart axis
|
|
19
|
+
*/
|
|
20
|
+
export declare function dateBucketLabel(key: string, bucket: TimeBucket): string;
|
|
21
|
+
/**
|
|
22
|
+
* Extract a comparable string value from an item using a column definition.
|
|
23
|
+
*
|
|
24
|
+
* @param item - Raw data item
|
|
25
|
+
* @param column - Column definition to read from
|
|
26
|
+
* @returns String value used by filters and groups
|
|
27
|
+
*/
|
|
28
|
+
export declare function getStringValue<T>(item: T, column: ChartColumn<T>): string;
|
|
29
|
+
/**
|
|
30
|
+
* Aggregate numeric values using the requested function.
|
|
31
|
+
*
|
|
32
|
+
* @param values - Numeric values to aggregate
|
|
33
|
+
* @param fn - Aggregation strategy
|
|
34
|
+
* @param includeZeros - Whether zero values should participate in avg/min/max
|
|
35
|
+
* @returns Aggregated numeric result
|
|
36
|
+
*/
|
|
37
|
+
export declare function aggregate(values: number[], fn: AggregateFunction, includeZeros?: boolean): number;
|
|
38
|
+
//# sourceMappingURL=pipeline-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-helpers.d.ts","sourceRoot":"","sources":["../../src/core/pipeline-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAC,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAC,MAAM,YAAY,CAAA;AAE1E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAoBpE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAEvE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,CAqBzE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,YAAY,UAAO,GAAG,MAAM,CAkB9F"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for the chart transformation pipeline.
|
|
3
|
+
*/
|
|
4
|
+
import { formatTimeBucketLabel } from './formatting.js';
|
|
5
|
+
/**
|
|
6
|
+
* Format a stable key for a date bucket.
|
|
7
|
+
*
|
|
8
|
+
* @param date - Source date
|
|
9
|
+
* @param bucket - Time bucket granularity
|
|
10
|
+
* @returns Machine-friendly bucket key
|
|
11
|
+
*/
|
|
12
|
+
export function dateBucketKey(date, bucket) {
|
|
13
|
+
const year = date.getFullYear();
|
|
14
|
+
const month = date.getMonth();
|
|
15
|
+
switch (bucket) {
|
|
16
|
+
case 'day':
|
|
17
|
+
return `${year}-${String(month + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
|
18
|
+
case 'week': {
|
|
19
|
+
const day = date.getDay();
|
|
20
|
+
const monday = new Date(date);
|
|
21
|
+
monday.setDate(date.getDate() - ((day + 6) % 7));
|
|
22
|
+
return `${monday.getFullYear()}-${String(monday.getMonth() + 1).padStart(2, '0')}-${String(monday.getDate()).padStart(2, '0')}`;
|
|
23
|
+
}
|
|
24
|
+
case 'month':
|
|
25
|
+
return `${year}-${String(month + 1).padStart(2, '0')}`;
|
|
26
|
+
case 'quarter':
|
|
27
|
+
return `${year}-Q${Math.floor(month / 3) + 1}`;
|
|
28
|
+
case 'year':
|
|
29
|
+
return `${year}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Format a bucket key into a human-readable label.
|
|
34
|
+
*
|
|
35
|
+
* @param key - Bucket key
|
|
36
|
+
* @param bucket - Time bucket granularity
|
|
37
|
+
* @returns Display label for the chart axis
|
|
38
|
+
*/
|
|
39
|
+
export function dateBucketLabel(key, bucket) {
|
|
40
|
+
return formatTimeBucketLabel(key, bucket, 'axis');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Extract a comparable string value from an item using a column definition.
|
|
44
|
+
*
|
|
45
|
+
* @param item - Raw data item
|
|
46
|
+
* @param column - Column definition to read from
|
|
47
|
+
* @returns String value used by filters and groups
|
|
48
|
+
*/
|
|
49
|
+
export function getStringValue(item, column) {
|
|
50
|
+
switch (column.type) {
|
|
51
|
+
case 'boolean': {
|
|
52
|
+
const value = column.accessor(item);
|
|
53
|
+
if (value === true)
|
|
54
|
+
return column.trueLabel;
|
|
55
|
+
if (value === false)
|
|
56
|
+
return column.falseLabel;
|
|
57
|
+
return 'Unknown';
|
|
58
|
+
}
|
|
59
|
+
case 'category': {
|
|
60
|
+
const value = column.accessor(item);
|
|
61
|
+
return value ?? 'Unknown';
|
|
62
|
+
}
|
|
63
|
+
case 'date': {
|
|
64
|
+
const value = column.accessor(item);
|
|
65
|
+
return value != null ? String(value) : 'Unknown';
|
|
66
|
+
}
|
|
67
|
+
case 'number': {
|
|
68
|
+
const value = column.accessor(item);
|
|
69
|
+
return value != null ? String(value) : 'Unknown';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Aggregate numeric values using the requested function.
|
|
75
|
+
*
|
|
76
|
+
* @param values - Numeric values to aggregate
|
|
77
|
+
* @param fn - Aggregation strategy
|
|
78
|
+
* @param includeZeros - Whether zero values should participate in avg/min/max
|
|
79
|
+
* @returns Aggregated numeric result
|
|
80
|
+
*/
|
|
81
|
+
export function aggregate(values, fn, includeZeros = true) {
|
|
82
|
+
if (fn === 'count')
|
|
83
|
+
return values.length;
|
|
84
|
+
const effectiveValues = !includeZeros && fn !== 'sum' ? values.filter((value) => value !== 0) : values;
|
|
85
|
+
if (effectiveValues.length === 0)
|
|
86
|
+
return 0;
|
|
87
|
+
switch (fn) {
|
|
88
|
+
case 'sum':
|
|
89
|
+
return effectiveValues.reduce((sum, value) => sum + value, 0);
|
|
90
|
+
case 'avg':
|
|
91
|
+
return effectiveValues.reduce((sum, value) => sum + value, 0) / effectiveValues.length;
|
|
92
|
+
case 'min':
|
|
93
|
+
return Math.min(...effectiveValues);
|
|
94
|
+
case 'max':
|
|
95
|
+
return Math.max(...effectiveValues);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=pipeline-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-helpers.js","sourceRoot":"","sources":["../../src/core/pipeline-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data transformation pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions that transform raw data into chart-ready format.
|
|
5
|
+
* Pipeline: Raw Data -> Filter -> Bucket by X-axis -> Pivot by groupBy -> Aggregate -> Sort
|
|
6
|
+
*/
|
|
7
|
+
import type { AvailableFilter, ChartColumn, ChartSeries, FilterState, Metric, SortConfig, TimeBucket, TransformedDataPoint } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Input for the transformation pipeline.
|
|
10
|
+
*
|
|
11
|
+
* @property data - Raw data items
|
|
12
|
+
* @property columns - Column definitions
|
|
13
|
+
* @property xAxisId - Active X-axis column ID
|
|
14
|
+
* @property groupById - Active groupBy column ID (null = no grouping)
|
|
15
|
+
* @property metric - What the Y-axis measures
|
|
16
|
+
* @property timeBucket - Time bucket size for date X-axes
|
|
17
|
+
* @property filters - Active filter state
|
|
18
|
+
* @property sorting - Sort configuration
|
|
19
|
+
*/
|
|
20
|
+
export type PipelineInput<T, TColumnId extends string = string> = {
|
|
21
|
+
data: readonly T[];
|
|
22
|
+
columns: readonly ChartColumn<T, TColumnId>[];
|
|
23
|
+
xAxisId: TColumnId;
|
|
24
|
+
groupById: TColumnId | null;
|
|
25
|
+
metric: Metric<TColumnId>;
|
|
26
|
+
timeBucket: TimeBucket;
|
|
27
|
+
filters: FilterState<TColumnId>;
|
|
28
|
+
sorting: SortConfig | null;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Output of the transformation pipeline.
|
|
32
|
+
*
|
|
33
|
+
* @property data - Transformed data points ready for recharts
|
|
34
|
+
* @property series - Series definitions for rendering
|
|
35
|
+
* @property groups - Unique group labels
|
|
36
|
+
*/
|
|
37
|
+
export type PipelineOutput = {
|
|
38
|
+
data: TransformedDataPoint[];
|
|
39
|
+
series: ChartSeries[];
|
|
40
|
+
groups: string[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Apply active filters to the raw data.
|
|
44
|
+
* Filters are AND-combined across columns and OR-combined within a column.
|
|
45
|
+
*
|
|
46
|
+
* @param data - Raw data items
|
|
47
|
+
* @param columns - Column definitions used to read values
|
|
48
|
+
* @param filters - Active filter state
|
|
49
|
+
* @returns Filtered data items
|
|
50
|
+
*/
|
|
51
|
+
export declare function applyFilters<T, TColumnId extends string>(data: readonly T[], columns: readonly ChartColumn<T, TColumnId>[], filters: FilterState<TColumnId>): T[];
|
|
52
|
+
/**
|
|
53
|
+
* Run the full transformation pipeline.
|
|
54
|
+
*
|
|
55
|
+
* Raw Data -> Filter -> Bucket -> Pivot -> Aggregate -> Sort -> Output
|
|
56
|
+
*
|
|
57
|
+
* @param input - Pipeline configuration and source data
|
|
58
|
+
* @returns Transformed data, series metadata, and group labels
|
|
59
|
+
*/
|
|
60
|
+
export declare function runPipeline<T, TColumnId extends string>(input: PipelineInput<T, TColumnId>): PipelineOutput;
|
|
61
|
+
/**
|
|
62
|
+
* Extract available filter options from data for every category and boolean
|
|
63
|
+
* column.
|
|
64
|
+
*
|
|
65
|
+
* @param data - Raw data items
|
|
66
|
+
* @param columns - Column definitions
|
|
67
|
+
* @returns Filter metadata and option counts per filterable column
|
|
68
|
+
*/
|
|
69
|
+
export declare function extractAvailableFilters<T, TColumnId extends string>(data: readonly T[], columns: readonly ChartColumn<T, TColumnId>[]): AvailableFilter<TColumnId>[];
|
|
70
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EACV,eAAe,EAGf,WAAW,EACX,WAAW,EACX,WAAW,EACX,MAAM,EAEN,UAAU,EACV,UAAU,EACV,oBAAoB,EACrB,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,GAAG,MAAM,IAAI;IAChE,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAA;IAC7C,OAAO,EAAE,SAAS,CAAA;IAClB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;IACzB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;IAC/B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAA;CAC3B,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,oBAAoB,EAAE,CAAA;IAC5B,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,EACtD,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,EAC7C,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,GAC9B,CAAC,EAAE,CAiBL;AAgED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,EACrD,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,SAAS,CAAC,GACjC,cAAc,CA2BhB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,SAAS,SAAS,MAAM,EACjE,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,GAC5C,eAAe,CAAC,SAAS,CAAC,EAAE,CA+B9B"}
|