@opendata-ai/openchart-core 8.0.0-rc.9 → 8.0.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.
Files changed (82) hide show
  1. package/dist/index.d.ts +363 -43
  2. package/dist/index.js +39 -18
  3. package/dist/index.js.map +1 -1
  4. package/dist/styles.css +1 -1
  5. package/dist/styles.css.map +1 -1
  6. package/package.json +1 -2
  7. package/schema/chart.schema.json +373 -67
  8. package/schema/table.schema.json +35 -1
  9. package/schema/vizspec.schema.json +950 -152
  10. package/src/accessibility/__tests__/alt-text.test.ts +0 -110
  11. package/src/accessibility/__tests__/aria.test.ts +0 -125
  12. package/src/accessibility/alt-text.ts +0 -155
  13. package/src/accessibility/aria.ts +0 -75
  14. package/src/accessibility/index.ts +0 -6
  15. package/src/colors/__tests__/colorblind.test.ts +0 -75
  16. package/src/colors/__tests__/contrast.test.ts +0 -119
  17. package/src/colors/__tests__/palettes.test.ts +0 -74
  18. package/src/colors/colorblind.ts +0 -131
  19. package/src/colors/contrast.ts +0 -143
  20. package/src/colors/index.ts +0 -36
  21. package/src/colors/palettes.ts +0 -206
  22. package/src/helpers/__tests__/deep-merge.test.ts +0 -54
  23. package/src/helpers/__tests__/spec-builders.test.ts +0 -338
  24. package/src/helpers/deep-merge.ts +0 -29
  25. package/src/helpers/spec-builders.ts +0 -479
  26. package/src/index.ts +0 -215
  27. package/src/labels/__tests__/collision.test.ts +0 -310
  28. package/src/labels/collision.ts +0 -249
  29. package/src/labels/index.ts +0 -13
  30. package/src/layout/__tests__/chrome.test.ts +0 -208
  31. package/src/layout/__tests__/text-measure.test.ts +0 -57
  32. package/src/layout/chrome.ts +0 -470
  33. package/src/layout/index.ts +0 -18
  34. package/src/layout/text-measure.ts +0 -404
  35. package/src/layout/text-wrap.ts +0 -93
  36. package/src/locale/__tests__/format.test.ts +0 -606
  37. package/src/locale/format.ts +0 -459
  38. package/src/locale/index.ts +0 -21
  39. package/src/responsive/__tests__/breakpoints.test.ts +0 -146
  40. package/src/responsive/__tests__/metrics.test.ts +0 -52
  41. package/src/responsive/breakpoints.ts +0 -177
  42. package/src/responsive/index.ts +0 -53
  43. package/src/responsive/metrics.ts +0 -299
  44. package/src/schema/__tests__/generated-artifacts.test.ts +0 -42
  45. package/src/schema/__tests__/schema.test.ts +0 -179
  46. package/src/styles/__tests__/reduced-motion-selectors.test.ts +0 -28
  47. package/src/styles/animation.css +0 -213
  48. package/src/styles/base.css +0 -102
  49. package/src/styles/chrome.css +0 -174
  50. package/src/styles/dark.css +0 -44
  51. package/src/styles/graph.css +0 -135
  52. package/src/styles/index.css +0 -28
  53. package/src/styles/keyframes.css +0 -151
  54. package/src/styles/legend.css +0 -18
  55. package/src/styles/reduced-motion.css +0 -67
  56. package/src/styles/series-search.css +0 -153
  57. package/src/styles/sparkline.css +0 -16
  58. package/src/styles/table-animation.css +0 -93
  59. package/src/styles/table.css +0 -398
  60. package/src/styles/token-definitions.ts +0 -199
  61. package/src/styles/tokens.css +0 -156
  62. package/src/styles/tooltip.css +0 -126
  63. package/src/styles/you-draw-it.css +0 -126
  64. package/src/theme/__tests__/dark-mode.test.ts +0 -232
  65. package/src/theme/__tests__/defaults.test.ts +0 -73
  66. package/src/theme/__tests__/resolve.test.ts +0 -277
  67. package/src/theme/dark-mode.ts +0 -258
  68. package/src/theme/defaults.ts +0 -110
  69. package/src/theme/index.ts +0 -8
  70. package/src/theme/presets.ts +0 -64
  71. package/src/theme/resolve.ts +0 -312
  72. package/src/types/__tests__/encoding.test.ts +0 -368
  73. package/src/types/__tests__/gradient.test.ts +0 -95
  74. package/src/types/__tests__/spec.test.ts +0 -499
  75. package/src/types/encoding.ts +0 -280
  76. package/src/types/events.ts +0 -236
  77. package/src/types/index.ts +0 -290
  78. package/src/types/layout.ts +0 -2024
  79. package/src/types/schema-roots.ts +0 -32
  80. package/src/types/spec.ts +0 -2925
  81. package/src/types/table.ts +0 -108
  82. package/src/types/theme.ts +0 -209
