@open-mercato/ui 0.6.3-develop.3894.1.352abf4240 → 0.6.3

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 (67) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/ai/AiAssistantLauncher.js +61 -8
  3. package/dist/ai/AiAssistantLauncher.js.map +2 -2
  4. package/dist/ai/AiChat.js +29 -6
  5. package/dist/ai/AiChat.js.map +2 -2
  6. package/dist/ai/AiChatSessions.js +31 -9
  7. package/dist/ai/AiChatSessions.js.map +2 -2
  8. package/dist/ai/AiDock.js +8 -1
  9. package/dist/ai/AiDock.js.map +2 -2
  10. package/dist/ai/ConversationShareButton.js +40 -0
  11. package/dist/ai/ConversationShareButton.js.map +7 -0
  12. package/dist/ai/ConversationShareDialog.js +234 -0
  13. package/dist/ai/ConversationShareDialog.js.map +7 -0
  14. package/dist/ai/conversation-store.js +4 -2
  15. package/dist/ai/conversation-store.js.map +2 -2
  16. package/dist/ai/index.js +4 -0
  17. package/dist/ai/index.js.map +2 -2
  18. package/dist/ai/useAiChat.js +20 -4
  19. package/dist/ai/useAiChat.js.map +2 -2
  20. package/dist/backend/charts/BarChart.js +19 -76
  21. package/dist/backend/charts/BarChart.js.map +2 -2
  22. package/dist/backend/charts/BarChartImpl.js +91 -0
  23. package/dist/backend/charts/BarChartImpl.js.map +7 -0
  24. package/dist/backend/charts/LineChart.js +18 -91
  25. package/dist/backend/charts/LineChart.js.map +2 -2
  26. package/dist/backend/charts/LineChartImpl.js +112 -0
  27. package/dist/backend/charts/LineChartImpl.js.map +7 -0
  28. package/dist/backend/charts/PieChart.js +17 -62
  29. package/dist/backend/charts/PieChart.js.map +2 -2
  30. package/dist/backend/charts/PieChartImpl.js +76 -0
  31. package/dist/backend/charts/PieChartImpl.js.map +7 -0
  32. package/dist/backend/dashboard/DashboardScreen.js +9 -1
  33. package/dist/backend/dashboard/DashboardScreen.js.map +2 -2
  34. package/dist/backend/dashboard/widgetRegistry.js +18 -2
  35. package/dist/backend/dashboard/widgetRegistry.js.map +2 -2
  36. package/dist/backend/icons/lucideRegistry.generated.js +2 -0
  37. package/dist/backend/icons/lucideRegistry.generated.js.map +2 -2
  38. package/dist/backend/injection/useInjectionDataWidgets.js +12 -2
  39. package/dist/backend/injection/useInjectionDataWidgets.js.map +2 -2
  40. package/package.json +4 -5
  41. package/src/ai/AiAssistantLauncher.tsx +81 -5
  42. package/src/ai/AiChat.tsx +42 -2
  43. package/src/ai/AiChatSessions.tsx +55 -9
  44. package/src/ai/AiDock.tsx +13 -0
  45. package/src/ai/ConversationShareButton.tsx +39 -0
  46. package/src/ai/ConversationShareDialog.tsx +299 -0
  47. package/src/ai/__tests__/AiAssistantLauncher.test.tsx +6 -0
  48. package/src/ai/__tests__/AiChat.conversation.test.tsx +97 -0
  49. package/src/ai/__tests__/AiChatSessions.test.tsx +228 -0
  50. package/src/ai/__tests__/AiDock.test.tsx +31 -1
  51. package/src/ai/__tests__/conversation-store.test.ts +74 -1
  52. package/src/ai/conversation-store.ts +22 -2
  53. package/src/ai/index.ts +2 -0
  54. package/src/ai/useAiChat.ts +47 -4
  55. package/src/backend/__tests__/lazy-heavy-libraries.test.ts +53 -0
  56. package/src/backend/charts/BarChart.tsx +21 -72
  57. package/src/backend/charts/BarChartImpl.tsx +99 -0
  58. package/src/backend/charts/LineChart.tsx +23 -85
  59. package/src/backend/charts/LineChartImpl.tsx +120 -0
  60. package/src/backend/charts/PieChart.tsx +19 -60
  61. package/src/backend/charts/PieChartImpl.tsx +82 -0
  62. package/src/backend/dashboard/DashboardScreen.tsx +9 -1
  63. package/src/backend/dashboard/__tests__/DashboardScreen.test.tsx +45 -0
  64. package/src/backend/dashboard/__tests__/widgetRegistry.test.ts +60 -0
  65. package/src/backend/dashboard/widgetRegistry.ts +23 -5
  66. package/src/backend/icons/lucideRegistry.generated.tsx +2 -0
  67. package/src/backend/injection/useInjectionDataWidgets.ts +18 -2
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/backend/charts/BarChartImpl.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport {\n BarChart as RechartsBarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n ResponsiveContainer,\n} from 'recharts'\nimport { ChartTooltipContent, resolveChartColor } from './ChartUtils'\nimport type { BarChartDataItem, BarChartProps } from './BarChart'\n\ntype ImplProps = Pick<\n BarChartProps,\n | 'data'\n | 'index'\n | 'categories'\n | 'colors'\n | 'layout'\n | 'valueFormatter'\n | 'showLegend'\n | 'showGridLines'\n | 'categoryLabels'\n> & {\n valueFormatter: (value: number) => string\n}\n\nexport default function BarChartImpl({\n data,\n index,\n categories,\n colors,\n layout = 'vertical',\n valueFormatter,\n showLegend = true,\n showGridLines = true,\n categoryLabels,\n}: ImplProps) {\n const isHorizontal = layout === 'horizontal'\n const chartHeight = isHorizontal ? Math.max(200, data.length * 28) : 200\n const getBarColor = (idx: number): string => resolveChartColor(colors?.[idx], idx)\n\n return (\n <ResponsiveContainer width=\"100%\" height={chartHeight}>\n <RechartsBarChart\n data={data}\n layout={isHorizontal ? 'vertical' : 'horizontal'}\n margin={{ top: 5, right: 30, left: 20, bottom: 5 }}\n >\n {showGridLines && (\n <CartesianGrid strokeDasharray=\"3 3\" stroke=\"hsl(var(--border))\" />\n )}\n <XAxis\n type={isHorizontal ? 'number' : 'category'}\n dataKey={isHorizontal ? undefined : index}\n tickFormatter={isHorizontal ? valueFormatter : undefined}\n tick={{ fontSize: 11 }}\n />\n <YAxis\n type={isHorizontal ? 'category' : 'number'}\n dataKey={isHorizontal ? index : undefined}\n tickFormatter={isHorizontal ? undefined : valueFormatter}\n width={isHorizontal ? 90 : 50}\n interval={0}\n tick={{ fontSize: 10 }}\n />\n <Tooltip\n content={\n <ChartTooltipContent\n valueFormatter={valueFormatter}\n categoryLabels={categoryLabels}\n labelFormatter={(label, payload) => {\n const entry = payload?.[0] as { payload?: BarChartDataItem } | undefined\n const item = entry?.payload\n return item?.[index] ? String(item[index]) : label\n }}\n />\n }\n cursor={{ fill: 'hsl(var(--muted))', opacity: 0.2 }}\n />\n {showLegend && categories.length > 1 && (\n <Legend verticalAlign=\"top\" height={36} />\n )}\n {categories.map((category, idx) => (\n <Bar\n key={category}\n dataKey={category}\n fill={getBarColor(idx)}\n radius={isHorizontal ? [0, 4, 4, 0] : [4, 4, 0, 0]}\n />\n ))}\n </RechartsBarChart>\n </ResponsiveContainer>\n )\n}\n"],
5
+ "mappings": ";AAgDM,SAMI,KANJ;AA7CN;AAAA,EACE,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB,yBAAyB;AAkBxC,SAAR,aAA8B;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB;AACF,GAAc;AACZ,QAAM,eAAe,WAAW;AAChC,QAAM,cAAc,eAAe,KAAK,IAAI,KAAK,KAAK,SAAS,EAAE,IAAI;AACrE,QAAM,cAAc,CAAC,QAAwB,kBAAkB,SAAS,GAAG,GAAG,GAAG;AAEjF,SACE,oBAAC,uBAAoB,OAAM,QAAO,QAAQ,aACxC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,eAAe,aAAa;AAAA,MACpC,QAAQ,EAAE,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,QAAQ,EAAE;AAAA,MAEhD;AAAA,yBACC,oBAAC,iBAAc,iBAAgB,OAAM,QAAO,sBAAqB;AAAA,QAEnE;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,eAAe,WAAW;AAAA,YAChC,SAAS,eAAe,SAAY;AAAA,YACpC,eAAe,eAAe,iBAAiB;AAAA,YAC/C,MAAM,EAAE,UAAU,GAAG;AAAA;AAAA,QACvB;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,eAAe,aAAa;AAAA,YAClC,SAAS,eAAe,QAAQ;AAAA,YAChC,eAAe,eAAe,SAAY;AAAA,YAC1C,OAAO,eAAe,KAAK;AAAA,YAC3B,UAAU;AAAA,YACV,MAAM,EAAE,UAAU,GAAG;AAAA;AAAA,QACvB;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SACE;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA,gBAAgB,CAAC,OAAO,YAAY;AAClC,wBAAM,QAAQ,UAAU,CAAC;AACzB,wBAAM,OAAO,OAAO;AACpB,yBAAO,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,CAAC,IAAI;AAAA,gBAC/C;AAAA;AAAA,YACF;AAAA,YAEF,QAAQ,EAAE,MAAM,qBAAqB,SAAS,IAAI;AAAA;AAAA,QACpD;AAAA,QACC,cAAc,WAAW,SAAS,KACjC,oBAAC,UAAO,eAAc,OAAM,QAAQ,IAAI;AAAA,QAEzC,WAAW,IAAI,CAAC,UAAU,QACzB;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS;AAAA,YACT,MAAM,YAAY,GAAG;AAAA,YACrB,QAAQ,eAAe,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;AAAA;AAAA,UAH5C;AAAA,QAIP,CACD;AAAA;AAAA;AAAA,EACH,GACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -1,19 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import {
4
- LineChart as RechartsLineChart,
5
- AreaChart as RechartsAreaChart,
6
- Line,
7
- Area,
8
- XAxis,
9
- YAxis,
10
- CartesianGrid,
11
- Tooltip,
12
- ResponsiveContainer,
13
- Legend
14
- } from "recharts";
3
+ import dynamic from "next/dynamic";
15
4
  import { Spinner } from "@open-mercato/ui/primitives/spinner";
