@opendata-ai/openchart-engine 6.10.0 → 6.12.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.js CHANGED
@@ -590,7 +590,7 @@ function computeAnnotations(spec, scales, chartArea, strategy, isDark = false, o
590
590
  }
591
591
 
592
592
  // src/charts/bar/compute.ts
593
- import { abbreviateNumber, formatNumber } from "@opendata-ai/openchart-core";
593
+ import { abbreviateNumber, formatNumber, isGradientDef } from "@opendata-ai/openchart-core";
594
594
 
595
595
  // src/transforms/predicates.ts
596
596
  function isFieldPredicate(pred) {
@@ -933,9 +933,12 @@ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, band
933
933
  if (bandY === void 0) continue;
934
934
  let color2;
935
935
  if (conditionalColor) {
936
- color2 = String(
937
- resolveConditionalValue(row, conditionalColor) ?? getColor(scales, "__default__")
938
- );
936
+ const resolved = resolveConditionalValue(row, conditionalColor);
937
+ if (resolved != null) {
938
+ color2 = isGradientDef(resolved) ? resolved : String(resolved);
939
+ } else {
940
+ color2 = getColor(scales, "__default__");
941
+ }
939
942
  } else if (sequentialColor) {
940
943
  color2 = getSequentialColor(scales, value2);
941
944
  } else {
@@ -966,6 +969,7 @@ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, band
966
969
  import {
967
970
  buildD3Formatter,
968
971
  estimateTextWidth as estimateTextWidth2,
972
+ getRepresentativeColor,
969
973
  resolveCollisions
970
974
  } from "@opendata-ai/openchart-core";
971
975
  var SUFFIX_MULTIPLIERS = {
@@ -1024,7 +1028,7 @@ function computeBarLabels(marks, _chartArea, density = "auto", labelFormat, labe
1024
1028
  textAnchor = "end";
1025
1029
  } else {
1026
1030
  anchorX = mark.x + mark.width + LABEL_PADDING;
1027
- fill = mark.fill;
1031
+ fill = getRepresentativeColor(mark.fill);
1028
1032
  textAnchor = "start";
1029
1033
  }
1030
1034
  const anchorY = mark.y + mark.height / 2;
@@ -1103,7 +1107,7 @@ var barRenderer = (spec, scales, chartArea, strategy, _theme) => {
1103
1107
  };
1104
1108
 
1105
1109
  // src/charts/column/compute.ts
1106
- import { abbreviateNumber as abbreviateNumber2, formatNumber as formatNumber2 } from "@opendata-ai/openchart-core";
1110
+ import { abbreviateNumber as abbreviateNumber2, formatNumber as formatNumber2, isGradientDef as isGradientDef2 } from "@opendata-ai/openchart-core";
1107
1111
  var MIN_COLUMN_HEIGHT = 1;
1108
1112
  function formatColumnValue(value2) {
1109
1113
  if (Math.abs(value2) >= 1e3) return abbreviateNumber2(value2);
@@ -1192,9 +1196,12 @@ function computeSimpleColumns(data, categoryField, valueField, xScale, yScale, b
1192
1196
  if (bandX === void 0) continue;
1193
1197
  let color2;
1194
1198
  if (conditionalColor) {
1195
- color2 = String(
1196
- resolveConditionalValue(row, conditionalColor) ?? getColor(scales, "__default__")
1197
- );
1199
+ const resolved = resolveConditionalValue(row, conditionalColor);
1200
+ if (resolved != null) {
1201
+ color2 = isGradientDef2(resolved) ? resolved : String(resolved);
1202
+ } else {
1203
+ color2 = getColor(scales, "__default__");
1204
+ }
1198
1205
  } else if (sequentialColor) {
1199
1206
  color2 = getSequentialColor(scales, value2);
1200
1207
  } else {
@@ -1342,6 +1349,7 @@ function computeStackedColumns(data, categoryField, valueField, colorField, xSca
1342
1349
  import {
1343
1350
  buildD3Formatter as buildD3Formatter2,
1344
1351
  estimateTextWidth as estimateTextWidth3,
1352
+ getRepresentativeColor as getRepresentativeColor2,
1345
1353
  resolveCollisions as resolveCollisions2
1346
1354
  } from "@opendata-ai/openchart-core";
1347
1355
  var LABEL_FONT_SIZE2 = 10;
@@ -1380,7 +1388,7 @@ function computeColumnLabels(marks, _chartArea, density = "auto", labelFormat, l
1380
1388
  fontFamily: "system-ui, -apple-system, sans-serif",
1381
1389
  fontSize: LABEL_FONT_SIZE2,
1382
1390
  fontWeight: LABEL_FONT_WEIGHT2,
1383
- fill: mark.fill,
1391
+ fill: getRepresentativeColor2(mark.fill),
1384
1392
  lineHeight: 1.2,
1385
1393
  textAnchor: "middle",
1386
1394
  dominantBaseline: isNegative ? "hanging" : "auto"
@@ -1565,7 +1573,11 @@ function computeLollipopMarks(data, valueField, categoryField, xScale, yScale, b
1565
1573
  }
1566
1574
 
1567
1575
  // src/charts/dot/labels.ts
1568
- import { estimateTextWidth as estimateTextWidth4, resolveCollisions as resolveCollisions3 } from "@opendata-ai/openchart-core";
1576
+ import {
1577
+ estimateTextWidth as estimateTextWidth4,
1578
+ getRepresentativeColor as getRepresentativeColor3,
1579
+ resolveCollisions as resolveCollisions3
1580
+ } from "@opendata-ai/openchart-core";
1569
1581
  var LABEL_FONT_SIZE3 = 11;
1570
1582
  var LABEL_FONT_WEIGHT3 = 600;
1571
1583
  var LABEL_OFFSET_X = 10;
@@ -1592,7 +1604,7 @@ function computeDotLabels(marks, _chartArea, density = "auto", labelPrefix) {
1592
1604
  fontFamily: "system-ui, -apple-system, sans-serif",
1593
1605
  fontSize: LABEL_FONT_SIZE3,
1594
1606
  fontWeight: LABEL_FONT_WEIGHT3,
1595
- fill: mark.fill,
1607
+ fill: getRepresentativeColor3(mark.fill),
1596
1608
  lineHeight: 1.2,
1597
1609
  textAnchor: "start",
1598
1610
  dominantBaseline: "central"
@@ -1627,6 +1639,9 @@ var dotRenderer = (spec, scales, chartArea, strategy, _theme) => {
1627
1639
  return marks;
1628
1640
  };
1629
1641
 
1642
+ // src/charts/line/area.ts
1643
+ import { getRepresentativeColor as getRepresentativeColor4 } from "@opendata-ai/openchart-core";
1644
+
1630
1645
  // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/constant.js
1631
1646
  function constant_default(x2) {
1632
1647
  return function constant2() {
@@ -2581,7 +2596,7 @@ function computeSingleArea(spec, scales, _chartArea) {
2581
2596
  topPath: topPathStr,
2582
2597
  fill: color2,
2583
2598
  fillOpacity: DEFAULT_FILL_OPACITY,
2584
- stroke: color2,
2599
+ stroke: getRepresentativeColor4(color2),
2585
2600
  strokeWidth: 2,
2586
2601
  seriesKey: seriesKey === "__default__" ? void 0 : seriesKey,
2587
2602
  data: validPoints.map((p) => p.row),
@@ -2668,7 +2683,7 @@ function computeStackedArea(spec, scales, chartArea) {
2668
2683
  fill: color2,
2669
2684
  fillOpacity: 0.7,
2670
2685
  // Higher opacity for stacked so layers are visible
2671
- stroke: color2,
2686
+ stroke: getRepresentativeColor4(color2),
2672
2687
  strokeWidth: 1,
2673
2688
  seriesKey,
2674
2689
  data: layer.map((d) => {
@@ -2695,6 +2710,7 @@ function computeAreaMarks(spec, scales, chartArea) {
2695
2710
  }
2696
2711
 
2697
2712
  // src/charts/line/compute.ts
2713
+ import { getRepresentativeColor as getRepresentativeColor5 } from "@opendata-ai/openchart-core";
2698
2714
  var DEFAULT_STROKE_WIDTH = 2.5;
2699
2715
  var DEFAULT_POINT_RADIUS = 3;
2700
2716
  function computeLineMarks(spec, scales, _chartArea, _strategy) {
@@ -2712,6 +2728,7 @@ function computeLineMarks(spec, scales, _chartArea, _strategy) {
2712
2728
  const marks = [];
2713
2729
  for (const [seriesKey, rows] of groups) {
2714
2730
  const color2 = isSequentialColor ? getSequentialColor(scales, _getMidValue(rows, sequentialColorField)) : getColor(scales, seriesKey);
2731
+ const strokeColor = getRepresentativeColor5(color2);
2715
2732
  const sortedRows = sortByField(rows, xChannel.field);
2716
2733
  const pointsWithData = [];
2717
2734
  const segments = [];
@@ -2760,7 +2777,7 @@ function computeLineMarks(spec, scales, _chartArea, _strategy) {
2760
2777
  type: "line",
2761
2778
  points: allPoints,
2762
2779
  path: combinedPath,
2763
- stroke: color2,
2780
+ stroke: strokeColor,
2764
2781
  strokeWidth: styleOverride?.strokeWidth ?? DEFAULT_STROKE_WIDTH,
2765
2782
  strokeDasharray,
2766
2783
  opacity: styleOverride?.opacity,
@@ -2905,6 +2922,7 @@ var areaRenderer = (spec, scales, chartArea, strategy, _theme) => {
2905
2922
  };
2906
2923
 
2907
2924
  // src/charts/pie/compute.ts
2925
+ import { isConditionalDef, isGradientDef as isGradientDef3 } from "@opendata-ai/openchart-core";
2908
2926
  var SMALL_SLICE_THRESHOLD = 0.03;
2909
2927
  var DEFAULT_PALETTE = [
2910
2928
  "#1b7fa3",
@@ -2943,6 +2961,7 @@ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
2943
2961
  const encoding = spec.encoding;
2944
2962
  const valueChannel = encoding.y ?? encoding.x;
2945
2963
  const categoryField = encoding.color && "field" in encoding.color ? encoding.color.field : void 0;
2964
+ const conditionalColor = encoding.color && isConditionalDef(encoding.color) ? encoding.color : void 0;
2946
2965
  if (!valueChannel) return [];
2947
2966
  let slices = [];
2948
2967
  if (categoryField) {
@@ -2993,7 +3012,20 @@ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
2993
3012
  const arcDatum = arcs[i];
2994
3013
  const slice2 = arcDatum.data;
2995
3014
  let color2;
2996
- if (scales.color && categoryField) {
3015
+ if (conditionalColor) {
3016
+ const resolved = resolveConditionalValue(
3017
+ slice2.originalRow,
3018
+ conditionalColor
3019
+ );
3020
+ if (resolved != null) {
3021
+ color2 = isGradientDef3(resolved) ? resolved : String(resolved);
3022
+ } else if (scales.color && categoryField) {
3023
+ const colorScale = scales.color.scale;
3024
+ color2 = colorScale(slice2.label);
3025
+ } else {
3026
+ color2 = DEFAULT_PALETTE[i % DEFAULT_PALETTE.length];
3027
+ }
3028
+ } else if (scales.color && categoryField) {
2997
3029
  const colorScale = scales.color.scale;
2998
3030
  color2 = colorScale(slice2.label);
2999
3031
  } else {
@@ -3131,6 +3163,7 @@ function clearRenderers() {
3131
3163
  }
3132
3164
 
3133
3165
  // src/charts/rule/index.ts
3166
+ import { getRepresentativeColor as getRepresentativeColor6 } from "@opendata-ai/openchart-core";
3134
3167
  function computeRuleMarks(spec, scales, chartArea) {
3135
3168
  const encoding = spec.encoding;
3136
3169
  const xChannel = encoding.x;
@@ -3173,7 +3206,9 @@ function computeRuleMarks(spec, scales, chartArea) {
3173
3206
  const y2Val = scaleValue(scales.y.scale, scales.y.type, row[y2Channel.field]);
3174
3207
  if (y2Val != null) y2 = y2Val;
3175
3208
  }
3176
- const color2 = colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__");
3209
+ const color2 = getRepresentativeColor6(
3210
+ colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
3211
+ );
3177
3212
  const strokeDashEncoding = encoding.strokeDash && "field" in encoding.strokeDash ? encoding.strokeDash : void 0;
3178
3213
  const strokeDasharray = strokeDashEncoding ? String(row[strokeDashEncoding.field] ?? "") : void 0;
3179
3214
  const aria = {
@@ -5980,6 +6015,7 @@ var scatterRenderer = (spec, scales, chartArea, strategy, _theme) => {
5980
6015
  };
5981
6016
 
5982
6017
  // src/charts/text/index.ts
6018
+ import { getRepresentativeColor as getRepresentativeColor7 } from "@opendata-ai/openchart-core";
5983
6019
  function computeTextMarks(spec, scales) {
5984
6020
  const encoding = spec.encoding;
5985
6021
  const xChannel = encoding.x;
@@ -6005,7 +6041,9 @@ function computeTextMarks(spec, scales) {
6005
6041
  }
6006
6042
  const text = String(row[textChannel.field] ?? "");
6007
6043
  if (!text) continue;
6008
- const color2 = colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__");
6044
+ const color2 = getRepresentativeColor7(
6045
+ colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
6046
+ );
6009
6047
  const fontSize = sizeEncoding ? Math.max(8, Math.min(48, Number(row[sizeEncoding.field]) || 12)) : 12;
6010
6048
  const aria = {
6011
6049
  label: text
@@ -6030,6 +6068,7 @@ var textRenderer = (spec, scales, _chartArea, _strategy, _theme) => {
6030
6068
  };
6031
6069
 
6032
6070
  // src/charts/tick/index.ts
6071
+ import { getRepresentativeColor as getRepresentativeColor8 } from "@opendata-ai/openchart-core";
6033
6072
  var DEFAULT_TICK_LENGTH = 18;
6034
6073
  function computeTickMarks(spec, scales, _chartArea) {
6035
6074
  const encoding = spec.encoding;
@@ -6045,7 +6084,9 @@ function computeTickMarks(spec, scales, _chartArea) {
6045
6084
  const xVal = scaleValue(scales.x.scale, scales.x.type, row[xChannel.field]);
6046
6085
  const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
6047
6086
  if (xVal == null || yVal == null) continue;
6048
- const color2 = colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__");
6087
+ const color2 = getRepresentativeColor8(
6088
+ colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
6089
+ );
6049
6090
  const aria = {
6050
6091
  label: `${row[xChannel.field]}, ${row[yChannel.field]}`
6051
6092
  };
@@ -6203,7 +6244,8 @@ function normalizeChartSpec(spec, warnings) {
6203
6244
  theme: spec.theme ?? {},
6204
6245
  darkMode: spec.darkMode ?? "off",
6205
6246
  hiddenSeries: spec.hiddenSeries ?? [],
6206
- seriesStyles: spec.seriesStyles ?? {}
6247
+ seriesStyles: spec.seriesStyles ?? {},
6248
+ watermark: spec.watermark ?? true
6207
6249
  };
6208
6250
  }
6209
6251
  function normalizeTableSpec(spec, _warnings) {
@@ -6220,7 +6262,8 @@ function normalizeTableSpec(spec, _warnings) {
6220
6262
  stickyFirstColumn: spec.stickyFirstColumn ?? false,
6221
6263
  compact: spec.compact ?? false,
6222
6264
  responsive: spec.responsive ?? true,
6223
- animation: spec.animation
6265
+ animation: spec.animation,
6266
+ watermark: spec.watermark ?? true
6224
6267
  };
6225
6268
  }
6226
6269
  function normalizeSankeySpec(spec, _warnings) {
@@ -6240,7 +6283,8 @@ function normalizeSankeySpec(spec, _warnings) {
6240
6283
  darkMode: spec.darkMode ?? "off",
6241
6284
  animation: spec.animation,
6242
6285
  valueFormat: spec.valueFormat,
6243
- linkOpacity: spec.linkOpacity
6286
+ linkOpacity: spec.linkOpacity,
6287
+ watermark: spec.watermark ?? true
6244
6288
  };
6245
6289
  }
6246
6290
  function normalizeGraphSpec(spec, _warnings) {
@@ -6263,7 +6307,8 @@ function normalizeGraphSpec(spec, _warnings) {
6263
6307
  chrome: normalizeChrome(spec.chrome),
6264
6308
  annotations: normalizeAnnotations(spec.annotations),
6265
6309
  theme: spec.theme ?? {},
6266
- darkMode: spec.darkMode ?? "off"
6310
+ darkMode: spec.darkMode ?? "off",
6311
+ watermark: spec.watermark ?? true
6267
6312
  };
6268
6313
  }
6269
6314
  function normalizeSpec(spec, warnings = []) {
@@ -6290,14 +6335,23 @@ function normalizeSpec(spec, warnings = []) {
6290
6335
  `Unknown spec shape. Expected mark (chart), layer, type: 'table', type: 'graph', or type: 'sankey'.`
6291
6336
  );
6292
6337
  }
6293
- function flattenLayers(spec, parentData, parentEncoding, parentTransforms) {
6338
+ function flattenLayers(spec, parentData, parentEncoding, parentTransforms, parentWatermark) {
6294
6339
  const resolvedData = spec.data ?? parentData;
6295
6340
  const resolvedEncoding = parentEncoding && spec.encoding ? { ...parentEncoding, ...spec.encoding } : spec.encoding ?? parentEncoding;
6296
6341
  const resolvedTransforms = [...parentTransforms ?? [], ...spec.transform ?? []];
6342
+ const resolvedWatermark = spec.watermark ?? parentWatermark;
6297
6343
  const leaves = [];
6298
6344
  for (const child of spec.layer) {
6299
6345
  if (isLayerSpec(child)) {
6300
- leaves.push(...flattenLayers(child, resolvedData, resolvedEncoding, resolvedTransforms));
6346
+ leaves.push(
6347
+ ...flattenLayers(
6348
+ child,
6349
+ resolvedData,
6350
+ resolvedEncoding,
6351
+ resolvedTransforms,
6352
+ resolvedWatermark
6353
+ )
6354
+ );
6301
6355
  } else {
6302
6356
  const mergedData = child.data ?? resolvedData ?? [];
6303
6357
  const mergedEncoding = resolvedEncoding ? { ...resolvedEncoding, ...child.encoding } : child.encoding;
@@ -6306,7 +6360,9 @@ function flattenLayers(spec, parentData, parentEncoding, parentTransforms) {
6306
6360
  ...child,
6307
6361
  data: mergedData,
6308
6362
  encoding: mergedEncoding,
6309
- transform: mergedTransforms.length > 0 ? mergedTransforms : void 0
6363
+ transform: mergedTransforms.length > 0 ? mergedTransforms : void 0,
6364
+ // Inherit parent watermark if child doesn't explicitly set one
6365
+ ...child.watermark === void 0 && resolvedWatermark !== void 0 ? { watermark: resolvedWatermark } : {}
6310
6366
  });
6311
6367
  }
6312
6368
  }
@@ -7365,6 +7421,8 @@ function compileGraph(spec, options) {
7365
7421
  );
7366
7422
  }
7367
7423
  const graphSpec = normalized;
7424
+ const rawWatermark = spec.watermark;
7425
+ const watermark = rawWatermark !== void 0 ? graphSpec.watermark : options.watermark ?? true;
7368
7426
  const mergedThemeConfig = options.theme ? { ...graphSpec.theme, ...options.theme } : graphSpec.theme;
7369
7427
  let theme = resolveTheme(mergedThemeConfig);
7370
7428
  if (options.darkMode) {
@@ -7432,7 +7490,10 @@ function compileGraph(spec, options) {
7432
7490
  },
7433
7491
  theme,
7434
7492
  options.width,
7435
- options.measureText
7493
+ options.measureText,
7494
+ "full",
7495
+ void 0,
7496
+ watermark
7436
7497
  );
7437
7498
  return {
7438
7499
  nodes: compiledNodes,
@@ -7446,7 +7507,8 @@ function compileGraph(spec, options) {
7446
7507
  width: options.width,
7447
7508
  height: options.height
7448
7509
  },
7449
- simulationConfig
7510
+ simulationConfig,
7511
+ watermark
7450
7512
  };
7451
7513
  }
7452
7514
  var DEFAULT_COLLISION_PADDING = 5;
@@ -7745,7 +7807,7 @@ function scalePadding(basePadding, width, height) {
7745
7807
  }
7746
7808
  var MIN_CHART_WIDTH = 60;
7747
7809
  var MIN_CHART_HEIGHT = 40;
7748
- function computeDimensions(spec, options, legendLayout, theme, strategy) {
7810
+ function computeDimensions(spec, options, legendLayout, theme, strategy, watermark = true) {
7749
7811
  const { width, height } = options;
7750
7812
  const padding = scalePadding(theme.spacing.padding, width, height);
7751
7813
  const axisMargin = theme.spacing.axisMargin;
@@ -7756,7 +7818,8 @@ function computeDimensions(spec, options, legendLayout, theme, strategy) {
7756
7818
  width,
7757
7819
  options.measureText,
7758
7820
  chromeMode,
7759
- padding
7821
+ padding,
7822
+ watermark
7760
7823
  );
7761
7824
  const total = { x: 0, y: 0, width, height };
7762
7825
  const isRadial = spec.markType === "arc";
@@ -7914,7 +7977,8 @@ function computeDimensions(spec, options, legendLayout, theme, strategy) {
7914
7977
  width,
7915
7978
  options.measureText,
7916
7979
  fallbackMode,
7917
- padding
7980
+ padding,
7981
+ watermark
7918
7982
  );
7919
7983
  const fallbackTopAxisGap = isRadial && fallbackChrome.topHeight === 0 ? 0 : axisMargin;
7920
7984
  const newTop = padding + fallbackChrome.topHeight + fallbackTopAxisGap;
@@ -8400,7 +8464,7 @@ function truncateEntries(entries, maxCount) {
8400
8464
  });
8401
8465
  return truncated;
8402
8466
  }
8403
- function computeLegend(spec, strategy, theme, chartArea) {
8467
+ function computeLegend(spec, strategy, theme, chartArea, watermark = true) {
8404
8468
  if (spec.legend?.show === false || strategy.legendMaxHeight === 0) {
8405
8469
  return {
8406
8470
  position: "top",
@@ -8477,7 +8541,7 @@ function computeLegend(spec, strategy, theme, chartArea) {
8477
8541
  entryGap: 4
8478
8542
  };
8479
8543
  }
8480
- const availableWidth = chartArea.width - LEGEND_PADDING * 2 - BRAND_RESERVE_WIDTH;
8544
+ const availableWidth = chartArea.width - LEGEND_PADDING * 2 - (watermark ? BRAND_RESERVE_WIDTH : 0);
8481
8545
  if (spec.legend?.symbolLimit != null) {
8482
8546
  const limit = Math.max(1, spec.legend.symbolLimit);
8483
8547
  if (limit < entries.length) {
@@ -9096,6 +9160,8 @@ function compileSankey(spec, options) {
9096
9160
  );
9097
9161
  }
9098
9162
  const sankeySpec = normalized;
9163
+ const rawWatermark = spec.watermark;
9164
+ const watermark = rawWatermark !== void 0 ? sankeySpec.watermark : options.watermark ?? true;
9099
9165
  const mergedThemeConfig = options.theme ? { ...sankeySpec.theme, ...options.theme } : sankeySpec.theme;
9100
9166
  const lightTheme = resolveTheme2(mergedThemeConfig);
9101
9167
  let theme = lightTheme;
@@ -9116,7 +9182,10 @@ function compileSankey(spec, options) {
9116
9182
  },
9117
9183
  theme,
9118
9184
  options.width,
9119
- options.measureText
9185
+ options.measureText,
9186
+ "full",
9187
+ void 0,
9188
+ watermark
9120
9189
  );
9121
9190
  const padding = theme.spacing.padding;
9122
9191
  const fullArea = {
@@ -9126,7 +9195,7 @@ function compileSankey(spec, options) {
9126
9195
  height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
9127
9196
  };
9128
9197
  if (fullArea.width <= 0 || fullArea.height <= 0) {
9129
- return emptyLayout(fullArea, chrome, theme, options);
9198
+ return emptyLayout(fullArea, chrome, theme, options, watermark);
9130
9199
  }
9131
9200
  const sourceField = sankeySpec.encoding.source.field;
9132
9201
  const targetField = sankeySpec.encoding.target.field;
@@ -9162,7 +9231,7 @@ function compileSankey(spec, options) {
9162
9231
  height: fullArea.height - legend.bounds.height - legendGap
9163
9232
  };
9164
9233
  if (area.height <= 0) {
9165
- return emptyLayout(area, chrome, theme, options);
9234
+ return emptyLayout(area, chrome, theme, options, watermark);
9166
9235
  }
9167
9236
  const labelFontSize = theme.fonts.sizes.small;
9168
9237
  const labelFontWeight = theme.fonts.weights.normal;
@@ -9306,7 +9375,8 @@ function compileSankey(spec, options) {
9306
9375
  width: options.width,
9307
9376
  height: options.height
9308
9377
  },
9309
- animation: resolvedAnimation
9378
+ animation: resolvedAnimation,
9379
+ watermark
9310
9380
  };
9311
9381
  }
9312
9382
  function buildSankeyLegend(nodeColorMap, colorField, data, sourceField, targetField, theme, area) {
@@ -9413,7 +9483,7 @@ function buildTooltipDescriptors(nodes, links, valueFormat) {
9413
9483
  }
9414
9484
  return descriptors;
9415
9485
  }
9416
- function emptyLayout(area, chrome, theme, options) {
9486
+ function emptyLayout(area, chrome, theme, options, watermark) {
9417
9487
  return {
9418
9488
  area,
9419
9489
  chrome,
@@ -9445,7 +9515,8 @@ function emptyLayout(area, chrome, theme, options) {
9445
9515
  dimensions: {
9446
9516
  width: options.width,
9447
9517
  height: options.height
9448
- }
9518
+ },
9519
+ watermark
9449
9520
  };
9450
9521
  }
9451
9522
 
@@ -10045,6 +10116,7 @@ function compileTableLayout(spec, options, theme) {
10045
10116
  });
10046
10117
  return { id: rowId, cells, data: row };
10047
10118
  });
10119
+ const watermark = spec.watermark;
10048
10120
  const chrome = computeChrome4(
10049
10121
  {
10050
10122
  title: spec.chrome.title,
@@ -10055,7 +10127,10 @@ function compileTableLayout(spec, options, theme) {
10055
10127
  },
10056
10128
  theme,
10057
10129
  options.width,
10058
- options.measureText
10130
+ options.measureText,
10131
+ "full",
10132
+ void 0,
10133
+ watermark
10059
10134
  );
10060
10135
  const titleText = spec.chrome.title?.text ?? "";
10061
10136
  const caption = titleText ? `Table: ${titleText}` : `Data table with ${data.length} rows`;
@@ -10077,12 +10152,18 @@ function compileTableLayout(spec, options, theme) {
10077
10152
  summary: `${resolvedColumns.length} columns, ${totalFiltered} rows`
10078
10153
  },
10079
10154
  theme,
10080
- animation: resolveAnimation(spec.animation)
10155
+ animation: resolveAnimation(spec.animation),
10156
+ watermark
10081
10157
  };
10082
10158
  }
10083
10159
 
10084
10160
  // src/tooltips/compute.ts
10085
- import { buildTemporalFormatter as buildTemporalFormatter2, formatDate as formatDate3, formatNumber as formatNumber6 } from "@opendata-ai/openchart-core";
10161
+ import {
10162
+ buildTemporalFormatter as buildTemporalFormatter2,
10163
+ formatDate as formatDate3,
10164
+ formatNumber as formatNumber6,
10165
+ getRepresentativeColor as getRepresentativeColor9
10166
+ } from "@opendata-ai/openchart-core";
10086
10167
  function formatValue(value2, fieldType, format2) {
10087
10168
  if (value2 == null) return "";
10088
10169
  if (fieldType === "temporal" || value2 instanceof Date) {
@@ -10166,12 +10247,12 @@ function tooltipsForLine(mark, encoding, _markIndex) {
10166
10247
  }
10167
10248
  function tooltipsForPoint(mark, encoding, markIndex) {
10168
10249
  const title = getTooltipTitle(mark.data, encoding);
10169
- const fields = buildFields(mark.data, encoding, mark.fill);
10250
+ const fields = buildFields(mark.data, encoding, getRepresentativeColor9(mark.fill));
10170
10251
  return [[`point-${markIndex}`, { title, fields }]];
10171
10252
  }
10172
10253
  function tooltipsForRect(mark, encoding, markIndex) {
10173
10254
  const title = getTooltipTitle(mark.data, encoding);
10174
- const fields = buildFields(mark.data, encoding, mark.fill);
10255
+ const fields = buildFields(mark.data, encoding, getRepresentativeColor9(mark.fill));
10175
10256
  return [[`rect-${markIndex}`, { title, fields }]];
10176
10257
  }
10177
10258
  function tooltipsForArc(mark, encoding, markIndex) {
@@ -10184,14 +10265,14 @@ function tooltipsForArc(mark, encoding, markIndex) {
10184
10265
  fields.push({
10185
10266
  label: categoryName,
10186
10267
  value: formatValue(row[encoding.y.field], encoding.y.type, encoding.y.axis?.format),
10187
- color: mark.fill
10268
+ color: getRepresentativeColor9(mark.fill)
10188
10269
  });
10189
10270
  }
10190
10271
  } else if (encoding.y) {
10191
10272
  fields.push({
10192
10273
  label: encoding.y.field,
10193
10274
  value: formatValue(row[encoding.y.field], encoding.y.type, encoding.y.axis?.format),
10194
- color: mark.fill
10275
+ color: getRepresentativeColor9(mark.fill)
10195
10276
  });
10196
10277
  }
10197
10278
  const title = colorEnc ? String(row[colorEnc.field] ?? "") : void 0;
@@ -10202,7 +10283,7 @@ function tooltipsForArea(mark, encoding, _markIndex) {
10202
10283
  for (const dp of mark.dataPoints) {
10203
10284
  dp.tooltip = {
10204
10285
  title: getTooltipTitle(dp.datum, encoding),
10205
- fields: buildFields(dp.datum, encoding, mark.fill)
10286
+ fields: buildFields(dp.datum, encoding, getRepresentativeColor9(mark.fill))
10206
10287
  };
10207
10288
  }
10208
10289
  }
@@ -10518,6 +10599,8 @@ function compileChart(spec, options) {
10518
10599
  throw new Error("compileChart received a sankey spec. Use compileSankey instead.");
10519
10600
  }
10520
10601
  let chartSpec = normalized;
10602
+ const rawWatermark = spec.watermark;
10603
+ const watermark = rawWatermark !== void 0 ? chartSpec.watermark : options.watermark ?? true;
10521
10604
  const rawTransforms = spec.transform;
10522
10605
  if (rawTransforms && rawTransforms.length > 0) {
10523
10606
  chartSpec = { ...chartSpec, data: runTransforms(chartSpec.data, rawTransforms) };
@@ -10576,8 +10659,8 @@ function compileChart(spec, options) {
10576
10659
  width: options.width,
10577
10660
  height: options.height
10578
10661
  };
10579
- const legendLayout = computeLegend(chartSpec, strategy, theme, preliminaryArea);
10580
- const dims = computeDimensions(chartSpec, options, legendLayout, theme, strategy);
10662
+ const legendLayout = computeLegend(chartSpec, strategy, theme, preliminaryArea, watermark);
10663
+ const dims = computeDimensions(chartSpec, options, legendLayout, theme, strategy, watermark);
10581
10664
  const chartArea = dims.chartArea;
10582
10665
  const legendArea = { ...chartArea };
10583
10666
  if (legendLayout.entries.length > 0) {
@@ -10595,7 +10678,7 @@ function compileChart(spec, options) {
10595
10678
  break;
10596
10679
  }
10597
10680
  }
10598
- const finalLegend = computeLegend(chartSpec, strategy, theme, legendArea);
10681
+ const finalLegend = computeLegend(chartSpec, strategy, theme, legendArea, watermark);
10599
10682
  let renderData = chartSpec.data;
10600
10683
  if (chartSpec.hiddenSeries.length > 0 && chartSpec.encoding.color && "field" in chartSpec.encoding.color) {
10601
10684
  const colorField = chartSpec.encoding.color.field;
@@ -10630,7 +10713,7 @@ function compileChart(spec, options) {
10630
10713
  );
10631
10714
  }
10632
10715
  }
10633
- scales.defaultColor = theme.colors.categorical[0];
10716
+ scales.defaultColor = chartSpec.markDef.fill ?? theme.colors.categorical[0];
10634
10717
  const isRadial = chartSpec.markType === "arc";
10635
10718
  const axes = isRadial ? { x: void 0, y: void 0 } : computeAxes(scales, chartArea, strategy, theme, options.measureText);
10636
10719
  if (!isRadial) {
@@ -10662,12 +10745,14 @@ function compileChart(spec, options) {
10662
10745
  obstacles.push(computeLabelBounds(mark.label));
10663
10746
  }
10664
10747
  }
10665
- const brandPadding = theme.spacing.padding;
10666
- const brandX = dims.total.width - brandPadding - BRAND_RESERVE_WIDTH2;
10667
- const xAxisExtent = axes.x?.label ? 48 : axes.x ? 26 : 0;
10668
- const firstBottomChrome = dims.chrome.source ?? dims.chrome.byline ?? dims.chrome.footer;
10669
- const brandY = firstBottomChrome ? chartArea.y + chartArea.height + xAxisExtent + firstBottomChrome.y : chartArea.y + chartArea.height + xAxisExtent + theme.spacing.chartToFooter;
10670
- obstacles.push({ x: brandX, y: brandY, width: BRAND_RESERVE_WIDTH2, height: 30 });
10748
+ if (watermark) {
10749
+ const brandPadding = theme.spacing.padding;
10750
+ const brandX = dims.total.width - brandPadding - BRAND_RESERVE_WIDTH2;
10751
+ const xAxisExtent = axes.x?.label ? 48 : axes.x ? 26 : 0;
10752
+ const firstBottomChrome = dims.chrome.source ?? dims.chrome.byline ?? dims.chrome.footer;
10753
+ const brandY = firstBottomChrome ? chartArea.y + chartArea.height + xAxisExtent + firstBottomChrome.y : chartArea.y + chartArea.height + xAxisExtent + theme.spacing.chartToFooter;
10754
+ obstacles.push({ x: brandX, y: brandY, width: BRAND_RESERVE_WIDTH2, height: 30 });
10755
+ }
10671
10756
  const annotations = computeAnnotations(
10672
10757
  chartSpec,
10673
10758
  scales,
@@ -10748,7 +10833,8 @@ function compileChart(spec, options) {
10748
10833
  width: options.width,
10749
10834
  height: options.height
10750
10835
  },
10751
- animation: resolvedAnimation
10836
+ animation: resolvedAnimation,
10837
+ watermark
10752
10838
  };
10753
10839
  }
10754
10840
  function getMarkPrimaryValue(mark) {
@@ -10818,6 +10904,7 @@ function buildPrimarySpec(leaves, layerSpec) {
10818
10904
  responsive: layerSpec.responsive ?? leaves[0].responsive,
10819
10905
  theme: layerSpec.theme ?? leaves[0].theme,
10820
10906
  darkMode: layerSpec.darkMode ?? leaves[0].darkMode,
10907
+ watermark: layerSpec.watermark ?? leaves[0].watermark,
10821
10908
  hiddenSeries: layerSpec.hiddenSeries ?? leaves[0].hiddenSeries
10822
10909
  };
10823
10910
  return primary;
@@ -10834,7 +10921,9 @@ function compileTable(spec, options) {
10834
10921
  if (options.darkMode) {
10835
10922
  theme = adaptTheme3(theme);
10836
10923
  }
10837
- return compileTableLayout(tableSpec, options, theme);
10924
+ const rawWatermark = spec.watermark;
10925
+ const watermark = rawWatermark !== void 0 ? tableSpec.watermark : options.watermark ?? true;
10926
+ return compileTableLayout({ ...tableSpec, watermark }, options, theme);
10838
10927
  }
10839
10928
  function compileGraph2(spec, options) {
10840
10929
  return compileGraph(spec, options);