@eshal-bot/chat-widget 0.1.54 → 0.1.56
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/chat-widget.esm.js +2 -2
- package/dist/chat-widget.js +113 -16
- package/dist/chat-widget.min.js +2 -2
- package/dist/chat-widget.umd.js +2 -2
- package/package.json +1 -1
package/dist/chat-widget.js
CHANGED
|
@@ -54312,9 +54312,17 @@
|
|
|
54312
54312
|
}
|
|
54313
54313
|
function numericData(data, xKey, yKey) {
|
|
54314
54314
|
return (data || []).map(row => {
|
|
54315
|
-
|
|
54315
|
+
const raw = row === null || row === void 0 ? void 0 : row[xKey];
|
|
54316
54316
|
return {
|
|
54317
|
-
|
|
54317
|
+
// Pre-format the label so bar/line ticks read "Jan" instead
|
|
54318
|
+
// of "1" and "Office Supplies" instead of "office_supplies".
|
|
54319
|
+
// formatAxisTick handles the month-number → month-name mapping
|
|
54320
|
+
// when xKey matches /month/i AND value is 1..12; otherwise it
|
|
54321
|
+
// falls through to prettifyLabel. See Bug 1 + Bug 3 in the
|
|
54322
|
+
// 2026-06-16 chart-formatting fix.
|
|
54323
|
+
label: formatAxisTick(raw, xKey),
|
|
54324
|
+
// Raw value preserved — value formatting (currency etc.) is
|
|
54325
|
+
// applied at render-time by BarSvg/LineSvg using yKey.
|
|
54318
54326
|
value: Number(row === null || row === void 0 ? void 0 : row[yKey])
|
|
54319
54327
|
};
|
|
54320
54328
|
}).filter(d => Number.isFinite(d.value));
|
|
@@ -54352,18 +54360,23 @@
|
|
|
54352
54360
|
});
|
|
54353
54361
|
}
|
|
54354
54362
|
const t = String(type || '').trim().toLowerCase();
|
|
54363
|
+
// Pass yKey down so the SVG renderers can apply currency formatting
|
|
54364
|
+
// ($23,376.60) when the column name suggests money — see formatValueForKey.
|
|
54355
54365
|
let body;
|
|
54356
54366
|
if (t === 'pie' || t === 'donut') body = /*#__PURE__*/jsxRuntimeExports.jsx(PieSvg, {
|
|
54357
54367
|
rows: rows,
|
|
54358
54368
|
donut: t === 'donut',
|
|
54359
|
-
isDark: isDark
|
|
54369
|
+
isDark: isDark,
|
|
54370
|
+
yKey: y
|
|
54360
54371
|
});else if (t === 'line' || t === 'area') body = /*#__PURE__*/jsxRuntimeExports.jsx(LineSvg, {
|
|
54361
54372
|
rows: rows,
|
|
54362
54373
|
area: t === 'area',
|
|
54363
|
-
isDark: isDark
|
|
54374
|
+
isDark: isDark,
|
|
54375
|
+
yKey: y
|
|
54364
54376
|
});else body = /*#__PURE__*/jsxRuntimeExports.jsx(BarSvg, {
|
|
54365
54377
|
rows: rows,
|
|
54366
|
-
isDark: isDark
|
|
54378
|
+
isDark: isDark,
|
|
54379
|
+
yKey: y
|
|
54367
54380
|
}); // bar + every fallback
|
|
54368
54381
|
|
|
54369
54382
|
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
@@ -54380,7 +54393,8 @@
|
|
|
54380
54393
|
function BarSvg(_ref3) {
|
|
54381
54394
|
let {
|
|
54382
54395
|
rows,
|
|
54383
|
-
isDark
|
|
54396
|
+
isDark,
|
|
54397
|
+
yKey
|
|
54384
54398
|
} = _ref3;
|
|
54385
54399
|
const w = 320;
|
|
54386
54400
|
const h = 180;
|
|
@@ -54433,7 +54447,7 @@
|
|
|
54433
54447
|
fontSize: "9",
|
|
54434
54448
|
fill: labelStroke,
|
|
54435
54449
|
textAnchor: "middle",
|
|
54436
|
-
children:
|
|
54450
|
+
children: formatValueForKey(r.value, yKey)
|
|
54437
54451
|
})]
|
|
54438
54452
|
}, i);
|
|
54439
54453
|
})]
|
|
@@ -54443,7 +54457,8 @@
|
|
|
54443
54457
|
let {
|
|
54444
54458
|
rows,
|
|
54445
54459
|
area,
|
|
54446
|
-
isDark
|
|
54460
|
+
isDark,
|
|
54461
|
+
yKey
|
|
54447
54462
|
} = _ref4;
|
|
54448
54463
|
const w = 320;
|
|
54449
54464
|
const h = 180;
|
|
@@ -54491,14 +54506,14 @@
|
|
|
54491
54506
|
fontSize: "9",
|
|
54492
54507
|
fill: labelStroke,
|
|
54493
54508
|
textAnchor: "end",
|
|
54494
|
-
children:
|
|
54509
|
+
children: formatValueForKey(maxV, yKey)
|
|
54495
54510
|
}), /*#__PURE__*/jsxRuntimeExports.jsx("text", {
|
|
54496
54511
|
x: padLeft - 4,
|
|
54497
54512
|
y: padTop + innerH,
|
|
54498
54513
|
fontSize: "9",
|
|
54499
54514
|
fill: labelStroke,
|
|
54500
54515
|
textAnchor: "end",
|
|
54501
|
-
children:
|
|
54516
|
+
children: formatValueForKey(minV, yKey)
|
|
54502
54517
|
}), area && /*#__PURE__*/jsxRuntimeExports.jsx("path", {
|
|
54503
54518
|
d: areaPath,
|
|
54504
54519
|
fill: lineColor,
|
|
@@ -54531,7 +54546,8 @@
|
|
|
54531
54546
|
let {
|
|
54532
54547
|
rows,
|
|
54533
54548
|
donut,
|
|
54534
|
-
isDark
|
|
54549
|
+
isDark,
|
|
54550
|
+
yKey
|
|
54535
54551
|
} = _ref5;
|
|
54536
54552
|
const size = 200;
|
|
54537
54553
|
const cx = size / 2;
|
|
@@ -54626,7 +54642,7 @@
|
|
|
54626
54642
|
style: {
|
|
54627
54643
|
opacity: 0.7
|
|
54628
54644
|
},
|
|
54629
|
-
children:
|
|
54645
|
+
children: formatValueForKey(s.value, yKey)
|
|
54630
54646
|
})]
|
|
54631
54647
|
})]
|
|
54632
54648
|
}, i))
|
|
@@ -54720,7 +54736,7 @@
|
|
|
54720
54736
|
textAlign: 'left',
|
|
54721
54737
|
fontWeight: 600
|
|
54722
54738
|
},
|
|
54723
|
-
children: c
|
|
54739
|
+
children: prettifyLabel(c)
|
|
54724
54740
|
}, c))
|
|
54725
54741
|
})
|
|
54726
54742
|
}), /*#__PURE__*/jsxRuntimeExports.jsx("tbody", {
|
|
@@ -54730,7 +54746,7 @@
|
|
|
54730
54746
|
border,
|
|
54731
54747
|
padding: '6px 8px'
|
|
54732
54748
|
},
|
|
54733
|
-
children: row && typeof row === 'object' ? formatCell(row[c]) : ''
|
|
54749
|
+
children: row && typeof row === 'object' ? formatCell(row[c], c) : ''
|
|
54734
54750
|
}, c))
|
|
54735
54751
|
}, i))
|
|
54736
54752
|
})]
|
|
@@ -54953,9 +54969,66 @@
|
|
|
54953
54969
|
if (Number.isInteger(n)) return String(n);
|
|
54954
54970
|
return n.toFixed(2);
|
|
54955
54971
|
}
|
|
54956
|
-
|
|
54972
|
+
|
|
54973
|
+
// ── Bug 1 + Bug 3 helpers (2026-06-16) ───────────────────────────────────
|
|
54974
|
+
// PORTED from packages/frontend/src/components/charts/eshal-chart/
|
|
54975
|
+
// chartShared.tsx. Duplicated rather than shared because the widget is
|
|
54976
|
+
// bundle-size-conscious (a separate package import here would pull a
|
|
54977
|
+
// chunk of the frontend with it). The authoritative tests live with
|
|
54978
|
+
// the frontend copy in __tests__/chartShared.test.ts — keep this code
|
|
54979
|
+
// in lockstep with that file when either is touched. Regex boundaries
|
|
54980
|
+
// use `(^|[_\W])` instead of `\b` because JS regex `\b` doesn't fire
|
|
54981
|
+
// next to `_` (underscore is a word char), so "total_expenses" with
|
|
54982
|
+
// `\bexpense\b` would miss the match.
|
|
54983
|
+
|
|
54984
|
+
const MONTH_NAMES = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
54985
|
+
const CURRENCY_KEY_RE = /(^|[_\W])(price|salary|cost|amount|revenue|expense|total|value|budget|spend|income|sale|balance)/i;
|
|
54986
|
+
const MONTH_KEY_RE = /(^|[_\W])month/i;
|
|
54987
|
+
const USD_FORMATTER = new Intl.NumberFormat('en-US', {
|
|
54988
|
+
style: 'currency',
|
|
54989
|
+
currency: 'USD',
|
|
54990
|
+
minimumFractionDigits: 2,
|
|
54991
|
+
maximumFractionDigits: 2
|
|
54992
|
+
});
|
|
54993
|
+
function prettifyLabel(value) {
|
|
54994
|
+
if (value === null || value === undefined) return '';
|
|
54995
|
+
const s = String(value);
|
|
54996
|
+
if (!s) return '';
|
|
54997
|
+
return s.replace(/[_\-]+/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2').replace(/\s+/g, ' ').trim().split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' ');
|
|
54998
|
+
}
|
|
54999
|
+
function isCurrencyKey(key) {
|
|
55000
|
+
return typeof key === 'string' && CURRENCY_KEY_RE.test(key);
|
|
55001
|
+
}
|
|
55002
|
+
|
|
55003
|
+
// Like formatNum, but adds $ + comma + 2 decimals when `key` suggests
|
|
55004
|
+
// currency. Used for bar/line value labels and table cells so the
|
|
55005
|
+
// widget matches the frontend chart's formatting on the same data.
|
|
55006
|
+
function formatValueForKey(value, key) {
|
|
55007
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
55008
|
+
if (isCurrencyKey(key)) return USD_FORMATTER.format(value);
|
|
55009
|
+
return formatNum(value);
|
|
55010
|
+
}
|
|
55011
|
+
return prettifyLabel(value);
|
|
55012
|
+
}
|
|
55013
|
+
|
|
55014
|
+
// Axis-tick formatter: month-number columns (column matches /month/i,
|
|
55015
|
+
// value 1..12) render as 3-letter month names; everything else gets
|
|
55016
|
+
// prettifyLabel applied so "office_supplies" reads "Office Supplies".
|
|
55017
|
+
function formatAxisTick(value, dataKey) {
|
|
55018
|
+
if (typeof dataKey === 'string' && MONTH_KEY_RE.test(dataKey)) {
|
|
55019
|
+
const n = typeof value === 'number' ? value : Number(value);
|
|
55020
|
+
if (Number.isInteger(n) && n >= 1 && n <= 12) return MONTH_NAMES[n - 1];
|
|
55021
|
+
}
|
|
55022
|
+
return prettifyLabel(value);
|
|
55023
|
+
}
|
|
55024
|
+
function formatCell(v, columnKey) {
|
|
54957
55025
|
if (v == null) return '';
|
|
54958
|
-
if (typeof v === 'number')
|
|
55026
|
+
if (typeof v === 'number') {
|
|
55027
|
+
// Currency-keyed numeric cells in tables also get $ + decimals so
|
|
55028
|
+
// the table next to a chart agrees on its number formatting.
|
|
55029
|
+
if (isCurrencyKey(columnKey)) return USD_FORMATTER.format(v);
|
|
55030
|
+
return Number.isInteger(v) ? String(v) : v.toFixed(2);
|
|
55031
|
+
}
|
|
54959
55032
|
if (typeof v === 'object') return JSON.stringify(v);
|
|
54960
55033
|
return String(v);
|
|
54961
55034
|
}
|
|
@@ -58040,6 +58113,30 @@
|
|
|
58040
58113
|
window.cancelAnimationFrame(frame);
|
|
58041
58114
|
};
|
|
58042
58115
|
}, [autoScrollKey, isLoading]);
|
|
58116
|
+
|
|
58117
|
+
// When voice connects, scroll so the listening indicator (rendered after the
|
|
58118
|
+
// topic tags and quick questions) is visible at the bottom. Neither
|
|
58119
|
+
// autoScrollKey nor isLoading changes on voice-connect, so the main scroll
|
|
58120
|
+
// effect never fires — without this the indicator is pushed below the viewport
|
|
58121
|
+
// while the topic tags remain in view above it.
|
|
58122
|
+
reactExports.useEffect(() => {
|
|
58123
|
+
if (!isVoiceSessionActive || voiceStatus !== "connected") {
|
|
58124
|
+
return undefined;
|
|
58125
|
+
}
|
|
58126
|
+
if (typeof window === "undefined") {
|
|
58127
|
+
return undefined;
|
|
58128
|
+
}
|
|
58129
|
+
const frame = window.requestAnimationFrame(() => {
|
|
58130
|
+
var _messagesEndRef$curre3;
|
|
58131
|
+
(_messagesEndRef$curre3 = messagesEndRef.current) === null || _messagesEndRef$curre3 === void 0 || _messagesEndRef$curre3.scrollIntoView({
|
|
58132
|
+
behavior: "smooth",
|
|
58133
|
+
block: "end"
|
|
58134
|
+
});
|
|
58135
|
+
});
|
|
58136
|
+
return () => {
|
|
58137
|
+
window.cancelAnimationFrame(frame);
|
|
58138
|
+
};
|
|
58139
|
+
}, [isVoiceSessionActive, voiceStatus]);
|
|
58043
58140
|
const normalizedDisclaimerLinkUrl = reactExports.useMemo(() => normalizeExternalUrl(disclaimerLinkUrl), [disclaimerLinkUrl]);
|
|
58044
58141
|
return /*#__PURE__*/jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
58045
58142
|
children: [disclaimerEnabled && disclaimerText && disclaimerPosition === "top" && /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|