@opendata-ai/openchart-engine 6.4.1 → 6.5.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/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,