@bison-lab/ui 0.6.0 → 0.8.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.
package/dist/index.mjs CHANGED
@@ -6,9 +6,11 @@ import { defaultFontWeights, densityPresets, deriveDarkPalette, deriveLightPalet
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { Accordion as Accordion$1, AlertDialog as AlertDialog$1, AspectRatio as AspectRatio$1, Avatar as Avatar$1, Checkbox as Checkbox$1, ContextMenu as ContextMenu$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1, Label as Label$1, NavigationMenu as NavigationMenu$1, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, ScrollArea as ScrollArea$1, Select as Select$1, Separator as Separator$1, Slider as Slider$1, Slot, Switch as Switch$1, Tabs as Tabs$1, Tooltip as Tooltip$1 } from "radix-ui";
8
8
  import { cva } from "class-variance-authority";
9
- import { ArrowLeft, Camera, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Circle, FileQuestion, Inbox, Loader2, Mail, Menu, MoreHorizontal, Search, ServerCrash, Wrench, X } from "lucide-react";
9
+ import { ArrowDown, ArrowLeft, ArrowUp, ArrowUpDown, Camera, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsLeft, ChevronsRight, Circle, FileQuestion, Inbox, Loader2, Mail, Menu, MoreHorizontal, Search, ServerCrash, SlidersHorizontal, Wrench, X } from "lucide-react";
10
10
  import { Toaster as Toaster$1, toast } from "sonner";
11
+ import { flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
11
12
  import { Command as Command$1 } from "cmdk";
13
+ import { Area, AreaChart as AreaChart$1, Bar, BarChart as BarChart$1, CartesianGrid, Cell, Legend, Pie, PieChart, ResponsiveContainer, Tooltip as Tooltip$2, XAxis, YAxis } from "recharts";
12
14
  //#region src/lib/utils.ts
13
15
  function cn(...inputs) {
14
16
  return twMerge(clsx(inputs));
@@ -979,6 +981,300 @@ const TableCaption = React.forwardRef(({ className, ...props }, ref) => /* @__PU
979
981
  }));
980
982
  TableCaption.displayName = "TableCaption";
981
983
  //#endregion
984
+ //#region src/components/data-table.tsx
985
+ const sizeClasses = {
986
+ sm: {
987
+ cell: "px-3 py-1.5 text-xs",
988
+ header: "h-9 px-3 text-xs"
989
+ },
990
+ md: {
991
+ cell: "px-4 py-2 text-sm",
992
+ header: "h-10 px-4 text-sm"
993
+ },
994
+ lg: {
995
+ cell: "px-4 py-3 text-sm",
996
+ header: "h-12 px-4 text-sm"
997
+ }
998
+ };
999
+ const densitySizeMap = {
1000
+ compact: "sm",
1001
+ default: "md",
1002
+ spacious: "lg"
1003
+ };
1004
+ function DataTableColumnHeader({ column, title, className }) {
1005
+ if (!column.getCanSort()) return /* @__PURE__ */ jsx("div", {
1006
+ className: cn(className),
1007
+ children: title
1008
+ });
1009
+ const sorted = column.getIsSorted();
1010
+ return /* @__PURE__ */ jsxs(Button, {
1011
+ variant: "ghost",
1012
+ size: "sm",
1013
+ className: cn("-ml-3 h-8 data-[state=open]:bg-accent", className),
1014
+ onClick: () => column.toggleSorting(sorted === "asc"),
1015
+ children: [title, sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "ml-2 h-3.5 w-3.5" }) : sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "ml-2 h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "ml-2 h-3.5 w-3.5 text-muted-foreground/50" })]
1016
+ });
1017
+ }
1018
+ DataTableColumnHeader.displayName = "DataTableColumnHeader";
1019
+ function createSelectionColumn() {
1020
+ return {
1021
+ id: "_select",
1022
+ header: ({ table }) => /* @__PURE__ */ jsx(Checkbox, {
1023
+ checked: table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected() && "indeterminate",
1024
+ onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value),
1025
+ "aria-label": "Select all",
1026
+ className: "translate-y-[2px]"
1027
+ }),
1028
+ cell: ({ row }) => /* @__PURE__ */ jsx(Checkbox, {
1029
+ checked: row.getIsSelected(),
1030
+ onCheckedChange: (value) => row.toggleSelected(!!value),
1031
+ "aria-label": "Select row",
1032
+ className: "translate-y-[2px]"
1033
+ }),
1034
+ enableSorting: false,
1035
+ enableHiding: false,
1036
+ size: 40
1037
+ };
1038
+ }
1039
+ function useDensitySize() {
1040
+ const ref = React.useRef(null);
1041
+ const [size, setSize] = React.useState("md");
1042
+ React.useEffect(() => {
1043
+ const el = ref.current;
1044
+ if (!el) return;
1045
+ const container = el.closest(".bison-density-compact, .bison-density-default, .bison-density-spacious");
1046
+ if (!container) return;
1047
+ for (const [cls, sz] of Object.entries(densitySizeMap)) if (container.classList.contains(`bison-density-${cls}`)) {
1048
+ setSize(sz);
1049
+ return;
1050
+ }
1051
+ }, []);
1052
+ return size;
1053
+ }
1054
+ function DataTableInner({ columns, data, filterColumn, filterPlaceholder = "Filter...", pagination = true, pageSize = 10, pageSizeOptions = [
1055
+ 10,
1056
+ 20,
1057
+ 30,
1058
+ 50
1059
+ ], enableRowSelection = false, onRowSelectionChange, totalRows, paginationState: controlledPagination, onPaginationChange, sortingState: controlledSorting, onSortingChange: onSortingChangeProp, filterState: controlledFilters, onFilterChange, showColumnToggle = true, toolbarActions, size: sizeProp, emptyMessage = "No results.", className }, ref) {
1060
+ const isServerSide = totalRows !== void 0;
1061
+ const [internalSorting, setInternalSorting] = React.useState([]);
1062
+ const [internalFilters, setInternalFilters] = React.useState([]);
1063
+ const [internalPagination, setInternalPagination] = React.useState({
1064
+ pageIndex: 0,
1065
+ pageSize
1066
+ });
1067
+ const [columnVisibility, setColumnVisibility] = React.useState({});
1068
+ const [rowSelection, setRowSelection] = React.useState({});
1069
+ const sorting = controlledSorting ?? internalSorting;
1070
+ const setSorting = onSortingChangeProp ?? setInternalSorting;
1071
+ const columnFilters = controlledFilters ?? internalFilters;
1072
+ const setColumnFilters = onFilterChange ?? setInternalFilters;
1073
+ const paginationVal = controlledPagination ?? internalPagination;
1074
+ const setPaginationVal = onPaginationChange ?? setInternalPagination;
1075
+ const handleRowSelectionChange = React.useCallback((updater) => {
1076
+ setRowSelection((prev) => {
1077
+ const next = typeof updater === "function" ? updater(prev) : updater;
1078
+ onRowSelectionChange?.(next);
1079
+ return next;
1080
+ });
1081
+ }, [onRowSelectionChange]);
1082
+ const finalColumns = React.useMemo(() => {
1083
+ if (!enableRowSelection) return columns;
1084
+ return [createSelectionColumn(), ...columns];
1085
+ }, [columns, enableRowSelection]);
1086
+ const table = useReactTable({
1087
+ data,
1088
+ columns: finalColumns,
1089
+ state: {
1090
+ sorting,
1091
+ columnFilters,
1092
+ columnVisibility,
1093
+ rowSelection,
1094
+ pagination: paginationVal
1095
+ },
1096
+ onSortingChange: setSorting,
1097
+ onColumnFiltersChange: setColumnFilters,
1098
+ onColumnVisibilityChange: setColumnVisibility,
1099
+ onRowSelectionChange: handleRowSelectionChange,
1100
+ onPaginationChange: setPaginationVal,
1101
+ getCoreRowModel: getCoreRowModel(),
1102
+ ...isServerSide ? {
1103
+ manualPagination: true,
1104
+ manualSorting: true,
1105
+ manualFiltering: true,
1106
+ pageCount: Math.ceil(totalRows / paginationVal.pageSize)
1107
+ } : {
1108
+ getSortedRowModel: getSortedRowModel(),
1109
+ getFilteredRowModel: getFilteredRowModel(),
1110
+ ...pagination && { getPaginationRowModel: getPaginationRowModel() }
1111
+ },
1112
+ enableRowSelection
1113
+ });
1114
+ const densitySize = useDensitySize();
1115
+ const sc = sizeClasses[sizeProp ?? densitySize];
1116
+ const hasToolbar = filterColumn || showColumnToggle || toolbarActions;
1117
+ const selectedCount = Object.keys(rowSelection).length;
1118
+ const totalFilteredRows = isServerSide ? totalRows : table.getFilteredRowModel().rows.length;
1119
+ return /* @__PURE__ */ jsxs("div", {
1120
+ ref,
1121
+ className: cn("space-y-4", className),
1122
+ children: [
1123
+ hasToolbar && /* @__PURE__ */ jsxs("div", {
1124
+ className: "flex items-center justify-between gap-2",
1125
+ children: [/* @__PURE__ */ jsx("div", {
1126
+ className: "flex flex-1 items-center gap-2",
1127
+ children: filterColumn && /* @__PURE__ */ jsx(Input, {
1128
+ placeholder: filterPlaceholder,
1129
+ value: table.getColumn(filterColumn)?.getFilterValue() ?? "",
1130
+ onChange: (event) => table.getColumn(filterColumn)?.setFilterValue(event.target.value),
1131
+ className: "max-w-sm"
1132
+ })
1133
+ }), /* @__PURE__ */ jsxs("div", {
1134
+ className: "flex items-center gap-2",
1135
+ children: [toolbarActions, showColumnToggle && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
1136
+ asChild: true,
1137
+ children: /* @__PURE__ */ jsxs(Button, {
1138
+ variant: "outline",
1139
+ size: "sm",
1140
+ className: "ml-auto h-8",
1141
+ children: [/* @__PURE__ */ jsx(SlidersHorizontal, { className: "mr-2 h-4 w-4" }), "Columns"]
1142
+ })
1143
+ }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
1144
+ align: "end",
1145
+ className: "w-40",
1146
+ children: [
1147
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Toggle columns" }),
1148
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
1149
+ table.getAllColumns().filter((col) => col.getCanHide()).map((col) => /* @__PURE__ */ jsx(DropdownMenuCheckboxItem, {
1150
+ className: "capitalize",
1151
+ checked: col.getIsVisible(),
1152
+ onCheckedChange: (value) => col.toggleVisibility(!!value),
1153
+ children: col.id
1154
+ }, col.id))
1155
+ ]
1156
+ })] })]
1157
+ })]
1158
+ }),
1159
+ /* @__PURE__ */ jsx("div", {
1160
+ className: "rounded-md border",
1161
+ children: /* @__PURE__ */ jsxs(Table, { children: [/* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx(TableHead, {
1162
+ className: sc.header,
1163
+ style: { width: header.column.id === "_select" ? 40 : header.getSize() !== 150 ? header.getSize() : void 0 },
1164
+ children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())
1165
+ }, header.id)) }, headerGroup.id)) }), /* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(TableRow, {
1166
+ "data-state": row.getIsSelected() && "selected",
1167
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, {
1168
+ className: sc.cell,
1169
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
1170
+ }, cell.id))
1171
+ }, row.id)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, {
1172
+ colSpan: finalColumns.length,
1173
+ className: "h-24 text-center",
1174
+ children: emptyMessage
1175
+ }) }) })] })
1176
+ }),
1177
+ (pagination || enableRowSelection) && /* @__PURE__ */ jsxs("div", {
1178
+ className: "flex items-center justify-between px-2",
1179
+ children: [/* @__PURE__ */ jsx("div", {
1180
+ className: "flex-1 text-sm text-muted-foreground",
1181
+ children: enableRowSelection ? `${selectedCount} of ${totalFilteredRows} row(s) selected` : `${totalFilteredRows} row(s) total`
1182
+ }), pagination && /* @__PURE__ */ jsxs("div", {
1183
+ className: "flex items-center space-x-6 lg:space-x-8",
1184
+ children: [
1185
+ /* @__PURE__ */ jsxs("div", {
1186
+ className: "flex items-center space-x-2",
1187
+ children: [/* @__PURE__ */ jsx("p", {
1188
+ className: "text-sm font-medium",
1189
+ children: "Rows per page"
1190
+ }), /* @__PURE__ */ jsxs(Select, {
1191
+ value: `${paginationVal.pageSize}`,
1192
+ onValueChange: (value) => {
1193
+ setPaginationVal((old) => ({
1194
+ ...old,
1195
+ pageIndex: 0,
1196
+ pageSize: Number(value)
1197
+ }));
1198
+ },
1199
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
1200
+ className: "h-8 w-[70px]",
1201
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder: `${paginationVal.pageSize}` })
1202
+ }), /* @__PURE__ */ jsx(SelectContent, {
1203
+ side: "top",
1204
+ children: pageSizeOptions.map((s) => /* @__PURE__ */ jsx(SelectItem, {
1205
+ value: `${s}`,
1206
+ children: s
1207
+ }, s))
1208
+ })]
1209
+ })]
1210
+ }),
1211
+ /* @__PURE__ */ jsxs("div", {
1212
+ className: "flex w-[100px] items-center justify-center text-sm font-medium",
1213
+ children: [
1214
+ "Page ",
1215
+ paginationVal.pageIndex + 1,
1216
+ " of ",
1217
+ table.getPageCount()
1218
+ ]
1219
+ }),
1220
+ /* @__PURE__ */ jsxs("div", {
1221
+ className: "flex items-center space-x-2",
1222
+ children: [
1223
+ /* @__PURE__ */ jsxs(Button, {
1224
+ variant: "outline",
1225
+ size: "sm",
1226
+ className: "hidden h-8 w-8 p-0 lg:flex",
1227
+ onClick: () => table.setPageIndex(0),
1228
+ disabled: !table.getCanPreviousPage(),
1229
+ children: [/* @__PURE__ */ jsx("span", {
1230
+ className: "sr-only",
1231
+ children: "Go to first page"
1232
+ }), /* @__PURE__ */ jsx(ChevronsLeft, { className: "h-4 w-4" })]
1233
+ }),
1234
+ /* @__PURE__ */ jsxs(Button, {
1235
+ variant: "outline",
1236
+ size: "sm",
1237
+ className: "h-8 w-8 p-0",
1238
+ onClick: () => table.previousPage(),
1239
+ disabled: !table.getCanPreviousPage(),
1240
+ children: [/* @__PURE__ */ jsx("span", {
1241
+ className: "sr-only",
1242
+ children: "Go to previous page"
1243
+ }), /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })]
1244
+ }),
1245
+ /* @__PURE__ */ jsxs(Button, {
1246
+ variant: "outline",
1247
+ size: "sm",
1248
+ className: "h-8 w-8 p-0",
1249
+ onClick: () => table.nextPage(),
1250
+ disabled: !table.getCanNextPage(),
1251
+ children: [/* @__PURE__ */ jsx("span", {
1252
+ className: "sr-only",
1253
+ children: "Go to next page"
1254
+ }), /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })]
1255
+ }),
1256
+ /* @__PURE__ */ jsxs(Button, {
1257
+ variant: "outline",
1258
+ size: "sm",
1259
+ className: "hidden h-8 w-8 p-0 lg:flex",
1260
+ onClick: () => table.setPageIndex(table.getPageCount() - 1),
1261
+ disabled: !table.getCanNextPage(),
1262
+ children: [/* @__PURE__ */ jsx("span", {
1263
+ className: "sr-only",
1264
+ children: "Go to last page"
1265
+ }), /* @__PURE__ */ jsx(ChevronsRight, { className: "h-4 w-4" })]
1266
+ })
1267
+ ]
1268
+ })
1269
+ ]
1270
+ })]
1271
+ })
1272
+ ]
1273
+ });
1274
+ }
1275
+ const DataTable = React.forwardRef(DataTableInner);
1276
+ DataTable.displayName = "DataTable";
1277
+ //#endregion
982
1278
  //#region src/components/progress.tsx
