@mdxui/tremor 6.0.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.
Files changed (35) hide show
  1. package/README.md +255 -0
  2. package/dist/dashboard/components/index.d.ts +355 -0
  3. package/dist/dashboard/components/index.js +549 -0
  4. package/dist/dashboard/components/index.js.map +1 -0
  5. package/dist/dashboard/index.d.ts +275 -0
  6. package/dist/dashboard/index.js +1062 -0
  7. package/dist/dashboard/index.js.map +1 -0
  8. package/dist/database/index.d.ts +334 -0
  9. package/dist/database/index.js +474 -0
  10. package/dist/database/index.js.map +1 -0
  11. package/dist/index.d.ts +9 -0
  12. package/dist/index.js +1089 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/insights/components/index.d.ts +362 -0
  15. package/dist/insights/components/index.js +1397 -0
  16. package/dist/insights/components/index.js.map +1 -0
  17. package/dist/insights/index.d.ts +360 -0
  18. package/dist/insights/index.js +1815 -0
  19. package/dist/insights/index.js.map +1 -0
  20. package/dist/overview/components/index.d.ts +86 -0
  21. package/dist/overview/components/index.js +775 -0
  22. package/dist/overview/components/index.js.map +1 -0
  23. package/dist/overview/index.d.ts +301 -0
  24. package/dist/overview/index.js +1077 -0
  25. package/dist/overview/index.js.map +1 -0
  26. package/dist/shared/index.d.ts +296 -0
  27. package/dist/shared/index.js +395 -0
  28. package/dist/shared/index.js.map +1 -0
  29. package/dist/solar/components/index.d.ts +341 -0
  30. package/dist/solar/components/index.js +831 -0
  31. package/dist/solar/components/index.js.map +1 -0
  32. package/dist/solar/index.d.ts +301 -0
  33. package/dist/solar/index.js +1130 -0
  34. package/dist/solar/index.js.map +1 -0
  35. package/package.json +135 -0
