@eshal-bot/chat-widget 0.2.23 → 0.2.24

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.
@@ -87777,29 +87777,65 @@
87777
87777
  return String(n);
87778
87778
  }
87779
87779
 
87780
- // ── Currency-aware value formatting ──────────────────────────────────────
87780
+ // ── Money formatting ───────────────────────────────────────────────────────
87781
87781
  // A2UI chart data is normalized to `{ label, value }` by A2uiBlock's
87782
- // numericData(), which drops the original Y-column key. A2uiBlock now threads
87783
- // that key through as `props.yKey` so these renderers can decide whether the
87784
- // axis / tooltip values are money. Heuristic mirrors the frontend's
87785
- // chartShared.tsx `isCurrencyKey` - keep the keyword list in lockstep.
87782
+ // numericData(), which drops the original Y-column key. A2uiBlock threads that
87783
+ // key through as `props.yKey`, and the spec's `currency` as `props.currency`.
87784
+ // A currency symbol comes only from the currency the chart states (an ISO code
87785
+ // such as "USD" or "INR", or a symbol such as "₹"): a column name says money,
87786
+ // never which money, and the old guess from it put "$" on rupee spend (dev,
87787
+ // Oct 2026). A money-named column without a stated currency still reads as
87788
+ // money (comma-grouped, up to 2 decimals). The keyword list mirrors the
87789
+ // frontend's chartShared.tsx `isCurrencyKey` - keep them in lockstep.
87786
87790
  // `(^|[_\W])` (not `\b`) so "average_salary" / "total_expenses" still match -
87787
87791
  // JS `\b` doesn't fire next to `_`.
87788
- const CURRENCY_KEY_RE$1 = /(^|[_\W])(price|salary|cost|amount|revenue|expense|total|value|budget|spend|income|sale|balance)/i;
87789
- function isCurrencyKey$1(key) {
87790
- return typeof key === 'string' && CURRENCY_KEY_RE$1.test(key);
87792
+ const MONEY_KEY_RE = /(^|[_\W])(price|salary|cost|amount|revenue|expense|total|value|budget|spend|income|sale|balance)/i;
87793
+ function groupedNumber(v) {
87794
+ return Number(v).toLocaleString('en-US', {
87795
+ maximumFractionDigits: 2
87796
+ });
87791
87797
  }
87792
87798
 
87793
- // Compact currency for axis ticks → "$120.0k". Full currency for tooltips →
87794
- // "$87,600" (comma-grouped, up to 2 decimals, no forced trailing zeros so a
87795
- // whole-dollar salary reads "$81,200" not "$81,200.00").
87796
- function formatCurrencyCompact(v) {
87797
- return `$${formatCompactNumber(v)}`;
87798
- }
87799
- function formatCurrencyFull(v) {
87800
- return `$${Number(v).toLocaleString('en-US', {
87801
- maximumFractionDigits: 2
87802
- })}`;
87799
+ // `{ full, compact }` formatters for a chart's figures, or null for plain
87800
+ // numbers. Full is for tooltips and slice labels ("₹87,600"), compact for axis
87801
+ // ticks and bar labels ("₹87.6K").
87802
+ function moneyFormatters(currency, yKey) {
87803
+ const stated = typeof currency === 'string' ? currency.trim() : '';
87804
+ if (/^[A-Za-z]{3}$/.test(stated)) {
87805
+ try {
87806
+ const code = stated.toUpperCase();
87807
+ const full = new Intl.NumberFormat('en-US', {
87808
+ style: 'currency',
87809
+ currency: code,
87810
+ maximumFractionDigits: 2
87811
+ });
87812
+ const compact = new Intl.NumberFormat('en-US', {
87813
+ style: 'currency',
87814
+ currency: code,
87815
+ notation: 'compact',
87816
+ maximumFractionDigits: 1
87817
+ });
87818
+ return {
87819
+ full: v => full.format(Number(v)),
87820
+ compact: v => compact.format(Number(v))
87821
+ };
87822
+ } catch (_) {
87823
+ // an unknown code is shown as written, below
87824
+ }
87825
+ }
87826
+ if (stated) {
87827
+ return {
87828
+ full: v => `${stated}${groupedNumber(v)}`,
87829
+ compact: v => `${stated}${formatCompactNumber(v)}`
87830
+ };
87831
+ }
87832
+ if (typeof yKey === 'string' && MONEY_KEY_RE.test(yKey)) {
87833
+ return {
87834
+ full: groupedNumber,
87835
+ compact: formatCompactNumber
87836
+ };
87837
+ }
87838
+ return null;
87803
87839
  }
87804
87840
 
87805
87841
  /**
@@ -87813,8 +87849,9 @@
87813
87849
  isDark = false
87814
87850
  }) {
87815
87851
  const data = Array.isArray(props.data) ? props.data : [];
87816
- // Whether the Y values are money - drives the `$` on axis ticks + tooltip.
87817
- const currency = isCurrencyKey$1(props.yKey);
87852
+ // How the Y values read as money on axis ticks + tooltip: the stated
87853
+ // currency's symbol, or grouped digits for a money-named column.
87854
+ const money = moneyFormatters(props.currency, props.yKey);
87818
87855
  // Human series name for the tooltip ("Average Salary"), so it no longer
87819
87856
  // reads the generic dataKey "value".
87820
87857
  const seriesName = props.valueLabel || undefined;
@@ -87926,9 +87963,9 @@
87926
87963
  fontSize: 11,
87927
87964
  fill: labelColor
87928
87965
  } : undefined,
87929
- tickFormatter: v => currency ? formatCurrencyCompact(v) : props.unit ? `${formatCompactNumber(v)} ${props.unit}` : formatCompactNumber(v)
87966
+ tickFormatter: v => money ? money.compact(v) : props.unit ? `${formatCompactNumber(v)} ${props.unit}` : formatCompactNumber(v)
87930
87967
  }), /*#__PURE__*/jsxRuntimeExports.jsx(Tooltip, {
87931
- formatter: v => currency ? formatCurrencyFull(v) : props.unit ? `${Number(v).toLocaleString()} ${props.unit}` : Number(v).toLocaleString(),
87968
+ formatter: v => money ? money.full(v) : props.unit ? `${Number(v).toLocaleString()} ${props.unit}` : Number(v).toLocaleString(),
87932
87969
  contentStyle: {
87933
87970
  background: tooltipBg,
87934
87971
  border: `1px solid ${borderColor}`,
@@ -87945,7 +87982,7 @@
87945
87982
  position: 'top',
87946
87983
  fill: labelColor,
87947
87984
  fontSize: 10,
87948
- formatter: v => currency ? formatCurrencyCompact(v) : formatCompactNumber(v)
87985
+ formatter: v => money ? money.compact(v) : formatCompactNumber(v)
87949
87986
  }
87950
87987
  })]
87951
87988
  })
