@opendata-ai/openchart-core 8.0.0-rc.9 → 8.1.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 (83) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +403 -45
  3. package/dist/index.js +50 -18
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/dist/styles.css.map +1 -1
  7. package/package.json +1 -2
  8. package/schema/chart.schema.json +375 -69
  9. package/schema/table.schema.json +35 -1
  10. package/schema/vizspec.schema.json +992 -171
  11. package/src/accessibility/__tests__/alt-text.test.ts +0 -110
  12. package/src/accessibility/__tests__/aria.test.ts +0 -125
  13. package/src/accessibility/alt-text.ts +0 -155
  14. package/src/accessibility/aria.ts +0 -75
  15. package/src/accessibility/index.ts +0 -6
  16. package/src/colors/__tests__/colorblind.test.ts +0 -75
  17. package/src/colors/__tests__/contrast.test.ts +0 -119
  18. package/src/colors/__tests__/palettes.test.ts +0 -74
  19. package/src/colors/colorblind.ts +0 -131
  20. package/src/colors/contrast.ts +0 -143
  21. package/src/colors/index.ts +0 -36
  22. package/src/colors/palettes.ts +0 -206
  23. package/src/helpers/__tests__/deep-merge.test.ts +0 -54
  24. package/src/helpers/__tests__/spec-builders.test.ts +0 -338
  25. package/src/helpers/deep-merge.ts +0 -29
  26. package/src/helpers/spec-builders.ts +0 -479
  27. package/src/index.ts +0 -215
  28. package/src/labels/__tests__/collision.test.ts +0 -310
  29. package/src/labels/collision.ts +0 -249
  30. package/src/labels/index.ts +0 -13
  31. package/src/layout/__tests__/chrome.test.ts +0 -208
  32. package/src/layout/__tests__/text-measure.test.ts +0 -57
  33. package/src/layout/chrome.ts +0 -470
  34. package/src/layout/index.ts +0 -18
  35. package/src/layout/text-measure.ts +0 -404
  36. package/src/layout/text-wrap.ts +0 -93
  37. package/src/locale/__tests__/format.test.ts +0 -606
  38. package/src/locale/format.ts +0 -459
  39. package/src/locale/index.ts +0 -21
  40. package/src/responsive/__tests__/breakpoints.test.ts +0 -146
  41. package/src/responsive/__tests__/metrics.test.ts +0 -52
  42. package/src/responsive/breakpoints.ts +0 -177
  43. package/src/responsive/index.ts +0 -53
  44. package/src/responsive/metrics.ts +0 -299
  45. package/src/schema/__tests__/generated-artifacts.test.ts +0 -42
  46. package/src/schema/__tests__/schema.test.ts +0 -179
  47. package/src/styles/__tests__/reduced-motion-selectors.test.ts +0 -28
  48. package/src/styles/animation.css +0 -213
  49. package/src/styles/base.css +0 -102
  50. package/src/styles/chrome.css +0 -174
  51. package/src/styles/dark.css +0 -44
  52. package/src/styles/graph.css +0 -135
  53. package/src/styles/index.css +0 -28
  54. package/src/styles/keyframes.css +0 -151
  55. package/src/styles/legend.css +0 -18
  56. package/src/styles/reduced-motion.css +0 -67
  57. package/src/styles/series-search.css +0 -153
  58. package/src/styles/sparkline.css +0 -16
  59. package/src/styles/table-animation.css +0 -93
  60. package/src/styles/table.css +0 -398
  61. package/src/styles/token-definitions.ts +0 -199
  62. package/src/styles/tokens.css +0 -156
  63. package/src/styles/tooltip.css +0 -126
  64. package/src/styles/you-draw-it.css +0 -126
  65. package/src/theme/__tests__/dark-mode.test.ts +0 -232
  66. package/src/theme/__tests__/defaults.test.ts +0 -73
  67. package/src/theme/__tests__/resolve.test.ts +0 -277
  68. package/src/theme/dark-mode.ts +0 -258
  69. package/src/theme/defaults.ts +0 -110
  70. package/src/theme/index.ts +0 -8
  71. package/src/theme/presets.ts +0 -64
  72. package/src/theme/resolve.ts +0 -312
  73. package/src/types/__tests__/encoding.test.ts +0 -368
  74. package/src/types/__tests__/gradient.test.ts +0 -95
  75. package/src/types/__tests__/spec.test.ts +0 -499
  76. package/src/types/encoding.ts +0 -280
  77. package/src/types/events.ts +0 -236
  78. package/src/types/index.ts +0 -290
  79. package/src/types/layout.ts +0 -2024
  80. package/src/types/schema-roots.ts +0 -32
  81. package/src/types/spec.ts +0 -2925
  82. package/src/types/table.ts +0 -108
  83. 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;
