@opendata-ai/openchart-engine 7.10.0 → 7.11.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
@@ -658,6 +658,25 @@ declare function getChartRenderer(type: string): ChartRenderer | undefined;
658
658
  */
659
659
  declare function clearRenderers(): void;
660
660
 
661
+ /**
662
+ * Legend row-wrap geometry.
663
+ *
664
+ * Shared helper for measuring how legend entries flow across horizontal rows
665
+ * when wrapped at a max width. Both the main legend compute and the sankey
666
+ * legend compile use this to size their legends — the main legend uses
667
+ * `fittingCount` for truncation decisions, while sankey uses `rowCount` to
668
+ * reserve vertical height.
669
+ *
670
+ * The geometry matches the existing layout exactly: each entry occupies
671
+ * SWATCH_SIZE + SWATCH_GAP + labelWidth + ENTRY_GAP pixels, a new row is
672
+ * started when the accumulated row width plus the next entry would exceed
673
+ * maxWidth (and the current row is non-empty), and rowWidths captures the
674
+ * in-row accumulated width at the point of wrapping.
675
+ */
676
+
677
+ /** Gap between legend and chart area, responsive to container width. */
678
+ declare function legendGap(width: number): number;
679
+
661
680
  /**
662
681
  * Bin transform: discretizes a continuous field into bins.
663
682
  *
@@ -792,4 +811,4 @@ declare function runTimeUnit(data: DataRow[], transform: TimeUnitTransform): Dat
792
811
  */
793
812
  declare function runTransforms(data: DataRow[], transforms: Transform[]): DataRow[];
794
813
 
795
- export { type AnnotationContext, type AnnotationMeasureTextFn, type ChartRenderer, type CompileResult, type CompiledGraphEdge, type CompiledGraphNode, ENTER_DEFAULTS, EXIT_DEFAULTS, type GraphCompilation, type NormalizedBarListSpec, type NormalizedChartSpec, type NormalizedChrome, type NormalizedGraphSpec, type NormalizedSankeySpec, type NormalizedSpec, type NormalizedTableSpec, type NormalizedTileMapSpec, type ObstacleKind, type PlacementObstacle, type SimulationConfig, UPDATE_DEFAULTS, type ValidationError, type ValidationErrorCode, type ValidationResult, buildAreaPath, buildLinePath, clampStaggerDelay, clearRenderers, compile, compileBarList, compileChart, compileGraph, compileLayer, compileSankey, compileTable, compileTileMap, dedupeKeys, evaluatePredicate, getChartRenderer, heuristicMeasure, isConditionalValueDef, normalizeSpec, registerChartRenderer, resolveAnimation, resolveConditionalValue, runBin, runCalculate, runFilter, runTimeUnit, runTransforms, serializeKeyValue, validateSpec };
814
+ export { type AnnotationContext, type AnnotationMeasureTextFn, type ChartRenderer, type CompileResult, type CompiledGraphEdge, type CompiledGraphNode, ENTER_DEFAULTS, EXIT_DEFAULTS, type GraphCompilation, type NormalizedBarListSpec, type NormalizedChartSpec, type NormalizedChrome, type NormalizedGraphSpec, type NormalizedSankeySpec, type NormalizedSpec, type NormalizedTableSpec, type NormalizedTileMapSpec, type ObstacleKind, type PlacementObstacle, type SimulationConfig, UPDATE_DEFAULTS, type ValidationError, type ValidationErrorCode, type ValidationResult, buildAreaPath, buildLinePath, clampStaggerDelay, clearRenderers, compile, compileBarList, compileChart, compileGraph, compileLayer, compileSankey, compileTable, compileTileMap, dedupeKeys, evaluatePredicate, getChartRenderer, heuristicMeasure, isConditionalValueDef, legendGap, normalizeSpec, registerChartRenderer, resolveAnimation, resolveConditionalValue, runBin, runCalculate, runFilter, runTimeUnit, runTransforms, serializeKeyValue, validateSpec };
package/dist/index.js CHANGED
@@ -10153,6 +10153,7 @@ var SWATCH_GAP = 6;
10153
10153
  var ENTRY_GAP = 16;
10154
10154
  var ENTRY_GAP_COMPACT = 10;
10155
10155
  var LEGEND_GAP = 8;
10156
+ var TOP_LEGEND_GAP_ABOVE = 6;
10156
10157
  function legendGap(width) {
10157
10158
  return width < COMPACT_WIDTH ? 0 : LEGEND_GAP;
10158
10159
  }
@@ -10449,7 +10450,7 @@ function computeLegendContent(spec, strategy, theme, availableWidth, availableHe
10449
10450
  rowHeight
10450
10451
  };
10451
10452
  }