983
1279
  const Progress = React.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(Progress$1.Root, {
984
1280
  ref,
@@ -1389,6 +1685,270 @@ const CommandShortcut = ({ className, ...props }) => /* @__PURE__ */ jsx("span",
1389
1685
  //#region src/components/aspect-ratio.tsx
1390
1686
  const AspectRatio = AspectRatio$1.Root;
1391
1687
  //#endregion
1688
+ //#region src/lib/chart-utils.ts
1689
+ /**
1690
+ * Shared utilities for chart components.
1691
+ * Reads theme CSS custom properties to provide Recharts-compatible color strings.
1692
+ */
1693
+ /** Default chart color tokens mapped to CSS custom properties */
1694
+ const chartColorTokens = [
1695
+ "--primary",
1696
+ "--secondary",
1697
+ "--brand-accent",
1698
+ "--highlight",
1699
+ "--destructive"
1700
+ ];
1701
+ /**
1702
+ * Resolves a CSS custom property value to an `hsl(...)` string.
1703
+ * Falls back to the raw token name if resolution fails (e.g. SSR).
1704
+ */
1705
+ function resolveHslToken(token, el) {
1706
+ if (typeof window === "undefined") return `hsl(var(${token}))`;
1707
+ const target = el ?? document.documentElement;
1708
+ const raw = getComputedStyle(target).getPropertyValue(token).trim();
1709
+ if (!raw) return `hsl(var(${token}))`;
1710
+ if (raw.startsWith("hsl")) return raw;
1711
+ return `hsl(${raw})`;
1712
+ }
1713
+ /**
1714
+ * Returns an array of resolved theme colors for chart series.
1715
+ * Consumers can override with explicit `colors` prop.
1716
+ */
1717
+ function getThemeColors(el) {
1718
+ return chartColorTokens.map((token) => resolveHslToken(token, el));
1719
+ }
1720
+ /** Chart size presets (height in px) */
1721
+ const chartSizeMap = {
1722
+ sm: 200,
1723
+ md: 300,
1724
+ lg: 400
1725
+ };
1726
+ //#endregion
1727
+ //#region src/components/area-chart.tsx
1728
+ const AreaChart = React.forwardRef(({ className, data, index, categories, series, colors, size = "md", height, showGrid = true, showLegend = false, showTooltip = true, showYAxis = true, curveType = "monotone", stacked = false, ...props }, ref) => {
1729
+ const containerRef = React.useRef(null);
1730
+ const [themeColors, setThemeColors] = React.useState([]);
1731
+ React.useEffect(() => {
1732
+ const el = containerRef.current;
1733
+ setThemeColors(colors ?? getThemeColors(el));
1734
+ }, [colors]);
1735
+ const resolvedSeries = React.useMemo(() => {
1736
+ if (series) return series;
1737
+ return (categories ?? []).map((key) => ({
1738
+ dataKey: key,
1739
+ name: key
1740
+ }));
1741
+ }, [series, categories]);
1742
+ const chartHeight = height ?? chartSizeMap[size];
1743
+ const gridColor = themeColors.length > 0 ? void 0 : "hsl(var(--border-subtle))";
1744
+ return /* @__PURE__ */ jsx("div", {
1745
+ ref: (node) => {
1746
+ containerRef.current = node;
1747
+ if (typeof ref === "function") ref(node);
1748
+ else if (ref) ref.current = node;
1749
+ },
1750
+ className: cn("w-full", className),
1751
+ ...props,
1752
+ children: /* @__PURE__ */ jsx(ResponsiveContainer, {
1753
+ width: "100%",
1754
+ height: chartHeight,
1755
+ children: /* @__PURE__ */ jsxs(AreaChart$1, {
1756
+ data,
1757
+ children: [
1758
+ showGrid && /* @__PURE__ */ jsx(CartesianGrid, {
1759
+ strokeDasharray: "3 3",
1760
+ stroke: gridColor,
1761
+ className: "stroke-border-subtle"
1762
+ }),
1763
+ /* @__PURE__ */ jsx(XAxis, {
1764
+ dataKey: index,
1765
+ tick: { fontSize: 12 },
1766
+ tickLine: false,
1767
+ axisLine: false,
1768
+ className: "[&_text]:fill-content-secondary"
1769
+ }),
1770
+ showYAxis && /* @__PURE__ */ jsx(YAxis, {
1771
+ tick: { fontSize: 12 },
1772
+ tickLine: false,
1773
+ axisLine: false,
1774
+ width: 40,
1775
+ className: "[&_text]:fill-content-secondary"
1776
+ }),
1777
+ showTooltip && /* @__PURE__ */ jsx(Tooltip$2, { contentStyle: {
1778
+ backgroundColor: "hsl(var(--popover))",
1779
+ border: "1px solid hsl(var(--border))",
1780
+ borderRadius: "var(--radius-md)",
1781
+ color: "hsl(var(--popover-foreground))",
1782
+ fontSize: 12
1783
+ } }),
1784
+ showLegend && /* @__PURE__ */ jsx(Legend, {}),
1785
+ resolvedSeries.map((s, i) => {
1786
+ const color = s.color ?? themeColors[i % themeColors.length] ?? `hsl(var(--primary))`;
1787
+ return /* @__PURE__ */ jsx(Area, {
1788
+ type: curveType,
1789
+ dataKey: s.dataKey,
1790
+ name: s.name ?? s.dataKey,
1791
+ stroke: color,
1792
+ fill: color,
1793
+ fillOpacity: s.fillOpacity ?? .15,
1794
+ stackId: stacked ? "stack" : void 0
1795
+ }, s.dataKey);
1796
+ })
1797
+ ]
1798
+ })
1799
+ })
1800
+ });
1801
+ });
1802
+ AreaChart.displayName = "AreaChart";
1803
+ //#endregion
1804
+ //#region src/components/bar-chart.tsx
1805
+ const BarChart = React.forwardRef(({ className, data, index, categories, series, colors, size = "md", height, showGrid = true, showLegend = false, showTooltip = true, showYAxis = true, stacked = false, horizontal = false, ...props }, ref) => {
1806
+ const containerRef = React.useRef(null);
1807
+ const [themeColors, setThemeColors] = React.useState([]);
1808
+ React.useEffect(() => {
1809
+ const el = containerRef.current;
1810
+ setThemeColors(colors ?? getThemeColors(el));
1811
+ }, [colors]);
1812
+ const resolvedSeries = React.useMemo(() => {
1813
+ if (series) return series;
1814
+ return (categories ?? []).map((key) => ({
1815
+ dataKey: key,
1816
+ name: key
1817
+ }));
1818
+ }, [series, categories]);
1819
+ const chartHeight = height ?? chartSizeMap[size];
1820
+ const layout = horizontal ? "vertical" : "horizontal";
1821
+ return /* @__PURE__ */ jsx("div", {
1822
+ ref: (node) => {
1823
+ containerRef.current = node;
1824
+ if (typeof ref === "function") ref(node);
1825
+ else if (ref) ref.current = node;
1826
+ },
1827
+ className: cn("w-full", className),
1828
+ ...props,
1829
+ children: /* @__PURE__ */ jsx(ResponsiveContainer, {
1830
+ width: "100%",
1831
+ height: chartHeight,
1832
+ children: /* @__PURE__ */ jsxs(BarChart$1, {
1833
+ data,
1834
+ layout,
1835
+ children: [
1836
+ showGrid && /* @__PURE__ */ jsx(CartesianGrid, {
1837
+ strokeDasharray: "3 3",
1838
+ className: "stroke-border-subtle"
1839
+ }),
1840
+ horizontal ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(XAxis, {
1841
+ type: "number",
1842
+ tick: { fontSize: 12 },
1843
+ tickLine: false,
1844
+ axisLine: false,
1845
+ className: "[&_text]:fill-content-secondary"
1846
+ }), /* @__PURE__ */ jsx(YAxis, {
1847
+ dataKey: index,
1848
+ type: "category",
1849
+ tick: { fontSize: 12 },
1850
+ tickLine: false,
1851
+ axisLine: false,
1852
+ width: 80,
1853
+ className: "[&_text]:fill-content-secondary"
1854
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(XAxis, {
1855
+ dataKey: index,
1856
+ tick: { fontSize: 12 },
1857
+ tickLine: false,
1858
+ axisLine: false,
1859
+ className: "[&_text]:fill-content-secondary"
1860
+ }), showYAxis && /* @__PURE__ */ jsx(YAxis, {
1861
+ tick: { fontSize: 12 },
1862
+ tickLine: false,
1863
+ axisLine: false,
1864
+ width: 40,
1865
+ className: "[&_text]:fill-content-secondary"
1866
+ })] }),
1867
+ showTooltip && /* @__PURE__ */ jsx(Tooltip$2, { contentStyle: {
1868
+ backgroundColor: "hsl(var(--popover))",
1869
+ border: "1px solid hsl(var(--border))",
1870
+ borderRadius: "var(--radius-md)",
1871
+ color: "hsl(var(--popover-foreground))",
1872
+ fontSize: 12
1873
+ } }),
1874
+ showLegend && /* @__PURE__ */ jsx(Legend, {}),
1875
+ resolvedSeries.map((s, i) => {
1876
+ const color = s.color ?? themeColors[i % themeColors.length] ?? `hsl(var(--primary))`;
1877
+ return /* @__PURE__ */ jsx(Bar, {
1878
+ dataKey: s.dataKey,
1879
+ name: s.name ?? s.dataKey,
1880
+ fill: color,
1881
+ radius: s.radius ?? [
1882
+ 4,
1883
+ 4,
1884
+ 0,
1885
+ 0
1886
+ ],
1887
+ stackId: stacked ? "stack" : void 0
1888
+ }, s.dataKey);
1889
+ })
1890
+ ]
1891
+ })
1892
+ })
1893
+ });
1894
+ });
1895
+ BarChart.displayName = "BarChart";
1896
+ //#endregion
1897
+ //#region src/components/donut-chart.tsx
1898
+ const DonutChart = React.forwardRef(({ className, data, nameKey = "name", dataKey = "value", colors, size = "md", height, showLegend = false, showTooltip = true, showLabels = false, innerRadius = "60%", outerRadius = "80%", paddingAngle = 2, centerLabel, ...props }, ref) => {
1899
+ const containerRef = React.useRef(null);
1900
+ const [themeColors, setThemeColors] = React.useState([]);
1901
+ React.useEffect(() => {
1902
+ const el = containerRef.current;
1903
+ setThemeColors(colors ?? getThemeColors(el));
1904
+ }, [colors]);
1905
+ const chartHeight = height ?? chartSizeMap[size];
1906
+ return /* @__PURE__ */ jsxs("div", {
1907
+ ref: (node) => {
1908
+ containerRef.current = node;
1909
+ if (typeof ref === "function") ref(node);
1910
+ else if (ref) ref.current = node;
1911
+ },
1912
+ className: cn("relative w-full", className),
1913
+ ...props,
1914
+ children: [centerLabel && /* @__PURE__ */ jsx("div", {
1915
+ className: "pointer-events-none absolute inset-0 flex items-center justify-center",
1916
+ "aria-hidden": "true",
1917
+ children: /* @__PURE__ */ jsx("div", {
1918
+ className: "text-center",
1919
+ children: centerLabel
1920
+ })
1921
+ }), /* @__PURE__ */ jsx(ResponsiveContainer, {
1922
+ width: "100%",
1923
+ height: chartHeight,
1924
+ children: /* @__PURE__ */ jsxs(PieChart, { children: [
1925
+ /* @__PURE__ */ jsx(Pie, {
1926
+ data,
1927
+ nameKey,
1928
+ dataKey,
1929
+ innerRadius,
1930
+ outerRadius,
1931
+ paddingAngle,
1932
+ label: showLabels,
1933
+ strokeWidth: 0,
1934
+ children: data.map((_, i) => {
1935
+ return /* @__PURE__ */ jsx(Cell, { fill: themeColors[i % themeColors.length] ?? `hsl(var(--primary))` }, i);
1936
+ })
1937
+ }),
1938
+ showTooltip && /* @__PURE__ */ jsx(Tooltip$2, { contentStyle: {
1939
+ backgroundColor: "hsl(var(--popover))",
1940
+ border: "1px solid hsl(var(--border))",
1941
+ borderRadius: "var(--radius-md)",
1942
+ color: "hsl(var(--popover-foreground))",
1943
+ fontSize: 12
1944
+ } }),
1945
+ showLegend && /* @__PURE__ */ jsx(Legend, {})
1946
+ ] })
1947
+ })]
1948
+ });
1949
+ });
1950
+ DonutChart.displayName = "DonutChart";
1951
+ //#endregion
1392
1952
  //#region src/blocks/auth/social-providers.tsx
1393
1953
  const providerConfig = {
1394
1954
  google: {
@@ -2493,6 +3053,6 @@ function NotificationSettingsBlock({ groups, onSave, loading = false, error, dis
2493
3053
  });
2494
3054
  }
2495
3055
  //#endregion
2496
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountSettingsBlock, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, BisonProvider, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DensityProvider, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyStateBlock, FooterBlock, ForgotPasswordBlock, Form, FormError, FormField, HeaderBlock, Input, Label, MaintenanceBlock, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NotFoundBlock, NotificationSettingsBlock, PageShell, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverContent, PopoverTrigger, ProfileSettingsBlock, Progress, ProgressBar, RadioGroup, RadioGroupItem, ResetPasswordBlock, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, ServerErrorBlock, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBlock, SignInBlock, SignUpBlock, Skeleton, Slider, SocialProviders, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeProvider, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, VerifyBlock, badgeVariants, buttonVariants, cn, navigationMenuTriggerStyle, progressBarVariants, spinnerVariants, toast, useDensity, useFormContext, useScrollReveal, useTheme };
3056
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountSettingsBlock, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AreaChart, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, BarChart, BisonProvider, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataTable, DataTableColumnHeader, DensityProvider, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DonutChart, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyStateBlock, FooterBlock, ForgotPasswordBlock, Form, FormError, FormField, HeaderBlock, Input, Label, MaintenanceBlock, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NotFoundBlock, NotificationSettingsBlock, PageShell, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverContent, PopoverTrigger, ProfileSettingsBlock, Progress, ProgressBar, RadioGroup, RadioGroupItem, ResetPasswordBlock, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, ServerErrorBlock, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBlock, SignInBlock, SignUpBlock, Skeleton, Slider, SocialProviders, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeProvider, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, VerifyBlock, badgeVariants, buttonVariants, chartColorTokens, chartSizeMap, cn, getThemeColors, navigationMenuTriggerStyle, progressBarVariants, resolveHslToken, spinnerVariants, toast, useDensity, useFormContext, useScrollReveal, useTheme };
2497
3057
 
2498
3058
  //# sourceMappingURL=index.mjs.map