@@ -0,0 +1,1815 @@
1
+ // src/insights/components/charts/area-chart.tsx
2
+ import * as React from "react";
3
+ import {
4
+ Area,
5
+ CartesianGrid,
6
+ AreaChart as RechartsAreaChart,
7
+ Legend as RechartsLegend,
8
+ ResponsiveContainer,
9
+ Tooltip,
10
+ XAxis,
11
+ YAxis
12
+ } from "recharts";
13
+ import { twMerge } from "tailwind-merge";
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ var chartColors = {
16
+ blue: "#3b82f6",
17
+ green: "#22c55e",
18
+ red: "#ef4444",
19
+ yellow: "#eab308",
20
+ purple: "#a855f7",
21
+ cyan: "#06b6d4",
22
+ orange: "#f97316",
23
+ pink: "#ec4899",
24
+ indigo: "#6366f1",
25
+ teal: "#14b8a6",
26
+ emerald: "#10b981",
27
+ gray: "#6b7280"
28
+ };
29
+ function getColor(color, index) {
30
+ if (chartColors[color]) return chartColors[color];
31
+ const defaultColors = Object.values(chartColors);
32
+ return defaultColors[index % defaultColors.length];
33
+ }
34
+ var AreaChart = React.forwardRef(
35
+ ({
36
+ data,
37
+ index,
38
+ categories,
39
+ colors,
40
+ valueFormatter,
41
+ startEndOnly = false,
42
+ showLegend = true,
43
+ showGridLines = true,
44
+ showAnimation = true,
45
+ stack = false,
46
+ curveType = "monotone",
47
+ connectNulls = false,
48
+ yAxisWidth = 56,
49
+ minValue,
50
+ maxValue,
51
+ className
52
+ }, ref) => {
53
+ const formatValue = valueFormatter || ((value) => value.toString());
54
+ return /* @__PURE__ */ jsx("div", { ref, className: twMerge("h-80 w-full", className), children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
55
+ RechartsAreaChart,
56
+ {
57
+ data,
58
+ margin: { top: 10, right: 30, left: 0, bottom: 0 },
59
+ children: [
60
+ showGridLines && /* @__PURE__ */ jsx(
61
+ CartesianGrid,
62
+ {
63
+ strokeDasharray: "3 3",
64
+ className: "stroke-gray-200 dark:stroke-gray-800",
65
+ horizontal: true,
66
+ vertical: false
67
+ }
68
+ ),
69
+ /* @__PURE__ */ jsx(
70
+ XAxis,
71
+ {
72
+ dataKey: index,
73
+ tick: { fontSize: 12 },
74
+ tickLine: false,
75
+ axisLine: false,
76
+ className: "fill-gray-500 text-xs",
77
+ tickFormatter: startEndOnly ? void 0 : void 0
78
+ }
79
+ ),
80
+ /* @__PURE__ */ jsx(
81
+ YAxis,
82
+ {
83
+ width: yAxisWidth,
84
+ tick: { fontSize: 12 },
85
+ tickLine: false,
86
+ axisLine: false,
87
+ tickFormatter: formatValue,
88
+ className: "fill-gray-500 text-xs",
89
+ domain: [minValue ?? "auto", maxValue ?? "auto"]
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsx(
93
+ Tooltip,
94
+ {
95
+ formatter: (value, name) => {
96
+ const numValue = typeof value === "number" ? value : 0;
97
+ return [formatValue(numValue), String(name)];
98
+ },
99
+ contentStyle: {
100
+ backgroundColor: "white",
101
+ border: "1px solid #e5e7eb",
102
+ borderRadius: "6px",
103
+ boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)"
104
+ }
105
+ }
106
+ ),
107
+ showLegend && /* @__PURE__ */ jsx(RechartsLegend, { verticalAlign: "top", height: 36 }),
108
+ categories.map((category, idx) => {
109
+ const color = colors?.[idx] || category;
110
+ return /* @__PURE__ */ jsx(
111
+ Area,
112
+ {
113
+ type: curveType,
114
+ dataKey: category,
115
+ stroke: getColor(color, idx),
116
+ fill: getColor(color, idx),
117
+ fillOpacity: 0.3,
118
+ strokeWidth: 2,
119
+ stackId: stack ? "stack" : void 0,
120
+ isAnimationActive: showAnimation,
121
+ connectNulls
122
+ },
123
+ category
124
+ );
125
+ })
126
+ ]
127
+ }
128
+ ) }) });
129
+ }
130
+ );
131
+ AreaChart.displayName = "AreaChart";
132
+
133
+ // src/insights/components/charts/bar-chart.tsx
134
+ import * as React2 from "react";
135
+ import {
136
+ Bar,
137
+ CartesianGrid as CartesianGrid2,
138
+ BarChart as RechartsBarChart,
139
+ Legend as RechartsLegend2,
140
+ ResponsiveContainer as ResponsiveContainer2,
141
+ Tooltip as Tooltip2,
142
+ XAxis as XAxis2,
143
+ YAxis as YAxis2
144
+ } from "recharts";
145
+ import { twMerge as twMerge2 } from "tailwind-merge";
146
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
147
+ var chartColors2 = {
148
+ blue: "#3b82f6",
149
+ green: "#22c55e",
150
+ red: "#ef4444",
151
+ yellow: "#eab308",
152
+ purple: "#a855f7",
153
+ cyan: "#06b6d4",
154
+ orange: "#f97316",
155
+ pink: "#ec4899",
156
+ indigo: "#6366f1",
157
+ teal: "#14b8a6",
158
+ emerald: "#10b981",
159
+ gray: "#6b7280"
160
+ };
161
+ function getColor2(color, index) {
162
+ if (chartColors2[color]) return chartColors2[color];
163
+ const defaultColors = Object.values(chartColors2);
164
+ return defaultColors[index % defaultColors.length];
165
+ }
166
+ var BarChart = React2.forwardRef(
167
+ ({
168
+ data,
169
+ index,
170
+ categories,
171
+ colors,
172
+ valueFormatter,
173
+ layout = "vertical",
174
+ stack = false,
175
+ relative = false,
176
+ showLegend = true,
177
+ showGridLines = true,
178
+ showAnimation = true,
179
+ yAxisWidth = 56,
180
+ barCategoryGap,
181
+ className
182
+ }, ref) => {
183
+ const formatValue = valueFormatter || ((value) => value.toString());
184
+ const rechartsLayout = layout === "horizontal" ? "vertical" : "horizontal";
185
+ return /* @__PURE__ */ jsx2("div", { ref, className: twMerge2("h-80 w-full", className), children: /* @__PURE__ */ jsx2(ResponsiveContainer2, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs2(
186
+ RechartsBarChart,
187
+ {
188
+ data,
189
+ layout: rechartsLayout,
190
+ margin: { top: 10, right: 30, left: 0, bottom: 0 },
191
+ barCategoryGap,
192
+ stackOffset: relative ? "expand" : void 0,
193
+ children: [
194
+ showGridLines && /* @__PURE__ */ jsx2(
195
+ CartesianGrid2,
196
+ {
197
+ strokeDasharray: "3 3",
198
+ className: "stroke-gray-200 dark:stroke-gray-800",
199
+ horizontal: rechartsLayout !== "vertical",
200
+ vertical: rechartsLayout === "vertical"
201
+ }
202
+ ),
203
+ rechartsLayout === "horizontal" ? /* @__PURE__ */ jsxs2(Fragment, { children: [
204
+ /* @__PURE__ */ jsx2(
205
+ XAxis2,
206
+ {
207
+ dataKey: index,
208
+ tick: { fontSize: 12 },
209
+ tickLine: false,
210
+ axisLine: false,
211
+ className: "fill-gray-500 text-xs"
212
+ }
213
+ ),
214
+ /* @__PURE__ */ jsx2(
215
+ YAxis2,
216
+ {
217
+ width: yAxisWidth,
218
+ tick: { fontSize: 12 },
219
+ tickLine: false,
220
+ axisLine: false,
221
+ tickFormatter: relative ? (value) => `${(value * 100).toFixed(0)}%` : formatValue,
222
+ className: "fill-gray-500 text-xs"
223
+ }
224
+ )
225
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
226
+ /* @__PURE__ */ jsx2(
227
+ XAxis2,
228
+ {
229
+ type: "number",
230
+ tick: { fontSize: 12 },
231
+ tickLine: false,
232
+ axisLine: false,
233
+ tickFormatter: relative ? (value) => `${(value * 100).toFixed(0)}%` : formatValue,
234
+ className: "fill-gray-500 text-xs"
235
+ }
236
+ ),
237
+ /* @__PURE__ */ jsx2(
238
+ YAxis2,
239
+ {
240
+ type: "category",
241
+ dataKey: index,
242
+ width: yAxisWidth,
243
+ tick: { fontSize: 12 },
244
+ tickLine: false,
245
+ axisLine: false,
246
+ className: "fill-gray-500 text-xs"
247
+ }
248
+ )
249
+ ] }),
250
+ /* @__PURE__ */ jsx2(
251
+ Tooltip2,
252
+ {
253
+ formatter: (value, name) => {
254
+ const numValue = typeof value === "number" ? value : 0;
255
+ return [
256
+ relative ? `${(numValue * 100).toFixed(1)}%` : formatValue(numValue),
257
+ String(name)
258
+ ];
259
+ },
260
+ contentStyle: {
261
+ backgroundColor: "white",
262
+ border: "1px solid #e5e7eb",
263
+ borderRadius: "6px",
264
+ boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)"
265
+ }
266
+ }
267
+ ),
268
+ showLegend && /* @__PURE__ */ jsx2(RechartsLegend2, { verticalAlign: "top", height: 36 }),
269
+ categories.map((category, idx) => {
270
+ const color = colors?.[idx] || category;
271
+ return /* @__PURE__ */ jsx2(
272
+ Bar,
273
+ {
274
+ dataKey: category,
275
+ fill: getColor2(color, idx),
276
+ stackId: stack || relative ? "stack" : void 0,
277
+ isAnimationActive: showAnimation,
278
+ radius: [4, 4, 0, 0]
279
+ },
280
+ category
281
+ );
282
+ })
283
+ ]
284
+ }
285
+ ) }) });
286
+ }
287
+ );
288
+ BarChart.displayName = "BarChart";
289
+
290
+ // src/insights/components/charts/bar-chart-variant.tsx
291
+ import * as React3 from "react";
292
+ import {
293
+ Bar as Bar2,
294
+ CartesianGrid as CartesianGrid3,
295
+ Label,
296
+ BarChart as RechartsBarChart2,
297
+ Legend as RechartsLegend3,
298
+ ResponsiveContainer as ResponsiveContainer3,
299
+ Tooltip as Tooltip3,
300
+ XAxis as XAxis3,
301
+ YAxis as YAxis3
302
+ } from "recharts";
303
+ import { twMerge as twMerge3 } from "tailwind-merge";
304
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
305
+ var chartColors3 = {
306
+ blue: { fill: "#3b82f6", stroke: "#2563eb" },
307
+ emerald: { fill: "#10b981", stroke: "#059669" },
308
+ violet: { fill: "#8b5cf6", stroke: "#7c3aed" },
309
+ amber: { fill: "#f59e0b", stroke: "#d97706" },
310
+ gray: { fill: "#6b7280", stroke: "#4b5563" },
311
+ cyan: { fill: "#06b6d4", stroke: "#0891b2" },
312
+ pink: { fill: "#ec4899", stroke: "#db2777" },
313
+ lime: { fill: "#84cc16", stroke: "#65a30d" },
314
+ fuchsia: { fill: "#d946ef", stroke: "#c026d3" },
315
+ orange: { fill: "#f97316", stroke: "#ea580c" }
316
+ };
317
+ function getColor3(color, index) {
318
+ if (chartColors3[color]) return chartColors3[color];
319
+ const defaultColors = Object.values(chartColors3);
320
+ return defaultColors[index % defaultColors.length];
321
+ }
322
+ var renderShape = (props, activeBar, activeLegend, strokeColor, layout) => {
323
+ const { name, payload, value } = props;
324
+ let { x, width, y, height } = props;
325
+ let lineX1, lineY1, lineX2, lineY2;
326
+ if (layout === "horizontal" && height < 0) {
327
+ y += height;
328
+ height = Math.abs(height);
329
+ } else if (layout === "vertical" && width < 0) {
330
+ x += width;
331
+ width = Math.abs(width);
332
+ }
333
+ if (layout === "horizontal") {
334
+ lineX1 = x;
335
+ lineY1 = y;
336
+ lineX2 = x + width;
337
+ lineY2 = y;
338
+ } else {
339
+ lineX1 = x + width;
340
+ lineY1 = y;
341
+ lineX2 = x + width;
342
+ lineY2 = y + height;
343
+ }
344
+ const isActive = activeBar && activeBar.value === value && JSON.stringify(activeBar.payload) === JSON.stringify(payload);
345
+ const opacity = activeBar || activeLegend && activeLegend !== name ? isActive ? 0.2 : 0.1 : 0.2;
346
+ const lineOpacity = activeBar || activeLegend && activeLegend !== name ? isActive ? 1 : 0.5 : 1;
347
+ return /* @__PURE__ */ jsxs3("g", { children: [
348
+ /* @__PURE__ */ jsx3(
349
+ "rect",
350
+ {
351
+ x,
352
+ y,
353
+ width,
354
+ height,
355
+ fill: "currentColor",
356
+ opacity
357
+ }
358
+ ),
359
+ /* @__PURE__ */ jsx3(
360
+ "line",
361
+ {
362
+ x1: lineX1,
363
+ y1: lineY1,
364
+ x2: lineX2,
365
+ y2: lineY2,
366
+ stroke: strokeColor,
367
+ strokeWidth: "2",
368
+ opacity: lineOpacity
369
+ }
370
+ )
371
+ ] });
372
+ };
373
+ var BarChartVariant = React3.forwardRef((props, forwardedRef) => {
374
+ const {
375
+ data = [],
376
+ categories = [],
377
+ index,
378
+ colors = ["blue", "emerald", "violet", "amber"],
379
+ valueFormatter = (value) => value.toString(),
380
+ xValueFormatter = (value) => value.toString(),
381
+ showXAxis = true,
382
+ showYAxis = true,
383
+ showGridLines = true,
384
+ yAxisWidth = 56,
385
+ showTooltip = true,
386
+ showLegend = true,
387
+ autoMinValue = false,
388
+ minValue,
389
+ maxValue,
390
+ allowDecimals = true,
391
+ barCategoryGap = "2%",
392
+ xAxisLabel,
393
+ yAxisLabel,
394
+ type = "default",
395
+ legendPosition = "right",
396
+ layout = "horizontal",
397
+ className,
398
+ onValueChange,
399
+ syncId,
400
+ ...other
401
+ } = props;
402
+ const [legendHeight] = React3.useState(60);
403
+ const [activeLegend, setActiveLegend] = React3.useState(
404
+ void 0
405
+ );
406
+ const [activeBar, setActiveBar] = React3.useState(void 0);
407
+ const stacked = type === "stacked" || type === "percent";
408
+ const getYAxisDomain = () => {
409
+ const min = autoMinValue ? "auto" : minValue ?? 0;
410
+ const max = maxValue ?? "auto";
411
+ return [min, max];
412
+ };
413
+ const yAxisDomain = getYAxisDomain();
414
+ function valueToPercent(value) {
415
+ return `${(value * 100).toFixed(0)}%`;
416
+ }
417
+ function onBarClick(barData) {
418
+ if (!onValueChange) return;
419
+ if (activeBar && JSON.stringify(activeBar) === JSON.stringify(barData)) {
420
+ setActiveLegend(void 0);
421
+ setActiveBar(void 0);
422
+ onValueChange(null);
423
+ } else {
424
+ setActiveBar(barData);
425
+ onValueChange(barData);
426
+ }
427
+ }
428
+ return /* @__PURE__ */ jsx3(
429
+ "div",
430
+ {
431
+ ref: forwardedRef,
432
+ className: twMerge3("h-80 w-full", className),
433
+ ...other,
434
+ children: /* @__PURE__ */ jsx3(ResponsiveContainer3, { children: /* @__PURE__ */ jsxs3(
435
+ RechartsBarChart2,
436
+ {
437
+ data,
438
+ margin: {
439
+ bottom: xAxisLabel ? 30 : void 0,
440
+ left: yAxisLabel ? 20 : void 0,
441
+ right: yAxisLabel ? 5 : void 0,
442
+ top: 10
443
+ },
444
+ stackOffset: type === "percent" ? "expand" : void 0,
445
+ layout,
446
+ barCategoryGap,
447
+ syncId,
448
+ children: [
449
+ showGridLines && /* @__PURE__ */ jsx3(
450
+ CartesianGrid3,
451
+ {
452
+ className: "stroke-gray-100 stroke-1 dark:stroke-gray-900",
453
+ horizontal: layout !== "vertical",
454
+ vertical: layout === "vertical"
455
+ }
456
+ ),
457
+ /* @__PURE__ */ jsx3(
458
+ XAxis3,
459
+ {
460
+ hide: !showXAxis,
461
+ tick: {
462
+ transform: layout !== "vertical" ? "translate(0, 6)" : void 0
463
+ },
464
+ fill: "",
465
+ stroke: "",
466
+ className: "text-xs fill-gray-500 dark:fill-gray-500",
467
+ tickLine: false,
468
+ axisLine: false,
469
+ minTickGap: 5,
470
+ tickFormatter: xValueFormatter,
471
+ ...layout !== "vertical" ? {
472
+ dataKey: index
473
+ } : {
474
+ type: "number",
475
+ domain: yAxisDomain,
476
+ tickFormatter: type === "percent" ? valueToPercent : valueFormatter,
477
+ allowDecimals
478
+ },
479
+ children: xAxisLabel && /* @__PURE__ */ jsx3(
480
+ Label,
481
+ {
482
+ position: "insideBottom",
483
+ offset: -20,
484
+ className: "fill-gray-800 text-sm font-medium dark:fill-gray-200",
485
+ children: xAxisLabel
486
+ }
487
+ )
488
+ }
489
+ ),
490
+ /* @__PURE__ */ jsx3(
491
+ YAxis3,
492
+ {
493
+ width: yAxisWidth,
494
+ hide: !showYAxis,
495
+ axisLine: false,
496
+ tickLine: layout === "horizontal",
497
+ tickSize: 6,
498
+ fill: "",
499
+ stroke: "",
500
+ className: "text-xs fill-gray-500 stroke-gray-800 dark:fill-gray-500 dark:stroke-gray-300",
501
+ tick: {
502
+ transform: layout !== "vertical" ? "translate(-3, 0)" : "translate(0, 0)"
503
+ },
504
+ ...layout !== "vertical" ? {
505
+ type: "number",
506
+ domain: yAxisDomain,
507
+ tickFormatter: type === "percent" ? valueToPercent : valueFormatter,
508
+ allowDecimals
509
+ } : {
510
+ dataKey: index,
511
+ type: "category",
512
+ interval: "equidistantPreserveStart"
513
+ },
514
+ children: yAxisLabel && /* @__PURE__ */ jsx3(
515
+ Label,
516
+ {
517
+ position: "insideLeft",
518
+ style: { textAnchor: "middle" },
519
+ angle: -90,
520
+ offset: -15,
521
+ className: "fill-gray-800 text-sm font-medium dark:fill-gray-200",
522
+ children: yAxisLabel
523
+ }
524
+ )
525
+ }
526
+ ),
527
+ /* @__PURE__ */ jsx3(
528
+ Tooltip3,
529
+ {
530
+ wrapperStyle: { outline: "none" },
531
+ isAnimationActive: true,
532
+ animationDuration: 100,
533
+ cursor: { fill: "#d1d5db", opacity: "0.15" },
534
+ offset: 20,
535
+ position: {
536
+ y: layout === "horizontal" ? 0 : void 0,
537
+ x: layout === "horizontal" ? void 0 : yAxisWidth + 20
538
+ },
539
+ content: showTooltip ? ({ active, payload, label }) => {
540
+ if (active && payload && payload.length) {
541
+ return /* @__PURE__ */ jsxs3("div", { className: "w-44 rounded-md border border-gray-200 bg-white text-sm shadow-md dark:border-gray-800 dark:bg-gray-950", children: [
542
+ /* @__PURE__ */ jsx3("div", { className: "border-b border-inherit p-2", children: /* @__PURE__ */ jsx3("p", { className: "font-medium text-gray-900 dark:text-gray-50", children: xValueFormatter ? xValueFormatter(label) : label }) }),
543
+ /* @__PURE__ */ jsx3("div", { className: "space-y-1 p-2", children: payload.map(
544
+ (item, idx) => /* @__PURE__ */ jsxs3(
545
+ "div",
546
+ {
547
+ className: "flex items-center justify-between space-x-4",
548
+ children: [
549
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center space-x-2", children: [
550
+ /* @__PURE__ */ jsx3(
551
+ "span",
552
+ {
553
+ className: "size-2.5 shrink-0 rounded-sm",
554
+ style: {
555
+ backgroundColor: getColor3(
556
+ colors[idx] || "gray",
557
+ idx
558
+ ).fill
559
+ },
560
+ "aria-hidden": "true"
561
+ }
562
+ ),
563
+ /* @__PURE__ */ jsx3("p", { className: "whitespace-nowrap text-right text-gray-700 dark:text-gray-300", children: item.dataKey })
564
+ ] }),
565
+ /* @__PURE__ */ jsx3("p", { className: "whitespace-nowrap text-right font-medium tabular-nums text-gray-900 dark:text-gray-50", children: valueFormatter(item.value) })
566
+ ]
567
+ },
568
+ idx.toString()
569
+ )
570
+ ) })
571
+ ] });
572
+ }
573
+ return null;
574
+ } : () => null
575
+ }
576
+ ),
577
+ showLegend && /* @__PURE__ */ jsx3(RechartsLegend3, { verticalAlign: "top", height: legendHeight }),
578
+ categories.map((category, idx) => {
579
+ const colorConfig = getColor3(colors[idx] || "gray", idx);
580
+ return /* @__PURE__ */ jsx3(
581
+ Bar2,
582
+ {
583
+ name: category,
584
+ dataKey: category,
585
+ stackId: stacked ? "stack" : void 0,
586
+ isAnimationActive: false,
587
+ fill: colorConfig.fill,
588
+ className: onValueChange ? "cursor-pointer" : "",
589
+ shape: (shapeProps) => renderShape(
590
+ shapeProps,
591
+ activeBar,
592
+ activeLegend,
593
+ colorConfig.stroke,
594
+ layout
595
+ ),
596
+ onClick: (barData) => onBarClick(barData)
597
+ },
598
+ category
599
+ );
600
+ })
601
+ ]
602
+ }
603
+ ) })
604
+ }
605
+ );
606
+ });
607
+ BarChartVariant.displayName = "BarChartVariant";
608
+
609
+ // src/insights/components/charts/donut-chart.tsx
610
+ import * as React4 from "react";
611
+ import {
612
+ Cell,
613
+ Pie,
614
+ Legend as RechartsLegend4,
615
+ PieChart as RechartsPieChart,
616
+ ResponsiveContainer as ResponsiveContainer4,
617
+ Tooltip as Tooltip4
618
+ } from "recharts";
619
+ import { twMerge as twMerge4 } from "tailwind-merge";
620
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
621
+ var chartColors4 = {
622
+ blue: "#3b82f6",
623
+ green: "#22c55e",
624
+ red: "#ef4444",
625
+ yellow: "#eab308",
626
+ purple: "#a855f7",
627
+ cyan: "#06b6d4",
628
+ orange: "#f97316",
629
+ pink: "#ec4899",
630
+ indigo: "#6366f1",
631
+ teal: "#14b8a6",
632
+ emerald: "#10b981",
633
+ gray: "#6b7280"
634
+ };
635
+ function getColor4(color, index) {
636
+ if (color && chartColors4[color]) return chartColors4[color];
637
+ if (color && color.startsWith("#")) return color;
638
+ const defaultColors = Object.values(chartColors4);
639
+ return defaultColors[index % defaultColors.length];
640
+ }
641
+ var DonutChart = React4.forwardRef(
642
+ ({
643
+ data,
644
+ category,
645
+ value,
646
+ colors,
647
+ variant = "donut",
648
+ label,
649
+ showLegend = true,
650
+ showTooltip = true,
651
+ animationDuration = 500,
652
+ valueFormatter,
653
+ className
654
+ }, ref) => {
655
+ const formatValue = valueFormatter || ((val) => val.toString());
656
+ const innerRadius = variant === "donut" ? "60%" : 0;
657
+ return /* @__PURE__ */ jsx4("div", { ref, className: twMerge4("h-80 w-full", className), children: /* @__PURE__ */ jsx4(ResponsiveContainer4, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs4(RechartsPieChart, { children: [
658
+ /* @__PURE__ */ jsx4(
659
+ Pie,
660
+ {
661
+ data,
662
+ dataKey: value,
663
+ nameKey: category,
664
+ cx: "50%",
665
+ cy: "50%",
666
+ innerRadius,
667
+ outerRadius: "80%",
668
+ paddingAngle: 2,
669
+ isAnimationActive: animationDuration > 0,
670
+ animationDuration,
671
+ label: label ? false : void 0,
672
+ children: data.map((entry, index) => {
673
+ const entryColor = entry.color || colors?.[index];
674
+ return /* @__PURE__ */ jsx4(
675
+ Cell,
676
+ {
677
+ fill: getColor4(entryColor, index),
678
+ strokeWidth: 0
679
+ },
680
+ `cell-${index.toString()}`
681
+ );
682
+ })
683
+ }
684
+ ),
685
+ showTooltip && /* @__PURE__ */ jsx4(
686
+ Tooltip4,
687
+ {
688
+ formatter: (val, name) => {
689
+ const numValue = typeof val === "number" ? val : 0;
690
+ return [formatValue(numValue), String(name)];
691
+ },
692
+ contentStyle: {
693
+ backgroundColor: "white",
694
+ border: "1px solid #e5e7eb",
695
+ borderRadius: "6px",
696
+ boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)"
697
+ }
698
+ }
699
+ ),
700
+ showLegend && /* @__PURE__ */ jsx4(RechartsLegend4, { verticalAlign: "bottom", height: 36 }),
701
+ label && variant === "donut" && /* @__PURE__ */ jsx4(
702
+ "text",
703
+ {
704
+ x: "50%",
705
+ y: "50%",
706
+ textAnchor: "middle",
707
+ dominantBaseline: "middle",
708
+ className: "fill-gray-900 text-lg font-semibold dark:fill-gray-50",
709
+ children: label
710
+ }
711
+ )
712
+ ] }) }) });
713
+ }
714
+ );
715
+ DonutChart.displayName = "DonutChart";
716
+
717
+ // src/insights/components/charts/transaction-chart.tsx
718
+ import * as React5 from "react";
719
+ import { twMerge as twMerge5 } from "tailwind-merge";
720
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
721
+ var InfoIcon = ({ className }) => /* @__PURE__ */ jsx5(
722
+ "svg",
723
+ {
724
+ xmlns: "http://www.w3.org/2000/svg",
725
+ fill: "none",
726
+ viewBox: "0 0 24 24",
727
+ strokeWidth: 1.5,
728
+ stroke: "currentColor",
729
+ className,
730
+ "aria-hidden": "true",
731
+ children: /* @__PURE__ */ jsx5(
732
+ "path",
733
+ {
734
+ strokeLinecap: "round",
735
+ strokeLinejoin: "round",
736
+ d: "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"
737
+ }
738
+ )
739
+ }
740
+ );
741
+ function formatCurrency(value, maxFractionDigits = 0) {
742
+ return new Intl.NumberFormat("en-US", {
743
+ style: "currency",
744
+ currency: "USD",
745
+ maximumFractionDigits: maxFractionDigits
746
+ }).format(value);
747
+ }
748
+ function formatNumber(value) {
749
+ return new Intl.NumberFormat("en-US").format(value);
750
+ }
751
+ var chartConfigs = {
752
+ amount: {
753
+ title: "Total Transaction Amount",
754
+ tooltipContent: "Total amount of transactions for the selected period and amount range.",
755
+ color: "blue",
756
+ valueFormatter: (number) => formatCurrency(number),
757
+ xValueFormatter: (dateString) => {
758
+ const date = new Date(dateString);
759
+ return date.toLocaleDateString("en-GB", {
760
+ day: "2-digit",
761
+ month: "2-digit",
762
+ year: "2-digit"
763
+ });
764
+ }
765
+ },
766
+ count: {
767
+ title: "Transaction Count",
768
+ tooltipContent: "Total number of transactions for the selected period and amount range.",
769
+ color: "blue",
770
+ valueFormatter: (number) => formatNumber(number),
771
+ xValueFormatter: (dateString) => {
772
+ const date = new Date(dateString);
773
+ return date.toLocaleDateString("en-GB", {
774
+ day: "2-digit",
775
+ month: "2-digit",
776
+ year: "2-digit"
777
+ });
778
+ }
779
+ },
780
+ category: {
781
+ title: "Top 5 Categories by Transaction Amount",
782
+ tooltipContent: "Total amount of transactions for the top 5 categories in the selected period and amount range.",
783
+ valueFormatter: (number) => formatCurrency(number),
784
+ layout: "vertical",
785
+ color: "emerald"
786
+ },
787
+ merchant: {
788
+ title: "Top 5 Merchants by Transaction Amount",
789
+ tooltipContent: "Total amount of transactions for the top 5 merchants in the selected period and amount range.",
790
+ valueFormatter: (number) => formatCurrency(number),
791
+ layout: "vertical",
792
+ color: "orange"
793
+ }
794
+ };
795
+ var TransactionChart = React5.forwardRef(
796
+ ({
797
+ type,
798
+ data,
799
+ yAxisWidth,
800
+ showYAxis = true,
801
+ title,
802
+ tooltipContent,
803
+ className,
804
+ ...other
805
+ }, ref) => {
806
+ const config = chartConfigs[type];
807
+ const chartTitle = title || config.title;
808
+ const chartTooltip = tooltipContent || config.tooltipContent;
809
+ const totalValue = React5.useMemo(
810
+ () => Math.round(data.reduce((sum, item) => sum + item.value, 0)),
811
+ [data]
812
+ );
813
+ return /* @__PURE__ */ jsxs5("div", { ref, className: twMerge5("w-full", className), ...other, children: [
814
+ /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs5("div", { className: "flex gap-2", children: [
815
+ /* @__PURE__ */ jsx5(
816
+ "h2",
817
+ {
818
+ id: `${type}-chart-title`,
819
+ className: "text-sm text-gray-600 dark:text-gray-400",
820
+ children: chartTitle
821
+ }
822
+ ),
823
+ /* @__PURE__ */ jsx5(
824
+ "button",
825
+ {
826
+ type: "button",
827
+ className: "inline-flex items-center",
828
+ title: chartTooltip,
829
+ children: /* @__PURE__ */ jsx5(InfoIcon, { className: "size-4 text-gray-600 dark:text-gray-400" })
830
+ }
831
+ )
832
+ ] }) }),
833
+ /* @__PURE__ */ jsx5(
834
+ "p",
835
+ {
836
+ className: "mt-2 text-2xl font-semibold text-gray-900 dark:text-gray-50",
837
+ "aria-live": "polite",
838
+ children: config.valueFormatter(totalValue)
839
+ }
840
+ ),
841
+ /* @__PURE__ */ jsx5(
842
+ BarChartVariant,
843
+ {
844
+ data,
845
+ index: "key",
846
+ categories: ["value"],
847
+ showLegend: false,
848
+ colors: [config.color],
849
+ yAxisWidth,
850
+ valueFormatter: config.valueFormatter,
851
+ xValueFormatter: config.xValueFormatter,
852
+ showYAxis,
853
+ className: "mt-6 h-48",
854
+ layout: config.layout,
855
+ barCategoryGap: "6%",
856
+ "aria-labelledby": `${type}-chart-title`,
857
+ role: "figure",
858
+ "aria-roledescription": "chart"
859
+ }
860
+ )
861
+ ] });
862
+ }
863
+ );
864
+ TransactionChart.displayName = "TransactionChart";
865
+
866
+ // src/insights/components/kpi/kpi-card.tsx
867
+ import { twMerge as twMerge6 } from "tailwind-merge";
868
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
869
+ var icons = {
870
+ users: ({ className }) => /* @__PURE__ */ jsx6(
871
+ "svg",
872
+ {
873
+ className,
874
+ fill: "none",
875
+ viewBox: "0 0 24 24",
876
+ stroke: "currentColor",
877
+ strokeWidth: 1.5,
878
+ children: /* @__PURE__ */ jsx6(
879
+ "path",
880
+ {
881
+ strokeLinecap: "round",
882
+ strokeLinejoin: "round",
883
+ d: "M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"
884
+ }
885
+ )
886
+ }
887
+ ),
888
+ revenue: ({ className }) => /* @__PURE__ */ jsx6(
889
+ "svg",
890
+ {
891
+ className,
892
+ fill: "none",
893
+ viewBox: "0 0 24 24",
894
+ stroke: "currentColor",
895
+ strokeWidth: 1.5,
896
+ children: /* @__PURE__ */ jsx6(
897
+ "path",
898
+ {
899
+ strokeLinecap: "round",
900
+ strokeLinejoin: "round",
901
+ d: "M12 6v12m-3-2.818l.879.659c1.171.879 3.07.879 4.242 0 1.172-.879 1.172-2.303 0-3.182C13.536 12.219 12.768 12 12 12c-.725 0-1.45-.22-2.003-.659-1.106-.879-1.106-2.303 0-3.182s2.9-.879 4.006 0l.415.33M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
902
+ }
903
+ )
904
+ }
905
+ ),
906
+ chart: ({ className }) => /* @__PURE__ */ jsx6(
907
+ "svg",
908
+ {
909
+ className,
910
+ fill: "none",
911
+ viewBox: "0 0 24 24",
912
+ stroke: "currentColor",
913
+ strokeWidth: 1.5,
914
+ children: /* @__PURE__ */ jsx6(
915
+ "path",
916
+ {
917
+ strokeLinecap: "round",
918
+ strokeLinejoin: "round",
919
+ d: "M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"
920
+ }
921
+ )
922
+ }
923
+ )
924
+ };
925
+ function getTrendColorClass(trend) {
926
+ switch (trend) {
927
+ case "up":
928
+ return "text-emerald-500";
929
+ case "down":
930
+ return "text-red-500";
931
+ case "neutral":
932
+ default:
933
+ return "text-gray-500";
934
+ }
935
+ }
936
+ function formatChange(change) {
937
+ if (change === void 0) return "";
938
+ const sign = change > 0 ? "+" : "";
939
+ return `${sign}${change}%`;
940
+ }
941
+ function getVariantClasses(variant) {
942
+ switch (variant) {
943
+ case "outlined":
944
+ return "border border-gray-200 dark:border-gray-800";
945
+ case "elevated":
946
+ return "shadow-lg";
947
+ case "ghost":
948
+ return "bg-transparent";
949
+ default:
950
+ return "";
951
+ }
952
+ }
953
+ function KPICard({
954
+ label,
955
+ value,
956
+ previousValue,
957
+ change,
958
+ trend,
959
+ prefix = "",
960
+ suffix = "",
961
+ target,
962
+ format: _format = "number",
963
+ icon,
964
+ title: _title,
965
+ description: _description,
966
+ size: _size,
967
+ variant = "default",
968
+ loading = false,
969
+ error,
970
+ className
971
+ }) {
972
+ const displayValue = typeof value === "number" ? String(value) : value;
973
+ const formattedValue = `${prefix}${displayValue}${suffix}`;
974
+ const IconComponent = icon ? icons[icon] : null;
975
+ if (loading) {
976
+ return /* @__PURE__ */ jsx6(
977
+ "div",
978
+ {
979
+ "data-testid": "kpi-skeleton",
980
+ className: twMerge6(
981
+ "relative w-full rounded-lg border p-6 text-left",
982
+ "bg-white dark:bg-gray-950",
983
+ "border-gray-200 dark:border-gray-900",
984
+ getVariantClasses(variant),
985
+ className
986
+ ),
987
+ "aria-busy": "true",
988
+ "aria-label": `Loading ${label}`,
989
+ children: /* @__PURE__ */ jsxs6("div", { className: "animate-pulse", children: [
990
+ /* @__PURE__ */ jsx6("div", { className: "h-4 w-24 bg-gray-200 dark:bg-gray-800 rounded mb-3" }),
991
+ /* @__PURE__ */ jsx6("div", { className: "h-8 w-32 bg-gray-200 dark:bg-gray-800 rounded mb-2" }),
992
+ /* @__PURE__ */ jsx6("div", { className: "h-4 w-16 bg-gray-200 dark:bg-gray-800 rounded" })
993
+ ] })
994
+ }
995
+ );
996
+ }
997
+ return /* @__PURE__ */ jsxs6(
998
+ "div",
999
+ {
1000
+ "data-testid": "kpi-card",
1001
+ className: twMerge6(
1002
+ "relative w-full rounded-lg border p-6 text-left shadow-sm",
1003
+ "bg-white dark:bg-gray-950",
1004
+ "border-gray-200 dark:border-gray-900",
1005
+ getVariantClasses(variant),
1006
+ className
1007
+ ),
1008
+ "aria-label": `${label}: ${formattedValue}`,
1009
+ children: [
1010
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
1011
+ IconComponent && /* @__PURE__ */ jsx6("div", { "data-testid": "kpi-icon", className: "flex-shrink-0", children: /* @__PURE__ */ jsx6(IconComponent, { className: "h-5 w-5 text-gray-500 dark:text-gray-400" }) }),
1012
+ /* @__PURE__ */ jsx6("h3", { className: "text-sm font-medium text-gray-500 dark:text-gray-400", children: label })
1013
+ ] }),
1014
+ /* @__PURE__ */ jsx6("p", { className: "mt-2 text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50", children: formattedValue }),
1015
+ (trend || change !== void 0) && /* @__PURE__ */ jsxs6("div", { className: "mt-2 flex items-center gap-2", children: [
1016
+ /* @__PURE__ */ jsxs6(
1017
+ "span",
1018
+ {
1019
+ "data-testid": "trend-indicator",
1020
+ className: twMerge6(
1021
+ "inline-flex items-center text-sm font-medium",
1022
+ getTrendColorClass(trend)
1023
+ ),
1024
+ children: [
1025
+ trend === "up" && /* @__PURE__ */ jsx6(
1026
+ "svg",
1027
+ {
1028
+ className: "h-4 w-4 mr-0.5",
1029
+ fill: "none",
1030
+ viewBox: "0 0 24 24",
1031
+ stroke: "currentColor",
1032
+ strokeWidth: 2,
1033
+ children: /* @__PURE__ */ jsx6(
1034
+ "path",
1035
+ {
1036
+ strokeLinecap: "round",
1037
+ strokeLinejoin: "round",
1038
+ d: "M7 11l5-5m0 0l5 5m-5-5v12"
1039
+ }
1040
+ )
1041
+ }
1042
+ ),
1043
+ trend === "down" && /* @__PURE__ */ jsx6(
1044
+ "svg",
1045
+ {
1046
+ className: "h-4 w-4 mr-0.5",
1047
+ fill: "none",
1048
+ viewBox: "0 0 24 24",
1049
+ stroke: "currentColor",
1050
+ strokeWidth: 2,
1051
+ children: /* @__PURE__ */ jsx6(
1052
+ "path",
1053
+ {
1054
+ strokeLinecap: "round",
1055
+ strokeLinejoin: "round",
1056
+ d: "M17 13l-5 5m0 0l-5-5m5 5V6"
1057
+ }
1058
+ )
1059
+ }
1060
+ ),
1061
+ formatChange(change)
1062
+ ]
1063
+ }
1064
+ ),
1065
+ previousValue !== void 0 && /* @__PURE__ */ jsxs6("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: [
1066
+ "from ",
1067
+ previousValue
1068
+ ] })
1069
+ ] }),
1070
+ target !== void 0 && /* @__PURE__ */ jsx6("div", { className: "mt-2", children: /* @__PURE__ */ jsxs6("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: [
1071
+ "target: ",
1072
+ target
1073
+ ] }) }),
1074
+ error && /* @__PURE__ */ jsx6("div", { className: "mt-2", children: /* @__PURE__ */ jsx6("span", { className: "text-sm text-red-500", children: error }) })
1075
+ ]
1076
+ }
1077
+ );
1078
+ }
1079
+
1080
+ // src/insights/components/tables/transactions-table.tsx
1081
+ import {
1082
+ flexRender,
1083
+ getCoreRowModel,
1084
+ getPaginationRowModel,
1085
+ getSortedRowModel,
1086
+ useReactTable
1087
+ } from "@tanstack/react-table";
1088
+ import * as React6 from "react";
1089
+ import { twMerge as twMerge7 } from "tailwind-merge";
1090
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1091
+ var statusVariants = {
1092
+ completed: "bg-emerald-50 text-emerald-900 ring-emerald-600/30 dark:bg-emerald-400/10 dark:text-emerald-400 dark:ring-emerald-400/20",
1093
+ pending: "bg-gray-50 text-gray-900 ring-gray-500/30 dark:bg-gray-400/10 dark:text-gray-400 dark:ring-gray-400/20",
1094
+ failed: "bg-rose-50 text-rose-900 ring-rose-600/20 dark:bg-rose-400/10 dark:text-rose-500 dark:ring-rose-400/20",
1095
+ refunded: "bg-orange-50 text-orange-900 ring-orange-600/30 dark:bg-orange-400/10 dark:text-orange-500 dark:ring-orange-400/20"
1096
+ };
1097
+ function StatusBadge({ status }) {
1098
+ return /* @__PURE__ */ jsx7(
1099
+ "span",
1100
+ {
1101
+ className: twMerge7(
1102
+ "inline-flex items-center gap-x-1 whitespace-nowrap rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset",
1103
+ statusVariants[status]
1104
+ ),
1105
+ children: status
1106
+ }
1107
+ );
1108
+ }
1109
+ function formatCurrency2(amount, currency = "USD") {
1110
+ const absAmount = Math.abs(amount);
1111
+ const formatted = new Intl.NumberFormat("en-US", {
1112
+ style: "currency",
1113
+ currency,
1114
+ minimumFractionDigits: 2,
1115
+ maximumFractionDigits: 2
1116
+ }).format(absAmount);
1117
+ return amount < 0 ? `-${formatted}` : formatted;
1118
+ }
1119
+ function formatDate(dateString) {
1120
+ const date = new Date(dateString);
1121
+ return date.toLocaleDateString("en-US", {
1122
+ month: "short",
1123
+ day: "numeric",
1124
+ year: "numeric"
1125
+ });
1126
+ }
1127
+ function createColumns(currency = "USD") {
1128
+ return [
1129
+ {
1130
+ accessorKey: "date",
1131
+ header: "Date",
1132
+ cell: ({ getValue }) => {
1133
+ const date = getValue();
1134
+ return /* @__PURE__ */ jsx7("span", { className: "tabular-nums text-gray-900 dark:text-gray-50", children: formatDate(date) });
1135
+ }
1136
+ },
1137
+ {
1138
+ accessorKey: "description",
1139
+ header: "Description",
1140
+ cell: ({ getValue }) => /* @__PURE__ */ jsx7("span", { className: "text-gray-700 dark:text-gray-300", children: getValue() })
1141
+ },
1142
+ {
1143
+ accessorKey: "amount",
1144
+ header: "Amount",
1145
+ cell: ({ getValue, row }) => {
1146
+ const amount = getValue();
1147
+ const isNegative = row.original.type === "debit" || amount < 0;
1148
+ const displayAmount = isNegative && amount > 0 ? -amount : amount;
1149
+ return /* @__PURE__ */ jsx7(
1150
+ "span",
1151
+ {
1152
+ className: twMerge7(
1153
+ "tabular-nums font-medium",
1154
+ isNegative ? "text-rose-600 dark:text-rose-400" : "text-gray-900 dark:text-gray-50"
1155
+ ),
1156
+ children: formatCurrency2(displayAmount, currency)
1157
+ }
1158
+ );
1159
+ },
1160
+ meta: {
1161
+ className: "text-right"
1162
+ }
1163
+ },
1164
+ {
1165
+ accessorKey: "status",
1166
+ header: "Status",
1167
+ cell: ({ getValue }) => /* @__PURE__ */ jsx7(StatusBadge, { status: getValue() })
1168
+ }
1169
+ ];
1170
+ }
1171
+ function LoadingSkeleton() {
1172
+ return /* @__PURE__ */ jsx7("div", { "data-testid": "transactions-table-loading", className: "space-y-3", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs7("div", { className: "animate-pulse flex space-x-4", children: [
1173
+ /* @__PURE__ */ jsx7("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-24" }),
1174
+ /* @__PURE__ */ jsx7("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded flex-1" }),
1175
+ /* @__PURE__ */ jsx7("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-20" }),
1176
+ /* @__PURE__ */ jsx7("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-16" })
1177
+ ] }, i)) });
1178
+ }
1179
+ function TransactionsTable(props) {
1180
+ const {
1181
+ transactions,
1182
+ title,
1183
+ currency = "USD",
1184
+ pageSize = 10,
1185
+ emptyMessage = "No transactions",
1186
+ loading = false,
1187
+ className
1188
+ } = props;
1189
+ const columns = React6.useMemo(() => createColumns(currency), [currency]);
1190
+ const table = useReactTable({
1191
+ data: transactions,
1192
+ columns,
1193
+ initialState: {
1194
+ pagination: {
1195
+ pageIndex: 0,
1196
+ pageSize
1197
+ }
1198
+ },
1199
+ getCoreRowModel: getCoreRowModel(),
1200
+ getPaginationRowModel: getPaginationRowModel(),
1201
+ getSortedRowModel: getSortedRowModel()
1202
+ });
1203
+ const totalRows = transactions.length;
1204
+ const currentPage = table.getState().pagination.pageIndex;
1205
+ const firstRowIndex = currentPage * pageSize + 1;
1206
+ const lastRowIndex = Math.min(totalRows, firstRowIndex + pageSize - 1);
1207
+ if (loading) {
1208
+ return /* @__PURE__ */ jsxs7("div", { className: twMerge7("space-y-4", className), children: [
1209
+ title && /* @__PURE__ */ jsx7("h3", { className: "text-lg font-semibold text-gray-900 dark:text-gray-50", children: title }),
1210
+ /* @__PURE__ */ jsx7(LoadingSkeleton, {})
1211
+ ] });
1212
+ }
1213
+ return /* @__PURE__ */ jsxs7("div", { className: twMerge7("space-y-4", className), children: [
1214
+ title && /* @__PURE__ */ jsx7("h3", { className: "text-lg font-semibold text-gray-900 dark:text-gray-50", children: title }),
1215
+ /* @__PURE__ */ jsx7("div", { className: "relative overflow-hidden overflow-x-auto", children: /* @__PURE__ */ jsxs7("table", { className: "w-full caption-bottom border-b border-gray-200 dark:border-gray-800", children: [
1216
+ /* @__PURE__ */ jsx7("thead", { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx7(
1217
+ "tr",
1218
+ {
1219
+ className: "border-y border-gray-200 dark:border-gray-800",
1220
+ children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx7(
1221
+ "th",
1222
+ {
1223
+ className: twMerge7(
1224
+ "border-b px-4 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-50 border-gray-200 dark:border-gray-800",
1225
+ header.column.columnDef.meta?.className
1226
+ ),
1227
+ children: flexRender(
1228
+ header.column.columnDef.header,
1229
+ header.getContext()
1230
+ )
1231
+ },
1232
+ header.id
1233
+ ))
1234
+ },
1235
+ headerGroup.id
1236
+ )) }),
1237
+ /* @__PURE__ */ jsx7("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-800", children: table.getRowModel().rows.length > 0 ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx7(
1238
+ "tr",
1239
+ {
1240
+ className: "hover:bg-gray-50 hover:dark:bg-gray-900",
1241
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx7(
1242
+ "td",
1243
+ {
1244
+ className: twMerge7(
1245
+ "p-4 text-sm text-gray-600 dark:text-gray-400",
1246
+ cell.column.columnDef.meta?.className
1247
+ ),
1248
+ children: flexRender(
1249
+ cell.column.columnDef.cell,
1250
+ cell.getContext()
1251
+ )
1252
+ },
1253
+ cell.id
1254
+ ))
1255
+ },
1256
+ row.id
1257
+ )) : /* @__PURE__ */ jsx7("tr", { children: /* @__PURE__ */ jsx7(
1258
+ "td",
1259
+ {
1260
+ colSpan: columns.length,
1261
+ className: "h-24 text-center text-sm text-gray-500 dark:text-gray-400",
1262
+ children: emptyMessage
1263
+ }
1264
+ ) }) })
1265
+ ] }) }),
1266
+ totalRows > pageSize && /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
1267
+ /* @__PURE__ */ jsxs7("div", { className: "text-sm tabular-nums text-gray-500", children: [
1268
+ "Showing ",
1269
+ firstRowIndex,
1270
+ "-",
1271
+ lastRowIndex,
1272
+ " of ",
1273
+ totalRows
1274
+ ] }),
1275
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-x-1.5", children: [
1276
+ /* @__PURE__ */ jsx7(
1277
+ "button",
1278
+ {
1279
+ onClick: () => table.setPageIndex(0),
1280
+ disabled: !table.getCanPreviousPage(),
1281
+ className: "p-1.5 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 disabled:opacity-50 disabled:cursor-not-allowed",
1282
+ "aria-label": "First page",
1283
+ children: /* @__PURE__ */ jsx7(
1284
+ "svg",
1285
+ {
1286
+ className: "size-4",
1287
+ fill: "none",
1288
+ viewBox: "0 0 24 24",
1289
+ strokeWidth: 1.5,
1290
+ stroke: "currentColor",
1291
+ children: /* @__PURE__ */ jsx7(
1292
+ "path",
1293
+ {
1294
+ strokeLinecap: "round",
1295
+ strokeLinejoin: "round",
1296
+ d: "M18.75 19.5l-7.5-7.5 7.5-7.5M11.25 19.5l-7.5-7.5 7.5-7.5"
1297
+ }
1298
+ )
1299
+ }
1300
+ )
1301
+ }
1302
+ ),
1303
+ /* @__PURE__ */ jsx7(
1304
+ "button",
1305
+ {
1306
+ onClick: () => table.previousPage(),
1307
+ disabled: !table.getCanPreviousPage(),
1308
+ className: "p-1.5 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 disabled:opacity-50 disabled:cursor-not-allowed",
1309
+ "aria-label": "Previous page",
1310
+ children: /* @__PURE__ */ jsx7(
1311
+ "svg",
1312
+ {
1313
+ className: "size-4",
1314
+ fill: "none",
1315
+ viewBox: "0 0 24 24",
1316
+ strokeWidth: 1.5,
1317
+ stroke: "currentColor",
1318
+ children: /* @__PURE__ */ jsx7(
1319
+ "path",
1320
+ {
1321
+ strokeLinecap: "round",
1322
+ strokeLinejoin: "round",
1323
+ d: "M15.75 19.5L8.25 12l7.5-7.5"
1324
+ }
1325
+ )
1326
+ }
1327
+ )
1328
+ }
1329
+ ),
1330
+ /* @__PURE__ */ jsx7(
1331
+ "button",
1332
+ {
1333
+ onClick: () => table.nextPage(),
1334
+ disabled: !table.getCanNextPage(),
1335
+ className: "p-1.5 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 disabled:opacity-50 disabled:cursor-not-allowed",
1336
+ "aria-label": "Next page",
1337
+ children: /* @__PURE__ */ jsx7(
1338
+ "svg",
1339
+ {
1340
+ className: "size-4",
1341
+ fill: "none",
1342
+ viewBox: "0 0 24 24",
1343
+ strokeWidth: 1.5,
1344
+ stroke: "currentColor",
1345
+ children: /* @__PURE__ */ jsx7(
1346
+ "path",
1347
+ {
1348
+ strokeLinecap: "round",
1349
+ strokeLinejoin: "round",
1350
+ d: "M8.25 4.5l7.5 7.5-7.5 7.5"
1351
+ }
1352
+ )
1353
+ }
1354
+ )
1355
+ }
1356
+ ),
1357
+ /* @__PURE__ */ jsx7(
1358
+ "button",
1359
+ {
1360
+ onClick: () => table.setPageIndex(table.getPageCount() - 1),
1361
+ disabled: !table.getCanNextPage(),
1362
+ className: "p-1.5 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 disabled:opacity-50 disabled:cursor-not-allowed",
1363
+ "aria-label": "Last page",
1364
+ children: /* @__PURE__ */ jsx7(
1365
+ "svg",
1366
+ {
1367
+ className: "size-4",
1368
+ fill: "none",
1369
+ viewBox: "0 0 24 24",
1370
+ strokeWidth: 1.5,
1371
+ stroke: "currentColor",
1372
+ children: /* @__PURE__ */ jsx7(
1373
+ "path",
1374
+ {
1375
+ strokeLinecap: "round",
1376
+ strokeLinejoin: "round",
1377
+ d: "M5.25 4.5l7.5 7.5-7.5 7.5M12.75 4.5l7.5 7.5-7.5 7.5"
1378
+ }
1379
+ )
1380
+ }
1381
+ )
1382
+ }
1383
+ )
1384
+ ] })
1385
+ ] })
1386
+ ] });
1387
+ }
1388
+
1389
+ // src/insights/layouts/insights-app.tsx
1390
+ import { jsx as jsx8 } from "react/jsx-runtime";
1391
+ function InsightsApp({ name, children }) {
1392
+ return /* @__PURE__ */ jsx8(
1393
+ "div",
1394
+ {
1395
+ "data-app-name": name,
1396
+ className: "min-h-screen bg-white dark:bg-gray-950",
1397
+ children
1398
+ }
1399
+ );
1400
+ }
1401
+
1402
+ // src/insights/layouts/insights-dashboard.tsx
1403
+ import { twMerge as twMerge8 } from "tailwind-merge";
1404
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1405
+ function InsightsDashboard({
1406
+ title = "Dashboard",
1407
+ description,
1408
+ metrics,
1409
+ actions,
1410
+ children,
1411
+ className
1412
+ }) {
1413
+ return /* @__PURE__ */ jsxs8("main", { className: twMerge8("", className), children: [
1414
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between", children: [
1415
+ /* @__PURE__ */ jsxs8("div", { children: [
1416
+ /* @__PURE__ */ jsx9("h1", { className: "text-2xl font-semibold text-gray-900 dark:text-gray-50", children: title }),
1417
+ description && /* @__PURE__ */ jsx9("p", { className: "text-gray-500 sm:text-sm/6 dark:text-gray-500", children: description })
1418
+ ] }),
1419
+ actions && /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2", children: actions })
1420
+ ] }),
1421
+ metrics && metrics.length > 0 && /* @__PURE__ */ jsx9("div", { className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4", children: metrics.map((metric) => /* @__PURE__ */ jsxs8(
1422
+ "div",
1423
+ {
1424
+ className: "rounded-lg border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900",
1425
+ children: [
1426
+ /* @__PURE__ */ jsx9("p", { className: "text-sm font-medium text-gray-500 dark:text-gray-400", children: metric.label }),
1427
+ /* @__PURE__ */ jsx9("p", { className: "mt-1 text-2xl font-semibold text-gray-900 dark:text-gray-50", children: metric.value }),
1428
+ metric.change !== void 0 && /* @__PURE__ */ jsxs8(
1429
+ "p",
1430
+ {
1431
+ className: twMerge8(
1432
+ "mt-1 text-sm font-medium",
1433
+ metric.trend === "up" ? "text-green-600 dark:text-green-400" : metric.trend === "down" ? "text-red-600 dark:text-red-400" : "text-gray-500 dark:text-gray-400"
1434
+ ),
1435
+ children: [
1436
+ metric.trend === "up" && "+",
1437
+ metric.change,
1438
+ "%"
1439
+ ]
1440
+ }
1441
+ )
1442
+ ]
1443
+ },
1444
+ metric.label
1445
+ )) }),
1446
+ /* @__PURE__ */ jsx9("div", { className: "my-6 border-t border-gray-200 dark:border-gray-800" }),
1447
+ children
1448
+ ] });
1449
+ }
1450
+
1451
+ // src/insights/layouts/insights-header.tsx
1452
+ import { twMerge as twMerge9 } from "tailwind-merge";
1453
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1454
+ function InsightsHeader({
1455
+ user,
1456
+ showSearch = true,
1457
+ showNotifications = true,
1458
+ breadcrumbs,
1459
+ logo,
1460
+ notifications,
1461
+ userProfile,
1462
+ className
1463
+ }) {
1464
+ return /* @__PURE__ */ jsxs9(
1465
+ "header",
1466
+ {
1467
+ className: twMerge9(
1468
+ "flex h-16 items-center justify-between border-b border-gray-200 bg-white px-4 dark:border-gray-800 dark:bg-gray-950 sm:px-6",
1469
+ className
1470
+ ),
1471
+ children: [
1472
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-4", children: [
1473
+ logo ?? /* @__PURE__ */ jsx10("div", { className: "h-6 w-20 rounded bg-gray-200 dark:bg-gray-800" }),
1474
+ breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx10("nav", { "aria-label": "Breadcrumb", className: "hidden sm:block", children: /* @__PURE__ */ jsx10("ol", { className: "flex items-center gap-2", children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsxs9("li", { className: "flex items-center gap-2", children: [
1475
+ index > 0 && /* @__PURE__ */ jsx10("span", { className: "text-gray-400 dark:text-gray-600", children: "/" }),
1476
+ crumb.href ? /* @__PURE__ */ jsx10(
1477
+ "a",
1478
+ {
1479
+ href: crumb.href,
1480
+ className: "text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300",
1481
+ children: crumb.label
1482
+ }
1483
+ ) : /* @__PURE__ */ jsx10("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: crumb.label })
1484
+ ] }, crumb.label)) }) })
1485
+ ] }),
1486
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
1487
+ showSearch && /* @__PURE__ */ jsx10(
1488
+ "button",
1489
+ {
1490
+ type: "button",
1491
+ className: "rounded-lg p-2 text-gray-500 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-300",
1492
+ "aria-label": "Search",
1493
+ children: /* @__PURE__ */ jsx10(
1494
+ "svg",
1495
+ {
1496
+ className: "h-5 w-5",
1497
+ fill: "none",
1498
+ viewBox: "0 0 24 24",
1499
+ stroke: "currentColor",
1500
+ "aria-hidden": "true",
1501
+ children: /* @__PURE__ */ jsx10(
1502
+ "path",
1503
+ {
1504
+ strokeLinecap: "round",
1505
+ strokeLinejoin: "round",
1506
+ strokeWidth: 2,
1507
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
1508
+ }
1509
+ )
1510
+ }
1511
+ )
1512
+ }
1513
+ ),
1514
+ showNotifications && (notifications ?? /* @__PURE__ */ jsx10(
1515
+ "button",
1516
+ {
1517
+ type: "button",
1518
+ className: "rounded-lg p-2 text-gray-500 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-300",
1519
+ "aria-label": "Notifications",
1520
+ children: /* @__PURE__ */ jsx10(
1521
+ "svg",
1522
+ {
1523
+ className: "h-5 w-5",
1524
+ fill: "none",
1525
+ viewBox: "0 0 24 24",
1526
+ stroke: "currentColor",
1527
+ "aria-hidden": "true",
1528
+ children: /* @__PURE__ */ jsx10(
1529
+ "path",
1530
+ {
1531
+ strokeLinecap: "round",
1532
+ strokeLinejoin: "round",
1533
+ strokeWidth: 2,
1534
+ d: "M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
1535
+ }
1536
+ )
1537
+ }
1538
+ )
1539
+ }
1540
+ )),
1541
+ userProfile ?? (user && /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-2", children: user.avatar ? /* @__PURE__ */ jsx10(
1542
+ "img",
1543
+ {
1544
+ src: user.avatar,
1545
+ alt: user.name,
1546
+ className: "h-8 w-8 rounded-full"
1547
+ }
1548
+ ) : /* @__PURE__ */ jsx10("div", { className: "flex h-8 w-8 items-center justify-center rounded-full bg-gray-200 text-sm font-medium text-gray-600 dark:bg-gray-700 dark:text-gray-300", children: user.name.charAt(0) }) }))
1549
+ ] })
1550
+ ]
1551
+ }
1552
+ );
1553
+ }
1554
+
1555
+ // src/insights/layouts/insights-settings.tsx
1556
+ import { twMerge as twMerge10 } from "tailwind-merge";
1557
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1558
+ var sectionLabels = {
1559
+ profile: "Profile",
1560
+ security: "Security",
1561
+ notifications: "Notifications",
1562
+ billing: "Billing",
1563
+ team: "Team",
1564
+ api: "API",
1565
+ integrations: "Integrations"
1566
+ };
1567
+ function InsightsSettings({
1568
+ sections = ["profile", "security", "notifications"],
1569
+ activeSection = "profile",
1570
+ children,
1571
+ className
1572
+ }) {
1573
+ return /* @__PURE__ */ jsxs10("div", { className: twMerge10("flex gap-8", className), children: [
1574
+ /* @__PURE__ */ jsx11("nav", { className: "w-48 flex-shrink-0", children: /* @__PURE__ */ jsx11("ul", { className: "space-y-1", children: sections.map((section) => /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsx11(
1575
+ "a",
1576
+ {
1577
+ href: `/settings/${section}`,
1578
+ className: twMerge10(
1579
+ "block rounded-lg px-3 py-2 text-sm font-medium transition-colors",
1580
+ section === activeSection ? "bg-gray-100 text-gray-900 dark:bg-gray-800 dark:text-gray-100" : "text-gray-600 hover:bg-gray-50 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800/50 dark:hover:text-gray-300"
1581
+ ),
1582
+ children: sectionLabels[section]
1583
+ }
1584
+ ) }, section)) }) }),
1585
+ /* @__PURE__ */ jsx11("div", { className: "flex-1", children: children ?? /* @__PURE__ */ jsxs10("div", { className: "rounded-lg border border-gray-200 bg-white p-6 dark:border-gray-800 dark:bg-gray-900", children: [
1586
+ /* @__PURE__ */ jsx11("h2", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: sectionLabels[activeSection] }),
1587
+ /* @__PURE__ */ jsxs10("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: [
1588
+ "Configure your ",
1589
+ sectionLabels[activeSection].toLowerCase(),
1590
+ " ",
1591
+ "settings."
1592
+ ] })
1593
+ ] }) })
1594
+ ] });
1595
+ }
1596
+
1597
+ // src/insights/layouts/insights-shell.tsx
1598
+ import { twMerge as twMerge11 } from "tailwind-merge";
1599
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1600
+ function InsightsShell({
1601
+ children,
1602
+ sidebar,
1603
+ header,
1604
+ collapsed = false,
1605
+ className
1606
+ }) {
1607
+ return /* @__PURE__ */ jsxs11(
1608
+ "div",
1609
+ {
1610
+ "data-insights-shell": true,
1611
+ "data-collapsed": collapsed ? "true" : "false",
1612
+ className: twMerge11("mx-auto max-w-screen-2xl", className),
1613
+ children: [
1614
+ sidebar,
1615
+ /* @__PURE__ */ jsxs11(
1616
+ "main",
1617
+ {
1618
+ className: twMerge11(
1619
+ "ease transform-gpu transition-all duration-100 will-change-transform",
1620
+ "lg:bg-gray-50 lg:py-3 lg:pr-3 lg:dark:bg-gray-950",
1621
+ collapsed ? "lg:pl-[60px]" : "lg:pl-64"
1622
+ ),
1623
+ children: [
1624
+ header,
1625
+ /* @__PURE__ */ jsx12("div", { className: "bg-white p-4 sm:p-6 lg:rounded-lg lg:border lg:border-gray-200 dark:bg-gray-925 lg:dark:border-gray-900", children })
1626
+ ]
1627
+ }
1628
+ )
1629
+ ]
1630
+ }
1631
+ );
1632
+ }
1633
+
1634
+ // src/insights/layouts/insights-sidebar.tsx
1635
+ import { twMerge as twMerge12 } from "tailwind-merge";
1636
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1637
+ function InsightsSidebar({
1638
+ items,
1639
+ footerItems,
1640
+ logo,
1641
+ collapsed = false,
1642
+ onCollapse,
1643
+ header,
1644
+ footer,
1645
+ className
1646
+ }) {
1647
+ return /* @__PURE__ */ jsx13(
1648
+ "nav",
1649
+ {
1650
+ "data-collapsed": collapsed ? "true" : "false",
1651
+ className: twMerge12(
1652
+ "hidden overflow-x-hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:flex-col",
1653
+ "ease transform-gpu transition-all duration-100 will-change-transform",
1654
+ collapsed ? "lg:w-[60px]" : "lg:w-64",
1655
+ className
1656
+ ),
1657
+ children: /* @__PURE__ */ jsxs12("aside", { className: "flex grow flex-col gap-y-4 overflow-y-auto whitespace-nowrap px-3 py-4", children: [
1658
+ header ? header : logo ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-x-1.5", children: [
1659
+ onCollapse && /* @__PURE__ */ jsx13(
1660
+ "button",
1661
+ {
1662
+ type: "button",
1663
+ className: "group inline-flex rounded-md p-2 hover:bg-gray-200/50 hover:dark:bg-gray-900",
1664
+ onClick: onCollapse,
1665
+ "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
1666
+ children: /* @__PURE__ */ jsx13("span", { className: "size-5 shrink-0 text-gray-500 group-hover:text-gray-700 dark:text-gray-500 group-hover:dark:text-gray-300", children: collapsed ? ">" : "<" })
1667
+ }
1668
+ ),
1669
+ /* @__PURE__ */ jsx13(
1670
+ "a",
1671
+ {
1672
+ href: logo.href ?? "/",
1673
+ className: twMerge12(
1674
+ "text-sm font-semibold text-gray-900 transition-opacity dark:text-gray-50",
1675
+ collapsed ? "opacity-0" : "opacity-100"
1676
+ ),
1677
+ "aria-label": "Home",
1678
+ children: /* @__PURE__ */ jsx13("img", { src: collapsed && logo.collapsedSrc ? logo.collapsedSrc : logo.src, alt: logo.alt, className: "h-8" })
1679
+ }
1680
+ )
1681
+ ] }) : null,
1682
+ /* @__PURE__ */ jsxs12("div", { className: "flex flex-1 flex-col space-y-10", children: [
1683
+ /* @__PURE__ */ jsx13("ul", { className: "mt-1 space-y-2", children: items.map((item) => /* @__PURE__ */ jsx13("li", { children: item.href ? /* @__PURE__ */ jsxs12(
1684
+ "a",
1685
+ {
1686
+ href: item.href,
1687
+ "aria-current": item.active ? "page" : void 0,
1688
+ "aria-disabled": item.disabled,
1689
+ className: twMerge12(
1690
+ "flex items-center gap-x-2.5 rounded-md p-2 text-sm font-medium transition-opacity",
1691
+ "hover:bg-gray-200/50 hover:dark:bg-gray-900",
1692
+ "focus:outline-none focus:ring-2 focus:ring-blue-500",
1693
+ item.active ? "text-blue-600 dark:text-blue-500" : "text-gray-700 dark:text-gray-300",
1694
+ item.disabled && "pointer-events-none opacity-50"
1695
+ ),
1696
+ onClick: item.disabled ? void 0 : item.onClick,
1697
+ children: [
1698
+ item.icon && /* @__PURE__ */ jsx13("span", { className: "size-5 shrink-0", "aria-hidden": "true", children: item.icon }),
1699
+ !collapsed && item.label
1700
+ ]
1701
+ }
1702
+ ) : /* @__PURE__ */ jsxs12(
1703
+ "button",
1704
+ {
1705
+ type: "button",
1706
+ onClick: item.onClick,
1707
+ disabled: item.disabled,
1708
+ className: twMerge12(
1709
+ "flex w-full items-center gap-x-2.5 rounded-md p-2 text-sm font-medium transition-opacity",
1710
+ "hover:bg-gray-200/50 hover:dark:bg-gray-900",
1711
+ "focus:outline-none focus:ring-2 focus:ring-blue-500",
1712
+ item.active ? "text-blue-600 dark:text-blue-500" : "text-gray-700 dark:text-gray-300",
1713
+ item.disabled && "pointer-events-none opacity-50"
1714
+ ),
1715
+ children: [
1716
+ item.icon && /* @__PURE__ */ jsx13("span", { className: "size-5 shrink-0", "aria-hidden": "true", children: item.icon }),
1717
+ !collapsed && item.label
1718
+ ]
1719
+ }
1720
+ ) }, item.id)) }),
1721
+ footerItems && footerItems.length > 0 && /* @__PURE__ */ jsx13("ul", { className: "mt-auto space-y-2", children: footerItems.map((item) => /* @__PURE__ */ jsx13("li", { children: item.href ? /* @__PURE__ */ jsxs12(
1722
+ "a",
1723
+ {
1724
+ href: item.href,
1725
+ "aria-current": item.active ? "page" : void 0,
1726
+ "aria-disabled": item.disabled,
1727
+ className: twMerge12(
1728
+ "flex items-center gap-x-2.5 rounded-md p-2 text-sm font-medium transition-opacity",
1729
+ "hover:bg-gray-200/50 hover:dark:bg-gray-900",
1730
+ "focus:outline-none focus:ring-2 focus:ring-blue-500",
1731
+ item.active ? "text-blue-600 dark:text-blue-500" : "text-gray-700 dark:text-gray-300",
1732
+ item.disabled && "pointer-events-none opacity-50"
1733
+ ),
1734
+ onClick: item.disabled ? void 0 : item.onClick,
1735
+ children: [
1736
+ item.icon && /* @__PURE__ */ jsx13("span", { className: "size-5 shrink-0", "aria-hidden": "true", children: item.icon }),
1737
+ !collapsed && item.label
1738
+ ]
1739
+ }
1740
+ ) : /* @__PURE__ */ jsxs12(
1741
+ "button",
1742
+ {
1743
+ type: "button",
1744
+ onClick: item.onClick,
1745
+ disabled: item.disabled,
1746
+ className: twMerge12(
1747
+ "flex w-full items-center gap-x-2.5 rounded-md p-2 text-sm font-medium transition-opacity",
1748
+ "hover:bg-gray-200/50 hover:dark:bg-gray-900",
1749
+ "focus:outline-none focus:ring-2 focus:ring-blue-500",
1750
+ item.active ? "text-blue-600 dark:text-blue-500" : "text-gray-700 dark:text-gray-300",
1751
+ item.disabled && "pointer-events-none opacity-50"
1752
+ ),
1753
+ children: [
1754
+ item.icon && /* @__PURE__ */ jsx13("span", { className: "size-5 shrink-0", "aria-hidden": "true", children: item.icon }),
1755
+ !collapsed && item.label
1756
+ ]
1757
+ }
1758
+ ) }, item.id)) })
1759
+ ] }),
1760
+ footer && /* @__PURE__ */ jsx13("div", { className: "mt-auto border-t border-gray-200 pt-3 dark:border-gray-800", children: footer })
1761
+ ] })
1762
+ }
1763
+ );
1764
+ }
1765
+
1766
+ // src/insights/index.ts
1767
+ var components = {
1768
+ // Layout
1769
+ Shell: InsightsShell,
1770
+ Sidebar: InsightsSidebar,
1771
+ // KPI/Metrics
1772
+ KPICard,
1773
+ // Charts
1774
+ AreaChart,
1775
+ BarChart,
1776
+ DonutChart,
1777
+ BarChartVariant,
1778
+ TransactionChart,
1779
+ // Tables
1780
+ TransactionsTable
1781
+ };
1782
+ var AppComponents = {
1783
+ /** Root application wrapper */
1784
+ App: InsightsApp,
1785
+ /** Flexible shell layout for analytics */
1786
+ Shell: InsightsShell,
1787
+ /** Navigation sidebar */
1788
+ Sidebar: InsightsSidebar,
1789
+ /** Header bar component */
1790
+ Header: InsightsHeader,
1791
+ /** Dashboard page layout */
1792
+ Dashboard: InsightsDashboard,
1793
+ /** Settings page layout */
1794
+ Settings: InsightsSettings
1795
+ };
1796
+ export {
1797
+ AppComponents,
1798
+ AreaChart,
1799
+ BarChart,
1800
+ BarChartVariant,
1801
+ DonutChart,
1802
+ InsightsApp,
1803
+ InsightsDashboard,
1804
+ InsightsHeader,
1805
+ InsightsSettings,
1806
+ InsightsShell,
1807
+ InsightsSidebar,
1808
+ KPICard,
1809
+ InsightsShell as Shell,
1810
+ InsightsSidebar as Sidebar,
1811
+ TransactionChart,
1812
+ TransactionsTable,
1813
+ components
1814
+ };
1815
+ //# sourceMappingURL=index.js.map