@matthieumordrel/chart-studio 0.2.4 → 0.3.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/README.md +42 -42
- package/dist/core/config-utils.mjs +3 -2
- package/dist/core/define-chart-schema.d.mts +26 -94
- package/dist/core/define-chart-schema.mjs +26 -34
- package/dist/core/infer-columns.d.mts +2 -2
- package/dist/core/infer-columns.mjs +4 -2
- package/dist/core/metric-utils.mjs +13 -5
- package/dist/core/schema-builder.mjs +335 -0
- package/dist/core/schema-builder.types.d.mts +279 -0
- package/dist/core/types.d.mts +24 -11
- package/dist/core/use-chart-options.d.mts +7 -4
- package/dist/core/use-chart.d.mts +4 -4
- package/dist/core/use-chart.mjs +20 -15
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/ui/chart-canvas.d.mts +7 -3
- package/dist/ui/chart-canvas.mjs +62 -22
- package/dist/ui/chart-context.d.mts +8 -4
- package/dist/ui/chart-debug.d.mts +6 -2
- package/dist/ui/chart-debug.mjs +5 -1
- package/dist/ui/chart-toolbar.d.mts +6 -2
- package/dist/ui/chart-toolbar.mjs +4 -0
- package/dist/ui/percent-stacked.mjs +36 -0
- package/package.json +1 -1
package/dist/core/types.d.mts
CHANGED
|
@@ -501,7 +501,18 @@ type ChartSchemaValidationTarget<T, TSchema extends ChartSchema<T, any>> = {
|
|
|
501
501
|
type ValidatedChartSchema<T, TSchema> = TSchema extends ChartSchema<T, any> ? TSchema & ExactShape<ChartSchemaValidationTarget<T, TSchema>, TSchema> & ValidateChartSchemaLiterals<T, TSchema> : TSchema;
|
|
502
502
|
/** Strict schema object returned by `defineChartSchema(...)`. */
|
|
503
503
|
type DefinedChartSchema<T, TSchema extends ChartSchema<T, any> = ChartSchema<T, any>> = TSchema & ChartSchemaDefinitionBrand;
|
|
504
|
-
|
|
504
|
+
/**
|
|
505
|
+
* Public schema definition input accepted by chart-studio APIs.
|
|
506
|
+
*
|
|
507
|
+
* Most callers use the fluent builder returned by `defineChartSchema<Row>()`.
|
|
508
|
+
* Plain schema objects are also accepted at the runtime boundary.
|
|
509
|
+
*/
|
|
510
|
+
type ChartSchemaDefinition<T, TSchema extends ChartSchema<T, any> = ChartSchema<T, any>> = TSchema | {
|
|
511
|
+
build: () => DefinedChartSchema<T, TSchema>;
|
|
512
|
+
};
|
|
513
|
+
type ResolvedChartSchemaFromDefinition<TSchema> = TSchema extends DefinedChartSchema<any, infer TResolvedSchema> ? TResolvedSchema : TSchema extends {
|
|
514
|
+
build: () => DefinedChartSchema<any, infer TResolvedSchema>;
|
|
515
|
+
} ? TResolvedSchema : TSchema extends ChartSchema<any, any> ? TSchema : undefined;
|
|
505
516
|
/** GroupBy IDs narrowed by explicit schema restrictions when present. */
|
|
506
517
|
type RestrictedGroupByColumnIdFromSchema<T, TSchema extends ChartSchema<T, any> | undefined = undefined> = RestrictOptionsFromControlConfig<ResolvedGroupByColumnIdFromSchema<T, TSchema>, ConfigSection<TSchema, 'groupBy'>>;
|
|
507
518
|
/** X-axis IDs narrowed by explicit schema restrictions when present. */
|
|
@@ -657,7 +668,7 @@ type ChartTypeConfig = SelectableControlConfig<ChartType>;
|
|
|
657
668
|
type TimeBucketConfig = SelectableControlConfig<TimeBucket>;
|
|
658
669
|
type ExtractSchemaColumns<TSchema> = TSchema extends {
|
|
659
670
|
columns?: infer TColumns;
|
|
660
|
-
} ? Extract<TColumns, Record<string, unknown>> : undefined;
|
|
671
|
+
} ? [Extract<TColumns, Record<string, unknown>>] extends [never] ? undefined : Extract<TColumns, Record<string, unknown>> : undefined;
|
|
661
672
|
type RawSchemaColumnsFromColumns<T, TColumns extends Record<string, unknown> | undefined> = TColumns extends Record<string, unknown> ? { [TKey in keyof TColumns as TKey extends InferableFieldKey<T> ? TKey : never]: TColumns[TKey] } : undefined;
|
|
662
673
|
type RawSchemaColumns<T, TSchema> = RawSchemaColumnsFromColumns<T, ExtractSchemaColumns<TSchema>>;
|
|
663
674
|
type DerivedColumnIdsFromColumns<TColumns extends Record<string, unknown> | undefined> = Extract<TColumns extends Record<string, unknown> ? { [TKey in keyof TColumns]-?: TColumns[TKey] extends DerivedColumnSchema<any> ? TKey : never }[keyof TColumns] : never, string>;
|
|
@@ -750,11 +761,11 @@ type SortConfig = {
|
|
|
750
761
|
* @property data - Array of raw data items
|
|
751
762
|
* @property schema - Optional explicit schema layered on top of inference
|
|
752
763
|
*/
|
|
753
|
-
type ChartSourceOptions<TId extends string = string, T = unknown, TSchema extends
|
|
764
|
+
type ChartSourceOptions<TId extends string = string, T = unknown, TSchema extends ChartSchemaDefinition<T, any> | undefined = undefined> = {
|
|
754
765
|
id: TId;
|
|
755
766
|
label: string;
|
|
756
767
|
data: readonly T[];
|
|
757
|
-
schema?:
|
|
768
|
+
schema?: TSchema;
|
|
758
769
|
};
|
|
759
770
|
/** Convenience alias for any multi-source input definition. */
|
|
760
771
|
type AnyChartSourceOptions = {
|
|
@@ -933,14 +944,16 @@ type ChartInstance<T, TColumnId extends string = string, TChartType extends Char
|
|
|
933
944
|
};
|
|
934
945
|
/** Single-source chart instance narrowed by one explicit schema. */
|
|
935
946
|
type ChartInstanceFromSchema<T, TSchema extends ChartSchema<T, any> | undefined = undefined> = ChartInstance<T, ResolvedColumnIdFromSchema<T, TSchema>, RestrictedChartTypeFromSchema<TSchema>, RestrictedXAxisColumnIdFromSchema<T, TSchema>, RestrictedGroupByColumnIdFromSchema<T, TSchema>, Extract<MetricColumnIdFromMetric<RestrictedMetricFromSchema<T, TSchema>>, ResolvedMetricColumnIdFromSchema<T, TSchema>>, RestrictedMetricFromSchema<T, TSchema>, RestrictedFilterColumnIdFromSchema<T, TSchema>, ResolvedDateColumnIdFromSchema<T, TSchema>, RestrictedTimeBucketFromSchema<TSchema>>;
|
|
947
|
+
/** Single-source chart instance narrowed by any supported schema input. */
|
|
948
|
+
type ChartInstanceFromSchemaDefinition<T, TSchema extends ChartSchemaDefinition<T, any> | undefined = undefined> = ChartInstanceFromSchema<T, ResolvedChartSchemaFromDefinition<TSchema>>;
|
|
936
949
|
type SourceIdFromSource<TSource extends AnyChartSourceOptions> = TSource['id'];
|
|
937
950
|
type SourceRowFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, any> ? TRow : never;
|
|
938
|
-
type SourceColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? ResolvedColumnIdFromSchema<TRow,
|
|
939
|
-
type SourceXAxisColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? RestrictedXAxisColumnIdFromSchema<TRow,
|
|
940
|
-
type SourceGroupByColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? RestrictedGroupByColumnIdFromSchema<TRow,
|
|
941
|
-
type SourceMetricColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? Extract<MetricColumnIdFromMetric<RestrictedMetricFromSchema<TRow,
|
|
942
|
-
type SourceFilterColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? RestrictedFilterColumnIdFromSchema<TRow,
|
|
943
|
-
type SourceDateColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? ResolvedDateColumnIdFromSchema<TRow,
|
|
951
|
+
type SourceColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? ResolvedColumnIdFromSchema<TRow, ResolvedChartSchemaFromDefinition<TSchema>> : never;
|
|
952
|
+
type SourceXAxisColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? RestrictedXAxisColumnIdFromSchema<TRow, ResolvedChartSchemaFromDefinition<TSchema>> : never;
|
|
953
|
+
type SourceGroupByColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? RestrictedGroupByColumnIdFromSchema<TRow, ResolvedChartSchemaFromDefinition<TSchema>> : never;
|
|
954
|
+
type SourceMetricColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? Extract<MetricColumnIdFromMetric<RestrictedMetricFromSchema<TRow, ResolvedChartSchemaFromDefinition<TSchema>>>, ResolvedMetricColumnIdFromSchema<TRow, ResolvedChartSchemaFromDefinition<TSchema>>> : never;
|
|
955
|
+
type SourceFilterColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? RestrictedFilterColumnIdFromSchema<TRow, ResolvedChartSchemaFromDefinition<TSchema>> : never;
|
|
956
|
+
type SourceDateColumnIdFromSource<TSource extends AnyChartSourceOptions> = TSource extends ChartSourceOptions<string, infer TRow, infer TSchema> ? ResolvedDateColumnIdFromSchema<TRow, ResolvedChartSchemaFromDefinition<TSchema>> : never;
|
|
944
957
|
type SourceIdFromSources<TSources extends NonEmptyChartSourceOptions> = Extract<TSources[number]['id'], string>;
|
|
945
958
|
type SourceColumnIdFromSources<TSources extends NonEmptyChartSourceOptions> = TSources[number] extends infer TSource ? TSource extends AnyChartSourceOptions ? SourceColumnIdFromSource<TSource> : never : never;
|
|
946
959
|
type MultiSourceChartBranch<TSources extends NonEmptyChartSourceOptions, TSource extends AnyChartSourceOptions> = Omit<ChartInstance<SourceRowFromSource<TSource>, SourceColumnIdFromSources<TSources>>, 'activeSourceId' | 'setActiveSource' | 'sources' | 'xAxisId' | 'setXAxis' | 'availableXAxes' | 'groupById' | 'setGroupBy' | 'availableGroupBys' | 'metric' | 'setMetric' | 'availableMetrics' | 'filters' | 'toggleFilter' | 'clearFilter' | 'availableFilters' | 'dateRange' | 'referenceDateId' | 'setReferenceDateId' | 'availableDateColumns' | 'columns'> & {
|
|
@@ -985,4 +998,4 @@ type MultiSourceChartBranch<TSources extends NonEmptyChartSourceOptions, TSource
|
|
|
985
998
|
*/
|
|
986
999
|
type MultiSourceChartInstance<TSources extends NonEmptyChartSourceOptions> = TSources[number] extends infer TSource ? TSource extends AnyChartSourceOptions ? MultiSourceChartBranch<TSources, TSource> : never : never;
|
|
987
1000
|
//#endregion
|
|
988
|
-
export { AggregateFunction, AggregateMetric, AvailableFilter, BooleanColumn, CategoricalChartType, CategoryColumn, ChartColumn, ChartColumnType, ChartInstance, ChartInstanceFromSchema, ChartSchema, ChartSeries, ChartSourceOptions, ChartType, ChartTypeConfig, ColumnFormat, ColumnFormatPreset, CountMetric, DateColumn, DateColumnFormat, DefinedChartSchema, DerivedBooleanColumnSchema, DerivedCategoryColumnSchema, DerivedColumnSchema, DerivedDateColumnSchema, DerivedNumberColumnSchema,
|
|
1001
|
+
export { AggregateFunction, AggregateMetric, AvailableFilter, BaseColumnHint, BooleanColumn, CategoricalChartType, CategoryColumn, ChartColumn, ChartColumnType, ChartInstance, ChartInstanceFromSchema, ChartInstanceFromSchemaDefinition, ChartSchema, ChartSchemaDefinition, ChartSeries, ChartSourceOptions, ChartType, ChartTypeConfig, ColumnFormat, ColumnFormatPreset, CountMetric, DateColumn, DateColumnFormat, DefinedChartSchema, DerivedBooleanColumnSchema, DerivedCategoryColumnSchema, DerivedColumnSchema, DerivedDateColumnSchema, DerivedNumberColumnSchema, FilterState, FiltersConfig, GroupByConfig, InferableFieldKey, Metric, MetricConfig, MultiSourceChartInstance, NonEmptyChartSourceOptions, NumberColumn, NumberColumnFormat, NumericAggregateFunction, RawColumnSchemaFor, RawColumnSchemaMap, ResolvedChartSchemaFromDefinition, ResolvedColumnIdFromSchema, ResolvedFilterColumnIdFromSchema, ResolvedGroupByColumnIdFromSchema, ResolvedMetricColumnIdFromSchema, ResolvedXAxisColumnIdFromSchema, RestrictedChartTypeFromSchema, RestrictedFilterColumnIdFromSchema, RestrictedGroupByColumnIdFromSchema, RestrictedMetricFromSchema, RestrictedTimeBucketFromSchema, RestrictedXAxisColumnIdFromSchema, SelectableControlConfig, SortConfig, SortDirection, TimeBucket, TimeBucketConfig, TimeSeriesChartType, TransformedDataPoint, ValidatedChartSchema, XAxisConfig };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChartSchemaDefinition, ChartSourceOptions, NonEmptyChartSourceOptions } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/use-chart-options.d.ts
|
|
4
4
|
/**
|
|
@@ -7,7 +7,7 @@ import { ChartSchema, ChartSourceOptions, DefinedChartSchema, NonEmptyChartSourc
|
|
|
7
7
|
* This is the common case: one dataset, one optional schema, one optional
|
|
8
8
|
* human-readable source label.
|
|
9
9
|
*/
|
|
10
|
-
interface SingleSourceOptions<T, TSchema extends
|
|
10
|
+
interface SingleSourceOptions<T, TSchema extends ChartSchemaDefinition<T, any> | undefined = undefined> {
|
|
11
11
|
/**
|
|
12
12
|
* Raw rows that chart-studio should inspect and transform.
|
|
13
13
|
*
|
|
@@ -18,6 +18,9 @@ interface SingleSourceOptions<T, TSchema extends ChartSchema<T, any> | undefined
|
|
|
18
18
|
/**
|
|
19
19
|
* Optional explicit schema layered on top of inference.
|
|
20
20
|
*
|
|
21
|
+
* Usually this is the fluent builder returned by `defineChartSchema<Row>()`.
|
|
22
|
+
* Plain schema objects are also accepted.
|
|
23
|
+
*
|
|
21
24
|
* Use this when you want to:
|
|
22
25
|
* - rename fields with `label`
|
|
23
26
|
* - force or refine column `type`
|
|
@@ -26,7 +29,7 @@ interface SingleSourceOptions<T, TSchema extends ChartSchema<T, any> | undefined
|
|
|
26
29
|
* - create derived columns
|
|
27
30
|
* - restrict what users can select in the chart UI
|
|
28
31
|
*/
|
|
29
|
-
schema?:
|
|
32
|
+
schema?: TSchema;
|
|
30
33
|
/**
|
|
31
34
|
* Human-readable source name shown by the built-in UI when relevant.
|
|
32
35
|
*
|
|
@@ -59,6 +62,6 @@ interface MultiSourceOptions<TSources extends NonEmptyChartSourceOptions = NonEm
|
|
|
59
62
|
/**
|
|
60
63
|
* Options for the useChart hook.
|
|
61
64
|
*/
|
|
62
|
-
type UseChartOptions<T, TSchema extends
|
|
65
|
+
type UseChartOptions<T, TSchema extends ChartSchemaDefinition<T, any> | undefined = undefined> = SingleSourceOptions<T, TSchema> | MultiSourceOptions;
|
|
63
66
|
//#endregion
|
|
64
67
|
export { SingleSourceOptions, UseChartOptions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChartInstanceFromSchemaDefinition, ChartSchemaDefinition, MultiSourceChartInstance, NonEmptyChartSourceOptions } from "./types.mjs";
|
|
2
2
|
import { SingleSourceOptions } from "./use-chart-options.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/core/use-chart.d.ts
|
|
@@ -15,8 +15,8 @@ import { SingleSourceOptions } from "./use-chart-options.mjs";
|
|
|
15
15
|
* Chart configuration options. Should provide either:
|
|
16
16
|
* - `data`, optional `schema`, and (optionally) `sourceLabel` for a single source
|
|
17
17
|
* - or `sources` array for multiple sources
|
|
18
|
-
* Any explicit single-source or per-source schema
|
|
19
|
-
* `defineChartSchema<Row>()
|
|
18
|
+
* Any explicit single-source or per-source schema is usually authored with
|
|
19
|
+
* `defineChartSchema<Row>()...`. Plain schema objects are also accepted.
|
|
20
20
|
*
|
|
21
21
|
* @returns {ChartInstance}
|
|
22
22
|
* An object representing chart configuration, state, and all derived data/operations:
|
|
@@ -45,6 +45,6 @@ declare function useChart<const TSources extends NonEmptyChartSourceOptions>(opt
|
|
|
45
45
|
sourceLabel?: never;
|
|
46
46
|
sources: TSources;
|
|
47
47
|
}): MultiSourceChartInstance<TSources>;
|
|
48
|
-
declare function useChart<T, const TSchema extends
|
|
48
|
+
declare function useChart<T, const TSchema extends ChartSchemaDefinition<T, any> | undefined = undefined>(options: SingleSourceOptions<T, TSchema>): ChartInstanceFromSchemaDefinition<T, TSchema>;
|
|
49
49
|
//#endregion
|
|
50
50
|
export { useChart };
|
package/dist/core/use-chart.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { TIME_BUCKET_ORDER, resolveConfiguredIdSelection, resolveConfiguredValue, restrictConfiguredIdOptions, restrictConfiguredValues } from "./config-utils.mjs";
|
|
2
2
|
import { CHART_TYPE_CONFIG, getAvailableChartTypes } from "./chart-capabilities.mjs";
|
|
3
3
|
import { resolvePresetFilter } from "./date-range-presets.mjs";
|
|
4
|
+
import { buildAvailableMetrics, isSameMetric, resolveMetric, restrictAvailableMetrics } from "./metric-utils.mjs";
|
|
5
|
+
import { resolveChartSchemaDefinition } from "./schema-builder.mjs";
|
|
4
6
|
import { inferColumnsFromData } from "./infer-columns.mjs";
|
|
5
|
-
import { DEFAULT_METRIC, buildAvailableMetrics, isSameMetric, resolveMetric, restrictAvailableMetrics } from "./metric-utils.mjs";
|
|
6
7
|
import { applyFilters, extractAvailableFilters, runPipeline } from "./pipeline.mjs";
|
|
7
8
|
import { computeDateRange, filterByDateRange } from "./date-utils.mjs";
|
|
8
9
|
import { DEFAULT_TIME_BUCKET } from "./use-chart-options.mjs";
|
|
@@ -21,28 +22,32 @@ function createAvailableFilterValueMap(availableFilters) {
|
|
|
21
22
|
function useChart(options) {
|
|
22
23
|
if ("sources" in options && options.sources?.length === 0) throw new Error("useChart requires at least one source");
|
|
23
24
|
const sources = useMemo(() => {
|
|
24
|
-
if ("sources" in options && options.sources) return options.sources.map((source) =>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
if ("sources" in options && options.sources) return options.sources.map((source) => {
|
|
26
|
+
const schema = resolveChartSchemaDefinition(source.schema);
|
|
27
|
+
return {
|
|
28
|
+
id: source.id,
|
|
29
|
+
label: source.label,
|
|
30
|
+
data: source.data,
|
|
31
|
+
columns: inferColumnsFromData(source.data, schema),
|
|
32
|
+
schema
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
const schema = resolveChartSchemaDefinition(options.schema);
|
|
31
36
|
return [{
|
|
32
37
|
id: "default",
|
|
33
38
|
label: options.sourceLabel ?? "Unnamed Source",
|
|
34
39
|
data: options.data,
|
|
35
|
-
columns: inferColumnsFromData(options.data,
|
|
36
|
-
schema
|
|
40
|
+
columns: inferColumnsFromData(options.data, schema),
|
|
41
|
+
schema
|
|
37
42
|
}];
|
|
38
43
|
}, [options]);
|
|
39
44
|
const hasMultipleSources = sources.length > 1;
|
|
40
45
|
const [activeSourceIdRaw, setActiveSourceRaw] = useState(sources[0]?.id ?? "default");
|
|
41
|
-
const [chartType, setChartTypeRaw] = useState(
|
|
46
|
+
const [chartType, setChartTypeRaw] = useState(null);
|
|
42
47
|
const [xAxisId, setXAxisRaw] = useState(null);
|
|
43
48
|
const [groupById, setGroupByRaw] = useState(null);
|
|
44
|
-
const [metric, setMetricRaw] = useState(
|
|
45
|
-
const [timeBucket, setTimeBucketRaw] = useState(
|
|
49
|
+
const [metric, setMetricRaw] = useState(null);
|
|
50
|
+
const [timeBucket, setTimeBucketRaw] = useState(null);
|
|
46
51
|
const [filters, setFilters] = useState(() => /* @__PURE__ */ new Map());
|
|
47
52
|
const [sorting, setSorting] = useState(null);
|
|
48
53
|
const [referenceDateIdRaw, setReferenceDateIdRaw] = useState(null);
|
|
@@ -114,7 +119,7 @@ function useChart(options) {
|
|
|
114
119
|
resolvedXAxisType,
|
|
115
120
|
activeSource.schema
|
|
116
121
|
]);
|
|
117
|
-
const resolvedChartType = useMemo(() => resolveConfiguredValue(chartType, availableChartTypes, activeSource.schema?.chartType?.default), [
|
|
122
|
+
const resolvedChartType = useMemo(() => resolveConfiguredValue(chartType, availableChartTypes, activeSource.schema?.chartType?.default, "bar"), [
|
|
118
123
|
chartType,
|
|
119
124
|
availableChartTypes,
|
|
120
125
|
activeSource.schema
|
|
@@ -127,7 +132,7 @@ function useChart(options) {
|
|
|
127
132
|
resolvedChartType,
|
|
128
133
|
activeSource.schema
|
|
129
134
|
]);
|
|
130
|
-
const resolvedTimeBucket = useMemo(() => resolveConfiguredValue(timeBucket, availableTimeBuckets, activeSource.schema?.timeBucket?.default), [
|
|
135
|
+
const resolvedTimeBucket = useMemo(() => resolveConfiguredValue(timeBucket, availableTimeBuckets, activeSource.schema?.timeBucket?.default, DEFAULT_TIME_BUCKET), [
|
|
131
136
|
timeBucket,
|
|
132
137
|
availableTimeBuckets,
|
|
133
138
|
activeSource.schema
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AggregateFunction, AggregateMetric, AvailableFilter, BooleanColumn, CategoricalChartType, CategoryColumn, ChartColumn, ChartColumnType, ChartInstance, ChartInstanceFromSchema, ChartSchema, ChartSeries, ChartSourceOptions, ChartType, ChartTypeConfig, ColumnFormat, ColumnFormatPreset, CountMetric, DateColumn, DateColumnFormat, DefinedChartSchema, DerivedBooleanColumnSchema, DerivedCategoryColumnSchema, DerivedColumnSchema, DerivedDateColumnSchema, DerivedNumberColumnSchema, FilterState, FiltersConfig, GroupByConfig, InferableFieldKey, Metric, MetricConfig, MultiSourceChartInstance, NumberColumn, NumberColumnFormat, NumericAggregateFunction, RawColumnSchemaFor, RawColumnSchemaMap, ResolvedColumnIdFromSchema, RestrictedChartTypeFromSchema, RestrictedFilterColumnIdFromSchema, RestrictedGroupByColumnIdFromSchema, RestrictedMetricFromSchema, RestrictedTimeBucketFromSchema, RestrictedXAxisColumnIdFromSchema, SelectableControlConfig, SortConfig, SortDirection, TimeBucket, TimeBucketConfig, TimeSeriesChartType, TransformedDataPoint, ValidatedChartSchema, XAxisConfig } from "./core/types.mjs";
|
|
1
|
+
import { AggregateFunction, AggregateMetric, AvailableFilter, BooleanColumn, CategoricalChartType, CategoryColumn, ChartColumn, ChartColumnType, ChartInstance, ChartInstanceFromSchema, ChartInstanceFromSchemaDefinition, ChartSchema, ChartSchemaDefinition, ChartSeries, ChartSourceOptions, ChartType, ChartTypeConfig, ColumnFormat, ColumnFormatPreset, CountMetric, DateColumn, DateColumnFormat, DefinedChartSchema, DerivedBooleanColumnSchema, DerivedCategoryColumnSchema, DerivedColumnSchema, DerivedDateColumnSchema, DerivedNumberColumnSchema, FilterState, FiltersConfig, GroupByConfig, InferableFieldKey, Metric, MetricConfig, MultiSourceChartInstance, NumberColumn, NumberColumnFormat, NumericAggregateFunction, RawColumnSchemaFor, RawColumnSchemaMap, ResolvedColumnIdFromSchema, RestrictedChartTypeFromSchema, RestrictedFilterColumnIdFromSchema, RestrictedGroupByColumnIdFromSchema, RestrictedMetricFromSchema, RestrictedTimeBucketFromSchema, RestrictedXAxisColumnIdFromSchema, SelectableControlConfig, SortConfig, SortDirection, TimeBucket, TimeBucketConfig, TimeSeriesChartType, TransformedDataPoint, ValidatedChartSchema, XAxisConfig } from "./core/types.mjs";
|
|
2
2
|
import { CHART_TYPE_CONFIG, ChartAxisType, ChartTypeCapabilities } from "./core/chart-capabilities.mjs";
|
|
3
3
|
import { buildColorMap, getSeriesColor } from "./core/colors.mjs";
|
|
4
4
|
import { defineChartSchema } from "./core/define-chart-schema.mjs";
|
|
@@ -7,4 +7,4 @@ import { buildAvailableMetrics, getMetricLabel } from "./core/metric-utils.mjs";
|
|
|
7
7
|
import { PipelineInput, PipelineOutput, applyFilters, extractAvailableFilters, runPipeline } from "./core/pipeline.mjs";
|
|
8
8
|
import { UseChartOptions } from "./core/use-chart-options.mjs";
|
|
9
9
|
import { useChart } from "./core/use-chart.mjs";
|
|
10
|
-
export { type AggregateFunction, type AggregateMetric, type AvailableFilter, type BooleanColumn, CHART_TYPE_CONFIG, type CategoricalChartType, type CategoryColumn, type ChartAxisType, type ChartColumn, type ChartColumnType, type ChartInstance, type ChartInstanceFromSchema, type ChartSchema, type ChartSeries, type ChartSourceOptions, type ChartType, type ChartTypeCapabilities, type ChartTypeConfig, type ColumnFormat, type ColumnFormatPreset, type CountMetric, type DateColumn, type DateColumnFormat, type DefinedChartSchema, type DerivedBooleanColumnSchema, type DerivedCategoryColumnSchema, type DerivedColumnSchema, type DerivedDateColumnSchema, type DerivedNumberColumnSchema, type FilterState, type FiltersConfig, type GroupByConfig, type InferableFieldKey, type Metric, type MetricConfig, type MultiSourceChartInstance, type NumberColumn, type NumberColumnFormat, type NumericAggregateFunction, type PipelineInput, type PipelineOutput, type RawColumnSchemaFor, type RawColumnSchemaMap, type ResolvedColumnIdFromSchema, type RestrictedChartTypeFromSchema, type RestrictedFilterColumnIdFromSchema, type RestrictedGroupByColumnIdFromSchema, type RestrictedMetricFromSchema, type RestrictedTimeBucketFromSchema, type RestrictedXAxisColumnIdFromSchema, type SelectableControlConfig, type SortConfig, type SortDirection, type TimeBucket, type TimeBucketConfig, type TimeSeriesChartType, type TransformedDataPoint, type UseChartOptions, type ValidatedChartSchema, type XAxisConfig, applyFilters, buildAvailableMetrics, buildColorMap, defineChartSchema, extractAvailableFilters, getMetricLabel, getSeriesColor, inferColumnsFromData, runPipeline, useChart };
|
|
10
|
+
export { type AggregateFunction, type AggregateMetric, type AvailableFilter, type BooleanColumn, CHART_TYPE_CONFIG, type CategoricalChartType, type CategoryColumn, type ChartAxisType, type ChartColumn, type ChartColumnType, type ChartInstance, type ChartInstanceFromSchema, type ChartInstanceFromSchemaDefinition, type ChartSchema, type ChartSchemaDefinition, type ChartSeries, type ChartSourceOptions, type ChartType, type ChartTypeCapabilities, type ChartTypeConfig, type ColumnFormat, type ColumnFormatPreset, type CountMetric, type DateColumn, type DateColumnFormat, type DefinedChartSchema, type DerivedBooleanColumnSchema, type DerivedCategoryColumnSchema, type DerivedColumnSchema, type DerivedDateColumnSchema, type DerivedNumberColumnSchema, type FilterState, type FiltersConfig, type GroupByConfig, type InferableFieldKey, type Metric, type MetricConfig, type MultiSourceChartInstance, type NumberColumn, type NumberColumnFormat, type NumericAggregateFunction, type PipelineInput, type PipelineOutput, type RawColumnSchemaFor, type RawColumnSchemaMap, type ResolvedColumnIdFromSchema, type RestrictedChartTypeFromSchema, type RestrictedFilterColumnIdFromSchema, type RestrictedGroupByColumnIdFromSchema, type RestrictedMetricFromSchema, type RestrictedTimeBucketFromSchema, type RestrictedXAxisColumnIdFromSchema, type SelectableControlConfig, type SortConfig, type SortDirection, type TimeBucket, type TimeBucketConfig, type TimeSeriesChartType, type TransformedDataPoint, type UseChartOptions, type ValidatedChartSchema, type XAxisConfig, applyFilters, buildAvailableMetrics, buildColorMap, defineChartSchema, extractAvailableFilters, getMetricLabel, getSeriesColor, inferColumnsFromData, runPipeline, useChart };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CHART_TYPE_CONFIG } from "./core/chart-capabilities.mjs";
|
|
2
2
|
import { buildColorMap, getSeriesColor } from "./core/colors.mjs";
|
|
3
|
+
import { buildAvailableMetrics, getMetricLabel } from "./core/metric-utils.mjs";
|
|
3
4
|
import { defineChartSchema } from "./core/define-chart-schema.mjs";
|
|
4
5
|
import { inferColumnsFromData } from "./core/infer-columns.mjs";
|
|
5
|
-
import { buildAvailableMetrics, getMetricLabel } from "./core/metric-utils.mjs";
|
|
6
6
|
import { applyFilters, extractAvailableFilters, runPipeline } from "./core/pipeline.mjs";
|
|
7
7
|
import { useChart } from "./core/use-chart.mjs";
|
|
8
8
|
export { CHART_TYPE_CONFIG, applyFilters, buildAvailableMetrics, buildColorMap, defineChartSchema, extractAvailableFilters, getMetricLabel, getSeriesColor, inferColumnsFromData, runPipeline, useChart };
|
|
@@ -15,11 +15,15 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
|
15
15
|
* @property showDataLabels - Opt into cartesian/pie value labels using the shared formatting rules.
|
|
16
16
|
*/
|
|
17
17
|
type ChartCanvasProps = {
|
|
18
|
-
height?: number;
|
|
19
|
-
className?: string;
|
|
18
|
+
/** Chart height in pixels (default: 300) */height?: number; /** Additional CSS classes */
|
|
19
|
+
className?: string; /** Will show labels using the shared formatting rules. (default: false) */
|
|
20
20
|
showDataLabels?: boolean;
|
|
21
21
|
};
|
|
22
|
-
/** Renders the appropriate recharts chart based on the chart instance state.
|
|
22
|
+
/** Renders the appropriate recharts chart based on the chart instance state.
|
|
23
|
+
* @param height - Chart height in pixels (default: 300)
|
|
24
|
+
* @param className - Additional CSS classes
|
|
25
|
+
* @param showDataLabels - Opt into cartesian/pie value labels using the shared formatting rules.
|
|
26
|
+
*/
|
|
23
27
|
declare function ChartCanvas({
|
|
24
28
|
height,
|
|
25
29
|
className,
|
package/dist/ui/chart-canvas.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { getSeriesColor } from "../core/colors.mjs";
|
|
|
2
2
|
import { createNumericRange, formatChartValue, formatTimeBucketLabel, shouldAllowDecimalTicks } from "../core/formatting.mjs";
|
|
3
3
|
import { useChartContext } from "./chart-context.mjs";
|
|
4
4
|
import { selectVisibleXAxisTicks } from "./chart-axis-ticks.mjs";
|
|
5
|
+
import { getPercentStackedDisplayValue } from "./percent-stacked.mjs";
|
|
5
6
|
import { useEffect, useRef, useState } from "react";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
import { Area, AreaChart, Bar, BarChart, CartesianGrid, LabelList, Legend, Line, LineChart, Pie, PieChart, Tooltip, XAxis, YAxis } from "recharts";
|
|
@@ -213,7 +214,11 @@ function useCssBarRadius() {
|
|
|
213
214
|
}, []);
|
|
214
215
|
return radiusPx;
|
|
215
216
|
}
|
|
216
|
-
/** Renders the appropriate recharts chart based on the chart instance state.
|
|
217
|
+
/** Renders the appropriate recharts chart based on the chart instance state.
|
|
218
|
+
* @param height - Chart height in pixels (default: 300)
|
|
219
|
+
* @param className - Additional CSS classes
|
|
220
|
+
* @param showDataLabels - Opt into cartesian/pie value labels using the shared formatting rules.
|
|
221
|
+
*/
|
|
217
222
|
function ChartCanvas({ height = 300, className, showDataLabels = false }) {
|
|
218
223
|
const chart = useChartContext();
|
|
219
224
|
const { chartType, transformedData, series, connectNulls } = chart;
|
|
@@ -335,13 +340,19 @@ function ChartCanvas({ height = 300, className, showDataLabels = false }) {
|
|
|
335
340
|
*/
|
|
336
341
|
const PERCENT_STACKED_COLUMN = {
|
|
337
342
|
type: "number",
|
|
338
|
-
format: "percent"
|
|
339
|
-
formatter: void 0
|
|
343
|
+
format: "percent"
|
|
340
344
|
};
|
|
341
345
|
const PERCENT_STACKED_RANGE = {
|
|
342
346
|
min: 0,
|
|
343
347
|
max: 1
|
|
344
348
|
};
|
|
349
|
+
function createStackedTooltipItemSorter(series) {
|
|
350
|
+
const order = new Map(series.map((s, index) => [s.dataKey, index]));
|
|
351
|
+
return (item) => {
|
|
352
|
+
const dataKey = typeof item.dataKey === "string" ? item.dataKey : typeof item.name === "string" ? item.name : "";
|
|
353
|
+
return -(order.get(dataKey) ?? -1);
|
|
354
|
+
};
|
|
355
|
+
}
|
|
345
356
|
/**
|
|
346
357
|
* Remove data points where every series value is null.
|
|
347
358
|
*
|
|
@@ -360,7 +371,7 @@ function filterAllNullPoints(data, series) {
|
|
|
360
371
|
* Owns the grid, axes, tooltip, and legend — the only things that change
|
|
361
372
|
* per chart type are the root component and the series element.
|
|
362
373
|
*/
|
|
363
|
-
function CartesianChartShell({ data, series, width, height, valueColumn, valueRange, allowDecimalTicks, xColumn, timeBucket, showDataLabels, Chart, renderSeries }) {
|
|
374
|
+
function CartesianChartShell({ data, series, width, height, valueColumn, valueRange, allowDecimalTicks, xColumn, timeBucket, showDataLabels, Chart, renderSeries, tooltipItemSorter }) {
|
|
364
375
|
const yAxisWidth = estimateYAxisWidth(valueRange, valueColumn);
|
|
365
376
|
const xAxisTickValues = selectVisibleXAxisTicks({
|
|
366
377
|
values: data.map(getXAxisTickValue),
|
|
@@ -402,6 +413,7 @@ function CartesianChartShell({ data, series, width, height, valueColumn, valueRa
|
|
|
402
413
|
}) : String(value)
|
|
403
414
|
}),
|
|
404
415
|
/* @__PURE__ */ jsx(Tooltip, {
|
|
416
|
+
itemSorter: tooltipItemSorter,
|
|
405
417
|
formatter: (value) => typeof value === "number" ? formatChartValue(value, {
|
|
406
418
|
column: valueColumn,
|
|
407
419
|
surface: "tooltip",
|
|
@@ -443,6 +455,7 @@ function BarChartRenderer(props) {
|
|
|
443
455
|
return /* @__PURE__ */ jsx(CartesianChartShell, {
|
|
444
456
|
...props,
|
|
445
457
|
Chart: BarChart,
|
|
458
|
+
tooltipItemSorter: isStacked ? createStackedTooltipItemSorter(series) : void 0,
|
|
446
459
|
renderSeries: (s) => {
|
|
447
460
|
const isTop = !isStacked || s.dataKey === topSeriesKey;
|
|
448
461
|
return /* @__PURE__ */ jsx(Bar, {
|
|
@@ -511,6 +524,8 @@ function AreaChartRenderer(props) {
|
|
|
511
524
|
}
|
|
512
525
|
function PercentAreaChartRenderer(props) {
|
|
513
526
|
const { series, data, xColumn, timeBucket, showDataLabels, connectNulls, width, height } = props;
|
|
527
|
+
const seriesKeys = series.map((s) => s.dataKey);
|
|
528
|
+
const tooltipItemSorter = createStackedTooltipItemSorter(series);
|
|
514
529
|
const stackableData = filterAllNullPoints(data, series);
|
|
515
530
|
const yAxisWidth = estimateYAxisWidth(PERCENT_STACKED_RANGE, PERCENT_STACKED_COLUMN);
|
|
516
531
|
const xAxisTickValues = selectVisibleXAxisTicks({
|
|
@@ -553,11 +568,20 @@ function PercentAreaChartRenderer(props) {
|
|
|
553
568
|
width: yAxisWidth
|
|
554
569
|
}),
|
|
555
570
|
/* @__PURE__ */ jsx(Tooltip, {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
571
|
+
itemSorter: tooltipItemSorter,
|
|
572
|
+
formatter: (_value, _name, entry) => {
|
|
573
|
+
const proportion = getPercentStackedDisplayValue(entry, String(entry.dataKey ?? ""), seriesKeys);
|
|
574
|
+
if (proportion != null) return formatChartValue(proportion, {
|
|
575
|
+
column: PERCENT_STACKED_COLUMN,
|
|
576
|
+
surface: "tooltip",
|
|
577
|
+
numericRange: PERCENT_STACKED_RANGE
|
|
578
|
+
});
|
|
579
|
+
return typeof _value === "number" ? formatChartValue(_value, {
|
|
580
|
+
column: PERCENT_STACKED_COLUMN,
|
|
581
|
+
surface: "tooltip",
|
|
582
|
+
numericRange: PERCENT_STACKED_RANGE
|
|
583
|
+
}) : _value;
|
|
584
|
+
},
|
|
561
585
|
labelFormatter: (label, payload) => formatTooltipLabel(label, payload, xColumn, timeBucket)
|
|
562
586
|
}),
|
|
563
587
|
series.length > 1 && /* @__PURE__ */ jsx(Legend, {}),
|
|
@@ -573,6 +597,7 @@ function PercentAreaChartRenderer(props) {
|
|
|
573
597
|
children: showDataLabels && /* @__PURE__ */ jsx(LabelList, {
|
|
574
598
|
position: "top",
|
|
575
599
|
offset: 8,
|
|
600
|
+
valueAccessor: (entry) => getPercentStackedDisplayValue(entry, s.dataKey, seriesKeys) ?? 0,
|
|
576
601
|
formatter: (value) => formatDataLabel(value, PERCENT_STACKED_COLUMN, PERCENT_STACKED_RANGE)
|
|
577
602
|
})
|
|
578
603
|
}, s.dataKey))
|
|
@@ -608,14 +633,9 @@ function PercentBarChartRenderer(props) {
|
|
|
608
633
|
const { series, data, xColumn, timeBucket, showDataLabels, width, height } = props;
|
|
609
634
|
const barRadius = useCssBarRadius();
|
|
610
635
|
const topSeriesKey = series[series.length - 1]?.dataKey;
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}, {
|
|
615
|
-
type: "number",
|
|
616
|
-
format: void 0,
|
|
617
|
-
formatter: void 0
|
|
618
|
-
});
|
|
636
|
+
const seriesKeys = series.map((s) => s.dataKey);
|
|
637
|
+
const tooltipItemSorter = createStackedTooltipItemSorter(series);
|
|
638
|
+
const yAxisWidth = estimateYAxisWidth(PERCENT_STACKED_RANGE, PERCENT_STACKED_COLUMN);
|
|
619
639
|
const xAxisTickValues = selectVisibleXAxisTicks({
|
|
620
640
|
values: data.map(getXAxisTickValue),
|
|
621
641
|
labels: data.map((point) => formatXAxisValue(getXAxisTickValue(point), xColumn, timeBucket, "axis")),
|
|
@@ -648,13 +668,27 @@ function PercentBarChartRenderer(props) {
|
|
|
648
668
|
tickLine: false,
|
|
649
669
|
axisLine: false,
|
|
650
670
|
tickMargin: 4,
|
|
651
|
-
tickFormatter: (value) => typeof value === "number" ?
|
|
671
|
+
tickFormatter: (value) => typeof value === "number" ? formatChartValue(value, {
|
|
672
|
+
column: PERCENT_STACKED_COLUMN,
|
|
673
|
+
surface: "axis",
|
|
674
|
+
numericRange: PERCENT_STACKED_RANGE
|
|
675
|
+
}) : String(value),
|
|
652
676
|
width: yAxisWidth
|
|
653
677
|
}),
|
|
654
678
|
/* @__PURE__ */ jsx(Tooltip, {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
679
|
+
itemSorter: tooltipItemSorter,
|
|
680
|
+
formatter: (_value, _name, entry) => {
|
|
681
|
+
const proportion = getPercentStackedDisplayValue(entry, String(entry.dataKey ?? ""), seriesKeys);
|
|
682
|
+
if (proportion != null) return formatChartValue(proportion, {
|
|
683
|
+
column: PERCENT_STACKED_COLUMN,
|
|
684
|
+
surface: "tooltip",
|
|
685
|
+
numericRange: PERCENT_STACKED_RANGE
|
|
686
|
+
});
|
|
687
|
+
return typeof _value === "number" ? formatChartValue(_value, {
|
|
688
|
+
column: PERCENT_STACKED_COLUMN,
|
|
689
|
+
surface: "tooltip",
|
|
690
|
+
numericRange: PERCENT_STACKED_RANGE
|
|
691
|
+
}) : _value;
|
|
658
692
|
},
|
|
659
693
|
labelFormatter: (label, payload) => formatTooltipLabel(label, payload, xColumn, timeBucket)
|
|
660
694
|
}),
|
|
@@ -672,7 +706,13 @@ function PercentBarChartRenderer(props) {
|
|
|
672
706
|
0,
|
|
673
707
|
0
|
|
674
708
|
] : 0,
|
|
675
|
-
stackId: "percent"
|
|
709
|
+
stackId: "percent",
|
|
710
|
+
children: showDataLabels && /* @__PURE__ */ jsx(LabelList, {
|
|
711
|
+
position: "top",
|
|
712
|
+
offset: 8,
|
|
713
|
+
valueAccessor: (entry) => getPercentStackedDisplayValue(entry, s.dataKey, seriesKeys) ?? 0,
|
|
714
|
+
formatter: (value) => formatDataLabel(value, PERCENT_STACKED_COLUMN, PERCENT_STACKED_RANGE)
|
|
715
|
+
})
|
|
676
716
|
}, s.dataKey);
|
|
677
717
|
})
|
|
678
718
|
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChartColumn, ChartInstance,
|
|
1
|
+
import { ChartColumn, ChartInstance, ChartInstanceFromSchemaDefinition, ChartSchemaDefinition, Metric } from "../core/types.mjs";
|
|
2
2
|
import { ReactElement, ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/ui/chart-context.d.ts
|
|
@@ -70,10 +70,14 @@ declare function useChartContext(): ChartContextChart;
|
|
|
70
70
|
* React cannot infer provider generics through arbitrary subtrees, so callers
|
|
71
71
|
* provide the row type (and optional schema type) explicitly.
|
|
72
72
|
*/
|
|
73
|
-
declare function useTypedChartContext<T, const TSchema extends
|
|
73
|
+
declare function useTypedChartContext<T, const TSchema extends ChartSchemaDefinition<T, any> | undefined = undefined>(): ChartInstanceFromSchemaDefinition<T, TSchema>;
|
|
74
74
|
/**
|
|
75
75
|
* Root provider component. Wraps children with the chart instance context.
|
|
76
76
|
*
|
|
77
|
+
* @param chart - The chart instance to share
|
|
78
|
+
* @param children - The children to render
|
|
79
|
+
* @param className - Additional CSS classes for the chart container
|
|
80
|
+
*
|
|
77
81
|
* @example
|
|
78
82
|
* ```tsx
|
|
79
83
|
* <Chart chart={chart}>
|
|
@@ -87,8 +91,8 @@ declare function Chart({
|
|
|
87
91
|
children,
|
|
88
92
|
className
|
|
89
93
|
}: {
|
|
90
|
-
chart: AnyChartInstance;
|
|
91
|
-
children: ReactNode;
|
|
94
|
+
/** The chart instance to share. Create it with `useChart()` first.*/chart: AnyChartInstance; /** The children to render. Can be any UI primitives from the UI package. */
|
|
95
|
+
children: ReactNode; /** Additional CSS classes for the chart container. */
|
|
92
96
|
className?: string;
|
|
93
97
|
}): ReactElement;
|
|
94
98
|
//#endregion
|
|
@@ -5,12 +5,16 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
|
5
5
|
* Debug panel — shows raw data, transformed data, series, and current state.
|
|
6
6
|
* Drop `<ChartDebug />` inside a `<Chart>` to inspect what's happening.
|
|
7
7
|
*/
|
|
8
|
-
/** Debug panel that renders chart internals as formatted JSON.
|
|
8
|
+
/** Debug panel that renders chart internals as formatted JSON.
|
|
9
|
+
*
|
|
10
|
+
* @param className - Additional CSS classes for the debug panel.
|
|
11
|
+
* @param defaultOpen - Whether the debug panel should be open by default. (default: false)
|
|
12
|
+
*/
|
|
9
13
|
declare function ChartDebug({
|
|
10
14
|
className,
|
|
11
15
|
defaultOpen
|
|
12
16
|
}: {
|
|
13
|
-
className?: string;
|
|
17
|
+
/** Additional CSS classes for the debug panel. */className?: string; /** Whether the debug panel should be open by default. (default: false) */
|
|
14
18
|
defaultOpen?: boolean;
|
|
15
19
|
}): react_jsx_runtime0.JSX.Element;
|
|
16
20
|
//#endregion
|
package/dist/ui/chart-debug.mjs
CHANGED
|
@@ -112,7 +112,11 @@ function TabButton({ tab, isActive, onClick }) {
|
|
|
112
112
|
children: tab.label
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
|
-
/** Debug panel that renders chart internals as formatted JSON.
|
|
115
|
+
/** Debug panel that renders chart internals as formatted JSON.
|
|
116
|
+
*
|
|
117
|
+
* @param className - Additional CSS classes for the debug panel.
|
|
118
|
+
* @param defaultOpen - Whether the debug panel should be open by default. (default: false)
|
|
119
|
+
*/
|
|
116
120
|
function ChartDebug({ className, defaultOpen = false }) {
|
|
117
121
|
const chart = useChartContext();
|
|
118
122
|
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
@@ -10,8 +10,8 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
|
10
10
|
* @property hidden - Control IDs to completely hide (not in toolbar, not in overflow)
|
|
11
11
|
*/
|
|
12
12
|
type ChartToolbarProps = {
|
|
13
|
-
className?: string;
|
|
14
|
-
pinned?: readonly ControlId[];
|
|
13
|
+
/** Additional CSS classes for the toolbar container. */className?: string; /** Control IDs to always show in the toolbar row (outside the overflow menu) */
|
|
14
|
+
pinned?: readonly ControlId[]; /** Control IDs to completely hide (not in toolbar, not in overflow) */
|
|
15
15
|
hidden?: readonly ControlId[];
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
@@ -19,6 +19,10 @@ type ChartToolbarProps = {
|
|
|
19
19
|
*
|
|
20
20
|
* Controls are rendered in registry order. Each sub-component still
|
|
21
21
|
* auto-hides when not relevant (e.g. time bucket only shows for date X-axis).
|
|
22
|
+
*
|
|
23
|
+
* @param className - Additional CSS classes for the toolbar container
|
|
24
|
+
* @param pinned - Control IDs to always show in the toolbar row (outside the overflow menu)
|
|
25
|
+
* @param hidden - Control IDs to completely hide (not in toolbar, not in overflow)
|
|
22
26
|
*/
|
|
23
27
|
declare function ChartToolbar({
|
|
24
28
|
className,
|
|
@@ -32,6 +32,10 @@ const DEFAULT_PINNED_CONTROLS = ["dateRange"];
|
|
|
32
32
|
*
|
|
33
33
|
* Controls are rendered in registry order. Each sub-component still
|
|
34
34
|
* auto-hides when not relevant (e.g. time bucket only shows for date X-axis).
|
|
35
|
+
*
|
|
36
|
+
* @param className - Additional CSS classes for the toolbar container
|
|
37
|
+
* @param pinned - Control IDs to always show in the toolbar row (outside the overflow menu)
|
|
38
|
+
* @param hidden - Control IDs to completely hide (not in toolbar, not in overflow)
|
|
35
39
|
*/
|
|
36
40
|
function ChartToolbar({ className, pinned = DEFAULT_PINNED_CONTROLS, hidden = [] }) {
|
|
37
41
|
const pinnedSet = useMemo(() => new Set(pinned), [pinned]);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/ui/percent-stacked.ts
|
|
2
|
+
/**
|
|
3
|
+
* Recharts stacked graphical entries expose [lower, upper] bounds after
|
|
4
|
+
* stackOffset="expand". The visible segment size is upper - lower.
|
|
5
|
+
*/
|
|
6
|
+
function getPercentStackedProportion(entry) {
|
|
7
|
+
const value = entry.value;
|
|
8
|
+
if (Array.isArray(value) && typeof value[0] === "number" && typeof value[1] === "number") return value[1] - value[0];
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Recharts tooltip payload entries are rebuilt from the raw transformed row,
|
|
13
|
+
* so value stays as the raw metric and payload contains the full bucket.
|
|
14
|
+
*/
|
|
15
|
+
function getPercentStackedProportionFromPayload(payload, dataKey, seriesKeys) {
|
|
16
|
+
if (!payload || typeof payload !== "object") return null;
|
|
17
|
+
const point = payload;
|
|
18
|
+
const rawValue = point[dataKey];
|
|
19
|
+
if (typeof rawValue !== "number") return null;
|
|
20
|
+
let total = 0;
|
|
21
|
+
for (const seriesKey of seriesKeys) {
|
|
22
|
+
const seriesValue = point[seriesKey];
|
|
23
|
+
if (typeof seriesValue === "number") total += seriesValue;
|
|
24
|
+
}
|
|
25
|
+
if (total <= 0) return null;
|
|
26
|
+
return rawValue / total;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Prefer the raw-row calculation because it works for both tooltip payloads
|
|
30
|
+
* and label entries, then fall back to stacked bounds when present.
|
|
31
|
+
*/
|
|
32
|
+
function getPercentStackedDisplayValue(entry, dataKey, seriesKeys) {
|
|
33
|
+
return getPercentStackedProportionFromPayload(entry.payload, dataKey, seriesKeys) ?? getPercentStackedProportion(entry);
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { getPercentStackedDisplayValue };
|