indas-ui 0.1.3 → 0.1.4

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 (59) hide show
  1. package/dist/cjs/components/chat/ai-messages.js +3 -2
  2. package/dist/cjs/components/chat/chat.js +2 -1
  3. package/dist/cjs/components/dashboard/charts/Area.js +6 -4
  4. package/dist/cjs/components/dashboard/charts/Bar.js +6 -4
  5. package/dist/cjs/components/dashboard/charts/FlowMap.js +2 -1
  6. package/dist/cjs/components/dashboard/charts/Funnel.js +2 -1
  7. package/dist/cjs/components/dashboard/charts/GeoMap.js +2 -1
  8. package/dist/cjs/components/dashboard/charts/Line.js +5 -3
  9. package/dist/cjs/components/dashboard/charts/Pareto.js +2 -1
  10. package/dist/cjs/components/dashboard/charts/Sankey.js +4 -3
  11. package/dist/cjs/components/dashboard/charts/Sparkline.js +2 -1
  12. package/dist/cjs/components/dashboard/charts/Treemap.js +2 -1
  13. package/dist/cjs/components/dashboard/charts/index.js +7 -1
  14. package/dist/cjs/components/dashboard/kpi/KpiBreakdown.js +3 -2
  15. package/dist/cjs/components/dashboard/kpi/KpiComparison.js +2 -1
  16. package/dist/cjs/components/dashboard/kpi/KpiQuickStats.js +2 -1
  17. package/dist/cjs/components/dashboard/kpi/KpiRating.js +3 -2
  18. package/dist/cjs/components/datagrid/columns/ColumnContextMenu.js +2 -1
  19. package/dist/cjs/components/datagrid/controls/menu/view/CardView.js +2 -1
  20. package/dist/cjs/components/datagrid/controls/menu/view/ChartView.js +2 -1
  21. package/dist/cjs/components/datagrid/utils/grid-helpers.js +6 -5
  22. package/dist/cjs/components/layout/footer.js +2 -1
  23. package/dist/cjs/components/layout/side-panel.js +4 -1
  24. package/dist/cjs/components/ui/display/stats-card.js +2 -1
  25. package/dist/cjs/lib/number-format.js +60 -0
  26. package/dist/cjs/lib/utils.js +4 -3
  27. package/dist/components/chat/ai-messages.js +3 -2
  28. package/dist/components/chat/chat.js +2 -1
  29. package/dist/components/dashboard/charts/Area.d.ts +5 -1
  30. package/dist/components/dashboard/charts/Area.js +6 -4
  31. package/dist/components/dashboard/charts/Bar.d.ts +5 -1
  32. package/dist/components/dashboard/charts/Bar.js +6 -4
  33. package/dist/components/dashboard/charts/FlowMap.js +2 -1
  34. package/dist/components/dashboard/charts/Funnel.js +2 -1
  35. package/dist/components/dashboard/charts/GeoMap.js +2 -1
  36. package/dist/components/dashboard/charts/Line.d.ts +5 -1
  37. package/dist/components/dashboard/charts/Line.js +5 -3
  38. package/dist/components/dashboard/charts/Pareto.js +2 -1
  39. package/dist/components/dashboard/charts/Sankey.js +4 -3
  40. package/dist/components/dashboard/charts/Sparkline.js +2 -1
  41. package/dist/components/dashboard/charts/Treemap.js +2 -1
  42. package/dist/components/dashboard/charts/index.d.ts +1 -0
  43. package/dist/components/dashboard/charts/index.js +2 -0
  44. package/dist/components/dashboard/kpi/KpiBreakdown.js +3 -2
  45. package/dist/components/dashboard/kpi/KpiComparison.js +2 -1
  46. package/dist/components/dashboard/kpi/KpiQuickStats.js +2 -1
  47. package/dist/components/dashboard/kpi/KpiRating.js +3 -2
  48. package/dist/components/datagrid/columns/ColumnContextMenu.js +2 -1
  49. package/dist/components/datagrid/controls/menu/view/CardView.js +2 -1
  50. package/dist/components/datagrid/controls/menu/view/ChartView.js +2 -1
  51. package/dist/components/datagrid/utils/grid-helpers.d.ts +1 -1
  52. package/dist/components/datagrid/utils/grid-helpers.js +3 -2
  53. package/dist/components/layout/footer.js +2 -1
  54. package/dist/components/layout/side-panel.js +4 -1
  55. package/dist/components/ui/display/stats-card.js +2 -1
  56. package/dist/lib/number-format.d.ts +18 -0
  57. package/dist/lib/number-format.js +54 -0
  58. package/dist/lib/utils.js +4 -3
  59. package/package.json +4 -4
@@ -16,6 +16,7 @@ const utils_1 = require("../../lib/utils.js");
16
16
  const lucide_react_1 = require("lucide-react");
17
17
  const react_markdown_1 = __importDefault(require("react-markdown"));
18
18
  const remark_gfm_1 = __importDefault(require("remark-gfm"));
19
+ const number_format_1 = require("../../lib/number-format.js");
19
20
  // Individual Message Bubble Component
20
21
  function Message({ message, onSelectItem, onEditMessage, onRegenerateAi, onFeedback, botAvatar, renderBotContent }) {
21
22
  const isUser = message.role === 'user';
@@ -164,7 +165,7 @@ function Message({ message, onSelectItem, onEditMessage, onRegenerateAi, onFeedb
164
165
  return full;
165
166
  });
166
167
  return processed;
167
- })() }) })) })) })) }), !isEditing && ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex items-center gap-2 mt-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200', isUser ? 'justify-end' : 'justify-start'), children: [formattedTimestamp && ((0, jsx_runtime_1.jsx)("span", { className: "text-[0.7rem] text-[rgb(var(--fg-muted))]/70 select-none", children: formattedTimestamp })), isUser && onEditMessage && ((0, jsx_runtime_1.jsx)("button", { onClick: handleRegenerate, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Regenerate response", title: "Regenerate", children: (0, jsx_runtime_1.jsx)(lucide_react_1.RotateCcw, { className: "w-3.5 h-3.5" }) })), isUser && onEditMessage && ((0, jsx_runtime_1.jsx)("button", { onClick: handleStartEdit, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Edit message", title: "Edit", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Pencil, { className: "w-3.5 h-3.5" }) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleCopy, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Copy message", title: "Copy", children: copied ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "w-3.5 h-3.5" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "w-3.5 h-3.5" })) }), !isUser && onRegenerateAi && ((0, jsx_runtime_1.jsx)("button", { onClick: handleRegenerateAi, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Regenerate response", title: "Regenerate", children: (0, jsx_runtime_1.jsx)(lucide_react_1.RotateCcw, { className: "w-3.5 h-3.5" }) })), !isUser && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => handleFeedback('up'), className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Good response", title: "Good response", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ThumbsUp, { className: "w-3.5 h-3.5", fill: feedback === 'up' ? 'currentColor' : 'none' }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => handleFeedback('down'), className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Bad response", title: "Bad response", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ThumbsDown, { className: "w-3.5 h-3.5", fill: feedback === 'down' ? 'currentColor' : 'none' }) })] })), !isUser && message.tokens && process.env.NEXT_PUBLIC_SHOW_TOKENS === 'true' && ((0, jsx_runtime_1.jsxs)("span", { className: "text-[0.65rem] text-[rgb(var(--fg-muted))]/70 font-mono select-none ml-1", children: ["P: ", message.tokens.prompt.toLocaleString(), " R: ", message.tokens.completion.toLocaleString(), " T: ", message.tokens.total.toLocaleString()] }))] }))] })] }));
168
+ })() }) })) })) })) }), !isEditing && ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex items-center gap-2 mt-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200', isUser ? 'justify-end' : 'justify-start'), children: [formattedTimestamp && ((0, jsx_runtime_1.jsx)("span", { className: "text-[0.7rem] text-[rgb(var(--fg-muted))]/70 select-none", children: formattedTimestamp })), isUser && onEditMessage && ((0, jsx_runtime_1.jsx)("button", { onClick: handleRegenerate, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Regenerate response", title: "Regenerate", children: (0, jsx_runtime_1.jsx)(lucide_react_1.RotateCcw, { className: "w-3.5 h-3.5" }) })), isUser && onEditMessage && ((0, jsx_runtime_1.jsx)("button", { onClick: handleStartEdit, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Edit message", title: "Edit", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Pencil, { className: "w-3.5 h-3.5" }) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleCopy, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Copy message", title: "Copy", children: copied ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "w-3.5 h-3.5" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "w-3.5 h-3.5" })) }), !isUser && onRegenerateAi && ((0, jsx_runtime_1.jsx)("button", { onClick: handleRegenerateAi, className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Regenerate response", title: "Regenerate", children: (0, jsx_runtime_1.jsx)(lucide_react_1.RotateCcw, { className: "w-3.5 h-3.5" }) })), !isUser && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => handleFeedback('up'), className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Good response", title: "Good response", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ThumbsUp, { className: "w-3.5 h-3.5", fill: feedback === 'up' ? 'currentColor' : 'none' }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => handleFeedback('down'), className: "w-7 h-7 rounded-md flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors", "aria-label": "Bad response", title: "Bad response", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ThumbsDown, { className: "w-3.5 h-3.5", fill: feedback === 'down' ? 'currentColor' : 'none' }) })] })), !isUser && message.tokens && process.env.NEXT_PUBLIC_SHOW_TOKENS === 'true' && ((0, jsx_runtime_1.jsxs)("span", { className: "text-[0.65rem] text-[rgb(var(--fg-muted))]/70 font-mono select-none ml-1", children: ["P: ", (0, number_format_1.formatNumber)(message.tokens.prompt), " R: ", (0, number_format_1.formatNumber)(message.tokens.completion), " T: ", (0, number_format_1.formatNumber)(message.tokens.total)] }))] }))] })] }));
168
169
  }
