@audere/ui 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ type AIActionCardProps = {
5
+ title: string;
6
+ description: string;
7
+ badge?: ReactNode;
8
+ children?: ReactNode;
9
+ };
10
+ declare function AIActionCard({ title, description, badge, children, }: AIActionCardProps): react_jsx_runtime.JSX.Element;
11
+
12
+ type AIInsightPanelProps = {
13
+ title: string;
14
+ children: ReactNode;
15
+ headerAccessory?: ReactNode;
16
+ };
17
+ declare function AIInsightPanel({ title, children, headerAccessory, }: AIInsightPanelProps): react_jsx_runtime.JSX.Element;
18
+
19
+ type ChatMessage = {
20
+ id: string | number;
21
+ role: "assistant" | "user";
22
+ content: ReactNode;
23
+ };
24
+ type AIChatPanelProps = {
25
+ title: string;
26
+ messages: ChatMessage[];
27
+ footer?: ReactNode;
28
+ className?: string;
29
+ };
30
+ declare function AIChatPanel({ title, messages, footer, className }: AIChatPanelProps): react_jsx_runtime.JSX.Element;
31
+
32
+ export { AIActionCard, type AIActionCardProps, AIChatPanel, type AIChatPanelProps, AIInsightPanel, type AIInsightPanelProps, type ChatMessage };
@@ -0,0 +1,98 @@
1
+ import { cva } from 'class-variance-authority';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ // src/surface/Surface.tsx
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ var surfaceVariants = cva(
11
+ "rounded-xl border border-border bg-card text-card-foreground shadow-sm",
12
+ {
13
+ variants: {
14
+ padding: {
15
+ none: "p-0",
16
+ sm: "p-4",
17
+ md: "p-6"
18
+ }
19
+ },
20
+ defaultVariants: {
21
+ padding: "none"
22
+ }
23
+ }
24
+ );
25
+ function Surface({ className, padding, ...props }) {
26
+ return /* @__PURE__ */ jsx(
27
+ "div",
28
+ {
29
+ "data-slot": "surface",
30
+ className: cn(surfaceVariants({ padding }), className),
31
+ ...props
32
+ }
33
+ );
34
+ }
35
+ function AIActionCard({
36
+ title,
37
+ description,
38
+ badge,
39
+ children
40
+ }) {
41
+ return /* @__PURE__ */ jsxs(Surface, { padding: "md", className: "overflow-hidden border-primary/20", children: [
42
+ badge ? /* @__PURE__ */ jsx("div", { className: "mb-4 flex items-center gap-2 text-sm font-semibold text-primary", children: badge }) : null,
43
+ /* @__PURE__ */ jsx("h3", { className: "mb-2 text-xl font-medium text-foreground", children: title }),
44
+ /* @__PURE__ */ jsx("p", { className: "mb-6 max-w-3xl text-muted-foreground", children: description }),
45
+ children ? /* @__PURE__ */ jsx("div", { className: "space-y-4", children }) : null
46
+ ] });
47
+ }
48
+ function AIInsightPanel({
49
+ title,
50
+ children,
51
+ headerAccessory
52
+ }) {
53
+ return /* @__PURE__ */ jsxs(
54
+ Surface,
55
+ {
56
+ padding: "md",
57
+ className: "relative overflow-hidden bg-gradient-to-br from-primary/5 via-card to-card",
58
+ children: [
59
+ /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center justify-between gap-4", children: [
60
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: title }),
61
+ headerAccessory
62
+ ] }),
63
+ /* @__PURE__ */ jsx("div", { className: "leading-relaxed text-foreground", children })
64
+ ]
65
+ }
66
+ );
67
+ }
68
+ function AIChatPanel({ title, messages, footer, className }) {
69
+ return /* @__PURE__ */ jsxs(
70
+ Surface,
71
+ {
72
+ padding: "none",
73
+ className: cn("flex flex-col", className ?? "h-[400px]"),
74
+ children: [
75
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between rounded-t-[inherit] border-b border-border bg-muted/40 p-4", children: /* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-foreground", children: title }) }),
76
+ /* @__PURE__ */ jsx("div", { className: "flex-1 space-y-4 overflow-y-auto p-4", children: messages.map((message) => /* @__PURE__ */ jsx(
77
+ "div",
78
+ {
79
+ className: message.role === "assistant" ? "flex max-w-[85%] gap-3" : "ml-auto flex max-w-[85%] justify-end gap-3",
80
+ children: /* @__PURE__ */ jsx(
81
+ "div",
82
+ {
83
+ className: message.role === "assistant" ? "rounded-2xl rounded-tl-sm border border-border bg-muted p-3 text-sm text-foreground" : "rounded-2xl rounded-tr-sm bg-primary p-3 text-sm text-primary-foreground",
84
+ children: message.content
85
+ }
86
+ )
87
+ },
88
+ message.id
89
+ )) }),
90
+ footer ? /* @__PURE__ */ jsx("div", { className: "border-t border-border p-4", children: footer }) : null
91
+ ]
92
+ }
93
+ );
94
+ }
95
+
96
+ export { AIActionCard, AIChatPanel, AIInsightPanel };
97
+ //# sourceMappingURL=index.js.map
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/utils.ts","../../src/surface/Surface.tsx","../../src/ai/AIActionCard.tsx","../../src/ai/AIInsightPanel.tsx","../../src/ai/AIChatPanel.tsx"],"names":["jsx","jsxs"],"mappings":";;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACAA,IAAM,eAAA,GAAkB,GAAA;AAAA,EACtB,wEAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,KAAA;AAAA,QACN,EAAA,EAAI,KAAA;AAAA,QACJ,EAAA,EAAI;AAAA;AACN,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS;AAAA;AACX;AAEJ,CAAA;AASO,SAAS,QAAQ,EAAE,SAAA,EAAW,OAAA,EAAS,GAAG,OAAM,EAAiB;AACtE,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,SAAA;AAAA,MACV,WAAW,EAAA,CAAG,eAAA,CAAgB,EAAE,OAAA,EAAS,GAAG,SAAS,CAAA;AAAA,MACpD,GAAG;AAAA;AAAA,GACN;AAEJ;ACzBO,SAAS,YAAA,CAAa;AAAA,EAC3B,KAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,uBACE,IAAA,CAAC,OAAA,EAAA,EAAQ,OAAA,EAAQ,IAAA,EAAK,WAAU,mCAAA,EAC7B,QAAA,EAAA;AAAA,IAAA,KAAA,mBACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iEAAA,EACZ,iBACH,CAAA,GACE,IAAA;AAAA,oBACJA,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAA4C,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,oBAChEA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wCAAwC,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,IAChE,2BAAWA,GAAAA,CAAC,SAAI,SAAA,EAAU,WAAA,EAAa,UAAS,CAAA,GAAS;AAAA,GAAA,EAC5D,CAAA;AAEJ;ACnBO,SAAS,cAAA,CAAe;AAAA,EAC7B,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,uBACEC,IAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,IAAA;AAAA,MACR,SAAA,EAAU,4EAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAAA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8CAAA,EACb,QAAA,EAAA;AAAA,0BAAAD,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,uCAAA,EAAyC,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,UAC5D;AAAA,SAAA,EACH,CAAA;AAAA,wBACAA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mCAAmC,QAAA,EAAS;AAAA;AAAA;AAAA,GAC7D;AAEJ;ACTO,SAAS,YAAY,EAAE,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,WAAU,EAAqB;AACpF,EAAA,uBACEC,IAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,MAAA;AAAA,MACR,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,SAAA,IAAa,WAAW,CAAA;AAAA,MAEvD,QAAA,EAAA;AAAA,wBAAAD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8FAAA,EACb,QAAA,kBAAAA,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qCAAA,EAAuC,QAAA,EAAA,KAAA,EAAM,CAAA,EAC9D,CAAA;AAAA,wBACAA,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCACZ,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,qBACbA,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YAEC,SAAA,EACE,OAAA,CAAQ,IAAA,KAAS,WAAA,GACb,wBAAA,GACA,4CAAA;AAAA,YAGN,QAAA,kBAAAA,GAAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EACE,OAAA,CAAQ,IAAA,KAAS,WAAA,GACb,qFAAA,GACA,0EAAA;AAAA,gBAGL,QAAA,EAAA,OAAA,CAAQ;AAAA;AAAA;AACX,WAAA;AAAA,UAfK,OAAA,CAAQ;AAAA,SAiBhB,CAAA,EACH,CAAA;AAAA,QACC,yBAASA,GAAAA,CAAC,SAAI,SAAA,EAAU,4BAAA,EAA8B,kBAAO,CAAA,GAAS;AAAA;AAAA;AAAA,GACzE;AAEJ","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../lib/utils\";\n\nconst surfaceVariants = cva(\n \"rounded-xl border border-border bg-card text-card-foreground shadow-sm\",\n {\n variants: {\n padding: {\n none: \"p-0\",\n sm: \"p-4\",\n md: \"p-6\",\n },\n },\n defaultVariants: {\n padding: \"none\",\n },\n },\n);\n\nexport type SurfaceProps = React.ComponentProps<\"div\"> &\n VariantProps<typeof surfaceVariants>;\n\n/**\n * Default elevated panel for tables, metrics, charts, and grouped content.\n * Uses theme CSS variables (`--card`, `--border`); host apps must define :root tokens.\n */\nexport function Surface({ className, padding, ...props }: SurfaceProps) {\n return (\n <div\n data-slot=\"surface\"\n className={cn(surfaceVariants({ padding }), className)}\n {...props}\n />\n );\n}\n\nexport { surfaceVariants };\n","import type { ReactNode } from \"react\";\n\nimport { Surface } from \"../surface/Surface\";\n\nexport type AIActionCardProps = {\n title: string;\n description: string;\n badge?: ReactNode;\n children?: ReactNode;\n};\n\nexport function AIActionCard({\n title,\n description,\n badge,\n children,\n}: AIActionCardProps) {\n return (\n <Surface padding=\"md\" className=\"overflow-hidden border-primary/20\">\n {badge ? (\n <div className=\"mb-4 flex items-center gap-2 text-sm font-semibold text-primary\">\n {badge}\n </div>\n ) : null}\n <h3 className=\"mb-2 text-xl font-medium text-foreground\">{title}</h3>\n <p className=\"mb-6 max-w-3xl text-muted-foreground\">{description}</p>\n {children ? <div className=\"space-y-4\">{children}</div> : null}\n </Surface>\n );\n}\n","import type { ReactNode } from \"react\";\n\nimport { Surface } from \"../surface/Surface\";\n\nexport type AIInsightPanelProps = {\n title: string;\n children: ReactNode;\n headerAccessory?: ReactNode;\n};\n\nexport function AIInsightPanel({\n title,\n children,\n headerAccessory,\n}: AIInsightPanelProps) {\n return (\n <Surface\n padding=\"md\"\n className=\"relative overflow-hidden bg-gradient-to-br from-primary/5 via-card to-card\"\n >\n <div className=\"mb-4 flex items-center justify-between gap-4\">\n <h3 className=\"text-sm font-semibold text-foreground\">{title}</h3>\n {headerAccessory}\n </div>\n <div className=\"leading-relaxed text-foreground\">{children}</div>\n </Surface>\n );\n}\n","import type { ReactNode } from \"react\";\n\nimport { Surface } from \"../surface/Surface\";\nimport { cn } from \"../lib/utils\";\n\nexport type ChatMessage = {\n id: string | number;\n role: \"assistant\" | \"user\";\n content: ReactNode;\n};\n\nexport type AIChatPanelProps = {\n title: string;\n messages: ChatMessage[];\n footer?: ReactNode;\n className?: string;\n};\n\nexport function AIChatPanel({ title, messages, footer, className }: AIChatPanelProps) {\n return (\n <Surface\n padding=\"none\"\n className={cn(\"flex flex-col\", className ?? \"h-[400px]\")}\n >\n <div className=\"flex items-center justify-between rounded-t-[inherit] border-b border-border bg-muted/40 p-4\">\n <div className=\"text-sm font-medium text-foreground\">{title}</div>\n </div>\n <div className=\"flex-1 space-y-4 overflow-y-auto p-4\">\n {messages.map((message) => (\n <div\n key={message.id}\n className={\n message.role === \"assistant\"\n ? \"flex max-w-[85%] gap-3\"\n : \"ml-auto flex max-w-[85%] justify-end gap-3\"\n }\n >\n <div\n className={\n message.role === \"assistant\"\n ? \"rounded-2xl rounded-tl-sm border border-border bg-muted p-3 text-sm text-foreground\"\n : \"rounded-2xl rounded-tr-sm bg-primary p-3 text-sm text-primary-foreground\"\n }\n >\n {message.content}\n </div>\n </div>\n ))}\n </div>\n {footer ? <div className=\"border-t border-border p-4\">{footer}</div> : null}\n </Surface>\n );\n}\n"]}
@@ -0,0 +1,78 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ type ChartContainerProps = {
5
+ title?: string;
6
+ className?: string;
7
+ height?: number;
8
+ children: ReactNode;
9
+ };
10
+ /** Wrapper for shared chart cards: consistent surface, height, optional title. */
11
+ declare function ChartContainer({ title, className, height, children, }: ChartContainerProps): react_jsx_runtime.JSX.Element;
12
+
13
+ type PieChartDataItem = {
14
+ name: string;
15
+ value: number;
16
+ };
17
+ type SharedPieChartProps = {
18
+ data: PieChartDataItem[];
19
+ title?: string;
20
+ height?: number;
21
+ showLegend?: boolean;
22
+ /** Name of the value field for tooltip (e.g. "Clients", "Revenue") */
23
+ valueLabel?: string;
24
+ };
25
+ declare function SharedPieChart({ data, title, height, showLegend, valueLabel, }: SharedPieChartProps): react_jsx_runtime.JSX.Element;
26
+
27
+ type BarChartDataItem = Record<string, string | number>;
28
+ type SharedBarChartProps = {
29
+ data: BarChartDataItem[];
30
+ /** Key in each item for the category axis (e.g. "name", "month") */
31
+ dataKey: string;
32
+ /** Key(s) for the bar value(s). Single = one bar series, multiple = grouped/stacked */
33
+ valueKeys?: string[];
34
+ title?: string;
35
+ height?: number;
36
+ /** Optional reference line value (e.g. monthly target) */
37
+ referenceLine?: {
38
+ value: number;
39
+ label?: string;
40
+ };
41
+ /** Bar fill colour (default Audere teal) */
42
+ fill?: string;
43
+ };
44
+ declare function SharedBarChart({ data, dataKey, valueKeys, title, height, referenceLine, fill, }: SharedBarChartProps): react_jsx_runtime.JSX.Element;
45
+
46
+ type AreaChartDataItem = Record<string, string | number>;
47
+ type SharedAreaChartProps = {
48
+ data: AreaChartDataItem[];
49
+ dataKey: string;
50
+ valueKey: string;
51
+ title?: string;
52
+ height?: number;
53
+ /** Optional second series key for stacked/dual area (e.g. inflow vs outflow) */
54
+ secondaryValueKey?: string;
55
+ fill?: string;
56
+ };
57
+ declare function SharedAreaChart({ data, dataKey, valueKey, title, height, secondaryValueKey, fill, }: SharedAreaChartProps): react_jsx_runtime.JSX.Element;
58
+
59
+ type CashflowChartDataItem = {
60
+ /** Period label (e.g. "Jan", "Q1") */
61
+ period: string;
62
+ /** Inflow amount */
63
+ inflow: number;
64
+ /** Outflow amount */
65
+ outflow: number;
66
+ /** Optional net (inflow - outflow); computed if not provided */
67
+ net?: number;
68
+ };
69
+ type CashflowChartProps = {
70
+ data: CashflowChartDataItem[];
71
+ title?: string;
72
+ height?: number;
73
+ /** Currency or unit for tooltip (e.g. "£", "$") */
74
+ currency?: string;
75
+ };
76
+ declare function CashflowChart({ data, title, height, currency, }: CashflowChartProps): react_jsx_runtime.JSX.Element;
77
+
78
+ export { type AreaChartDataItem, type BarChartDataItem, CashflowChart, type CashflowChartDataItem, type CashflowChartProps, ChartContainer, type ChartContainerProps, type PieChartDataItem, SharedAreaChart, type SharedAreaChartProps, SharedBarChart, type SharedBarChartProps, SharedPieChart, type SharedPieChartProps };
@@ -0,0 +1,388 @@
1
+ import { cva } from 'class-variance-authority';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+ import { ResponsiveContainer, PieChart, Pie, Cell, Tooltip, Legend, BarChart, CartesianGrid, XAxis, YAxis, ReferenceLine, Bar, AreaChart, Area } from 'recharts';
6
+
7
+ // src/surface/Surface.tsx
8
+ function cn(...inputs) {
9
+ return twMerge(clsx(inputs));
10
+ }
11
+ var surfaceVariants = cva(
12
+ "rounded-xl border border-border bg-card text-card-foreground shadow-sm",
13
+ {
14
+ variants: {
15
+ padding: {
16
+ none: "p-0",
17
+ sm: "p-4",
18
+ md: "p-6"
19
+ }
20
+ },
21
+ defaultVariants: {
22
+ padding: "none"
23
+ }
24
+ }
25
+ );
26
+ function Surface({ className, padding, ...props }) {
27
+ return /* @__PURE__ */ jsx(
28
+ "div",
29
+ {
30
+ "data-slot": "surface",
31
+ className: cn(surfaceVariants({ padding }), className),
32
+ ...props
33
+ }
34
+ );
35
+ }
36
+ function ChartContainer({
37
+ title,
38
+ className = "",
39
+ height = 280,
40
+ children
41
+ }) {
42
+ return /* @__PURE__ */ jsxs(Surface, { className: cn("flex flex-col overflow-hidden", className), children: [
43
+ title ? /* @__PURE__ */ jsx("div", { className: "px-6 pb-2 pt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: title }) }) : null,
44
+ /* @__PURE__ */ jsx("div", { className: "flex-1 px-4 pb-4", style: { minHeight: height }, children })
45
+ ] });
46
+ }
47
+ var AUDERE_CHART_COLORS = [
48
+ "#0f172a",
49
+ // navy900
50
+ "#14b8a6",
51
+ // teal500
52
+ "#64748b",
53
+ // slate-500
54
+ "#0d9488",
55
+ // teal-600
56
+ "#94a3b8",
57
+ // slate-400
58
+ "#2dd4bf"
59
+ // teal-400
60
+ ];
61
+ function SharedPieChart({
62
+ data,
63
+ title,
64
+ height = 280,
65
+ showLegend = true,
66
+ valueLabel = "Value"
67
+ }) {
68
+ return /* @__PURE__ */ jsx(ChartContainer, { title, height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxs(PieChart, { margin: { top: 8, right: 8, bottom: 8, left: 8 }, children: [
69
+ /* @__PURE__ */ jsx(
70
+ Pie,
71
+ {
72
+ data,
73
+ cx: "50%",
74
+ cy: "50%",
75
+ innerRadius: 60,
76
+ outerRadius: 90,
77
+ paddingAngle: 2,
78
+ dataKey: "value",
79
+ nameKey: "name",
80
+ label: ({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`,
81
+ labelLine: false,
82
+ children: data.map((_, index) => /* @__PURE__ */ jsx(
83
+ Cell,
84
+ {
85
+ fill: AUDERE_CHART_COLORS[index % AUDERE_CHART_COLORS.length],
86
+ stroke: "white",
87
+ strokeWidth: 2
88
+ },
89
+ `cell-${index}`
90
+ ))
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsx(
94
+ Tooltip,
95
+ {
96
+ formatter: (value) => [value, valueLabel],
97
+ contentStyle: {
98
+ borderRadius: "8px",
99
+ border: "1px solid var(--border)",
100
+ backgroundColor: "var(--card)",
101
+ color: "var(--card-foreground)",
102
+ boxShadow: "0 1px 3px 0 rgb(15 23 42 / 0.08)",
103
+ fontSize: "12px"
104
+ },
105
+ labelStyle: { color: "var(--foreground)", fontWeight: 600 }
106
+ }
107
+ ),
108
+ showLegend && /* @__PURE__ */ jsx(
109
+ Legend,
110
+ {
111
+ verticalAlign: "bottom",
112
+ height: 36,
113
+ formatter: (value, entry) => /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
114
+ value,
115
+ entry?.payload?.payload?.value != null && ` (${entry.payload.payload.value})`
116
+ ] })
117
+ }
118
+ )
119
+ ] }) }) });
120
+ }
121
+ var DEFAULT_FILL = "#14b8a6";
122
+ function SharedBarChart({
123
+ data,
124
+ dataKey,
125
+ valueKeys = ["value"],
126
+ title,
127
+ height = 260,
128
+ referenceLine,
129
+ fill = DEFAULT_FILL
130
+ }) {
131
+ const colors = ["#14b8a6", "#0f172a", "#64748b", "#0d9488"];
132
+ return /* @__PURE__ */ jsx(ChartContainer, { title, height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxs(
133
+ BarChart,
134
+ {
135
+ data,
136
+ margin: { top: 8, right: 8, bottom: 8, left: 8 },
137
+ children: [
138
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
139
+ /* @__PURE__ */ jsx(
140
+ XAxis,
141
+ {
142
+ dataKey,
143
+ axisLine: false,
144
+ tickLine: false,
145
+ tick: { fontSize: 12, fill: "#64748b" },
146
+ dy: 8
147
+ }
148
+ ),
149
+ /* @__PURE__ */ jsx(
150
+ YAxis,
151
+ {
152
+ axisLine: false,
153
+ tickLine: false,
154
+ tick: { fontSize: 12, fill: "#64748b" },
155
+ dx: -8
156
+ }
157
+ ),
158
+ /* @__PURE__ */ jsx(
159
+ Tooltip,
160
+ {
161
+ contentStyle: {
162
+ borderRadius: "8px",
163
+ border: "1px solid var(--border)",
164
+ backgroundColor: "var(--card)",
165
+ color: "var(--card-foreground)",
166
+ boxShadow: "0 1px 3px 0 rgb(15 23 42 / 0.08)",
167
+ fontSize: "12px"
168
+ },
169
+ cursor: { fill: "var(--muted)" }
170
+ }
171
+ ),
172
+ referenceLine != null && /* @__PURE__ */ jsx(
173
+ ReferenceLine,
174
+ {
175
+ y: referenceLine.value,
176
+ stroke: "#dc2626",
177
+ strokeDasharray: "4 4",
178
+ label: {
179
+ value: referenceLine.label ?? "Target",
180
+ position: "right",
181
+ fontSize: 11,
182
+ fill: "#64748b"
183
+ }
184
+ }
185
+ ),
186
+ valueKeys.map((key, idx) => /* @__PURE__ */ jsx(
187
+ Bar,
188
+ {
189
+ dataKey: key,
190
+ fill: colors[idx % colors.length],
191
+ radius: [4, 4, 0, 0],
192
+ name: key.replace(/([A-Z])/g, " $1").trim()
193
+ },
194
+ key
195
+ ))
196
+ ]
197
+ }
198
+ ) }) });
199
+ }
200
+ var DEFAULT_FILL2 = "#0f172a";
201
+ var SECONDARY_FILL = "#14b8a6";
202
+ function SharedAreaChart({
203
+ data,
204
+ dataKey,
205
+ valueKey,
206
+ title,
207
+ height = 260,
208
+ secondaryValueKey,
209
+ fill = DEFAULT_FILL2
210
+ }) {
211
+ return /* @__PURE__ */ jsx(ChartContainer, { title, height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxs(
212
+ AreaChart,
213
+ {
214
+ data,
215
+ margin: { top: 8, right: 8, bottom: 8, left: 8 },
216
+ children: [
217
+ /* @__PURE__ */ jsxs("defs", { children: [
218
+ /* @__PURE__ */ jsxs("linearGradient", { id: "areaFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
219
+ /* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: fill, stopOpacity: 0.35 }),
220
+ /* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: fill, stopOpacity: 0 })
221
+ ] }),
222
+ secondaryValueKey && /* @__PURE__ */ jsxs("linearGradient", { id: "areaFillSecondary", x1: "0", y1: "0", x2: "0", y2: "1", children: [
223
+ /* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: SECONDARY_FILL, stopOpacity: 0.35 }),
224
+ /* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: SECONDARY_FILL, stopOpacity: 0 })
225
+ ] })
226
+ ] }),
227
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
228
+ /* @__PURE__ */ jsx(
229
+ XAxis,
230
+ {
231
+ dataKey,
232
+ axisLine: false,
233
+ tickLine: false,
234
+ tick: { fontSize: 12, fill: "#64748b" },
235
+ dy: 8
236
+ }
237
+ ),
238
+ /* @__PURE__ */ jsx(
239
+ YAxis,
240
+ {
241
+ axisLine: false,
242
+ tickLine: false,
243
+ tick: { fontSize: 12, fill: "#64748b" },
244
+ dx: -8
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsx(
248
+ Tooltip,
249
+ {
250
+ contentStyle: {
251
+ borderRadius: "8px",
252
+ border: "1px solid var(--border)",
253
+ backgroundColor: "var(--card)",
254
+ color: "var(--card-foreground)",
255
+ boxShadow: "0 1px 3px 0 rgb(15 23 42 / 0.08)",
256
+ fontSize: "12px"
257
+ }
258
+ }
259
+ ),
260
+ secondaryValueKey && /* @__PURE__ */ jsx(
261
+ Area,
262
+ {
263
+ type: "monotone",
264
+ dataKey: secondaryValueKey,
265
+ stroke: SECONDARY_FILL,
266
+ strokeWidth: 2,
267
+ fill: "url(#areaFillSecondary)"
268
+ }
269
+ ),
270
+ /* @__PURE__ */ jsx(
271
+ Area,
272
+ {
273
+ type: "monotone",
274
+ dataKey: valueKey,
275
+ stroke: fill,
276
+ strokeWidth: 2,
277
+ fill: "url(#areaFill)"
278
+ }
279
+ )
280
+ ]
281
+ }
282
+ ) }) });
283
+ }
284
+ function formatValue(value, currency = "") {
285
+ const abs = Math.abs(value);
286
+ const sign = value < 0 ? "\u2212" : "";
287
+ if (abs >= 1e6) return `${sign}${currency}${(abs / 1e6).toFixed(1)}M`;
288
+ if (abs >= 1e3) return `${sign}${currency}${(abs / 1e3).toFixed(1)}k`;
289
+ return `${sign}${currency}${abs.toLocaleString()}`;
290
+ }
291
+ function CashflowChart({
292
+ data,
293
+ title,
294
+ height = 260,
295
+ currency = "\xA3"
296
+ }) {
297
+ const series = data.map((d) => ({
298
+ ...d,
299
+ net: d.net ?? d.inflow - d.outflow
300
+ }));
301
+ return /* @__PURE__ */ jsx(ChartContainer, { title, height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxs(
302
+ AreaChart,
303
+ {
304
+ data: series,
305
+ margin: { top: 8, right: 8, bottom: 8, left: 8 },
306
+ children: [
307
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: "cashflowNet", x1: "0", y1: "0", x2: "0", y2: "1", children: [
308
+ /* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: "#14b8a6", stopOpacity: 0.4 }),
309
+ /* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: "#14b8a6", stopOpacity: 0 })
310
+ ] }) }),
311
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
312
+ /* @__PURE__ */ jsx(
313
+ XAxis,
314
+ {
315
+ dataKey: "period",
316
+ axisLine: false,
317
+ tickLine: false,
318
+ tick: { fontSize: 12, fill: "#64748b" },
319
+ dy: 8
320
+ }
321
+ ),
322
+ /* @__PURE__ */ jsx(
323
+ YAxis,
324
+ {
325
+ axisLine: false,
326
+ tickLine: false,
327
+ tick: { fontSize: 12, fill: "#64748b" },
328
+ dx: -8,
329
+ tickFormatter: (v) => formatValue(v, currency)
330
+ }
331
+ ),
332
+ /* @__PURE__ */ jsx(ReferenceLine, { y: 0, stroke: "#94a3b8", strokeDasharray: "2 2" }),
333
+ /* @__PURE__ */ jsx(
334
+ Tooltip,
335
+ {
336
+ contentStyle: {
337
+ borderRadius: "8px",
338
+ border: "1px solid #e2e8f0",
339
+ boxShadow: "0 1px 3px 0 rgb(15 23 42 / 0.08)",
340
+ fontSize: "12px"
341
+ },
342
+ formatter: (value, name) => [
343
+ formatValue(Number(value), currency),
344
+ name === "inflow" ? "Inflow" : name === "outflow" ? "Outflow" : "Net"
345
+ ],
346
+ labelFormatter: (label) => `Period: ${label}`,
347
+ content: ({ active, payload, label }) => {
348
+ if (!active || !payload?.length || !label) return null;
349
+ const row = series.find((d) => d.period === label);
350
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-card px-3 py-2 text-card-foreground shadow-sm", children: [
351
+ /* @__PURE__ */ jsx("div", { className: "mb-1.5 text-xs font-semibold", children: label }),
352
+ row && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-0.5 text-xs text-muted-foreground", children: [
353
+ /* @__PURE__ */ jsxs("span", { children: [
354
+ "Inflow: ",
355
+ formatValue(row.inflow, currency)
356
+ ] }),
357
+ /* @__PURE__ */ jsxs("span", { children: [
358
+ "Outflow: ",
359
+ formatValue(row.outflow, currency)
360
+ ] }),
361
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", children: [
362
+ "Net: ",
363
+ formatValue(row.net ?? row.inflow - row.outflow, currency)
364
+ ] })
365
+ ] })
366
+ ] });
367
+ }
368
+ }
369
+ ),
370
+ /* @__PURE__ */ jsx(
371
+ Area,
372
+ {
373
+ type: "monotone",
374
+ dataKey: "net",
375
+ stroke: "#14b8a6",
376
+ strokeWidth: 2,
377
+ fill: "url(#cashflowNet)",
378
+ name: "net"
379
+ }
380
+ )
381
+ ]
382
+ }
383
+ ) }) });
384
+ }
385
+
386
+ export { CashflowChart, ChartContainer, SharedAreaChart, SharedBarChart, SharedPieChart };
387
+ //# sourceMappingURL=index.js.map
388
+ //# sourceMappingURL=index.js.map