@@ -88049,7 +88086,7 @@
88049
88086
  donut = false
88050
88087
  }) {
88051
88088
  const data = Array.isArray(props.data) ? props.data : [];
88052
- const currency = isCurrencyKey$1(props.yKey);
88089
+ const money = moneyFormatters(props.currency, props.yKey);
88053
88090
  const borderColor = isDark ? '#374151' : '#e2e8f0';
88054
88091
  const bgColor = isDark ? '#1f2937' : '#ffffff';
88055
88092
  const titleColor = isDark ? '#f3f4f6' : '#0f172a';
@@ -88080,7 +88117,7 @@
88080
88117
  const a = -Number(entry.midAngle) * RADIAN;
88081
88118
  const cos = Math.cos(a);
88082
88119
  const sin = Math.sin(a);
88083
- const text = currency ? formatCurrencyFull(v) : Number(v).toLocaleString();
88120
+ const text = money ? money.full(v) : Number(v).toLocaleString();
88084
88121
  if (placement === 'inside') {
88085
88122
  const r = rIn + (rOut - rIn) * (donut ? 0.78 : 0.6);
88086
88123
  return /*#__PURE__*/jsxRuntimeExports.jsx("text", {
@@ -88181,7 +88218,7 @@
88181
88218
  fill: PIE_COLORS[i % PIE_COLORS.length]
88182
88219
  }, i))
88183
88220
  }), /*#__PURE__*/jsxRuntimeExports.jsx(Tooltip, {
88184
- formatter: v => currency ? formatCurrencyFull(v) : Number(v).toLocaleString(),
88221
+ formatter: v => money ? money.full(v) : Number(v).toLocaleString(),
88185
88222
  contentStyle: {
88186
88223
  background: tooltipBg,
88187
88224
  border: `1px solid ${borderColor}`,
@@ -88214,7 +88251,7 @@
88214
88251
  area = false
88215
88252
  }) {
88216
88253
  const data = Array.isArray(props.data) ? props.data : [];
88217
- const currency = isCurrencyKey$1(props.yKey);
88254
+ const money = moneyFormatters(props.currency, props.yKey);
88218
88255
  const seriesName = props.valueLabel || undefined;
88219
88256
  const borderColor = isDark ? '#374151' : '#e2e8f0';
88220
88257
  const bgColor = isDark ? '#1f2937' : '#ffffff';
@@ -88309,9 +88346,9 @@
88309
88346
  fontSize: 11,
88310
88347
  fill: labelColor
88311
88348
  },
88312
- tickFormatter: v => currency ? formatCurrencyCompact(v) : props.unit ? `${formatCompactNumber(v)} ${props.unit}` : formatCompactNumber(v)
88349
+ tickFormatter: v => money ? money.compact(v) : props.unit ? `${formatCompactNumber(v)} ${props.unit}` : formatCompactNumber(v)
88313
88350
  }), /*#__PURE__*/jsxRuntimeExports.jsx(Tooltip, {
88314
- formatter: v => currency ? formatCurrencyFull(v) : props.unit ? `${Number(v).toLocaleString()} ${props.unit}` : Number(v).toLocaleString(),
88351
+ formatter: v => money ? money.full(v) : props.unit ? `${Number(v).toLocaleString()} ${props.unit}` : Number(v).toLocaleString(),
88315
88352
  contentStyle: {
88316
88353
  background: tooltipBg,
88317
88354
  border: `1px solid ${borderColor}`,
@@ -88721,12 +88758,14 @@
88721
88758
  xAxisLabel: spec.xAxisLabel,
88722
88759
  yAxisLabel: spec.yAxisLabel,
88723
88760
  // numericData() collapses the rows to { label, value }, dropping the
88724
- // original Y-column key. Pass it through so the renderer can detect a
88725
- // currency column (→ "$" on the Y-axis + tooltip) and label the tooltip
88726
- // series with the human column name ("Average Salary") instead of the
88727
- // generic dataKey "value".
88761
+ // original Y-column key. Pass it through so the renderer can read a
88762
+ // money column as money and label the tooltip series with the human
88763
+ // column name ("Average Salary") instead of the generic dataKey "value".
88728
88764
  yKey: y,
88729
- valueLabel: prettifyLabel(y)
88765
+ valueLabel: prettifyLabel(y),
88766
+ // The currency the chart states ("USD", "INR", "₹"): the only source of
88767
+ // a currency symbol (widgetCatalog moneyFormatters).
88768
+ currency: spec.currency
88730
88769
  };
88731
88770
  if (t === 'pie') return /*#__PURE__*/jsxRuntimeExports.jsx(PieChartRenderer, {
88732
88771
  props: chartProps,