169
170
  // Synthia thinking phrases — the fun ones
170
171
  const SYNTHIA_THINKING = [
@@ -266,6 +267,6 @@ function Messages({ messages, isLoading = false, onExport, onShare, onSelectItem
266
267
  }, { prompt: 0, completion: 0, total: 0 });
267
268
  if (totals.total === 0)
268
269
  return (0, jsx_runtime_1.jsx)("div", {});
269
- return ((0, jsx_runtime_1.jsxs)("span", { className: "text-[0.65rem] text-[rgb(var(--fg-muted))] font-mono", children: ["P:", totals.prompt.toLocaleString(), " \u00B7 C:", totals.completion.toLocaleString(), " \u00B7 T:", totals.total.toLocaleString(), " \u00B7 ", messages.filter(m => m.tokens).length, " calls"] }));
270
+ return ((0, jsx_runtime_1.jsxs)("span", { className: "text-[0.65rem] text-[rgb(var(--fg-muted))] font-mono", children: ["P:", (0, number_format_1.formatNumber)(totals.prompt), " \u00B7 C:", (0, number_format_1.formatNumber)(totals.completion), " \u00B7 T:", (0, number_format_1.formatNumber)(totals.total), " \u00B7 ", messages.filter(m => m.tokens).length, " calls"] }));
270
271
  })() : (0, jsx_runtime_1.jsx)("div", {}), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [onExport && ((0, jsx_runtime_1.jsxs)("button", { onClick: onExport, className: "flex items-center gap-2 px-3 py-1.5 text-sm text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-lg transition-colors", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { className: "w-4 h-4" }), "Export"] })), onShare && ((0, jsx_runtime_1.jsxs)("button", { onClick: onShare, className: "flex items-center gap-2 px-3 py-1.5 text-sm text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-lg transition-colors", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { className: "w-4 h-4" }), "Share"] }))] })] })), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto", children: (0, jsx_runtime_1.jsxs)("div", { className: "max-w-5xl mx-auto px-3 sm:px-4 py-6 space-y-6 animate-[fadeInUp_0.28s_ease-out]", children: [messages.map((message) => ((0, jsx_runtime_1.jsx)(Message, { message: message, onSelectItem: onSelectItem, onEditMessage: onEditMessage, onRegenerateAi: onRegenerateAi, onFeedback: onFeedback, botAvatar: botAvatar, renderBotContent: renderBotContent }, message.id))), isLoading && (0, jsx_runtime_1.jsx)(TypingIndicator, { lastUserMessage: messages.filter(m => m.role === 'user').at(-1)?.content }), (0, jsx_runtime_1.jsx)("div", { ref: bottomRef })] }, fadeKey) })] }));
271
272
  }
@@ -21,6 +21,7 @@ const multimodal_input_1 = require("./multimodal-input.js");
21
21
  const chat_prompt_navigator_1 = require("./chat-prompt-navigator.js");
22
22
  const date_picker_1 = require("../forms/date-picker/index.js");
23
23
  const utils_2 = require("../../lib/utils.js");