10452
- function placeLegend(content, chartArea, containerWidth, _theme, xAxisHeight) {
10453
+ function placeLegend(content, chartArea, containerWidth, _theme, xAxisHeight, axisGapBelowLegend = 0) {
10453
10454
  const { position, entries, labelStyle, legendWidth, height, offset } = content;
10454
10455
  if (entries.length === 0) {
10455
10456
  return {
@@ -10477,7 +10478,7 @@ function placeLegend(content, chartArea, containerWidth, _theme, xAxisHeight) {
10477
10478
  boundsY = chartArea.y + chartArea.height + xAxisHeight + gap + offsetDy;
10478
10479
  } else {
10479
10480
  boundsX = chartArea.x + offsetDx;
10480
- boundsY = chartArea.y - gap - height + offsetDy;
10481
+ boundsY = chartArea.y - axisGapBelowLegend - gap - height + offsetDy;
10481
10482
  }
10482
10483
  const bounds = { x: boundsX, y: boundsY, width: legendWidth, height };
10483
10484
  const entryPositions = resolveEntryPositions(content.relativePositions, bounds);
@@ -11815,7 +11816,7 @@ function resolveLayoutPlan(chartSpec, renderSpec, options, theme, strategy, wate
11815
11816
  const topAxisGap = axisMargin + inlineTickOverhang;
11816
11817
  const effectiveTopAxisGap = hasTopLegend ? inlineTickOverhang : topAxisGap;
11817
11818
  let topMargin = topPad + chrome.topHeight;
11818
- if (hasTopLegend) topMargin += legendContent.height + gap;
11819
+ if (hasTopLegend) topMargin += TOP_LEGEND_GAP_ABOVE + legendContent.height + gap;
11819
11820
  topMargin += effectiveTopAxisGap;
11820
11821
  const bMargin = bottomMargin(chrome.bottomHeight, padding, xAxisExtent);
11821
11822
  const chartHeight = Math.max(0, height - topMargin - bMargin);
@@ -12969,7 +12970,15 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
12969
12970
  width: Math.max(0, width - margins2.left - margins2.right),
12970
12971
  height: Math.max(0, height - margins2.top - margins2.bottom)
12971
12972
  };
12972
- return { total: total2, chrome, chartArea: chartArea2, margins: margins2, theme, xAxisHeight: xAxisSpace };
12973
+ return {
12974
+ total: total2,
12975
+ chrome,
12976
+ chartArea: chartArea2,
12977
+ margins: margins2,
12978
+ theme,
12979
+ xAxisHeight: xAxisSpace,
12980
+ effectiveAxisGap: 0
12981
+ };
12973
12982
  }
12974
12983
  const total = { x: 0, y: 0, width, height };
12975
12984
  const isRadial = spec.markType === "arc";
@@ -13205,10 +13214,11 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
13205
13214
  if (legendPos === "right" || legendPos === "bottom-right") {
13206
13215
  margins.right += legendBoundsWidth + 8;
13207
13216
  } else if (legendPos === "top") {
13208
- margins.top += legendHeight + gap;
13217
+ margins.top += TOP_LEGEND_GAP_ABOVE + legendHeight + gap;
13209
13218
  }
13210
13219
  }
13211
- margins.top += hasTopLegend ? inlineTickOverhang : topAxisGap;
13220
+ const effectiveAxisGap = hasTopLegend ? inlineTickOverhang : topAxisGap;
13221
+ margins.top += effectiveAxisGap;
13212
13222
  let chartArea = {
13213
13223
  x: margins.left,
13214
13224
  y: margins.top,
@@ -13236,7 +13246,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
13236
13246
  const bottomDelta = margins.bottom - newBottom;
13237
13247
  if (topDelta > 0 || bottomDelta > 0) {
13238
13248
  const gap = legendGap(width);
13239
- margins.top = newTop + (hasTopLegend ? legendHeight + gap : 0) + fallbackEffectiveAxisGap;
13249
+ margins.top = newTop + (hasTopLegend ? TOP_LEGEND_GAP_ABOVE + legendHeight + gap : 0) + fallbackEffectiveAxisGap;
13240
13250
  margins.bottom = newBottom;
13241
13251
  chartArea = {
13242
13252
  x: margins.left,
@@ -13269,7 +13279,8 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
13269
13279
  margins,
13270
13280
  theme,
13271
13281
  metrics: fallbackMetrics,
13272
- xAxisHeight
13282
+ xAxisHeight,
13283
+ effectiveAxisGap: fallbackEffectiveAxisGap
13273
13284
  };
13274
13285
  }
13275
13286
  }
@@ -13291,7 +13302,8 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
13291
13302
  margins,
13292
13303
  theme,
13293
13304
  metrics: resolvedMetrics,
13294
- xAxisHeight
13305
+ xAxisHeight,
13306
+ effectiveAxisGap
13295
13307
  };
13296
13308
  }
13297
13309
  function resolveMetrics(spec, metricsTopY, metricsArea, remainingChartHeight, measureText, theme) {
@@ -16466,7 +16478,8 @@ function compileChart(spec, options) {
16466
16478
  chartArea,
16467
16479
  options.width,
16468
16480
  theme,
16469
- plan.xAxisExtent
16481
+ plan.xAxisExtent,
16482
+ dims.effectiveAxisGap
16470
16483
  );
16471
16484
  let scaleArea = chartArea;
16472
16485
  if (plan.inlineYLabelInset > 0 && plan.inlineYLabelInset < chartArea.width) {
@@ -16640,7 +16653,8 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
16640
16653
  chartArea,
16641
16654
  options.width,
16642
16655
  theme,
16643
- plan.xAxisExtent
16656
+ plan.xAxisExtent,
16657
+ dims.effectiveAxisGap
16644
16658
  );
16645
16659
  const leftReservation = plan.leftGutter;
16646
16660
  const bottomReservation = plan.xAxisExtent;
@@ -16839,6 +16853,7 @@ export {
16839
16853
  getChartRenderer,
16840
16854
  heuristicMeasure,
16841
16855
  isConditionalValueDef,
16856
+ legendGap,
16842
16857
  normalizeSpec,
16843
16858
  registerChartRenderer,
16844
16859
  resolveAnimation,