@opendata-ai/openchart-vanilla 2.3.4 → 2.4.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
@@ -2116,6 +2116,23 @@ import { compileChart } from "@opendata-ai/openchart-engine";
2116
2116
  // src/svg-renderer.ts
2117
2117
  import { estimateTextWidth } from "@opendata-ai/openchart-core";
2118
2118
  var SVG_NS = "http://www.w3.org/2000/svg";
2119
+ function computeXAxisExtent(layout) {
2120
+ const xAxis = layout.axes.x;
2121
+ if (!xAxis) return 0;
2122
+ if (xAxis.tickAngle && Math.abs(xAxis.tickAngle) > 10) {
2123
+ const fontSize = xAxis.tickLabelStyle.fontSize;
2124
+ const fontWeight = xAxis.tickLabelStyle.fontWeight;
2125
+ const angleRad = Math.abs(xAxis.tickAngle) * (Math.PI / 180);
2126
+ let maxLabelWidth = 40;
2127
+ for (const tick of xAxis.ticks) {
2128
+ const w = estimateTextWidth(tick.label, fontSize, fontWeight);
2129
+ if (w > maxLabelWidth) maxLabelWidth = w;
2130
+ }
2131
+ const rotatedHeight = Math.min(maxLabelWidth * Math.sin(angleRad) + 6, 120);
2132
+ return xAxis.label ? rotatedHeight + 20 : rotatedHeight;
2133
+ }
2134
+ return xAxis.label ? 48 : 26;
2135
+ }
2119
2136
  function createSVGElement(tag) {
2120
2137
  return document.createElementNS(SVG_NS, tag);
2121
2138
  }
@@ -2160,7 +2177,7 @@ function renderChrome(parent, layout) {
2160
2177
  if (chrome.subtitle) {
2161
2178
  renderChromeElement(g, chrome.subtitle, "viz-subtitle", "subtitle");
2162
2179
  }
2163
- const xAxisExtent = layout.axes.x ? layout.axes.x.label ? 48 : 26 : 0;
2180
+ const xAxisExtent = computeXAxisExtent(layout);
2164
2181
  const bottomOffset = layout.area.y + layout.area.height + xAxisExtent;
2165
2182
  if (chrome.source) {
2166
2183
  renderChromeElement(
@@ -2209,11 +2226,23 @@ function renderAxis(parent, axis, orientation, layout) {
2209
2226
  if (orientation === "x") {
2210
2227
  const label = createSVGElement("text");
2211
2228
  label.setAttribute("class", "viz-axis-tick");
2212
- setAttrs(label, {
2213
- x: tick.position,
2214
- y: area.y + area.height + 14,
2215
- "text-anchor": "middle"
2216
- });
2229
+ if (axis.tickAngle && Math.abs(axis.tickAngle) > 10) {
2230
+ const labelX = tick.position;
2231
+ const labelY = area.y + area.height + 6;
2232
+ setAttrs(label, {
2233
+ x: labelX,
2234
+ y: labelY,
2235
+ "text-anchor": axis.tickAngle < 0 ? "end" : "start",
2236
+ "dominant-baseline": "central",
2237
+ transform: `rotate(${axis.tickAngle}, ${labelX}, ${labelY})`
2238
+ });
2239
+ } else {
2240
+ setAttrs(label, {
2241
+ x: tick.position,
2242
+ y: area.y + area.height + 14,
2243
+ "text-anchor": "middle"
2244
+ });
2245
+ }
2217
2246
  applyTextStyle(label, axis.tickLabelStyle);
2218
2247
  label.textContent = tick.label;
2219
2248
  g.appendChild(label);
@@ -2263,9 +2292,24 @@ function renderAxis(parent, axis, orientation, layout) {
2263
2292
  applyTextStyle(axisLabel, axis.labelStyle);
2264
2293
  axisLabel.textContent = axis.label;
2265
2294
  if (orientation === "x") {
2295
+ let titleY = area.y + area.height + 35;
2296
+ if (axis.tickAngle && Math.abs(axis.tickAngle) > 10) {
2297
+ const angleRad = Math.abs(axis.tickAngle) * (Math.PI / 180);
2298
+ let maxLabelWidth = 40;
2299
+ for (const tick of axis.ticks) {
2300
+ const w = estimateTextWidth(
2301
+ tick.label,
2302
+ axis.tickLabelStyle.fontSize,
2303
+ axis.tickLabelStyle.fontWeight
2304
+ );
2305
+ if (w > maxLabelWidth) maxLabelWidth = w;
2306
+ }
2307
+ const rotatedHeight = Math.min(maxLabelWidth * Math.sin(angleRad) + 6, 120);
2308
+ titleY = area.y + area.height + rotatedHeight + 14;
2309
+ }
2266
2310
  setAttrs(axisLabel, {
2267
2311
  x: area.x + area.width / 2,
2268
- y: area.y + area.height + 35,
2312
+ y: titleY,
2269
2313
  "text-anchor": "middle"
2270
2314
  });
2271
2315
  } else {
@@ -2749,7 +2793,7 @@ function brandPosition(layout) {
2749
2793
  const padding = layout.theme.spacing.padding;
2750
2794
  const rightEdge = width - padding;
2751
2795
  const { chrome } = layout;
2752
- const xAxisExtent = layout.axes.x ? layout.axes.x.label ? 48 : 26 : 0;
2796
+ const xAxisExtent = computeXAxisExtent(layout);
2753
2797
  const bottomOffset = layout.area.y + layout.area.height + xAxisExtent;
2754
2798
  const firstBottom = chrome.source ?? chrome.byline ?? chrome.footer;
2755
2799
  const chromeY = firstBottom ? bottomOffset + firstBottom.y : bottomOffset + layout.theme.spacing.chartToFooter;
@@ -4448,6 +4492,8 @@ import { getBreakpoint } from "@opendata-ai/openchart-core";
4448
4492
  import { compileTable } from "@opendata-ai/openchart-engine";
4449
4493
 
4450
4494
  // src/table-renderer.ts
4495
+ var BRAND_URL2 = "https://tryopendata.ai";
4496
+ var BRAND_FONT_SIZE2 = 20;
4451
4497
  function renderChromeBlock(layout, position) {
4452
4498
  const chrome = layout.chrome;
4453
4499
  if (position === "header") {
@@ -4673,10 +4719,10 @@ function renderTable(layout, container) {
4673
4719
  brand.className = "viz-table-ref";
4674
4720
  brand.style.cssText = "text-align: right; padding: 4px 8px;";
4675
4721
  const brandLink = document.createElement("a");
4676
- brandLink.href = "https://tryopendata.ai";
4722
+ brandLink.href = BRAND_URL2;
4677
4723
  brandLink.target = "_blank";
4678
4724
  brandLink.rel = "noopener";
4679
- brandLink.style.cssText = `font-size: 20px; font-weight: 600; color: ${brandColor}; opacity: 0.55; text-decoration: none; font-family: ${theme ? theme.fonts.family : "sans-serif"};`;
4725
+ brandLink.style.cssText = `font-size: ${BRAND_FONT_SIZE2}px; font-weight: 600; color: ${brandColor}; opacity: 0.55; text-decoration: none; font-family: ${theme ? theme.fonts.family : "sans-serif"};`;
4680
4726
  brandLink.textContent = "OpenData";
4681
4727
  brand.appendChild(brandLink);
4682
4728
  wrapper.appendChild(brand);