@@ -1935,6 +1939,17 @@ function footnoteBandHeight(count, theme) {
1935
1939
  }
1936
1940
  function computeChrome(chrome, theme, width, measureText, chromeMode = "full", padding, watermark = true, bottomLegendHeight = 0) {
1937
1941
  if (!chrome || chromeMode === "hidden") {
1942
+ if (watermark && width >= BRAND_MIN_WIDTH) {
1943
+ const hiddenPad = padding ?? theme.spacing.padding;
1944
+ const brandHeight = estimateTextHeight(BRAND_FONT_SIZE, 1);
1945
+ return {
1946
+ topHeight: 0,
1947
+ bottomHeight: theme.spacing.chartToFooter + brandHeight + hiddenPad + bottomLegendHeight
1948
+ };
1949
+ }
1950
+ if (bottomLegendHeight > 0) {
1951
+ return { topHeight: 0, bottomHeight: bottomLegendHeight };
1952
+ }
1938
1953
  return { topHeight: 0, bottomHeight: 0 };
1939
1954
  }
1940
1955
  const pad2 = padding ?? theme.spacing.padding;
@@ -1953,12 +1968,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1953
1968
  width,
1954
1969
  eyebrowNorm.style
1955
1970
  );
1956
- const lineCount = estimateLineCount(eyebrowNorm.text, style, maxWidth, measureText);
1971
+ const maxLines = eyebrowNorm.style?.maxLines;
1972
+ const lineCount = estimateLineCount(eyebrowNorm.text, style, maxWidth, measureText, maxLines);
1957
1973
  const element = {
1958
1974
  text: eyebrowNorm.text,
1959
1975
  x: pad2 + (eyebrowNorm.offset?.dx ?? 0),
1960
1976
  y: topY + (eyebrowNorm.offset?.dy ?? 0),
1961
1977
  maxWidth,
1978
+ ...maxLines != null ? { maxLines } : {},
1962
1979
  style
1963
1980
  };
1964
1981
  topElements.eyebrow = element;
@@ -1973,12 +1990,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1973
1990
  width,
1974
1991
  titleNorm.style
1975
1992
  );
1976
- const lineCount = estimateLineCount(titleNorm.text, style, maxWidth, measureText);
1993
+ const maxLines = titleNorm.style?.maxLines;
1994
+ const lineCount = estimateLineCount(titleNorm.text, style, maxWidth, measureText, maxLines);
1977
1995
  const element = {
1978
1996
  text: titleNorm.text,
1979
1997
  x: pad2 + (titleNorm.offset?.dx ?? 0),
1980
1998
  y: topY + (titleNorm.offset?.dy ?? 0),
1981
1999
  maxWidth,
2000
+ ...maxLines != null ? { maxLines } : {},
1982
2001
  style
1983
2002
  };
1984
2003
  topElements.title = element;
@@ -1993,12 +2012,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1993
2012
  width,
1994
2013
  subtitleNorm.style
1995
2014
  );
