@opendata-ai/openchart-engine 6.4.1 → 6.5.1
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/dist/index.d.ts +22 -2
- package/dist/index.js +143 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/compile-animation.test.ts +161 -0
- package/src/charts/bar/compute.ts +3 -0
- package/src/charts/column/compute.ts +4 -0
- package/src/compile.ts +66 -0
- package/src/compiler/__tests__/animation.test.ts +121 -0
- package/src/compiler/animation.ts +122 -0
- package/src/compiler/normalize.ts +1 -0
- package/src/compiler/types.ts +2 -0
- package/src/index.ts +6 -0
- package/src/tables/__tests__/compile-table.test.ts +28 -0
- package/src/tables/compile-table.ts +2 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _opendata_ai_openchart_core from '@opendata-ai/openchart-core';
|
|
2
|
-
import { LegendLayout, ResolvedChrome, TooltipContent, A11yMetadata, ResolvedTheme, CompileOptions, ChartLayout, LayerSpec, CompileTableOptions, TableLayout, MarkType, MarkDef, DataRow, Encoding, ChromeText, Annotation, LabelConfig, LegendConfig, ThemeConfig, DarkMode, ColumnConfig, GraphSpec, GraphEncoding, GraphLayoutConfig, NodeOverride, VizSpec, ScaleType, EncodingChannel, Rect, LayoutStrategy, Mark, BinTransform, CalculateTransform, ConditionalValueDef, FilterPredicate, TimeUnitTransform, Transform } from '@opendata-ai/openchart-core';
|
|
2
|
+
import { LegendLayout, ResolvedChrome, TooltipContent, A11yMetadata, ResolvedTheme, CompileOptions, ChartLayout, LayerSpec, CompileTableOptions, TableLayout, AnimationSpec, ResolvedAnimation, MarkType, MarkDef, DataRow, Encoding, ChromeText, Annotation, LabelConfig, LegendConfig, ThemeConfig, DarkMode, ColumnConfig, GraphSpec, GraphEncoding, GraphLayoutConfig, NodeOverride, VizSpec, ScaleType, EncodingChannel, Rect, LayoutStrategy, Mark, BinTransform, CalculateTransform, ConditionalValueDef, FilterPredicate, TimeUnitTransform, Transform } from '@opendata-ai/openchart-core';
|
|
3
3
|
export { ChartLayout, ChartSpec, CompileOptions, CompileTableOptions, GraphLayout, GraphSpec, LayerSpec, TableLayout, TableSpec, VizSpec } from '@opendata-ai/openchart-core';
|
|
4
4
|
import { ScaleLinear, ScaleTime, ScaleLogarithmic, ScalePower, ScaleSymLog, ScaleBand, ScalePoint, ScaleOrdinal, ScaleQuantile, ScaleQuantize, ScaleThreshold } from 'd3-scale';
|
|
5
5
|
|
|
@@ -168,6 +168,25 @@ declare function compileTable(spec: unknown, options: CompileTableOptions): Tabl
|
|
|
168
168
|
*/
|
|
169
169
|
declare function compileGraph(spec: unknown, options: CompileOptions): GraphCompilation;
|
|
170
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Animation resolver: normalizes AnimationSpec into fully resolved config.
|
|
173
|
+
*
|
|
174
|
+
* Handles the shorthand forms:
|
|
175
|
+
* - true -> { enter: true } -> full defaults
|
|
176
|
+
* - { enter: { duration: 800 } } -> merge with defaults
|
|
177
|
+
* - false/undefined -> undefined (no animation)
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Resolve an AnimationSpec into a fully resolved config with all defaults filled.
|
|
182
|
+
* Returns undefined if animation is disabled (false or omitted).
|
|
183
|
+
*/
|
|
184
|
+
declare function resolveAnimation(spec: AnimationSpec | undefined): ResolvedAnimation | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* Clamp stagger delay so total stagger time doesn't exceed MAX_TOTAL_STAGGER_MS.
|
|
187
|
+
*/
|
|
188
|
+
declare function clampStaggerDelay(delay: number, elementCount: number): number;
|
|
189
|
+
|
|
171
190
|
/** Chrome with all string values normalized to ChromeText objects. */
|
|
172
191
|
interface NormalizedChrome {
|
|
173
192
|
title?: ChromeText;
|
|
@@ -214,6 +233,7 @@ interface NormalizedTableSpec {
|
|
|
214
233
|
stickyFirstColumn: boolean;
|
|
215
234
|
compact: boolean;
|
|
216
235
|
responsive: boolean;
|
|
236
|
+
animation?: AnimationSpec;
|
|
217
237
|
}
|
|
218
238
|
/** A GraphSpec with all optional fields filled with sensible defaults. */
|
|
219
239
|
interface NormalizedGraphSpec {
|
|
@@ -510,4 +530,4 @@ declare function runTimeUnit(data: DataRow[], transform: TimeUnitTransform): Dat
|
|
|
510
530
|
*/
|
|
511
531
|
declare function runTransforms(data: DataRow[], transforms: Transform[]): DataRow[];
|
|
512
532
|
|
|
513
|
-
export { type ChartRenderer, type CompileResult, type CompiledGraphEdge, type CompiledGraphNode, type GraphCompilation, type NormalizedChartSpec, type NormalizedChrome, type NormalizedGraphSpec, type NormalizedSpec, type NormalizedTableSpec, type SimulationConfig, type ValidationError, type ValidationErrorCode, type ValidationResult, clearRenderers, compile, compileChart, compileGraph, compileLayer, compileTable, evaluatePredicate, getChartRenderer, isConditionalValueDef, normalizeSpec, registerChartRenderer, resolveConditionalValue, runBin, runCalculate, runFilter, runTimeUnit, runTransforms, validateSpec };
|
|
533
|
+
export { type ChartRenderer, type CompileResult, type CompiledGraphEdge, type CompiledGraphNode, type GraphCompilation, type NormalizedChartSpec, type NormalizedChrome, type NormalizedGraphSpec, type NormalizedSpec, type NormalizedTableSpec, type SimulationConfig, type ValidationError, type ValidationErrorCode, type ValidationResult, clampStaggerDelay, clearRenderers, compile, compileChart, compileGraph, compileLayer, compileTable, evaluatePredicate, getChartRenderer, isConditionalValueDef, normalizeSpec, registerChartRenderer, resolveAnimation, resolveConditionalValue, runBin, runCalculate, runFilter, runTimeUnit, runTransforms, validateSpec };
|
package/dist/index.js
CHANGED
|
@@ -774,7 +774,9 @@ function computeStackedBars(data, valueField, categoryField, colorField, xScale,
|
|
|
774
774
|
fill: color2,
|
|
775
775
|
cornerRadius: 0,
|
|
776
776
|
data: row,
|
|
777
|
-
aria
|
|
777
|
+
aria,
|
|
778
|
+
orient: "horizontal",
|
|
779
|
+
stackGroup: category
|
|
778
780
|
});
|
|
779
781
|
cumulativeValue += value;
|
|
780
782
|
}
|
|
@@ -813,7 +815,8 @@ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, band
|
|
|
813
815
|
fill: color2,
|
|
814
816
|
cornerRadius: 2,
|
|
815
817
|
data: row,
|
|
816
|
-
aria
|
|
818
|
+
aria,
|
|
819
|
+
orient: "horizontal"
|
|
817
820
|
});
|
|
818
821
|
}
|
|
819
822
|
return marks;
|
|
@@ -1051,7 +1054,8 @@ function computeSimpleColumns(data, categoryField, valueField, xScale, yScale, b
|
|
|
1051
1054
|
fill: color2,
|
|
1052
1055
|
cornerRadius: 2,
|
|
1053
1056
|
data: row,
|
|
1054
|
-
aria
|
|
1057
|
+
aria,
|
|
1058
|
+
orient: "vertical"
|
|
1055
1059
|
});
|
|
1056
1060
|
}
|
|
1057
1061
|
return marks;
|
|
@@ -1081,7 +1085,8 @@ function computeColoredColumns(data, categoryField, valueField, colorField, xSca
|
|
|
1081
1085
|
fill: color2,
|
|
1082
1086
|
cornerRadius: 2,
|
|
1083
1087
|
data: row,
|
|
1084
|
-
aria
|
|
1088
|
+
aria,
|
|
1089
|
+
orient: "vertical"
|
|
1085
1090
|
});
|
|
1086
1091
|
}
|
|
1087
1092
|
return marks;
|
|
@@ -1113,7 +1118,9 @@ function computeStackedColumns(data, categoryField, valueField, colorField, xSca
|
|
|
1113
1118
|
fill: color2,
|
|
1114
1119
|
cornerRadius: 0,
|
|
1115
1120
|
data: row,
|
|
1116
|
-
aria
|
|
1121
|
+
aria,
|
|
1122
|
+
orient: "vertical",
|
|
1123
|
+
stackGroup: category
|
|
1117
1124
|
});
|
|
1118
1125
|
cumulativeValue += value;
|
|
1119
1126
|
}
|
|
@@ -5992,7 +5999,8 @@ function normalizeTableSpec(spec, _warnings) {
|
|
|
5992
5999
|
pagination: spec.pagination ?? false,
|
|
5993
6000
|
stickyFirstColumn: spec.stickyFirstColumn ?? false,
|
|
5994
6001
|
compact: spec.compact ?? false,
|
|
5995
|
-
responsive: spec.responsive ?? true
|
|
6002
|
+
responsive: spec.responsive ?? true,
|
|
6003
|
+
animation: spec.animation
|
|
5996
6004
|
};
|
|
5997
6005
|
}
|
|
5998
6006
|
function normalizeGraphSpec(spec, _warnings) {
|
|
@@ -6659,6 +6667,77 @@ ${errorMessages}`);
|
|
|
6659
6667
|
return { spec: normalized, warnings };
|
|
6660
6668
|
}
|
|
6661
6669
|
|
|
6670
|
+
// src/compiler/animation.ts
|
|
6671
|
+
var ENTER_DEFAULTS = {
|
|
6672
|
+
duration: 500,
|
|
6673
|
+
ease: "smooth",
|
|
6674
|
+
staggerDelay: 80,
|
|
6675
|
+
staggerOrder: "index",
|
|
6676
|
+
annotationDelay: 200
|
|
6677
|
+
};
|
|
6678
|
+
var MAX_TOTAL_STAGGER_MS = 2e3;
|
|
6679
|
+
function resolveAnimation(spec) {
|
|
6680
|
+
if (spec === void 0 || spec === false) return void 0;
|
|
6681
|
+
if (spec === true) {
|
|
6682
|
+
return {
|
|
6683
|
+
enabled: true,
|
|
6684
|
+
duration: ENTER_DEFAULTS.duration,
|
|
6685
|
+
ease: ENTER_DEFAULTS.ease,
|
|
6686
|
+
staggerDelay: ENTER_DEFAULTS.staggerDelay,
|
|
6687
|
+
staggerOrder: ENTER_DEFAULTS.staggerOrder,
|
|
6688
|
+
annotationDelay: ENTER_DEFAULTS.annotationDelay
|
|
6689
|
+
};
|
|
6690
|
+
}
|
|
6691
|
+
const config = spec;
|
|
6692
|
+
if (config.enter === false || config.enter === void 0 && !hasAnyPhase(config)) {
|
|
6693
|
+
return void 0;
|
|
6694
|
+
}
|
|
6695
|
+
const enterConfig = resolvePhaseConfig(config.enter);
|
|
6696
|
+
return {
|
|
6697
|
+
enabled: true,
|
|
6698
|
+
duration: enterConfig.duration,
|
|
6699
|
+
ease: enterConfig.ease,
|
|
6700
|
+
staggerDelay: enterConfig.staggerDelay,
|
|
6701
|
+
staggerOrder: enterConfig.staggerOrder,
|
|
6702
|
+
annotationDelay: config.annotationDelay ?? ENTER_DEFAULTS.annotationDelay
|
|
6703
|
+
};
|
|
6704
|
+
}
|
|
6705
|
+
function clampStaggerDelay(delay, elementCount) {
|
|
6706
|
+
if (elementCount <= 1) return 0;
|
|
6707
|
+
return Math.min(delay, MAX_TOTAL_STAGGER_MS / elementCount);
|
|
6708
|
+
}
|
|
6709
|
+
function hasAnyPhase(config) {
|
|
6710
|
+
return config.enter !== void 0 || config.update !== void 0 || config.exit !== void 0;
|
|
6711
|
+
}
|
|
6712
|
+
function resolvePhaseConfig(phase) {
|
|
6713
|
+
if (phase === void 0 || phase === true) {
|
|
6714
|
+
return {
|
|
6715
|
+
duration: ENTER_DEFAULTS.duration,
|
|
6716
|
+
ease: ENTER_DEFAULTS.ease,
|
|
6717
|
+
staggerDelay: ENTER_DEFAULTS.staggerDelay,
|
|
6718
|
+
staggerOrder: ENTER_DEFAULTS.staggerOrder
|
|
6719
|
+
};
|
|
6720
|
+
}
|
|
6721
|
+
const cfg = phase;
|
|
6722
|
+
const stagger = resolveStagger(cfg.stagger);
|
|
6723
|
+
return {
|
|
6724
|
+
duration: cfg.duration ?? ENTER_DEFAULTS.duration,
|
|
6725
|
+
ease: cfg.ease ?? ENTER_DEFAULTS.ease,
|
|
6726
|
+
staggerDelay: stagger.delay,
|
|
6727
|
+
staggerOrder: stagger.order
|
|
6728
|
+
};
|
|
6729
|
+
}
|
|
6730
|
+
function resolveStagger(stagger) {
|
|
6731
|
+
if (stagger === false) return { delay: 0, order: "index" };
|
|
6732
|
+
if (stagger === void 0 || stagger === true) {
|
|
6733
|
+
return { delay: ENTER_DEFAULTS.staggerDelay, order: ENTER_DEFAULTS.staggerOrder };
|
|
6734
|
+
}
|
|
6735
|
+
return {
|
|
6736
|
+
delay: stagger.delay ?? ENTER_DEFAULTS.staggerDelay,
|
|
6737
|
+
order: stagger.order ?? ENTER_DEFAULTS.staggerOrder
|
|
6738
|
+
};
|
|
6739
|
+
}
|
|
6740
|
+
|
|
6662
6741
|
// src/graphs/compile-graph.ts
|
|
6663
6742
|
import { adaptTheme, computeChrome, resolveTheme } from "@opendata-ai/openchart-core";
|
|
6664
6743
|
|
|
@@ -8747,7 +8826,8 @@ function compileTableLayout(spec, options, theme) {
|
|
|
8747
8826
|
caption,
|
|
8748
8827
|
summary: `${resolvedColumns.length} columns, ${totalFiltered} rows`
|
|
8749
8828
|
},
|
|
8750
|
-
theme
|
|
8829
|
+
theme,
|
|
8830
|
+
animation: resolveAnimation(spec.animation)
|
|
8751
8831
|
};
|
|
8752
8832
|
}
|
|
8753
8833
|
|
|
@@ -9230,6 +9310,8 @@ function compileChart(spec, options) {
|
|
|
9230
9310
|
};
|
|
9231
9311
|
}
|
|
9232
9312
|
}
|
|
9313
|
+
const rawAnimationSpec = overrides?.[breakpoint]?.animation ?? rawSpec.animation;
|
|
9314
|
+
const resolvedAnimation = resolveAnimation(rawAnimationSpec);
|
|
9233
9315
|
const mergedThemeConfig = options.theme ? { ...chartSpec.theme, ...options.theme } : chartSpec.theme;
|
|
9234
9316
|
let theme = resolveTheme2(mergedThemeConfig);
|
|
9235
9317
|
if (options.darkMode) {
|
|
@@ -9360,6 +9442,37 @@ function compileChart(spec, options) {
|
|
|
9360
9442
|
},
|
|
9361
9443
|
chartSpec.data
|
|
9362
9444
|
);
|
|
9445
|
+
if (resolvedAnimation?.enabled && resolvedAnimation.staggerOrder === "value") {
|
|
9446
|
+
const indexed = marks.map((m, i) => ({ mark: m, idx: i }));
|
|
9447
|
+
indexed.sort((a, b) => {
|
|
9448
|
+
const av = getMarkPrimaryValue(a.mark);
|
|
9449
|
+
const bv = getMarkPrimaryValue(b.mark);
|
|
9450
|
+
return av - bv;
|
|
9451
|
+
});
|
|
9452
|
+
for (let i = 0; i < indexed.length; i++) {
|
|
9453
|
+
const m = indexed[i].mark;
|
|
9454
|
+
if (m.type === "rect" && m.stackGroup) continue;
|
|
9455
|
+
m.animationIndex = i;
|
|
9456
|
+
}
|
|
9457
|
+
}
|
|
9458
|
+
if (resolvedAnimation?.enabled) {
|
|
9459
|
+
const groupIndexMap = /* @__PURE__ */ new Map();
|
|
9460
|
+
const groupStackPos = /* @__PURE__ */ new Map();
|
|
9461
|
+
let nextGroupIndex = 0;
|
|
9462
|
+
for (const mark of marks) {
|
|
9463
|
+
if (mark.type === "rect" && mark.stackGroup) {
|
|
9464
|
+
const rect = mark;
|
|
9465
|
+
const group = rect.stackGroup;
|
|
9466
|
+
if (!groupIndexMap.has(group)) {
|
|
9467
|
+
groupIndexMap.set(group, nextGroupIndex++);
|
|
9468
|
+
}
|
|
9469
|
+
rect.animationIndex = groupIndexMap.get(group);
|
|
9470
|
+
const pos = groupStackPos.get(group) ?? 0;
|
|
9471
|
+
rect.stackPos = pos;
|
|
9472
|
+
groupStackPos.set(group, pos + 1);
|
|
9473
|
+
}
|
|
9474
|
+
}
|
|
9475
|
+
}
|
|
9363
9476
|
return {
|
|
9364
9477
|
area: chartArea,
|
|
9365
9478
|
chrome: dims.chrome,
|
|
@@ -9381,9 +9494,29 @@ function compileChart(spec, options) {
|
|
|
9381
9494
|
dimensions: {
|
|
9382
9495
|
width: options.width,
|
|
9383
9496
|
height: options.height
|
|
9384
|
-
}
|
|
9497
|
+
},
|
|
9498
|
+
animation: resolvedAnimation
|
|
9385
9499
|
};
|
|
9386
9500
|
}
|
|
9501
|
+
function getMarkPrimaryValue(mark) {
|
|
9502
|
+
switch (mark.type) {
|
|
9503
|
+
case "rect":
|
|
9504
|
+
return mark.height;
|
|
9505
|
+
// bar height is the primary value encoding
|
|
9506
|
+
case "point":
|
|
9507
|
+
return mark.cy;
|
|
9508
|
+
// y position for scatter
|
|
9509
|
+
case "arc":
|
|
9510
|
+
return mark.endAngle - mark.startAngle;
|
|
9511
|
+
// arc angle extent
|
|
9512
|
+
case "line":
|
|
9513
|
+
case "area":
|
|
9514
|
+
return 0;
|
|
9515
|
+
// series marks don't have individual values
|
|
9516
|
+
default:
|
|
9517
|
+
return 0;
|
|
9518
|
+
}
|
|
9519
|
+
}
|
|
9387
9520
|
function compileLayer(spec, options) {
|
|
9388
9521
|
const leaves = flattenLayers(spec);
|
|
9389
9522
|
if (leaves.length === 0) {
|
|
@@ -9454,6 +9587,7 @@ function compileGraph2(spec, options) {
|
|
|
9454
9587
|
return compileGraph(spec, options);
|
|
9455
9588
|
}
|
|
9456
9589
|
export {
|
|
9590
|
+
clampStaggerDelay,
|
|
9457
9591
|
clearRenderers,
|
|
9458
9592
|
compile,
|
|
9459
9593
|
compileChart,
|
|
@@ -9465,6 +9599,7 @@ export {
|
|
|
9465
9599
|
isConditionalValueDef,
|
|
9466
9600
|
normalizeSpec,
|
|
9467
9601
|
registerChartRenderer,
|
|
9602
|
+
resolveAnimation,
|
|
9468
9603
|
resolveConditionalValue,
|
|
9469
9604
|
runBin,
|
|
9470
9605
|
runCalculate,
|