16
- import { ChartTooltipContent, resolveChartColor } from "./ChartUtils.js";
17
5
  function defaultValueFormatter(value) {
18
6
  if (Math.abs(value) >= 1e6) {
19
7
  return `${(value / 1e6).toFixed(1)}M`;
@@ -23,6 +11,10 @@ function defaultValueFormatter(value) {
23
11
  }
24
12
  return value.toLocaleString(void 0, { maximumFractionDigits: 2 });
25
13
  }
14
+ const LineChartImpl = dynamic(() => import("./LineChartImpl.js"), {
15
+ ssr: false,
16
+ loading: () => /* @__PURE__ */ jsx("div", { className: "flex h-48 items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { className: "h-6 w-6 text-muted-foreground" }) })
17
+ });
26
18
  function LineChart({
27
19
  title,
28
20
  data,
@@ -41,9 +33,6 @@ function LineChart({
41
33
  emptyMessage = "No data available",
42
34
  categoryLabels
43
35
  }) {
44
- const getLineColor = (idx) => {
45
- return resolveChartColor(colors?.[idx], idx);
46
- };
47
36
  if (error) {
48
37
  return /* @__PURE__ */ jsxs("div", { className: `rounded-lg border bg-card p-4 ${className}`, children: [
49
38
  title && /* @__PURE__ */ jsx("h3", { className: "mb-4 text-base font-medium text-card-foreground", children: title }),
@@ -62,86 +51,24 @@ function LineChart({
62
51
  /* @__PURE__ */ jsx("div", { className: "flex h-48 items-center justify-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessage }) })
63
52
  ] });
64
53
  }
65
- const ChartComponent = showArea ? RechartsAreaChart : RechartsLineChart;
66
54
  return /* @__PURE__ */ jsxs("div", { className: `rounded-lg border bg-card p-4 ${className}`, children: [
67
55
  title && /* @__PURE__ */ jsx("h3", { className: "mb-4 text-base font-medium text-card-foreground", children: title }),
68
- /* @__PURE__ */ jsx("div", { className: "h-52 w-full", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
69
- ChartComponent,
56
+ /* @__PURE__ */ jsx("div", { className: "h-52 w-full", children: /* @__PURE__ */ jsx(
57
+ LineChartImpl,
70
58
  {
71
59
  data,
72
- margin: { top: 5, right: 10, left: 10, bottom: 5 },
73
- children: [
74
- showGridLines && /* @__PURE__ */ jsx(
75
- CartesianGrid,
76
- {
77
- strokeDasharray: "3 3",
78
- stroke: "hsl(var(--border))"
79
- }
80
- ),
81
- /* @__PURE__ */ jsx(
82
- XAxis,
83
- {
84
- dataKey: index,
85
- tick: { fontSize: 12 },
86
- tickLine: false,
87
- axisLine: false
88
- }
89
- ),
90
- /* @__PURE__ */ jsx(
91
- YAxis,
92
- {
93
- tickFormatter: valueFormatter,
94
- tick: { fontSize: 12 },
95
- tickLine: false,
96
- axisLine: false,
97
- width: 56
98
- }
99
- ),
100
- /* @__PURE__ */ jsx(
101
- Tooltip,
102
- {
103
- content: /* @__PURE__ */ jsx(ChartTooltipContent, { valueFormatter, categoryLabels }),
104
- cursor: { stroke: "hsl(var(--muted-foreground))", strokeDasharray: "3 3" }
105
- }
106
- ),
107
- showLegend && categories.length > 1 && /* @__PURE__ */ jsx(
108
- Legend,
109
- {
110
- verticalAlign: "top",
111
- height: 36,
112
- formatter: (value) => /* @__PURE__ */ jsx("span", { style: { color: "hsl(var(--muted-foreground))", fontSize: "12px" }, children: value })
113
- }
114
- ),
115
- showArea ? categories.map((category, idx) => /* @__PURE__ */ jsx(
116
- Area,
117
- {
118
- type: curveType,
119
- dataKey: category,
120
- stroke: getLineColor(idx),
121
- fill: getLineColor(idx),
122
- fillOpacity: 0.2,
123
- strokeWidth: 2,
124
- connectNulls,
125
- dot: false,
126
- activeDot: { r: 4, strokeWidth: 0 }
127
- },
128
- category
129
- )) : categories.map((category, idx) => /* @__PURE__ */ jsx(
130
- Line,
131
- {
132
- type: curveType,
133
- dataKey: category,
134
- stroke: getLineColor(idx),
135
- strokeWidth: 2,
136
- connectNulls,
137
- dot: false,
138
- activeDot: { r: 4, strokeWidth: 0 }
139
- },
140
- category
141
- ))
142
- ]
60
+ index,
61
+ categories,
62
+ colors,
63
+ showArea,
64
+ valueFormatter,
65
+ showLegend,
66
+ showGridLines,
67
+ curveType,
68
+ connectNulls,
69
+ categoryLabels
143
70
  }
144
- ) }) })
71
+ ) })
145
72
  ] });
146
73
  }
147
74
  var LineChart_default = LineChart;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/backend/charts/LineChart.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport {\n LineChart as RechartsLineChart,\n AreaChart as RechartsAreaChart,\n Line,\n Area,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n Legend,\n} from 'recharts'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { ChartTooltipContent, resolveChartColor } from './ChartUtils'\n\nexport type LineChartDataItem = Record<string, string | number | null | undefined>\n\nexport type LineChartProps = {\n title?: string\n data: LineChartDataItem[]\n index: string\n categories: string[]\n loading?: boolean\n error?: string | null\n colors?: string[]\n showArea?: boolean\n valueFormatter?: (value: number) => string\n showLegend?: boolean\n showGridLines?: boolean\n curveType?: 'linear' | 'natural' | 'monotone' | 'step'\n connectNulls?: boolean\n className?: string\n emptyMessage?: string\n categoryLabels?: Record<string, string>\n}\n\nfunction defaultValueFormatter(value: number): string {\n if (Math.abs(value) >= 1_000_000) {\n return `${(value / 1_000_000).toFixed(1)}M`\n }\n if (Math.abs(value) >= 1_000) {\n return `${(value / 1_000).toFixed(1)}K`\n }\n return value.toLocaleString(undefined, { maximumFractionDigits: 2 })\n}\n\nexport function LineChart({\n title,\n data,\n index,\n categories,\n loading,\n error,\n colors,\n showArea = false,\n valueFormatter = defaultValueFormatter,\n showLegend = true,\n showGridLines = true,\n curveType = 'monotone',\n connectNulls = true,\n className = '',\n emptyMessage = 'No data available',\n categoryLabels,\n}: LineChartProps) {\n const getLineColor = (idx: number): string => {\n return resolveChartColor(colors?.[idx], idx)\n }\n\n if (error) {\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n </div>\n )\n }\n\n if (loading) {\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <Spinner className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n </div>\n )\n }\n\n if (!data || data.length === 0) {\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-muted-foreground\">{emptyMessage}</p>\n </div>\n </div>\n )\n }\n\n const ChartComponent = showArea ? RechartsAreaChart : RechartsLineChart\n\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"h-52 w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <ChartComponent\n data={data}\n margin={{ top: 5, right: 10, left: 10, bottom: 5 }}\n >\n {showGridLines && (\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"hsl(var(--border))\"\n />\n )}\n <XAxis\n dataKey={index}\n tick={{ fontSize: 12 }}\n tickLine={false}\n axisLine={false}\n />\n <YAxis\n tickFormatter={valueFormatter}\n tick={{ fontSize: 12 }}\n tickLine={false}\n axisLine={false}\n width={56}\n />\n <Tooltip\n content={<ChartTooltipContent valueFormatter={valueFormatter} categoryLabels={categoryLabels} />}\n cursor={{ stroke: 'hsl(var(--muted-foreground))', strokeDasharray: '3 3' }}\n />\n {showLegend && categories.length > 1 && (\n <Legend\n verticalAlign=\"top\"\n height={36}\n formatter={(value) => (\n <span style={{ color: 'hsl(var(--muted-foreground))', fontSize: '12px' }}>{value}</span>\n )}\n />\n )}\n {showArea\n ? categories.map((category, idx) => (\n <Area\n key={category}\n type={curveType}\n dataKey={category}\n stroke={getLineColor(idx)}\n fill={getLineColor(idx)}\n fillOpacity={0.2}\n strokeWidth={2}\n connectNulls={connectNulls}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 0 }}\n />\n ))\n : categories.map((category, idx) => (\n <Line\n key={category}\n type={curveType}\n dataKey={category}\n stroke={getLineColor(idx)}\n strokeWidth={2}\n connectNulls={connectNulls}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 0 }}\n />\n ))}\n </ChartComponent>\n </ResponsiveContainer>\n </div>\n </div>\n )\n}\n\nexport default LineChart\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\n\nexport type LineChartDataItem = Record<string, string | number | null | undefined>\n\nexport type LineChartProps = {\n title?: string\n data: LineChartDataItem[]\n index: string\n categories: string[]\n loading?: boolean\n error?: string | null\n colors?: string[]\n showArea?: boolean\n valueFormatter?: (value: number) => string\n showLegend?: boolean\n showGridLines?: boolean\n curveType?: 'linear' | 'natural' | 'monotone' | 'step'\n connectNulls?: boolean\n className?: string\n emptyMessage?: string\n categoryLabels?: Record<string, string>\n}\n\nfunction defaultValueFormatter(value: number): string {\n if (Math.abs(value) >= 1_000_000) {\n return `${(value / 1_000_000).toFixed(1)}M`\n }\n if (Math.abs(value) >= 1_000) {\n return `${(value / 1_000).toFixed(1)}K`\n }\n return value.toLocaleString(undefined, { maximumFractionDigits: 2 })\n}\n\nconst LineChartImpl = dynamic(() => import('./LineChartImpl'), {\n ssr: false,\n loading: () => (\n <div className=\"flex h-48 items-center justify-center\">\n <Spinner className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n ),\n})\n\nexport function LineChart({\n title,\n data,\n index,\n categories,\n loading,\n error,\n colors,\n showArea = false,\n valueFormatter = defaultValueFormatter,\n showLegend = true,\n showGridLines = true,\n curveType = 'monotone',\n connectNulls = true,\n className = '',\n emptyMessage = 'No data available',\n categoryLabels,\n}: LineChartProps) {\n if (error) {\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n </div>\n )\n }\n\n if (loading) {\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <Spinner className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n </div>\n )\n }\n\n if (!data || data.length === 0) {\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-muted-foreground\">{emptyMessage}</p>\n </div>\n </div>\n )\n }\n\n return (\n <div className={`rounded-lg border bg-card p-4 ${className}`}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"h-52 w-full\">\n <LineChartImpl\n data={data}\n index={index}\n categories={categories}\n colors={colors}\n showArea={showArea}\n valueFormatter={valueFormatter}\n showLegend={showLegend}\n showGridLines={showGridLines}\n curveType={curveType}\n connectNulls={connectNulls}\n categoryLabels={categoryLabels}\n />\n </div>\n </div>\n )\n}\n\nexport default LineChart\n"],
5
+ "mappings": ";AAyCM,cAyBA,YAzBA;AAtCN,OAAO,aAAa;AACpB,SAAS,eAAe;AAuBxB,SAAS,sBAAsB,OAAuB;AACpD,MAAI,KAAK,IAAI,KAAK,KAAK,KAAW;AAChC,WAAO,IAAI,QAAQ,KAAW,QAAQ,CAAC,CAAC;AAAA,EAC1C;AACA,MAAI,KAAK,IAAI,KAAK,KAAK,KAAO;AAC5B,WAAO,IAAI,QAAQ,KAAO,QAAQ,CAAC,CAAC;AAAA,EACtC;AACA,SAAO,MAAM,eAAe,QAAW,EAAE,uBAAuB,EAAE,CAAC;AACrE;AAEA,MAAM,gBAAgB,QAAQ,MAAM,OAAO,iBAAiB,GAAG;AAAA,EAC7D,KAAK;AAAA,EACL,SAAS,MACP,oBAAC,SAAI,WAAU,yCACb,8BAAC,WAAQ,WAAU,iCAAgC,GACrD;AAEJ,CAAC;AAEM,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AACF,GAAmB;AACjB,MAAI,OAAO;AACT,WACE,qBAAC,SAAI,WAAW,iCAAiC,SAAS,IACvD;AAAA,eAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,MACjF,oBAAC,SAAI,WAAU,yCACb,8BAAC,OAAE,WAAU,4BAA4B,iBAAM,GACjD;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,SAAS;AACX,WACE,qBAAC,SAAI,WAAW,iCAAiC,SAAS,IACvD;AAAA,eAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,MACjF,oBAAC,SAAI,WAAU,yCACb,8BAAC,WAAQ,WAAU,iCAAgC,GACrD;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WACE,qBAAC,SAAI,WAAW,iCAAiC,SAAS,IACvD;AAAA,eAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,MACjF,oBAAC,SAAI,WAAU,yCACb,8BAAC,OAAE,WAAU,iCAAiC,wBAAa,GAC7D;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAW,iCAAiC,SAAS,IACvD;AAAA,aAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,IACjF,oBAAC,SAAI,WAAU,eACb;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;AAEA,IAAO,oBAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,112 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ LineChart as RechartsLineChart,
5
+ AreaChart as RechartsAreaChart,
6
+ Line,
7
+ Area,
8
+ XAxis,
9
+ YAxis,
10
+ CartesianGrid,
11
+ Tooltip,
12
+ ResponsiveContainer,
13
+ Legend
14
+ } from "recharts";
15
+ import { ChartTooltipContent, resolveChartColor } from "./ChartUtils.js";
16
+ function LineChartImpl({
17
+ data,
18
+ index,
19
+ categories,
20
+ colors,
21
+ showArea = false,
22
+ valueFormatter,
23
+ showLegend = true,
24
+ showGridLines = true,
25
+ curveType = "monotone",
26
+ connectNulls = true,
27
+ categoryLabels
28
+ }) {
29
+ const getLineColor = (idx) => resolveChartColor(colors?.[idx], idx);
30
+ const ChartComponent = showArea ? RechartsAreaChart : RechartsLineChart;
31
+ return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
32
+ ChartComponent,
33
+ {
34
+ data,
35
+ margin: { top: 5, right: 10, left: 10, bottom: 5 },
36
+ children: [
37
+ showGridLines && /* @__PURE__ */ jsx(
38
+ CartesianGrid,
39
+ {
40
+ strokeDasharray: "3 3",
41
+ stroke: "hsl(var(--border))"
42
+ }
43
+ ),
44
+ /* @__PURE__ */ jsx(
45
+ XAxis,
46
+ {
47
+ dataKey: index,
48
+ tick: { fontSize: 12 },
49
+ tickLine: false,
50
+ axisLine: false
51
+ }
52
+ ),
53
+ /* @__PURE__ */ jsx(
54
+ YAxis,
55
+ {
56
+ tickFormatter: valueFormatter,
57
+ tick: { fontSize: 12 },
58
+ tickLine: false,
59
+ axisLine: false,
60
+ width: 56
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsx(
64
+ Tooltip,
65
+ {
66
+ content: /* @__PURE__ */ jsx(ChartTooltipContent, { valueFormatter, categoryLabels }),
67
+ cursor: { stroke: "hsl(var(--muted-foreground))", strokeDasharray: "3 3" }
68
+ }
69
+ ),
70
+ showLegend && categories.length > 1 && /* @__PURE__ */ jsx(
71
+ Legend,
72
+ {
73
+ verticalAlign: "top",
74
+ height: 36,
75
+ formatter: (value) => /* @__PURE__ */ jsx("span", { style: { color: "hsl(var(--muted-foreground))", fontSize: "12px" }, children: value })
76
+ }
77
+ ),
78
+ showArea ? categories.map((category, idx) => /* @__PURE__ */ jsx(
79
+ Area,
80
+ {
81
+ type: curveType,
82
+ dataKey: category,
83
+ stroke: getLineColor(idx),
84
+ fill: getLineColor(idx),
85
+ fillOpacity: 0.2,
86
+ strokeWidth: 2,
87
+ connectNulls,
88
+ dot: false,
89
+ activeDot: { r: 4, strokeWidth: 0 }
90
+ },
91
+ category
92
+ )) : categories.map((category, idx) => /* @__PURE__ */ jsx(
93
+ Line,
94
+ {
95
+ type: curveType,
96
+ dataKey: category,
97
+ stroke: getLineColor(idx),
98
+ strokeWidth: 2,
99
+ connectNulls,
100
+ dot: false,
101
+ activeDot: { r: 4, strokeWidth: 0 }
102
+ },
103
+ category
104
+ ))
105
+ ]
106
+ }
107
+ ) });
108
+ }
109
+ export {
110
+ LineChartImpl as default
111
+ };
112
+ //# sourceMappingURL=LineChartImpl.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/backend/charts/LineChartImpl.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport {\n LineChart as RechartsLineChart,\n AreaChart as RechartsAreaChart,\n Line,\n Area,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n Legend,\n} from 'recharts'\nimport { ChartTooltipContent, resolveChartColor } from './ChartUtils'\nimport type { LineChartProps } from './LineChart'\n\ntype ImplProps = Pick<\n LineChartProps,\n | 'data'\n | 'index'\n | 'categories'\n | 'colors'\n | 'showArea'\n | 'valueFormatter'\n | 'showLegend'\n | 'showGridLines'\n | 'curveType'\n | 'connectNulls'\n | 'categoryLabels'\n> & {\n valueFormatter: (value: number) => string\n}\n\nexport default function LineChartImpl({\n data,\n index,\n categories,\n colors,\n showArea = false,\n valueFormatter,\n showLegend = true,\n showGridLines = true,\n curveType = 'monotone',\n connectNulls = true,\n categoryLabels,\n}: ImplProps) {\n const getLineColor = (idx: number): string => resolveChartColor(colors?.[idx], idx)\n const ChartComponent = showArea ? RechartsAreaChart : RechartsLineChart\n\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <ChartComponent\n data={data}\n margin={{ top: 5, right: 10, left: 10, bottom: 5 }}\n >\n {showGridLines && (\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"hsl(var(--border))\"\n />\n )}\n <XAxis\n dataKey={index}\n tick={{ fontSize: 12 }}\n tickLine={false}\n axisLine={false}\n />\n <YAxis\n tickFormatter={valueFormatter}\n tick={{ fontSize: 12 }}\n tickLine={false}\n axisLine={false}\n width={56}\n />\n <Tooltip\n content={<ChartTooltipContent valueFormatter={valueFormatter} categoryLabels={categoryLabels} />}\n cursor={{ stroke: 'hsl(var(--muted-foreground))', strokeDasharray: '3 3' }}\n />\n {showLegend && categories.length > 1 && (\n <Legend\n verticalAlign=\"top\"\n height={36}\n formatter={(value) => (\n <span style={{ color: 'hsl(var(--muted-foreground))', fontSize: '12px' }}>{value}</span>\n )}\n />\n )}\n {showArea\n ? categories.map((category, idx) => (\n <Area\n key={category}\n type={curveType}\n dataKey={category}\n stroke={getLineColor(idx)}\n fill={getLineColor(idx)}\n fillOpacity={0.2}\n strokeWidth={2}\n connectNulls={connectNulls}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 0 }}\n />\n ))\n : categories.map((category, idx) => (\n <Line\n key={category}\n type={curveType}\n dataKey={category}\n stroke={getLineColor(idx)}\n strokeWidth={2}\n connectNulls={connectNulls}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 0 }}\n />\n ))}\n </ChartComponent>\n </ResponsiveContainer>\n )\n}\n"],
5
+ "mappings": ";AAqDM,SAKI,KALJ;AAlDN;AAAA,EACE,aAAa;AAAA,EACb,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB,yBAAyB;AAoBxC,SAAR,cAA+B;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AACF,GAAc;AACZ,QAAM,eAAe,CAAC,QAAwB,kBAAkB,SAAS,GAAG,GAAG,GAAG;AAClF,QAAM,iBAAiB,WAAW,oBAAoB;AAEtD,SACE,oBAAC,uBAAoB,OAAM,QAAO,QAAO,QACvC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,EAAE,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,QAAQ,EAAE;AAAA,MAEhD;AAAA,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,iBAAgB;AAAA,YAChB,QAAO;AAAA;AAAA,QACT;AAAA,QAEF;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,MAAM,EAAE,UAAU,GAAG;AAAA,YACrB,UAAU;AAAA,YACV,UAAU;AAAA;AAAA,QACZ;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,eAAe;AAAA,YACf,MAAM,EAAE,UAAU,GAAG;AAAA,YACrB,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO;AAAA;AAAA,QACT;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,oBAAC,uBAAoB,gBAAgC,gBAAgC;AAAA,YAC9F,QAAQ,EAAE,QAAQ,gCAAgC,iBAAiB,MAAM;AAAA;AAAA,QAC3E;AAAA,QACC,cAAc,WAAW,SAAS,KACjC;AAAA,UAAC;AAAA;AAAA,YACC,eAAc;AAAA,YACd,QAAQ;AAAA,YACR,WAAW,CAAC,UACV,oBAAC,UAAK,OAAO,EAAE,OAAO,gCAAgC,UAAU,OAAO,GAAI,iBAAM;AAAA;AAAA,QAErF;AAAA,QAED,WACG,WAAW,IAAI,CAAC,UAAU,QACxB;AAAA,UAAC;AAAA;AAAA,YAEC,MAAM;AAAA,YACN,SAAS;AAAA,YACT,QAAQ,aAAa,GAAG;AAAA,YACxB,MAAM,aAAa,GAAG;AAAA,YACtB,aAAa;AAAA,YACb,aAAa;AAAA,YACb;AAAA,YACA,KAAK;AAAA,YACL,WAAW,EAAE,GAAG,GAAG,aAAa,EAAE;AAAA;AAAA,UAT7B;AAAA,QAUP,CACD,IACD,WAAW,IAAI,CAAC,UAAU,QACxB;AAAA,UAAC;AAAA;AAAA,YAEC,MAAM;AAAA,YACN,SAAS;AAAA,YACT,QAAQ,aAAa,GAAG;AAAA,YACxB,aAAa;AAAA,YACb;AAAA,YACA,KAAK;AAAA,YACL,WAAW,EAAE,GAAG,GAAG,aAAa,EAAE;AAAA;AAAA,UAP7B;AAAA,QAQP,CACD;AAAA;AAAA;AAAA,EACP,GACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -1,17 +1,8 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import {
5
- PieChart as RechartsPieChart,
6
- Pie,
7
- Cell,
8
- Tooltip,
9
- ResponsiveContainer,
10
- Legend,
11
- Label
12
- } from "recharts";
4
+ import dynamic from "next/dynamic";
13
5
  import { Spinner } from "@open-mercato/ui/primitives/spinner";
14
- import { ChartTooltipContent, resolveChartColor } from "./ChartUtils.js";
15
6
  function defaultValueFormatter(value) {
16
7
  if (Math.abs(value) >= 1e6) {
17
8
  return `${(value / 1e6).toFixed(1)}M`;
@@ -21,6 +12,10 @@ function defaultValueFormatter(value) {
21
12
  }
22
13
  return value.toLocaleString(void 0, { maximumFractionDigits: 2 });
23
14
  }
15
+ const PieChartImpl = dynamic(() => import("./PieChartImpl.js"), {
16
+ ssr: false,
17
+ loading: () => /* @__PURE__ */ jsx("div", { className: "flex h-48 items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { className: "h-6 w-6 text-muted-foreground" }) })
18
+ });
24
19
  function PieChart({
25
20
  title,
26
21
  data,
@@ -34,9 +29,6 @@ function PieChart({
34
29
  className = "",
35
30
  emptyMessage = "No data available"
36
31
  }) {
37
- const getSliceColor = (idx) => {
38
- return resolveChartColor(colors?.[idx], idx);
39
- };
40
32
  const total = React.useMemo(() => {
41
33
  return data.reduce((sum, item) => sum + item.value, 0);
42
34
  }, [data]);
@@ -60,57 +52,20 @@ function PieChart({
60
52
  /* @__PURE__ */ jsx("div", { className: "flex h-48 items-center justify-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessage }) })
61
53
  ] });
62
54
  }
63
- const innerRadius = variant === "donut" ? "60%" : 0;
64
- const outerRadius = "80%";
65
55
  return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
66
56
  title && /* @__PURE__ */ jsx("h3", { className: "mb-4 text-base font-medium text-card-foreground", children: title }),
67
- /* @__PURE__ */ jsx("div", { className: "h-52 w-full", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(RechartsPieChart, { children: [
68
- /* @__PURE__ */ jsxs(
69
- Pie,
70
- {
71
- data,
72
- dataKey: "value",
73
- nameKey: "name",
74
- cx: "50%",
75
- cy: "40%",
76
- innerRadius,
77
- outerRadius,
78
- paddingAngle: 2,
79
- strokeWidth: 0,
80
- children: [
81
- data.map((_, idx) => /* @__PURE__ */ jsx(Cell, { fill: getSliceColor(idx) }, `cell-${idx}`)),
82
- showLabel && variant === "donut" && /* @__PURE__ */ jsx(
83
- Label,
84
- {
85
- value: valueFormatter(total),
86
- position: "center",
87
- className: "fill-foreground text-2xl font-bold"
88
- }
89
- )
90
- ]
91
- }
92
- ),
93
- showTooltip && /* @__PURE__ */ jsx(
94
- Tooltip,
95
- {
96
- content: /* @__PURE__ */ jsx(
97
- ChartTooltipContent,
98
- {
99
- valueFormatter,
100
- hideLabel: true
101
- }
102
- )
103
- }
104
- ),
105
- /* @__PURE__ */ jsx(
106
- Legend,
107
- {
108
- verticalAlign: "bottom",
109
- height: 36,
110
- formatter: (value) => /* @__PURE__ */ jsx("span", { style: { color: "hsl(var(--muted-foreground))", fontSize: "12px" }, children: value })
111
- }
112
- )
113
- ] }) }) })
57
+ /* @__PURE__ */ jsx("div", { className: "h-52 w-full", children: /* @__PURE__ */ jsx(
58
+ PieChartImpl,
59
+ {
60
+ data,
61
+ colors,
62
+ variant,
63
+ valueFormatter,
64
+ showLabel,
65
+ showTooltip,
66
+ total
67
+ }
68
+ ) })
114
69
  ] });
115
70
  }
116
71
  var PieChart_default = PieChart;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/backend/charts/PieChart.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport {\n PieChart as RechartsPieChart,\n Pie,\n Cell,\n Tooltip,\n ResponsiveContainer,\n Legend,\n Label,\n} from 'recharts'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { ChartTooltipContent, resolveChartColor } from './ChartUtils'\n\nexport type PieChartDataItem = {\n name: string\n value: number\n}\n\nexport type PieChartProps = {\n title?: string\n data: PieChartDataItem[]\n loading?: boolean\n error?: string | null\n colors?: string[]\n variant?: 'pie' | 'donut'\n valueFormatter?: (value: number) => string\n showLabel?: boolean\n showTooltip?: boolean\n className?: string\n emptyMessage?: string\n}\n\nfunction defaultValueFormatter(value: number): string {\n if (Math.abs(value) >= 1_000_000) {\n return `${(value / 1_000_000).toFixed(1)}M`\n }\n if (Math.abs(value) >= 1_000) {\n return `${(value / 1_000).toFixed(1)}K`\n }\n return value.toLocaleString(undefined, { maximumFractionDigits: 2 })\n}\n\nexport function PieChart({\n title,\n data,\n loading,\n error,\n colors,\n variant = 'donut',\n valueFormatter = defaultValueFormatter,\n showLabel = true,\n showTooltip = true,\n className = '',\n emptyMessage = 'No data available',\n}: PieChartProps) {\n const getSliceColor = (idx: number): string => {\n return resolveChartColor(colors?.[idx], idx)\n }\n\n const total = React.useMemo(() => {\n return data.reduce((sum, item) => sum + item.value, 0)\n }, [data])\n\n const hasWrapper = !!title\n const wrapperClass = hasWrapper ? `rounded-lg border bg-card p-4 ${className}` : className\n\n if (error) {\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n </div>\n )\n }\n\n if (loading) {\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <Spinner className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n </div>\n )\n }\n\n if (!data || data.length === 0) {\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-muted-foreground\">{emptyMessage}</p>\n </div>\n </div>\n )\n }\n\n const innerRadius = variant === 'donut' ? '60%' : 0\n const outerRadius = '80%'\n\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"h-52 w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RechartsPieChart>\n <Pie\n data={data}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"40%\"\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n paddingAngle={2}\n strokeWidth={0}\n >\n {data.map((_, idx) => (\n <Cell key={`cell-${idx}`} fill={getSliceColor(idx)} />\n ))}\n {showLabel && variant === 'donut' && (\n <Label\n value={valueFormatter(total)}\n position=\"center\"\n className=\"fill-foreground text-2xl font-bold\"\n />\n )}\n </Pie>\n {showTooltip && (\n <Tooltip\n content={\n <ChartTooltipContent\n valueFormatter={valueFormatter}\n hideLabel\n />\n }\n />\n )}\n <Legend\n verticalAlign=\"bottom\"\n height={36}\n formatter={(value) => (\n <span style={{ color: 'hsl(var(--muted-foreground))', fontSize: '12px' }}>{value}</span>\n )}\n />\n </RechartsPieChart>\n </ResponsiveContainer>\n </div>\n </div>\n )\n}\n\nexport default PieChart\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\n\nexport type PieChartDataItem = {\n name: string\n value: number\n}\n\nexport type PieChartProps = {\n title?: string\n data: PieChartDataItem[]\n loading?: boolean\n error?: string | null\n colors?: string[]\n variant?: 'pie' | 'donut'\n valueFormatter?: (value: number) => string\n showLabel?: boolean\n showTooltip?: boolean\n className?: string\n emptyMessage?: string\n}\n\nfunction defaultValueFormatter(value: number): string {\n if (Math.abs(value) >= 1_000_000) {\n return `${(value / 1_000_000).toFixed(1)}M`\n }\n if (Math.abs(value) >= 1_000) {\n return `${(value / 1_000).toFixed(1)}K`\n }\n return value.toLocaleString(undefined, { maximumFractionDigits: 2 })\n}\n\nconst PieChartImpl = dynamic(() => import('./PieChartImpl'), {\n ssr: false,\n loading: () => (\n <div className=\"flex h-48 items-center justify-center\">\n <Spinner className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n ),\n})\n\nexport function PieChart({\n title,\n data,\n loading,\n error,\n colors,\n variant = 'donut',\n valueFormatter = defaultValueFormatter,\n showLabel = true,\n showTooltip = true,\n className = '',\n emptyMessage = 'No data available',\n}: PieChartProps) {\n const total = React.useMemo(() => {\n return data.reduce((sum, item) => sum + item.value, 0)\n }, [data])\n\n const hasWrapper = !!title\n const wrapperClass = hasWrapper ? `rounded-lg border bg-card p-4 ${className}` : className\n\n if (error) {\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n </div>\n )\n }\n\n if (loading) {\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <Spinner className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n </div>\n )\n }\n\n if (!data || data.length === 0) {\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"flex h-48 items-center justify-center\">\n <p className=\"text-sm text-muted-foreground\">{emptyMessage}</p>\n </div>\n </div>\n )\n }\n\n return (\n <div className={wrapperClass}>\n {title && <h3 className=\"mb-4 text-base font-medium text-card-foreground\">{title}</h3>}\n <div className=\"h-52 w-full\">\n <PieChartImpl\n data={data}\n colors={colors}\n variant={variant}\n valueFormatter={valueFormatter}\n showLabel={showLabel}\n showTooltip={showTooltip}\n total={total}\n />\n </div>\n </div>\n )\n}\n\nexport default PieChart\n"],
5
+ "mappings": ";AAuCM,cA2BA,YA3BA;AArCN,YAAY,WAAW;AACvB,OAAO,aAAa;AACpB,SAAS,eAAe;AAqBxB,SAAS,sBAAsB,OAAuB;AACpD,MAAI,KAAK,IAAI,KAAK,KAAK,KAAW;AAChC,WAAO,IAAI,QAAQ,KAAW,QAAQ,CAAC,CAAC;AAAA,EAC1C;AACA,MAAI,KAAK,IAAI,KAAK,KAAK,KAAO;AAC5B,WAAO,IAAI,QAAQ,KAAO,QAAQ,CAAC,CAAC;AAAA,EACtC;AACA,SAAO,MAAM,eAAe,QAAW,EAAE,uBAAuB,EAAE,CAAC;AACrE;AAEA,MAAM,eAAe,QAAQ,MAAM,OAAO,gBAAgB,GAAG;AAAA,EAC3D,KAAK;AAAA,EACL,SAAS,MACP,oBAAC,SAAI,WAAU,yCACb,8BAAC,WAAQ,WAAU,iCAAgC,GACrD;AAEJ,CAAC;AAEM,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,eAAe;AACjB,GAAkB;AAChB,QAAM,QAAQ,MAAM,QAAQ,MAAM;AAChC,WAAO,KAAK,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC;AAAA,EACvD,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,aAAa,CAAC,CAAC;AACrB,QAAM,eAAe,aAAa,iCAAiC,SAAS,KAAK;AAEjF,MAAI,OAAO;AACT,WACE,qBAAC,SAAI,WAAW,cACb;AAAA,eAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,MACjF,oBAAC,SAAI,WAAU,yCACb,8BAAC,OAAE,WAAU,4BAA4B,iBAAM,GACjD;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,SAAS;AACX,WACE,qBAAC,SAAI,WAAW,cACb;AAAA,eAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,MACjF,oBAAC,SAAI,WAAU,yCACb,8BAAC,WAAQ,WAAU,iCAAgC,GACrD;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WACE,qBAAC,SAAI,WAAW,cACb;AAAA,eAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,MACjF,oBAAC,SAAI,WAAU,yCACb,8BAAC,OAAE,WAAU,iCAAiC,wBAAa,GAC7D;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAW,cACb;AAAA,aAAS,oBAAC,QAAG,WAAU,mDAAmD,iBAAM;AAAA,IACjF,oBAAC,SAAI,WAAU,eACb;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;AAEA,IAAO,mBAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,76 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ PieChart as RechartsPieChart,
5
+ Pie,
6
+ Cell,
7
+ Tooltip,
8
+ ResponsiveContainer,
9
+ Legend,
10
+ Label
11
+ } from "recharts";
12
+ import { ChartTooltipContent, resolveChartColor } from "./ChartUtils.js";
13
+ function PieChartImpl({
14
+ data,
15
+ colors,
16
+ variant = "donut",
17
+ valueFormatter,
18
+ showLabel = true,
19
+ showTooltip = true,
20
+ total
21
+ }) {
22
+ const getSliceColor = (idx) => resolveChartColor(colors?.[idx], idx);
23
+ const innerRadius = variant === "donut" ? "60%" : 0;
24
+ const outerRadius = "80%";
25
+ return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(RechartsPieChart, { children: [
26
+ /* @__PURE__ */ jsxs(
27
+ Pie,
28
+ {
29
+ data,
30
+ dataKey: "value",
31
+ nameKey: "name",
32
+ cx: "50%",
33
+ cy: "40%",
34
+ innerRadius,
35
+ outerRadius,
36
+ paddingAngle: 2,
37
+ strokeWidth: 0,
38
+ children: [
39
+ data.map((_, idx) => /* @__PURE__ */ jsx(Cell, { fill: getSliceColor(idx) }, `cell-${idx}`)),
40
+ showLabel && variant === "donut" && /* @__PURE__ */ jsx(
41
+ Label,
42
+ {
43
+ value: valueFormatter(total),
44
+ position: "center",
45
+ className: "fill-foreground text-2xl font-bold"
46
+ }
47
+ )
48
+ ]
49
+ }
50
+ ),
51
+ showTooltip && /* @__PURE__ */ jsx(
52
+ Tooltip,
53
+ {
54
+ content: /* @__PURE__ */ jsx(
55
+ ChartTooltipContent,
56
+ {
57
+ valueFormatter,
58
+ hideLabel: true
59
+ }
60
+ )
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsx(
64
+ Legend,
65
+ {
66
+ verticalAlign: "bottom",
67
+ height: 36,
68
+ formatter: (value) => /* @__PURE__ */ jsx("span", { style: { color: "hsl(var(--muted-foreground))", fontSize: "12px" }, children: value })
69
+ }
70
+ )
71
+ ] }) });
72
+ }
73
+ export {
74
+ PieChartImpl as default
75
+ };
76
+ //# sourceMappingURL=PieChartImpl.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/backend/charts/PieChartImpl.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport {\n PieChart as RechartsPieChart,\n Pie,\n Cell,\n Tooltip,\n ResponsiveContainer,\n Legend,\n Label,\n} from 'recharts'\nimport { ChartTooltipContent, resolveChartColor } from './ChartUtils'\nimport type { PieChartProps } from './PieChart'\n\ntype ImplProps = Pick<\n PieChartProps,\n 'data' | 'colors' | 'variant' | 'valueFormatter' | 'showLabel' | 'showTooltip'\n> & {\n valueFormatter: (value: number) => string\n total: number\n}\n\nexport default function PieChartImpl({\n data,\n colors,\n variant = 'donut',\n valueFormatter,\n showLabel = true,\n showTooltip = true,\n total,\n}: ImplProps) {\n const getSliceColor = (idx: number): string => resolveChartColor(colors?.[idx], idx)\n const innerRadius = variant === 'donut' ? '60%' : 0\n const outerRadius = '80%'\n\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RechartsPieChart>\n <Pie\n data={data}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"40%\"\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n paddingAngle={2}\n strokeWidth={0}\n >\n {data.map((_, idx) => (\n <Cell key={`cell-${idx}`} fill={getSliceColor(idx)} />\n ))}\n {showLabel && variant === 'donut' && (\n <Label\n value={valueFormatter(total)}\n position=\"center\"\n className=\"fill-foreground text-2xl font-bold\"\n />\n )}\n </Pie>\n {showTooltip && (\n <Tooltip\n content={\n <ChartTooltipContent\n valueFormatter={valueFormatter}\n hideLabel\n />\n }\n />\n )}\n <Legend\n verticalAlign=\"bottom\"\n height={36}\n formatter={(value) => (\n <span style={{ color: 'hsl(var(--muted-foreground))', fontSize: '12px' }}>{value}</span>\n )}\n />\n </RechartsPieChart>\n </ResponsiveContainer>\n )\n}\n"],
5
+ "mappings": ";AAuCQ,SAYI,KAZJ;AApCR;AAAA,EACE,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB,yBAAyB;AAWxC,SAAR,aAA8B;AAAA,EACnC;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA,YAAY;AAAA,EACZ,cAAc;AAAA,EACd;AACF,GAAc;AACZ,QAAM,gBAAgB,CAAC,QAAwB,kBAAkB,SAAS,GAAG,GAAG,GAAG;AACnF,QAAM,cAAc,YAAY,UAAU,QAAQ;AAClD,QAAM,cAAc;AAEpB,SACE,oBAAC,uBAAoB,OAAM,QAAO,QAAO,QACvC,+BAAC,oBACC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,SAAQ;AAAA,QACR,SAAQ;AAAA,QACR,IAAG;AAAA,QACH,IAAG;AAAA,QACH;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,aAAa;AAAA,QAEZ;AAAA,eAAK,IAAI,CAAC,GAAG,QACZ,oBAAC,QAAyB,MAAM,cAAc,GAAG,KAAtC,QAAQ,GAAG,EAA8B,CACrD;AAAA,UACA,aAAa,YAAY,WACxB;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,eAAe,KAAK;AAAA,cAC3B,UAAS;AAAA,cACT,WAAU;AAAA;AAAA,UACZ;AAAA;AAAA;AAAA,IAEJ;AAAA,IACC,eACC;AAAA,MAAC;AAAA;AAAA,QACC,SACE;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,WAAS;AAAA;AAAA,QACX;AAAA;AAAA,IAEJ;AAAA,IAEF;AAAA,MAAC;AAAA;AAAA,QACC,eAAc;AAAA,QACd,QAAQ;AAAA,QACR,WAAW,CAAC,UACV,oBAAC,UAAK,OAAO,EAAE,OAAO,gCAAgC,UAAU,OAAO,GAAI,iBAAM;AAAA;AAAA,IAErF;AAAA,KACF,GACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -11,6 +11,7 @@ import { getDashboardWidgets, loadDashboardWidgetModule } from "./widgetRegistry
11
11
  import { cn } from "@open-mercato/shared/lib/utils";
12
12
  import { GripVertical, Info, Plus, RefreshCw, Settings2, Trash2, X, Loader2 } from "lucide-react";
13
13
  import { useT } from "@open-mercato/shared/lib/i18n/context";
14
+ import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
14
15
  import { InjectionSpot } from "../injection/InjectionSpot.js";
15
16
  function sizeClass(size) {
16
17
  switch (size) {
@@ -39,6 +40,7 @@ function generateId() {
39
40
  }
40
41
  function DashboardScreen() {
41
42
  const t = useT();
43
+ const organizationScopeVersion = useOrganizationScopeVersion();
42
44
  const [loading, setLoading] = React.useState(true);
43
45
  const [error, setError] = React.useState(null);
44
46
  const [hasRegisteredWidgets, setHasRegisteredWidgets] = React.useState(true);
@@ -109,7 +111,7 @@ function DashboardScreen() {
109
111
  }, [t]);
110
112
  React.useEffect(() => {
111
113
  load();
112
- }, [load]);
114
+ }, [load, organizationScopeVersion]);
113
115
  const metaById = React.useMemo(() => {
114
116
  const map = /* @__PURE__ */ new Map();
115
117
  for (const meta of widgetCatalog) map.set(meta.id, meta);
@@ -450,6 +452,12 @@ function DashboardWidgetCard({
450
452
  setLoadError(null);
451
453
  loadDashboardWidgetModule(meta.loaderKey).then((loaded) => {
452
454
  if (cancelled) return;
455
+ if (!loaded) {
456
+ setModule(null);
457
+ setLoadError(t("dashboard.widget.loadError"));
458
+ setLoading(false);
459
+ return;
460
+ }
453
461
  setModule(loaded);
454
462
  setLoading(false);
455
463
  }).catch((err) => {