@opendata-ai/openchart-core 8.0.0-rc.8 → 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 +461 -56
  2. package/dist/index.js +62 -24
  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 -172
  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 -208
  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 -154
  77. package/src/types/index.ts +0 -289
  78. package/src/types/layout.ts +0 -2001
  79. package/src/types/schema-roots.ts +0 -32
  80. package/src/types/spec.ts +0 -2906
  81. package/src/types/table.ts +0 -108
  82. package/src/types/theme.ts +0 -209
package/dist/index.js CHANGED
@@ -187,14 +187,31 @@ var GRAPH_ENCODING_RULES = {
187
187
 
188
188
  // src/types/events.ts
189
189
  var elementRef = {
190
- annotation: (index, id) => ({ type: "annotation", index, id }),
191
- chrome: (key) => ({ type: "chrome", key }),
192
- seriesLabel: (series) => ({ type: "series-label", series }),
193
- legend: () => ({ type: "legend" }),
194
- legendEntry: (series, index) => ({
190
+ annotation: (index, id, path) => ({
191
+ type: "annotation",
192
+ index,
193
+ ...id !== void 0 ? { id } : {},
194
+ ...path !== void 0 ? { path } : {}
195
+ }),
196
+ chrome: (key, path) => ({
197
+ type: "chrome",
198
+ key,
199
+ ...path !== void 0 ? { path } : {}
200
+ }),
201
+ seriesLabel: (series, path) => ({
202
+ type: "series-label",
203
+ series,
204
+ ...path !== void 0 ? { path } : {}
205
+ }),
206
+ legend: (path) => ({
207
+ type: "legend",
208
+ ...path !== void 0 ? { path } : {}
209
+ }),
210
+ legendEntry: (series, index, path) => ({
195
211
  type: "legend-entry",
196
212
  series,
197
- index
213
+ index,
214
+ ...path !== void 0 ? { path } : {}
198
215
  })
199
216
  };
200
217
 
@@ -267,7 +284,7 @@ function isTileMapSpec(spec) {
267
284
  function isBarListSpec(spec) {
268
285
  return "type" in spec && spec.type === "barlist";
269
286
  }
270
- function isMapSpec(spec) {
287
+ function isGeoMapSpec(spec) {
271
288
  return "type" in spec && spec.type === "map";
272
289
  }
273
290
  function isTextAnnotation(annotation) {
@@ -1260,7 +1277,7 @@ function getWidthStrategy(breakpoint) {
1260
1277
  case "full":
1261
1278
  return {
1262
1279
  labelMode: "all",
1263
- legendPosition: "right",
1280
+ legendPosition: "top",
1264
1281
  annotationPosition: "inline",
1265
1282
  axisLabelDensity: "full",
1266
1283
  chromeMode: "full",
@@ -1354,17 +1371,16 @@ function maxRotatedLabelWidth(tickAngle, tickFontSize) {
1354
1371
  const usable = X_AXIS_ROTATED_EXTENT_CAP - lineHeight * Math.cos(angleRad) - AXIS_TO_LABEL_GAP;
1355
1372
  return Math.max(0, usable / sin);
1356
1373
  }
1357
- function truncateRotatedLabel(label, tickAngle, tickFontSize, tickFontWeight, measure = estimateTextWidth) {
1358
- const budget = maxRotatedLabelWidth(tickAngle, tickFontSize);
1374
+ function truncateToWidth(label, budget, fontSize, fontWeight, measure = estimateTextWidth) {
1359
1375
  if (!Number.isFinite(budget)) return label;
1360
- if (measure(label, tickFontSize, tickFontWeight) <= budget) return label;
1376
+ if (measure(label, fontSize, fontWeight) <= budget) return label;
1361
1377
  const ELLIPSIS = "\u2026";
1362
1378
  let lo = 0;
1363
1379
  let hi = label.length;
1364
1380
  while (lo < hi) {
1365
1381
  const mid = Math.ceil((lo + hi) / 2);
1366
1382
  const candidate = label.slice(0, mid) + ELLIPSIS;
1367
- if (measure(candidate, tickFontSize, tickFontWeight) <= budget) {
1383
+ if (measure(candidate, fontSize, fontWeight) <= budget) {
1368
1384
  lo = mid;
1369
1385
  } else {
1370
1386
  hi = mid - 1;
@@ -1372,6 +1388,10 @@ function truncateRotatedLabel(label, tickAngle, tickFontSize, tickFontWeight, me
1372
1388
  }
1373
1389
  return lo > 0 ? label.slice(0, lo).trimEnd() + ELLIPSIS : ELLIPSIS;
1374
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
+ }
1375
1395
 
1376
1396
  // src/theme/defaults.ts
1377
1397
  var DEFAULT_THEME = {
@@ -1521,7 +1541,7 @@ function _luminanceFromHex(color2) {
1521
1541
  function adaptTheme(theme) {
1522
1542
  const pairs = theme._tokenPairs;
1523
1543
  const inputBg = theme.colors.background;
1524
- const isTransparent = inputBg === "transparent";
1544
+ const isTransparent = !isOpaqueColor(inputBg);
1525
1545
  const alreadyDark = isTransparent || _luminanceFromHex(inputBg) < 0.2;
1526
1546
  const darkBg = pairs?.["colors.background"] ? pairs["colors.background"].dark : alreadyDark ? inputBg : DARK_BG;
1527
1547
  const darkMuted = ACHROMATIC_RAMP.fgMuted;
@@ -1766,7 +1786,7 @@ function relativeLuminance2(hex2) {
1766
1786
  return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
1767
1787
  }
1768
1788
  function isDarkBackground(hex2) {
1769
- if (hex2 === "transparent") return false;
1789
+ if (!isOpaqueColor(hex2)) return false;
1770
1790
  return relativeLuminance2(hex2) < 0.2;
1771
1791
  }
1772
1792
  function adaptChromeForDarkBg(theme, textColor) {
@@ -1867,13 +1887,14 @@ function buildTextStyle(defaults, fontFamily, textColor, width, overrides) {
1867
1887
  textAnchor: "start"
1868
1888
  };
1869
1889
  }
1870
- function estimateLineCount(text, style, maxWidth, measureText) {
1890
+ function estimateLineCount(text, style, maxWidth, measureText, maxLines) {
1871
1891
  if (maxWidth <= 0) return 1;
1872
1892
  const segments = text.split("\n");
1873
1893
  if (segments.length > 1) {
1874
- return segments.reduce((total, segment) => {
1894
+ const count = segments.reduce((total, segment) => {
1875
1895
  return total + (segment.length === 0 ? 1 : estimateLineCount(segment, style, maxWidth, measureText));
1876
1896
  }, 0);
1897
+ return maxLines != null ? Math.min(count, maxLines) : count;
1877
1898
  }
1878
1899
  if (measureText) {
1879
1900
  const textWidth = measureText(text, style.fontSize, style.fontWeight).width;
@@ -1891,7 +1912,7 @@ function estimateLineCount(text, style, maxWidth, measureText) {
1891
1912
  current2 = candidate;
1892
1913
  }
1893
1914
  }
1894
- return lines2;
1915
+ return maxLines != null ? Math.min(lines2, maxLines) : lines2;
1895
1916
  }
1896
1917
  const charWidth = estimateCharWidth(style.fontSize, style.fontWeight);
1897
1918
  const maxChars = Math.floor(maxWidth / charWidth);
@@ -1908,7 +1929,7 @@ function estimateLineCount(text, style, maxWidth, measureText) {
1908
1929
  current = candidate;
1909
1930
  }
1910
1931
  }
1911
- return lines;
1932
+ return maxLines != null ? Math.min(lines, maxLines) : lines;
1912
1933
  }
1913
1934
  var FOOTNOTE_LINE_HEIGHT = 1.3;
1914
1935
  var FOOTNOTE_BAND_GAP = 4;
@@ -1936,12 +1957,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1936
1957
  width,
1937
1958
  eyebrowNorm.style
1938
1959
  );
1939
- const lineCount = estimateLineCount(eyebrowNorm.text, style, maxWidth, measureText);
1960
+ const maxLines = eyebrowNorm.style?.maxLines;
1961
+ const lineCount = estimateLineCount(eyebrowNorm.text, style, maxWidth, measureText, maxLines);
1940
1962
  const element = {
1941
1963
  text: eyebrowNorm.text,
1942
1964
  x: pad2 + (eyebrowNorm.offset?.dx ?? 0),
1943
1965
  y: topY + (eyebrowNorm.offset?.dy ?? 0),
1944
1966
  maxWidth,
1967
+ ...maxLines != null ? { maxLines } : {},
1945
1968
  style
1946
1969
  };
1947
1970
  topElements.eyebrow = element;
@@ -1956,12 +1979,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1956
1979
  width,
1957
1980
  titleNorm.style
1958
1981
  );
1959
- const lineCount = estimateLineCount(titleNorm.text, style, maxWidth, measureText);
1982
+ const maxLines = titleNorm.style?.maxLines;
1983
+ const lineCount = estimateLineCount(titleNorm.text, style, maxWidth, measureText, maxLines);
1960
1984
  const element = {
1961
1985
  text: titleNorm.text,
1962
1986
  x: pad2 + (titleNorm.offset?.dx ?? 0),
1963
1987
  y: topY + (titleNorm.offset?.dy ?? 0),
1964
1988
  maxWidth,
1989
+ ...maxLines != null ? { maxLines } : {},
1965
1990
  style
1966
1991
  };
1967
1992
  topElements.title = element;
@@ -1976,12 +2001,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
1976
2001
  width,
1977
2002
  subtitleNorm.style
1978
2003
  );
1979
- const lineCount = estimateLineCount(subtitleNorm.text, style, maxWidth, measureText);
2004
+ const maxLines = subtitleNorm.style?.maxLines;
2005
+ const lineCount = estimateLineCount(subtitleNorm.text, style, maxWidth, measureText, maxLines);
1980
2006
  const element = {
1981
2007
  text: subtitleNorm.text,
1982
2008
  x: pad2 + (subtitleNorm.offset?.dx ?? 0),
1983
2009
  y: topY + (subtitleNorm.offset?.dy ?? 0),
1984
2010
  maxWidth,
2011
+ ...maxLines != null ? { maxLines } : {},
1985
2012
  style
1986
2013
  };
1987
2014
  topElements.subtitle = element;
@@ -2046,7 +2073,14 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
2046
2073
  width,
2047
2074
  item.norm.style
2048
2075
  );
2049
- 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
+ );
2050
2084
  const height = estimateTextHeight(style.fontSize, lineCount, style.lineHeight);
2051
2085
  bottomElements[item.key] = {
2052
2086
  text: item.norm.text,
@@ -2054,6 +2088,7 @@ function computeChrome(chrome, theme, width, measureText, chromeMode = "full", p
2054
2088
  y: bottomHeight + (item.norm.offset?.dy ?? 0),
2055
2089
  // offset from where bottom chrome starts
2056
2090
  maxWidth: bottomMaxWidth,
2091
+ ...maxLines != null ? { maxLines } : {},
2057
2092
  style
2058
2093
  };
2059
2094
  bottomHeight += height + chromeGap;
@@ -3587,6 +3622,7 @@ function generateAltText(spec, data) {
3587
3622
  parts.push(`(${data.length} data points)`);
3588
3623
  return parts.join(" ");
3589
3624
  }
3625
+ var MAX_SR_TABLE_ROWS = 1e3;
3590
3626
  function generateDataTable(spec, data) {
3591
3627
  const fields = [];
3592
3628
  const encoding = spec.encoding;
@@ -3597,7 +3633,7 @@ function generateDataTable(spec, data) {
3597
3633
  const uniqueFields = [...new Set(fields)];
3598
3634
  if (uniqueFields.length === 0) return [];
3599
3635
  const headers = uniqueFields;
3600
- 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] ?? ""));
3601
3637
  return [headers, ...rows];
3602
3638
  }
3603
3639
 
@@ -4019,6 +4055,7 @@ export {
4019
4055
  MAX_LEFT_LABEL_FRACTION_DEFAULT,
4020
4056
  MAX_LEFT_LABEL_FRACTION_MEDIUM,
4021
4057
  MAX_LEFT_LABEL_FRACTION_MEDIUM_MAX,
4058
+ MAX_SR_TABLE_ROWS,
4022
4059
  NARROW_VIEWPORT_MAX,
4023
4060
  OFFSET_STRATEGIES,
4024
4061
  SEQUENTIAL_PALETTES,
@@ -4081,10 +4118,10 @@ export {
4081
4118
  isChartSpec,
4082
4119
  isConditionalDef,
4083
4120
  isEncodingChannel,
4121
+ isGeoMapSpec,
4084
4122
  isGradientDef,
4085
4123
  isGraphSpec,
4086
4124
  isLayerSpec,
4087
- isMapSpec,
4088
4125
  isOpaqueColor,
4089
4126
  isRangeAnnotation,
4090
4127
  isRefLineAnnotation,
@@ -4112,6 +4149,7 @@ export {
4112
4149
  textAscent,
4113
4150
  tileMap,
4114
4151
  truncateRotatedLabel,
4152
+ truncateToWidth,
4115
4153
  wire,
4116
4154
  wrapText
4117
4155
  };