24
+ const number_format_1 = require("../../lib/number-format.js");
24
25
  function buildSendPayload(ctx, message, autoTitle) {
25
26
  if (ctx.mode === 'new') {
26
27
  return { message, conversationId: undefined, newChat: true, title: autoTitle };
@@ -1022,7 +1023,7 @@ function Chat({ mode = 'fullpage', externalMuted, title = 'Chat', sidebarTitle,
1022
1023
  }, { prompt: 0, completion: 0, total: 0 });
1023
1024
  if (totals.total === 0)
1024
1025
  return null;
1025
- return ((0, jsx_runtime_1.jsxs)("span", { className: "text-[0.65rem] text-[rgb(var(--fg-muted))] font-mono", children: ["Prompt: ", totals.prompt.toLocaleString(), " \u00B7 Response: ", totals.completion.toLocaleString(), " \u00B7 Total: ", totals.total.toLocaleString(), " tokens \u00B7 ", messages.filter(m => m.tokens).length, " calls"] }));
1026
+ return ((0, jsx_runtime_1.jsxs)("span", { className: "text-[0.65rem] text-[rgb(var(--fg-muted))] font-mono", children: ["Prompt: ", (0, number_format_1.formatNumber)(totals.prompt), " \u00B7 Response: ", (0, number_format_1.formatNumber)(totals.completion), " \u00B7 Total: ", (0, number_format_1.formatNumber)(totals.total), " tokens \u00B7 ", messages.filter(m => m.tokens).length, " calls"] }));
1026
1027
  })(), (0, jsx_runtime_1.jsxs)("div", { className: "absolute right-3 flex items-center gap-0.5", children: [headerActions, (0, jsx_runtime_1.jsx)("button", { onClick: () => setIsMuted(!isMuted), className: "w-7 h-7 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-md transition-colors", title: isMuted ? "Unmute sounds" : "Mute sounds", children: isMuted ? (0, jsx_runtime_1.jsx)(lucide_react_1.VolumeX, { className: "w-3.5 h-3.5" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Volume2, { className: "w-3.5 h-3.5" }) }), messages.length > 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleExport, className: "w-7 h-7 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-md transition-colors", title: t('Export'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Download, { className: "w-3.5 h-3.5" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleShare, className: "w-7 h-7 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-md transition-colors", title: t('Share'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { className: "w-3.5 h-3.5" }) })] })), fullpagePath && mode === 'modal' && ((0, jsx_runtime_1.jsx)("button", { onClick: () => {
1027
1028
  const target = currentConversationId
1028
1029
  ? `${fullpagePath}?c=${currentConversationId}`
@@ -8,6 +8,7 @@ exports.AreaChart = AreaChart;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
10
10
  const utils_1 = require("../../../lib/utils.js");
11
+ const number_format_1 = require("../../../lib/number-format.js");
11
12
  // Convert any color (hex, rgb(), rgba(), space-separated rgb()) to rgba() with given alpha (0–1).
12
13
  // Hex+alpha-suffix concat (e.g. color + 'cc') breaks for non-hex inputs and crashes canvas gradients.
13
14
  function withAlpha(color, alpha) {
@@ -37,10 +38,11 @@ function withAlpha(color, alpha) {
37
38
  /**
38
39
  * AreaChart - ECharts Area Chart component
39
40
  */
40
- function AreaChart({ data, xKey, series, height = 300, showLegend = true, showGrid = true, smooth = true, className }) {
41
+ function AreaChart({ data, xKey, series, height = 300, showLegend = true, showGrid = true, smooth = true, valueFormatter, axisFormatter, className }) {
41
42
  const option = {
42
43
  tooltip: {
43
44
  trigger: 'axis',
45
+ valueFormatter: (v) => (typeof v === 'number' ? (valueFormatter ?? number_format_1.formatNumber)(v) : String(v ?? '')),
44
46
  backgroundColor: 'rgba(255, 255, 255, 0.95)',
45
47
  borderColor: '#e9ecef',
46
48
  borderWidth: 1,
@@ -76,13 +78,13 @@ function AreaChart({ data, xKey, series, height = 300, showLegend = true, showGr
76
78
  },
77
79
  yAxis: series.some(s => s.secondaryAxis)
78
80
  ? [
79
- { type: 'value', axisLine: { show: false }, axisLabel: { color: '#6c757d', fontSize: 11 }, splitLine: { show: showGrid, lineStyle: { color: '#f0f0f0', type: 'dashed' } } },
80
- { type: 'value', axisLine: { show: false }, axisLabel: { color: '#6c757d', fontSize: 11 }, splitLine: { show: false } },
81
+ { type: 'value', axisLine: { show: false }, axisLabel: { color: '#6c757d', fontSize: 11, formatter: (v) => (axisFormatter ?? number_format_1.formatCompactNumber)(v) }, splitLine: { show: showGrid, lineStyle: { color: '#f0f0f0', type: 'dashed' } } },
82
+ { type: 'value', axisLine: { show: false }, axisLabel: { color: '#6c757d', fontSize: 11, formatter: (v) => (axisFormatter ?? number_format_1.formatCompactNumber)(v) }, splitLine: { show: false } },
81
83
  ]
82
84
  : {
83
85
  type: 'value',
84
86
  axisLine: { show: false },
85
- axisLabel: { color: '#6c757d', fontSize: 11 },
87
+ axisLabel: { color: '#6c757d', fontSize: 11, formatter: (v) => (axisFormatter ?? number_format_1.formatCompactNumber)(v) },
86
88
  splitLine: { show: showGrid, lineStyle: { color: '#f0f0f0', type: 'dashed' } }
87
89
  },
88
90
  series: series.map((s, index) => {
@@ -8,10 +8,11 @@ exports.BarChart = BarChart;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
10
10
  const utils_1 = require("../../../lib/utils.js");
11
+ const number_format_1 = require("../../../lib/number-format.js");
11
12
  /**
12
13
  * BarChart - ECharts Bar Chart component
13
14
  */
14
- function BarChart({ data, xKey, series, height = 300, showLegend = true, showGrid = true, horizontal = false, targetKey, className }) {
15
+ function BarChart({ data, xKey, series, height = 300, showLegend = true, showGrid = true, horizontal = false, targetKey, valueFormatter, axisFormatter, className }) {
15
16
  // Bullet mode: horizontal KPI-vs-target rows (CSS-rendered, not ECharts).
16
17
  if (horizontal && targetKey) {
17
18
  const actualKey = series[0]?.key;
@@ -31,13 +32,14 @@ function BarChart({ data, xKey, series, height = 300, showLegend = true, showGri
31
32
  : met
32
33
  ? 'linear-gradient(90deg, #34d399 0%, #10b981 100%)'
33
34
  : 'linear-gradient(90deg, #fbbf24 0%, #f59e0b 100%)';
34
- return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-[rgb(var(--fg-default))] truncate", children: name }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs font-semibold tabular-nums shrink-0", style: { color: barColor }, children: [achievement.toFixed(0), "%"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative h-2.5 rounded-full bg-[rgb(var(--bg-subtle))] overflow-visible", children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-y-0 left-0 rounded-full transition-all duration-300", style: { width: `${actualPct}%`, background: barGradient } }), (0, jsx_runtime_1.jsx)("div", { className: "absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-1 h-4 rounded-full ring-2 ring-[rgb(var(--bg-surface))]", style: { left: `${targetPct}%`, backgroundColor: '#475569' }, title: `Target: ${target.toLocaleString()}` })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline justify-between gap-2 text-[0.65rem] text-[rgb(var(--fg-muted))] tabular-nums", children: [(0, jsx_runtime_1.jsx)("span", { children: actual.toLocaleString() }), (0, jsx_runtime_1.jsx)("span", { children: `Target ${target.toLocaleString()}` })] })] }, `${name}-${idx}`));
35
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-[rgb(var(--fg-default))] truncate", children: name }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs font-semibold tabular-nums shrink-0", style: { color: barColor }, children: [achievement.toFixed(0), "%"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative h-2.5 rounded-full bg-[rgb(var(--bg-subtle))] overflow-visible", children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-y-0 left-0 rounded-full transition-all duration-300", style: { width: `${actualPct}%`, background: barGradient } }), (0, jsx_runtime_1.jsx)("div", { className: "absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-1 h-4 rounded-full ring-2 ring-[rgb(var(--bg-surface))]", style: { left: `${targetPct}%`, backgroundColor: '#475569' }, title: `Target: ${(0, number_format_1.formatNumber)(target)}` })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline justify-between gap-2 text-[0.65rem] text-[rgb(var(--fg-muted))] tabular-nums", children: [(0, jsx_runtime_1.jsx)("span", { children: (0, number_format_1.formatNumber)(actual) }), (0, jsx_runtime_1.jsx)("span", { children: `Target ${(0, number_format_1.formatNumber)(target)}` })] })] }, `${name}-${idx}`));
35
36
  }) }));
36
37
  }
37
38
  const categoryData = data.map(item => item[xKey]);
38
39
  const option = {
39
40
  tooltip: {
40
41
  trigger: 'item',
42
+ valueFormatter: (v) => (typeof v === 'number' ? (valueFormatter ?? number_format_1.formatNumber)(v) : String(v ?? '')),
41
43
  backgroundColor: 'rgba(255, 255, 255, 0.98)',
42
44
  borderColor: '#e9ecef',
43
45
  borderWidth: 1,
@@ -70,7 +72,7 @@ function BarChart({ data, xKey, series, height = 300, showLegend = true, showGri
70
72
  type: horizontal ? 'value' : 'category',
71
73
  data: horizontal ? undefined : categoryData,
72
74
  axisLine: { lineStyle: { color: '#dee2e6' } },
73
- axisLabel: { color: '#6c757d', fontSize: 11 },
75
+ axisLabel: horizontal ? { color: '#6c757d', fontSize: 11, hideOverlap: true, alignMaxLabel: 'right', formatter: (v) => (axisFormatter ?? number_format_1.formatCompactNumber)(v) } : { color: '#6c757d', fontSize: 11 },
74
76
  axisTick: { show: false },
75
77
  splitLine: horizontal && showGrid ? {
76
78
  lineStyle: { color: '#f0f0f0', type: 'dashed' }
@@ -80,7 +82,7 @@ function BarChart({ data, xKey, series, height = 300, showLegend = true, showGri
80
82
  type: horizontal ? 'category' : 'value',
81
83
  data: horizontal ? categoryData : undefined,
82
84
  axisLine: { show: false },
83
- axisLabel: { color: '#6c757d', fontSize: 11 },
85
+ axisLabel: horizontal ? { color: '#6c757d', fontSize: 11 } : { color: '#6c757d', fontSize: 11, formatter: (v) => (axisFormatter ?? number_format_1.formatCompactNumber)(v) },
84
86
  splitLine: !horizontal && showGrid ? {
85
87
  lineStyle: { color: '#f0f0f0', type: 'dashed' }
86
88
  } : { show: false }
@@ -45,6 +45,7 @@ const echarts = __importStar(require("echarts/core"));
45
45
  const utils_1 = require("../../../lib/utils.js");
46
46
  const india_map_1 = require("./india-map.js");
47
47
  const theme_1 = require("./theme.js");
48
+ const number_format_1 = require("../../../lib/number-format.js");
48
49
  /**
49
50
  * FlowMap - Geographic flow/route visualization
50
51
  *
@@ -200,7 +201,7 @@ function FlowMap({ markers = [], lines = [], height = 400, markerColor = '#5470c
200
201
  }
201
202
  if (params.seriesType === 'effectScatter' || params.seriesType === 'scatter') {
202
203
  const value = params.value?.[2];
203
- return `<strong>${params.name}</strong>${value ? `<br/>Value: ${value.toLocaleString()}` : ''}`;
204
+ return `<strong>${params.name}</strong>${value ? `<br/>Value: ${(0, number_format_1.formatNumber)(value)}` : ''}`;
204
205
  }
205
206
  return `<strong>${params.name}</strong>`;
206
207
  }
@@ -5,6 +5,7 @@ exports.FunnelChart = FunnelChart;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const react_1 = require("react");
7
7
  const utils_1 = require("../../../lib/utils.js");
8
+ const number_format_1 = require("../../../lib/number-format.js");
8
9
  const FUNNEL_COLORS = ['#5470c6', '#3ba272', '#fac858', '#ee6666', '#73c0de', '#9a60b4', '#fc8452', '#91cc75'];
9
10
  /**
10
11
  * FunnelChart — centered, tapering stage-bar funnel for conversion/process flows.
@@ -33,6 +34,6 @@ function FunnelChart({ data, height = 300, sort = 'descending', className }) {
33
34
  background: `linear-gradient(90deg, ${color}, ${color}cc)`,
34
35
  transform: isHover ? 'translateY(-1px)' : 'none',
35
36
  boxShadow: isHover ? `0 4px 14px ${color}55` : `0 1px 2px rgba(0,0,0,0.06)`,
36
- }, title: `${item.name}: ${item.value.toLocaleString()} (${pct.toFixed(1)}%)`, children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm font-semibold text-white truncate", children: item.name }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-white/90 tabular-nums shrink-0", children: item.value.toLocaleString() })] }) })] }, item.name));
37
+ }, title: `${item.name}: ${(0, number_format_1.formatNumber)(item.value)} (${pct.toFixed(1)}%)`, children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm font-semibold text-white truncate", children: item.name }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-white/90 tabular-nums shrink-0", children: (0, number_format_1.formatNumber)(item.value) })] }) })] }, item.name));
37
38
  }) }));
38
39
  }
@@ -44,6 +44,7 @@ const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
44
44
  const echarts = __importStar(require("echarts/core"));
45
45
  const utils_1 = require("../../../lib/utils.js");
46
46
  const india_map_1 = require("./india-map.js");
47
+ const number_format_1 = require("../../../lib/number-format.js");
47
48
  /**
48
49
  * GeoMap - Geographic scatter/bubble map for India
49
50
  * Shows location markers with optional size based on values
@@ -86,7 +87,7 @@ function GeoMap({ markers = [], height = 400, markerColor = '#5470c6', markerSiz
86
87
  formatter: (params) => {
87
88
  if (params.seriesType === 'effectScatter' || params.seriesType === 'scatter') {
88
89
  const value = params.value?.[2];
89
- return `<strong>${params.name}</strong>${value ? `<br/>Production: ${value.toLocaleString()} units` : ''}`;
90
+ return `<strong>${params.name}</strong>${value ? `<br/>Production: ${(0, number_format_1.formatNumber)(value)} units` : ''}`;
90
91
  }
91
92
  return `<strong>${params.name}</strong>`;
92
93
  }
@@ -9,16 +9,18 @@ const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
10
10
  const utils_1 = require("../../../lib/utils.js");
11
11
  const theme_1 = require("./theme.js");
12
+ const number_format_1 = require("../../../lib/number-format.js");
12
13
  /**
13
14
  * LineChart - ECharts Line Chart component (no area fill)
14
15
  */
15
- function LineChart({ data, xKey, series, height = 300, showLegend = true, showGrid = true, smooth = false, showLabels = false, yMin, yMax, className }) {
16
+ function LineChart({ data, xKey, series, height = 300, showLegend = true, showGrid = true, smooth = false, showLabels = false, yMin, yMax, valueFormatter, axisFormatter, className }) {
16
17
  const theme = (0, theme_1.getChartTheme)();
17
18
  const axisConfig = (0, theme_1.getAxisConfig)();
18
19
  const option = {
19
20
  tooltip: {
20
21
  trigger: 'axis',
21
- ...(0, theme_1.getTooltipConfig)()
22
+ ...(0, theme_1.getTooltipConfig)(),
23
+ valueFormatter: (v) => (typeof v === 'number' ? (valueFormatter ?? number_format_1.formatNumber)(v) : String(v ?? '')),
22
24
  },
23
25
  legend: showLegend ? (0, theme_1.getLegendConfig)('top') : undefined,
24
26
  grid: (0, theme_1.getGridConfig)(showLegend),
@@ -33,7 +35,7 @@ function LineChart({ data, xKey, series, height = 300, showLegend = true, showGr
33
35
  min: yMin,
34
36
  max: yMax,
35
37
  axisLine: { show: false },
36
- axisLabel: axisConfig.axisLabel,
38
+ axisLabel: { ...axisConfig.axisLabel, formatter: (v) => (axisFormatter ?? number_format_1.formatCompactNumber)(v) },
37
39
  splitLine: {
38
40
  show: showGrid,
39
41
  ...axisConfig.splitLine
@@ -8,6 +8,7 @@ exports.ParetoChart = ParetoChart;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
10
10
  const utils_1 = require("../../../lib/utils.js");
11
+ const number_format_1 = require("../../../lib/number-format.js");
11
12
  /**
12
13
  * ParetoChart - Combined bar and line chart showing values and cumulative percentage
13
14
  * Used for identifying the "vital few" from the "trivial many" (80/20 rule)
@@ -34,7 +35,7 @@ function ParetoChart({ data, height = 300, showLegend = true, barColor = '#5470c
34
35
  const bar = params.find((p) => p.seriesType === 'bar');
35
36
  const line = params.find((p) => p.seriesType === 'line');
36
37
  return `${bar?.name}<br/>
37
- Value: ${bar?.value?.toLocaleString()}<br/>
38
+ Value: ${(0, number_format_1.formatNumber)(bar?.value)}<br/>
38
39
  Cumulative: ${line?.value}%`;
39
40
  }
40
41
  },
@@ -8,6 +8,7 @@ exports.SankeyChart = SankeyChart;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
10
10
  const utils_1 = require("../../../lib/utils.js");
11
+ const number_format_1 = require("../../../lib/number-format.js");
11
12
  /**
12
13
  * SankeyChart - Flow/relationship visualization
13
14
  * Great for: Material flow, process flow, cost flow, conversion funnels
@@ -41,9 +42,9 @@ function SankeyChart({ nodes, links, height = 300, orient = 'horizontal', nodeWi
41
42
  textStyle: { color: '#344767', fontSize: 12 },
42
43
  formatter: (params) => {
43
44
  if (params.dataType === 'edge') {
44
- return `<strong>${params.data.source}</strong> → <strong>${params.data.target}</strong><br/>Value: ${params.data.value?.toLocaleString()}`;
45
+ return `<strong>${params.data.source}</strong> → <strong>${params.data.target}</strong><br/>Value: ${(0, number_format_1.formatNumber)(params.data.value)}`;
45
46
  }
46
- return `<strong>${params.name}</strong><br/>Value: ${params.value?.toLocaleString() || '-'}`;
47
+ return `<strong>${params.name}</strong><br/>Value: ${(0, number_format_1.formatNumber)(params.value) || '-'}`;
47
48
  }
48
49
  },
49
50
  series: [{
@@ -79,7 +80,7 @@ function SankeyChart({ nodes, links, height = 300, orient = 'horizontal', nodeWi
79
80
  color: '#344767',
80
81
  fontSize: 11,
81
82
  fontWeight: 500,
82
- formatter: (p) => `${p.name} (${p.value?.toLocaleString() ?? '-'})`
83
+ formatter: (p) => `${p.name} (${(0, number_format_1.formatNumber)(p.value) || '-'})`
83
84
  },
84
85
  data: nodesWithColors,
85
86
  links: links.map(link => ({
@@ -8,6 +8,7 @@ exports.Sparkline = Sparkline;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
10
10
  const utils_1 = require("../../../lib/utils.js");
11
+ const number_format_1 = require("../../../lib/number-format.js");
11
12
  // Convert any color (hex, rgb(), rgba(), space-separated rgb()) to rgba() with given alpha (0–1).
12
13
  // Hex+alpha-suffix concat (e.g. color + '40') breaks for non-hex inputs and crashes canvas gradients.
13
14
  function withAlpha(color, alpha) {
@@ -103,7 +104,7 @@ function Sparkline({ data, type = 'line', height = 40, width = '100%', color = '
103
104
  formatter: (params) => {
104
105
  const p = Array.isArray(params) ? params[0] : params;
105
106
  const cat = hasLabels && p.axisValue ? `${p.axisValue}<br/>` : '';
106
- return `${cat}<strong>${valuePrefix}${Number(p.value).toLocaleString()}${valueSuffix}</strong>`;
107
+ return `${cat}<strong>${valuePrefix}${(0, number_format_1.formatNumber)(Number(p.value))}${valueSuffix}</strong>`;
107
108
  }
108
109
  } : undefined,
109
110
  grid: {
@@ -8,6 +8,7 @@ exports.TreemapChart = TreemapChart;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const echarts_for_react_1 = __importDefault(require("echarts-for-react"));
10
10
  const utils_1 = require("../../../lib/utils.js");
11
+ const number_format_1 = require("../../../lib/number-format.js");
11
12
  /**
12
13
  * TreemapChart - Hierarchical data visualization
13
14
  * Great for: Cost breakdown, category distribution, budget allocation
@@ -28,7 +29,7 @@ function TreemapChart({ data, height = 300, showBreadcrumb = false, colors = ['#
28
29
  .map((node) => node.name)
29
30
  .filter((name) => name)
30
31
  .join(' → ');
31
- return `<strong>${path || params.name}</strong><br/>Value: ${params.value?.toLocaleString() || '-'}`;
32
+ return `<strong>${path || params.name}</strong><br/>Value: ${(0, number_format_1.formatNumber)(params.value) || '-'}`;
32
33
  }
33
34
  },
34
35
  series: [{
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.ChartCard = exports.FlowMap = exports.GanttChart = exports.Sparkline = exports.SankeyChart = exports.TreemapChart = exports.GeoMap = exports.BoxPlotChart = exports.BubbleChart = exports.ParetoChart = exports.ScatterChart = exports.HeatmapChart = exports.FunnelChart = exports.RadarChart = exports.LineChart = exports.GaugeChart = exports.DonutChart = exports.BarChart = exports.AreaChart = void 0;
4
+ exports.getNumberLocale = exports.setNumberLocale = exports.formatCompactNumber = exports.formatNumber = exports.ChartCard = exports.FlowMap = exports.GanttChart = exports.Sparkline = exports.SankeyChart = exports.TreemapChart = exports.GeoMap = exports.BoxPlotChart = exports.BubbleChart = exports.ParetoChart = exports.ScatterChart = exports.HeatmapChart = exports.FunnelChart = exports.RadarChart = exports.LineChart = exports.GaugeChart = exports.DonutChart = exports.BarChart = exports.AreaChart = void 0;
5
5
  // ECharts Components
6
6
  var Area_1 = require("./Area.js");
7
7
  Object.defineProperty(exports, "AreaChart", { enumerable: true, get: function () { return Area_1.AreaChart; } });
@@ -43,3 +43,9 @@ Object.defineProperty(exports, "FlowMap", { enumerable: true, get: function () {
43
43
  // Chart Wrapper
44
44
  var DashboardCard_1 = require("./DashboardCard.js");
45
45
  Object.defineProperty(exports, "ChartCard", { enumerable: true, get: function () { return DashboardCard_1.ChartCard; } });
46
+ // Number formatting: Indian grouping by default; setNumberLocale() switches it for a whole app
47
+ var number_format_1 = require("../../../lib/number-format.js");
48
+ Object.defineProperty(exports, "formatNumber", { enumerable: true, get: function () { return number_format_1.formatNumber; } });
49
+ Object.defineProperty(exports, "formatCompactNumber", { enumerable: true, get: function () { return number_format_1.formatCompactNumber; } });
50
+ Object.defineProperty(exports, "setNumberLocale", { enumerable: true, get: function () { return number_format_1.setNumberLocale; } });
51
+ Object.defineProperty(exports, "getNumberLocale", { enumerable: true, get: function () { return number_format_1.getNumberLocale; } });
@@ -5,6 +5,7 @@ exports.KpiBreakdown = KpiBreakdown;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const utils_1 = require("../../../lib/utils.js");
7
7
  const kpi_shell_1 = require("./kpi-shell.js");
8
+ const number_format_1 = require("../../../lib/number-format.js");
8
9
  /**
9
10
  * KpiBreakdown - KPI card with list breakdown
10
11
  *
@@ -32,11 +33,11 @@ function KpiBreakdown({ title, total, items, showPercentage = false, loading, co
32
33
  };
33
34
  const totalValue = typeof total === 'number' ? total :
34
35
  items.reduce((sum, item) => sum + (typeof item.value === 'number' ? item.value : 0), 0);
35
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('bg-[rgb(var(--bg-surface))] rounded-xl border border-[rgb(var(--bd-default))] shadow-sm', compact ? 'p-4' : 'p-5', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex items-center justify-between', compact ? 'mb-2' : 'mb-3'), children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: title }), total !== undefined && ((0, jsx_runtime_1.jsx)("p", { className: "text-lg font-bold text-[rgb(var(--fg-default))]", children: typeof total === 'number' ? total.toLocaleString() : total }))] }), (0, jsx_runtime_1.jsx)("div", { className: compact ? 'space-y-1' : 'space-y-2', children: items.map((item, index) => {
36
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('bg-[rgb(var(--bg-surface))] rounded-xl border border-[rgb(var(--bd-default))] shadow-sm', compact ? 'p-4' : 'p-5', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex items-center justify-between', compact ? 'mb-2' : 'mb-3'), children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: title }), total !== undefined && ((0, jsx_runtime_1.jsx)("p", { className: "text-lg font-bold text-[rgb(var(--fg-default))]", children: typeof total === 'number' ? (0, number_format_1.formatNumber)(total) : total }))] }), (0, jsx_runtime_1.jsx)("div", { className: compact ? 'space-y-1' : 'space-y-2', children: items.map((item, index) => {
36
37
  const colorClass = getColorClass(item.color);
37
38
  const isCustomColor = item.color?.startsWith('#') || item.color?.startsWith('rgb');
38
39
  const numValue = typeof item.value === 'number' ? item.value : 0;
39
40
  const percentage = totalValue > 0 ? Math.round((numValue / totalValue) * 100) : 0;
40
- return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('w-2 h-2 rounded-full', colorClass), style: isCustomColor ? { backgroundColor: item.color } : undefined }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm text-[rgb(var(--fg-default))]", children: item.label })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium", children: typeof item.value === 'number' ? item.value.toLocaleString() : item.value }), showPercentage && ((0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: ["(", percentage, "%)"] }))] })] }, index));
41
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('w-2 h-2 rounded-full', colorClass), style: isCustomColor ? { backgroundColor: item.color } : undefined }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm text-[rgb(var(--fg-default))]", children: item.label })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium", children: typeof item.value === 'number' ? (0, number_format_1.formatNumber)(item.value) : item.value }), showPercentage && ((0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: ["(", percentage, "%)"] }))] })] }, index));
41
42
  }) })] }));
42
43
  }
@@ -5,6 +5,7 @@ exports.KpiComparison = KpiComparison;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const utils_1 = require("../../../lib/utils.js");
7
7
  const kpi_shell_1 = require("./kpi-shell.js");
8
+ const number_format_1 = require("../../../lib/number-format.js");
8
9
  /**
9
10
  * KpiComparison - KPI card with comparison progress bars
10
11
  *
@@ -37,5 +38,5 @@ function KpiComparison({ title, value, target, status, bars, loading, className
37
38
  return 'bg-[rgb(var(--color-error))]/10 text-[rgb(var(--color-error))]';
38
39
  }
39
40
  };
40
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('bg-[rgb(var(--bg-surface))] rounded-xl p-5 border border-[rgb(var(--bd-default))] shadow-sm', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-1", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: title }), status && ((0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-xs px-2 py-0.5 rounded-full', getStatusStyles(status.type)), children: status.label }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline gap-2", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-3xl font-bold text-[rgb(var(--fg-default))]", children: value }), target && ((0, jsx_runtime_1.jsxs)("span", { className: "text-sm text-[rgb(var(--fg-muted))]", children: ["/ ", target, " target"] }))] }), (0, jsx_runtime_1.jsx)("div", { className: "mt-4 space-y-2", children: bars.map((bar, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-[rgb(var(--fg-muted))] w-16", children: bar.label }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-3 bg-[rgb(var(--bg-subtle))] rounded", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('h-full rounded', getBarColor(bar.color)), style: { width: `${Math.min(bar.percentage, 100)}%` } }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium w-12 text-right", children: typeof bar.value === 'number' ? bar.value.toLocaleString() : bar.value })] }, index))) })] }));
41
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('bg-[rgb(var(--bg-surface))] rounded-xl p-5 border border-[rgb(var(--bd-default))] shadow-sm', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-1", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: title }), status && ((0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-xs px-2 py-0.5 rounded-full', getStatusStyles(status.type)), children: status.label }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline gap-2", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-3xl font-bold text-[rgb(var(--fg-default))]", children: value }), target && ((0, jsx_runtime_1.jsxs)("span", { className: "text-sm text-[rgb(var(--fg-muted))]", children: ["/ ", target, " target"] }))] }), (0, jsx_runtime_1.jsx)("div", { className: "mt-4 space-y-2", children: bars.map((bar, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-[rgb(var(--fg-muted))] w-16", children: bar.label }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-3 bg-[rgb(var(--bg-subtle))] rounded", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('h-full rounded', getBarColor(bar.color)), style: { width: `${Math.min(bar.percentage, 100)}%` } }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium w-12 text-right", children: typeof bar.value === 'number' ? (0, number_format_1.formatNumber)(bar.value) : bar.value })] }, index))) })] }));
41
42
  }
@@ -5,6 +5,7 @@ exports.KpiQuickStats = KpiQuickStats;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const utils_1 = require("../../../lib/utils.js");
7
7
  const kpi_shell_1 = require("./kpi-shell.js");
8
+ const number_format_1 = require("../../../lib/number-format.js");
8
9
  /**
9
10
  * KpiQuickStats - KPI card with grid of icon stats
10
11
  *
@@ -36,6 +37,6 @@ function KpiQuickStats({ title, stats, columns = 2, loading, className }) {
36
37
  };
37
38
  return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('bg-[rgb(var(--bg-surface))] rounded-xl p-5 border border-[rgb(var(--bd-default))] shadow-sm', className), children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))] mb-3", children: title }), (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('grid gap-x-3 gap-y-2', gridClasses[columns]), children: stats.map((stat, index) => {
38
39
  const Icon = stat.icon;
39
- return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(Icon, { className: (0, utils_1.cn)('w-4 h-4', getIconColorClass(stat.iconColor)) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: "text-lg font-bold text-[rgb(var(--fg-default))]", children: typeof stat.value === 'number' ? stat.value.toLocaleString() : stat.value }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-[rgb(var(--fg-muted))]", children: stat.label })] })] }, index));
40
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(Icon, { className: (0, utils_1.cn)('w-4 h-4', getIconColorClass(stat.iconColor)) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: "text-lg font-bold text-[rgb(var(--fg-default))]", children: typeof stat.value === 'number' ? (0, number_format_1.formatNumber)(stat.value) : stat.value }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-[rgb(var(--fg-muted))]", children: stat.label })] })] }, index));
40
41
  }) })] }));
41
42
  }
@@ -5,6 +5,7 @@ exports.KpiRating = KpiRating;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const lucide_react_1 = require("lucide-react");
7
7
  const utils_1 = require("../../../lib/utils.js");
8
+ const number_format_1 = require("../../../lib/number-format.js");
8
9
  /**
9
10
  * KpiRating - KPI card with star rating display
10
11
  *
@@ -30,9 +31,9 @@ function KpiRating({ title, score, maxScore = 5, reviewCount, status, statusType
30
31
  return 'bg-[rgb(var(--color-warning))]';
31
32
  return 'bg-[rgb(var(--color-error))]';
32
33
  };
33
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('bg-[rgb(var(--bg-surface))] rounded-xl p-5 border border-[rgb(var(--bd-default))] shadow-sm relative group', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: title }), tooltip && ((0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-5 h-5 rounded-full bg-[rgb(var(--bg-subtle))] flex items-center justify-center cursor-help hover:bg-[rgb(var(--color-primary))]/10 transition-colors peer", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Info, { className: "w-3 h-3 text-[rgb(var(--fg-muted))]" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "absolute right-0 top-7 w-72 p-3 bg-[rgb(var(--bg-surface))] border border-[rgb(var(--bd-default))] rounded-lg shadow-lg opacity-0 invisible peer-hover:opacity-100 peer-hover:visible transition-all z-10", children: [tooltip.formula && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs font-medium text-[rgb(var(--fg-default))] mb-2", children: "Formula:" }), (0, jsx_runtime_1.jsx)("div", { className: "bg-[rgb(var(--bg-subtle))] rounded p-2 mb-3", children: (0, jsx_runtime_1.jsx)("p", { className: "text-[10px] font-mono text-[rgb(var(--fg-muted))]", children: tooltip.formula }) })] })), tooltip.description && ((0, jsx_runtime_1.jsx)("p", { className: "text-[10px] text-[rgb(var(--fg-muted))] mb-3", children: tooltip.description })), tooltip.breakdown && tooltip.breakdown.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "border-t border-[rgb(var(--bd-default))] pt-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs font-medium text-[rgb(var(--fg-default))] mb-2", children: "Rating Breakdown:" }), (0, jsx_runtime_1.jsx)("div", { className: "space-y-1.5", children: tooltip.breakdown.map((item) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))] w-3", children: item.stars }), (0, jsx_runtime_1.jsx)("svg", { className: "w-3 h-3 text-yellow-400", fill: "currentColor", viewBox: "0 0 20 20", children: (0, jsx_runtime_1.jsx)("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-1.5 bg-[rgb(var(--bg-subtle))] rounded-full overflow-hidden", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('h-full rounded-full', getBreakdownBarColor(item.percentage)), style: { width: `${item.percentage}%` } }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))] w-10 text-right", children: item.count.toLocaleString() }), (0, jsx_runtime_1.jsxs)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))] w-6 text-right", children: [item.percentage, "%"] })] }, item.stars))) })] }))] })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("p", { className: "text-4xl font-bold text-[rgb(var(--fg-default))]", children: score }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "flex gap-0.5", children: Array.from({ length: maxScore }, (_, i) => {
34
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('bg-[rgb(var(--bg-surface))] rounded-xl p-5 border border-[rgb(var(--bd-default))] shadow-sm relative group', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: title }), tooltip && ((0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-5 h-5 rounded-full bg-[rgb(var(--bg-subtle))] flex items-center justify-center cursor-help hover:bg-[rgb(var(--color-primary))]/10 transition-colors peer", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Info, { className: "w-3 h-3 text-[rgb(var(--fg-muted))]" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "absolute right-0 top-7 w-72 p-3 bg-[rgb(var(--bg-surface))] border border-[rgb(var(--bd-default))] rounded-lg shadow-lg opacity-0 invisible peer-hover:opacity-100 peer-hover:visible transition-all z-10", children: [tooltip.formula && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs font-medium text-[rgb(var(--fg-default))] mb-2", children: "Formula:" }), (0, jsx_runtime_1.jsx)("div", { className: "bg-[rgb(var(--bg-subtle))] rounded p-2 mb-3", children: (0, jsx_runtime_1.jsx)("p", { className: "text-[10px] font-mono text-[rgb(var(--fg-muted))]", children: tooltip.formula }) })] })), tooltip.description && ((0, jsx_runtime_1.jsx)("p", { className: "text-[10px] text-[rgb(var(--fg-muted))] mb-3", children: tooltip.description })), tooltip.breakdown && tooltip.breakdown.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "border-t border-[rgb(var(--bd-default))] pt-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs font-medium text-[rgb(var(--fg-default))] mb-2", children: "Rating Breakdown:" }), (0, jsx_runtime_1.jsx)("div", { className: "space-y-1.5", children: tooltip.breakdown.map((item) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))] w-3", children: item.stars }), (0, jsx_runtime_1.jsx)("svg", { className: "w-3 h-3 text-yellow-400", fill: "currentColor", viewBox: "0 0 20 20", children: (0, jsx_runtime_1.jsx)("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-1.5 bg-[rgb(var(--bg-subtle))] rounded-full overflow-hidden", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('h-full rounded-full', getBreakdownBarColor(item.percentage)), style: { width: `${item.percentage}%` } }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))] w-10 text-right", children: (0, number_format_1.formatNumber)(item.count) }), (0, jsx_runtime_1.jsxs)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))] w-6 text-right", children: [item.percentage, "%"] })] }, item.stars))) })] }))] })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("p", { className: "text-4xl font-bold text-[rgb(var(--fg-default))]", children: score }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "flex gap-0.5", children: Array.from({ length: maxScore }, (_, i) => {
34
35
  const starIndex = i + 1;
35
36
  const isFilled = starIndex <= filledStars || (starIndex === filledStars + 1 && hasPartialStar);
36
37
  return ((0, jsx_runtime_1.jsx)("svg", { className: (0, utils_1.cn)('w-5 h-5 transition-transform hover:scale-110 cursor-pointer', isFilled ? 'text-yellow-400' : 'text-yellow-400/30'), fill: "currentColor", viewBox: "0 0 20 20", children: (0, jsx_runtime_1.jsx)("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }, i));
37
- }) }), reviewCount !== undefined && ((0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-[rgb(var(--fg-muted))] mt-1", children: [reviewCount.toLocaleString(), " reviews"] }))] }), status && ((0, jsx_runtime_1.jsx)("div", { className: "ml-auto text-right", children: (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-xs px-2 py-0.5 rounded-full', getStatusStyles(statusType)), children: status }) }))] }), (change !== undefined || periodLabel) && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between pt-3 mt-3 border-t border-[rgb(var(--bd-default))]", children: [change !== undefined && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [change > 0 ? ((0, jsx_runtime_1.jsx)(lucide_react_1.TrendingUp, { className: "w-3 h-3 text-[rgb(var(--color-success))]" })) : change < 0 ? ((0, jsx_runtime_1.jsx)(lucide_react_1.TrendingDown, { className: "w-3 h-3 text-[rgb(var(--color-error))]" })) : null, (0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)('text-xs', change > 0 ? 'text-[rgb(var(--color-success))]' : change < 0 ? 'text-[rgb(var(--color-error))]' : 'text-[rgb(var(--fg-muted))]'), children: [change > 0 ? '+' : '', change, " ", changeLabel] })] })), periodLabel && ((0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))]", children: periodLabel }))] }))] }));
38
+ }) }), reviewCount !== undefined && ((0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-[rgb(var(--fg-muted))] mt-1", children: [(0, number_format_1.formatNumber)(reviewCount), " reviews"] }))] }), status && ((0, jsx_runtime_1.jsx)("div", { className: "ml-auto text-right", children: (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-xs px-2 py-0.5 rounded-full', getStatusStyles(statusType)), children: status }) }))] }), (change !== undefined || periodLabel) && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between pt-3 mt-3 border-t border-[rgb(var(--bd-default))]", children: [change !== undefined && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [change > 0 ? ((0, jsx_runtime_1.jsx)(lucide_react_1.TrendingUp, { className: "w-3 h-3 text-[rgb(var(--color-success))]" })) : change < 0 ? ((0, jsx_runtime_1.jsx)(lucide_react_1.TrendingDown, { className: "w-3 h-3 text-[rgb(var(--color-error))]" })) : null, (0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)('text-xs', change > 0 ? 'text-[rgb(var(--color-success))]' : change < 0 ? 'text-[rgb(var(--color-error))]' : 'text-[rgb(var(--fg-muted))]'), children: [change > 0 ? '+' : '', change, " ", changeLabel] })] })), periodLabel && ((0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-[rgb(var(--fg-muted))]", children: periodLabel }))] }))] }));
38
39
  }
@@ -11,6 +11,7 @@ const ui_2 = require("../../ui/index.js");
11
11
  const ui_3 = require("../../ui/index.js");
12
12
  const ui_4 = require("../../ui/index.js");
13
13
  const ui_5 = require("../../ui/index.js");
14
+ const number_format_1 = require("../../../lib/number-format.js");
14
15
  function ColumnContextMenu({ column, table, data, isVisible, position, onClose, onApplyFilter, }) {
15
16
  const [activeSubmenu, setActiveSubmenu] = (0, react_1.useState)(null);
16
17
  const [quickFilterValue, setQuickFilterValue] = (0, react_1.useState)('');
@@ -319,7 +320,7 @@ function ColumnContextMenu({ column, table, data, isVisible, position, onClose,
319
320
  }, className: "w-full flex items-center gap-2 px-2 py-1 text-left text-xs rounded hover:bg-[rgb(var(--bg-subtle))]", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Eye, { className: "h-3.5 w-3.5 text-[rgb(var(--fg-muted))] flex-shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: "truncate flex-1", children: col.label })] }, col.id))) })] }) }, item.id));
320
321
  }
321
322
  if (item.id === 'column-stats' && columnStats) {
322
- return ((0, jsx_runtime_1.jsxs)("div", { className: "p-2 space-y-1.5", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-sm font-medium text-[rgb(var(--fg-default))]", children: "Column Statistics" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-[auto_1fr] gap-x-4 gap-y-1 text-xs", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Total:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.totalCount.toLocaleString() }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Unique:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.uniqueCount.toLocaleString() }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Null:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.nullCount.toLocaleString() }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Type:" }), (0, jsx_runtime_1.jsx)("div", { className: "text-right", children: (0, jsx_runtime_1.jsx)(ui_5.Badge, { variant: "outline", className: "text-xs h-4", children: columnStats.dataType }) }), columnStats.dataType === 'number' && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Min:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.min }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Max:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.max }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Avg:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.avg?.toFixed(2) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Sum:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.sum?.toLocaleString() })] }))] })] }, item.id));
323
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "p-2 space-y-1.5", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-sm font-medium text-[rgb(var(--fg-default))]", children: "Column Statistics" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-[auto_1fr] gap-x-4 gap-y-1 text-xs", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Total:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: (0, number_format_1.formatNumber)(columnStats.totalCount) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Unique:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: (0, number_format_1.formatNumber)(columnStats.uniqueCount) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Null:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: (0, number_format_1.formatNumber)(columnStats.nullCount) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Type:" }), (0, jsx_runtime_1.jsx)("div", { className: "text-right", children: (0, jsx_runtime_1.jsx)(ui_5.Badge, { variant: "outline", className: "text-xs h-4", children: columnStats.dataType }) }), columnStats.dataType === 'number' && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Min:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.min }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Max:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.max }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Avg:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: columnStats.avg?.toFixed(2) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-muted))]", children: "Sum:" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-right", children: (0, number_format_1.formatNumber)(columnStats.sum) })] }))] })] }, item.id));
323
324
  }
324
325
  }
325
326
  const Icon = item.icon;
@@ -10,6 +10,7 @@ const ui_1 = require("../../../../ui/index.js");
10
10
  const SelectionCell_1 = require("../../../cells/SelectionCell.js");
11
11
  const skeleton_1 = require("../../../../ui/feedback/skeleton.js");
12
12
  const LanguageContext_1 = require("../../../../../contexts/LanguageContext.js");
13
+ const number_format_1 = require("../../../../../lib/number-format.js");
13
14
  const sizeConfig = {
14
15
  compact: {
15
16
  grid: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
@@ -131,7 +132,7 @@ function CardView({ data, columns, onRowClick, selectedRows, onRowSelect, isLoad
131
132
  return value ? ((0, jsx_runtime_1.jsx)(ui_1.Badge, { variant: "default", className: "h-4.5 text-[0.6rem] px-1.5 py-0 bg-[rgb(var(--color-success))]/10 text-[rgb(var(--color-success))] border-0 font-medium", children: t('Yes') })) : ((0, jsx_runtime_1.jsx)(ui_1.Badge, { variant: "secondary", className: "h-4.5 text-[0.6rem] px-1.5 py-0 bg-[rgb(var(--bg-subtle))] text-[rgb(var(--fg-muted))] border-0 font-medium", children: t('No') }));
132
133
  }
133
134
  if (typeof value === 'number')
134
- return value.toLocaleString();
135
+ return (0, number_format_1.formatNumber)(value);
135
136
  return value?.toString() || '—';
136
137
  }, [t]);
137
138
  const getFieldLabel = (0, react_1.useCallback)((column) => {
@@ -48,6 +48,7 @@ const ui_1 = require("../../../../ui/index.js");
48
48
  const ui_2 = require("../../../../ui/index.js");
49
49
  const components_1 = require("../../../../index.js");
50
50
  const ui_3 = require("../../../../ui/index.js");
51
+ const number_format_1 = require("../../../../../lib/number-format.js");
51
52
  const CHART_COLORS = [
52
53
  '#3b82f6', // Blue
53
54
  '#ef4444', // Red
@@ -381,7 +382,7 @@ function DataVisualization({ data, columns, title = "Data Insights" }) {
381
382
  if (data.length === 0) {
382
383
  return ((0, jsx_runtime_1.jsx)(ui_1.Card, { className: "p-8", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center text-gray-500", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.BarChart3, { className: "h-12 w-12 mx-auto mb-4 opacity-50" }), (0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-medium mb-2", children: "No Data Available" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm", children: "Add some data to view visualizations" })] }) }));
383
384
  }
384
- return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6 p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-2xl font-bold tracking-tight", children: title }), (0, jsx_runtime_1.jsxs)("p", { className: "text-sm text-gray-600 mt-1", children: ["Visual analysis of ", data.length, " records"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center space-x-2", children: [(0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'bar' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('bar'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.BarChart3, { className: "h-4 w-4 mr-2" }), "Bar"] }), (0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'line' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('line'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.LineChart, { className: "h-4 w-4 mr-2" }), "Line"] }), (0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'area' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('area'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Activity, { className: "h-4 w-4 mr-2" }), "Area"] }), (0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'pie' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('pie'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.PieChart, { className: "h-4 w-4 mr-2" }), "Pie"] })] })] }), summaryStats && ((0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-4", children: [(0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-blue-600", children: summaryStats.sum.toLocaleString() }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Total" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-green-600", children: summaryStats.avg.toFixed(1) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Average" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-orange-600", children: summaryStats.min.toLocaleString() }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Minimum" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-purple-600", children: summaryStats.max.toLocaleString() }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Maximum" })] }) })] })), (0, jsx_runtime_1.jsxs)(ui_1.Card, { children: [(0, jsx_runtime_1.jsx)(ui_1.CardHeader, { children: (0, jsx_runtime_1.jsx)(ui_1.CardTitle, { className: "text-lg", children: "Chart Configuration" }) }), (0, jsx_runtime_1.jsx)(ui_1.CardContent, { children: (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("label", { className: "text-sm font-medium mb-2 block", children: ["X-Axis (", selectedChart === 'pie' ? 'Category' : 'Categories', ")"] }), (0, jsx_runtime_1.jsx)(components_1.Dropdown, { options: categoricalColumns.map((col) => ({
385
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6 p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-2xl font-bold tracking-tight", children: title }), (0, jsx_runtime_1.jsxs)("p", { className: "text-sm text-gray-600 mt-1", children: ["Visual analysis of ", data.length, " records"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center space-x-2", children: [(0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'bar' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('bar'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.BarChart3, { className: "h-4 w-4 mr-2" }), "Bar"] }), (0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'line' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('line'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.LineChart, { className: "h-4 w-4 mr-2" }), "Line"] }), (0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'area' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('area'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Activity, { className: "h-4 w-4 mr-2" }), "Area"] }), (0, jsx_runtime_1.jsxs)(ui_2.Button, { variant: selectedChart === 'pie' ? 'primary' : 'outline', size: "sm", onClick: () => setSelectedChart('pie'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.PieChart, { className: "h-4 w-4 mr-2" }), "Pie"] })] })] }), summaryStats && ((0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-4", children: [(0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-blue-600", children: (0, number_format_1.formatNumber)(summaryStats.sum) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Total" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-green-600", children: summaryStats.avg.toFixed(1) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Average" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-orange-600", children: (0, number_format_1.formatNumber)(summaryStats.min) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Minimum" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Card, { children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { className: "p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-purple-600", children: (0, number_format_1.formatNumber)(summaryStats.max) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600", children: "Maximum" })] }) })] })), (0, jsx_runtime_1.jsxs)(ui_1.Card, { children: [(0, jsx_runtime_1.jsx)(ui_1.CardHeader, { children: (0, jsx_runtime_1.jsx)(ui_1.CardTitle, { className: "text-lg", children: "Chart Configuration" }) }), (0, jsx_runtime_1.jsx)(ui_1.CardContent, { children: (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("label", { className: "text-sm font-medium mb-2 block", children: ["X-Axis (", selectedChart === 'pie' ? 'Category' : 'Categories', ")"] }), (0, jsx_runtime_1.jsx)(components_1.Dropdown, { options: categoricalColumns.map((col) => ({
385
386
  value: col.key,
386
387
  label: col.label,
387
388
  })), value: xAxisColumn, onValueChange: (value) => setXAxisColumn(typeof value === 'string' ? value : value[0] || ''), placeholder: "Select column" })] }), selectedChart !== 'pie' && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { className: "text-sm font-medium mb-2 block", children: "Y-Axis (Values)" }), (0, jsx_runtime_1.jsx)(components_1.Dropdown, { options: numericColumns.map((col) => ({
@@ -1,8 +1,5 @@
1
1
  'use client';
2
2
  "use strict";
3
- /**
4
- * Grid utility functions and helpers
5
- */
6
3
  Object.defineProperty(exports, "__esModule", { value: true });
7
4
  exports.calculatePaginationInfo = calculatePaginationInfo;
8
5
  exports.generatePageNumbers = generatePageNumbers;
@@ -10,6 +7,10 @@ exports.debounce = debounce;
10
7
  exports.getRowId = getRowId;
11
8
  exports.formatNumber = formatNumber;
12
9
  exports.matchesSearch = matchesSearch;
10
+ const number_format_1 = require("../../../lib/number-format.js");
11
+ /**
12
+ * Grid utility functions and helpers
13
+ */
13
14
  /**
14
15
  * Calculate pagination info
15
16
  */
@@ -83,10 +84,10 @@ function getRowId(row, index, getRowIdFn) {
83
84
  return String(index);
84
85
  }
85
86
  /**
86
- * Format large numbers with commas
87
+ * Format large numbers with grouping, in the library's number locale (Indian by default)
87
88
  */
88
89
  function formatNumber(num) {
89
- return num.toLocaleString();
90
+ return (0, number_format_1.formatNumber)(num);
90
91
  }
91
92
  /**
92
93
  * Check if value matches search term