package/dist/index.js CHANGED
@@ -284,7 +284,7 @@ function isTileMapSpec(spec) {
284
284
  function isBarListSpec(spec) {
285
285
  return "type" in spec && spec.type === "barlist";
286
286
  }
287
- function isMapSpec(spec) {
287
+ function isGeoMapSpec(spec) {
288
288
  return "type" in spec && spec.type === "map";
289
289
  }
290
290
  function isTextAnnotation(annotation) {
@@ -1277,7 +1277,7 @@ function getWidthStrategy(breakpoint) {
1277
1277
  case "full":
1278
1278
  return {
1279
1279
  labelMode: "all",
1280
- legendPosition: "right",
1280
+ legendPosition: "top",
1281
1281
  annotationPosition: "inline",
1282
1282
  axisLabelDensity: "full",
1283
1283
  chromeMode: "full",
@@ -1371,17 +1371,16 @@ function maxRotatedLabelWidth(tickAngle, tickFontSize) {
1371
1371
  const usable = X_AXIS_ROTATED_EXTENT_CAP - lineHeight * Math.cos(angleRad) - AXIS_TO_LABEL_GAP;
1372
1372
  return Math.max(0, usable / sin);
1373
1373
  }
1374
- function truncateRotatedLabel(label, tickAngle, tickFontSize, tickFontWeight, measure = estimateTextWidth) {
1375
- const budget = maxRotatedLabelWidth(tickAngle, tickFontSize);
1374
+ function truncateToWidth(label, budget, fontSize, fontWeight, measure = estimateTextWidth) {
1376
1375
  if (!Number.isFinite(budget)) return label;
1377
- if (measure(label, tickFontSize, tickFontWeight) <= budget) return label;
1376
+ if (measure(label, fontSize, fontWeight) <= budget) return label;
1378
1377
  const ELLIPSIS = "\u2026";
1379
1378
  let lo = 0;
1380
1379
  let hi = label.length;
1381
1380
  while (lo < hi) {
1382
1381
  const mid = Math.ceil((lo + hi) / 2);
1383
1382
  const candidate = label.slice(0, mid) + ELLIPSIS;
1384
- if (measure(candidate, tickFontSize, tickFontWeight) <= budget) {
1383
+ if (measure(candidate, fontSize, fontWeight) <= budget) {
1385
1384
  lo = mid;
1386
1385
  } else {
1387
1386
  hi = mid - 1;
@@ -1389,6 +1388,10 @@ function truncateRotatedLabel(label, tickAngle, tickFontSize, tickFontWeight, me
1389
1388
  }
1390
1389
  return lo > 0 ? label.slice(0, lo).trimEnd() + ELLIPSIS : ELLIPSIS;
1391
1390
  }
1391
+ function truncateRotatedLabel(label, tickAngle, tickFontSize, tickFontWeight, measure = estimateTextWidth) {
1392
+ const budget = maxRotatedLabelWidth(tickAngle, tickFontSize);
1393
+ return truncateToWidth(label, budget, tickFontSize, tickFontWeight, measure);
1394
+ }
1392
1395
 
1393
1396
  // src/theme/defaults.ts
1394
1397
  var DEFAULT_THEME = {
@@ -1538,7 +1541,7 @@ function _luminanceFromHex(color2) {
1538
1541
  function adaptTheme(theme) {
1539
1542
  const pairs = theme._tokenPairs;
1540
1543
  const inputBg = theme.colors.background;
1541
- const isTransparent = inputBg === "transparent";
1544
+ const isTransparent = !isOpaqueColor(inputBg);
1542
1545
  const alreadyDark = isTransparent || _luminanceFromHex(inputBg) < 0.2;
1543
1546
  const darkBg = pairs?.["colors.background"] ? pairs["colors.background"].dark : alreadyDark ? inputBg : DARK_BG;
1544
1547
  const darkMuted = ACHROMATIC_RAMP.fgMuted;
@@ -1783,7 +1786,7 @@ function relativeLuminance2(hex2) {
1783
1786
  return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
1784
1787
  }
1785
1788
  function isDarkBackground(hex2) {
1786
- if (hex2 === "transparent") return false;
1789
+ if (!isOpaqueColor(hex2)) return false;
1787
1790
  return relativeLuminance2(hex2) < 0.2;
1788
1791
  }
1789
1792
  function adaptChromeForDarkBg(theme, textColor) {
@@ -1884,13 +1887,14 @@ function buildTextStyle(defaults, fontFamily, textColor, width, overrides) {
1884
1887
  textAnchor: "start"
1885
1888
  };
1886
1889
  }
1887
- function estimateLineCount(text, style, maxWidth, measureText) {
1890
+ function estimateLineCount(text, style, maxWidth, measureText, maxLines) {
1888
1891
  if (maxWidth <= 0) return 1;
1889
1892
  const segments = text.split("\n");
1890
1893
  if (segments.length > 1) {
1891
- return segments.reduce((total, segment) => {
1894
+ const count = segments.reduce((total, segment) => {
1892
1895
  return total + (segment.length === 0 ? 1 : estimateLineCount(segment, style, maxWidth, measureText));
1893
1896
  }, 0);
1897
+ return maxLines != null ? Math.min(count, maxLines) : count;
1894
1898
  }
1895
1899
  if (measureText) {
1896
1900
  const textWidth = measureText(text, style.fontSize, style.fontWeight).width;
@@ -1908,7 +1912,7 @@ function estimateLineCount(text, style, maxWidth, measureText) {
1908
1912
  current2 = candidate;
1909
1913
  }
1910
1914
  }
1911
- return lines2;
1915
+ return maxLines != null ? Math.min(lines2, maxLines) : lines2;
1912
1916
  }
1913
1917
  const charWidth = estimateCharWidth(style.fontSize, style.fontWeight);
1914
1918
  const maxChars = Math.floor(maxWidth / charWidth);
@@ -1925,7 +1929,7 @@ function estimateLineCount(text, style, maxWidth, measureText) {
1925
1929
  current = candidate;
1926
1930
  }
1927
1931
  }
1928
- return lines;
1932
+ return maxLines != null ? Math.min(lines, maxLines) : lines;
1929
1933
  }
1930
1934
  var FOOTNOTE_LINE_HEIGHT = 1.3;
1931
1935
  var FOOTNOTE_BAND_GAP = 4;
@@ -1953,12 +1957,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1953
1957
  width,
1954
1958
  eyebrowNorm.style
1955
1959
  );
1956
- const lineCount = estimateLineCount(eyebrowNorm.text, style, maxWidth, measureText);
1960
+ const maxLines = eyebrowNorm.style?.maxLines;
1961
+ const lineCount = estimateLineCount(eyebrowNorm.text, style, maxWidth, measureText, maxLines);
1957
1962
  const element = {
1958
1963
  text: eyebrowNorm.text,
1959
1964
  x: pad2 + (eyebrowNorm.offset?.dx ?? 0),
1960
1965
  y: topY + (eyebrowNorm.offset?.dy ?? 0),
1961
1966
  maxWidth,
1967
+ ...maxLines != null ? { maxLines } : {},
1962
1968
  style
1963
1969
  };
1964
1970
  topElements.eyebrow = element;
@@ -1973,12 +1979,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1973
1979
  width,
1974
1980
  titleNorm.style
1975
1981
  );
1976
- const lineCount = estimateLineCount(titleNorm.text, style, maxWidth, measureText);
1982
+ const maxLines = titleNorm.style?.maxLines;
1983
+ const lineCount = estimateLineCount(titleNorm.text, style, maxWidth, measureText, maxLines);
1977
1984
  const element = {
1978
1985
  text: titleNorm.text,
1979
1986
  x: pad2 + (titleNorm.offset?.dx ?? 0),
1980
1987
  y: topY + (titleNorm.offset?.dy ?? 0),
1981
1988
  maxWidth,
1989
+ ...maxLines != null ? { maxLines } : {},
1982
1990
  style
1983
1991
  };
1984
1992
  topElements.title = element;
@@ -1993,12 +2001,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1993
2001
  width,
1994
2002
  subtitleNorm.style
1995
2003
  );
1996
- const lineCount = estimateLineCount(subtitleNorm.text, style, maxWidth, measureText);
2004
+ const maxLines = subtitleNorm.style?.maxLines;
2005
+ const lineCount = estimateLineCount(subtitleNorm.text, style, maxWidth, measureText, maxLines);
1997
2006
  const element = {
1998
2007
  text: subtitleNorm.text,
1999
2008
  x: pad2 + (subtitleNorm.offset?.dx ?? 0),
2000
2009
  y: topY + (subtitleNorm.offset?.dy ?? 0),
2001
2010
  maxWidth,
2011
+ ...maxLines != null ? { maxLines } : {},
2002
2012
  style
2003
2013
  };
2004
2014
  topElements.subtitle = element;
@@ -2063,7 +2073,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
2063
2073
  width,
2064
2074
  item.norm.style
2065
2075
  );
2066
- const lineCount = estimateLineCount(item.norm.text, style, bottomMaxWidth, measureText);
2076
+ const maxLines = item.norm.style?.maxLines;
2077
+ const lineCount = estimateLineCount(
2078
+ item.norm.text,
2079
+ style,
2080
+ bottomMaxWidth,
2081
+ measureText,
2082
+ maxLines
2083
+ );
2067
2084
  const height = estimateTextHeight(style.fontSize, lineCount, style.lineHeight);
2068
2085
  bottomElements[item.key] = {
2069
2086
  text: item.norm.text,
@@ -2071,6 +2088,7 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
2071
2088
  y: bottomHeight + (item.norm.offset?.dy ?? 0),
2072
2089
  // offset from where bottom chrome starts
2073
2090
  maxWidth: bottomMaxWidth,
2091
+ ...maxLines != null ? { maxLines } : {},
2074
2092
  style
2075
2093
  };
2076
2094
  bottomHeight += height + chromeGap;
@@ -3604,6 +3622,7 @@ function generateAltText(spec, data) {
3604
3622
  parts.push(`(${data.length} data points)`);
3605
3623
  return parts.join(" ");
3606
3624
  }
3625
+ var MAX_SR_TABLE_ROWS = 1e3;
3607
3626
  function generateDataTable(spec, data) {
3608
3627
  const fields = [];
3609
3628
  const encoding = spec.encoding;
@@ -3614,7 +3633,7 @@ function generateDataTable(spec, data) {
3614
3633
  const uniqueFields = [...new Set(fields)];
3615
3634
  if (uniqueFields.length === 0) return [];
3616
3635
  const headers = uniqueFields;
3617
- const rows = data.map((row) => uniqueFields.map((field) => row[field] ?? ""));
3636
+ const rows = data.slice(0, MAX_SR_TABLE_ROWS).map((row) => uniqueFields.map((field) => row[field] ?? ""));
3618
3637
  return [headers, ...rows];
3619
3638
  }
3620
3639
 
@@ -4036,6 +4055,7 @@ export {
4036
4055
  MAX_LEFT_LABEL_FRACTION_DEFAULT,
4037
4056
  MAX_LEFT_LABEL_FRACTION_MEDIUM,
4038
4057
  MAX_LEFT_LABEL_FRACTION_MEDIUM_MAX,
4058
+ MAX_SR_TABLE_ROWS,
4039
4059
  NARROW_VIEWPORT_MAX,
4040
4060
  OFFSET_STRATEGIES,
4041
4061
  SEQUENTIAL_PALETTES,
@@ -4098,10 +4118,10 @@ export {
4098
4118
  isChartSpec,
4099
4119
  isConditionalDef,
4100
4120
  isEncodingChannel,
4121
+ isGeoMapSpec,
4101
4122
  isGradientDef,
4102
4123
  isGraphSpec,
4103
4124
  isLayerSpec,
4104
- isMapSpec,
4105
4125
  isOpaqueColor,
4106
4126
  isRangeAnnotation,
4107
4127
  isRefLineAnnotation,
@@ -4129,6 +4149,7 @@ export {
4129
4149
  textAscent,
4130
4150
  tileMap,
4131
4151
  truncateRotatedLabel,
4152
+ truncateToWidth,
4132
4153
  wire,
4133
4154
  wrapText
4134
4155
  };