1996
- const lineCount = estimateLineCount(subtitleNorm.text, style, maxWidth, measureText);
2015
+ const maxLines = subtitleNorm.style?.maxLines;
2016
+ const lineCount = estimateLineCount(subtitleNorm.text, style, maxWidth, measureText, maxLines);
1997
2017
  const element = {
1998
2018
  text: subtitleNorm.text,
1999
2019
  x: pad2 + (subtitleNorm.offset?.dx ?? 0),
2000
2020
  y: topY + (subtitleNorm.offset?.dy ?? 0),
2001
2021
  maxWidth,
2022
+ ...maxLines != null ? { maxLines } : {},
2002
2023
  style
2003
2024
  };
2004
2025
  topElements.subtitle = element;
@@ -2063,7 +2084,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
2063
2084
  width,
2064
2085
  item.norm.style
2065
2086
  );
2066
- const lineCount = estimateLineCount(item.norm.text, style, bottomMaxWidth, measureText);
2087
+ const maxLines = item.norm.style?.maxLines;
2088
+ const lineCount = estimateLineCount(
2089
+ item.norm.text,
2090
+ style,
2091
+ bottomMaxWidth,
2092
+ measureText,
2093
+ maxLines
2094
+ );
2067
2095
  const height = estimateTextHeight(style.fontSize, lineCount, style.lineHeight);
2068
2096
  bottomElements[item.key] = {
2069
2097
  text: item.norm.text,
@@ -2071,6 +2099,7 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
2071
2099
  y: bottomHeight + (item.norm.offset?.dy ?? 0),
2072
2100
  // offset from where bottom chrome starts
2073
2101
  maxWidth: bottomMaxWidth,
2102
+ ...maxLines != null ? { maxLines } : {},
2074
2103
  style
2075
2104
  };
2076
2105
  bottomHeight += height + chromeGap;
@@ -3604,6 +3633,7 @@ function generateAltText(spec, data) {
3604
3633
  parts.push(`(${data.length} data points)`);
3605
3634
  return parts.join(" ");
3606
3635
  }
3636
+ var MAX_SR_TABLE_ROWS = 1e3;
3607
3637
  function generateDataTable(spec, data) {
3608
3638
  const fields = [];
3609
3639
  const encoding = spec.encoding;
@@ -3614,7 +3644,7 @@ function generateDataTable(spec, data) {
3614
3644
  const uniqueFields = [...new Set(fields)];
3615
3645
  if (uniqueFields.length === 0) return [];
3616
3646
  const headers = uniqueFields;
3617
- const rows = data.map((row) => uniqueFields.map((field) => row[field] ?? ""));
3647
+ const rows = data.slice(0, MAX_SR_TABLE_ROWS).map((row) => uniqueFields.map((field) => row[field] ?? ""));
3618
3648
  return [headers, ...rows];
3619
3649
  }
3620
3650
 
@@ -4036,6 +4066,7 @@ export {
4036
4066
  MAX_LEFT_LABEL_FRACTION_DEFAULT,
4037
4067
  MAX_LEFT_LABEL_FRACTION_MEDIUM,
4038
4068
  MAX_LEFT_LABEL_FRACTION_MEDIUM_MAX,
4069
+ MAX_SR_TABLE_ROWS,
4039
4070
  NARROW_VIEWPORT_MAX,
4040
4071
  OFFSET_STRATEGIES,
4041
4072
  SEQUENTIAL_PALETTES,
@@ -4098,10 +4129,10 @@ export {
4098
4129
  isChartSpec,
4099
4130
  isConditionalDef,
4100
4131
  isEncodingChannel,
4132
+ isGeoMapSpec,
4101
4133
  isGradientDef,
4102
4134
  isGraphSpec,
4103
4135
  isLayerSpec,
4104
- isMapSpec,
4105
4136
  isOpaqueColor,
4106
4137
  isRangeAnnotation,
4107
4138
  isRefLineAnnotation,
@@ -4129,6 +4160,7 @@ export {
4129
4160
  textAscent,
4130
4161
  tileMap,
4131
4162
  truncateRotatedLabel,
4163
+ truncateToWidth,
4132
4164
  wire,
4133
4165
  wrapText
4134
4166
  };