primus-react-ui 1.0.10 → 1.0.12

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
@@ -1114,75 +1114,191 @@ var usePrimusAuth = () => {
1114
1114
 
1115
1115
  // src/components/shared/Button.tsx
1116
1116
  import React13 from "react";
1117
- import { clsx } from "clsx";
1118
- import { twMerge } from "tailwind-merge";
1119
1117
  import { jsx as jsx15 } from "react/jsx-runtime";
1120
- function cn(...inputs) {
1121
- return twMerge(clsx(inputs));
1122
- }
1123
1118
  var Button = React13.forwardRef(
1124
- ({ className, variant = "primary", size = "md", ...props }, ref) => {
1119
+ ({ style, variant = "primary", size = "md", color = "sapphire", disabled, ...props }, ref) => {
1120
+ const [isHovered, setIsHovered] = React13.useState(false);
1121
+ const colorStyles = {
1122
+ sapphire: {
1123
+ solid: "#1341a7",
1124
+ // Updated to user spec
1125
+ text: "#ffffff",
1126
+ hover: "rgba(19, 65, 167, 0.9)",
1127
+ subtle: "rgba(19, 65, 167, 0.12)"
1128
+ },
1129
+ emerald: {
1130
+ solid: "#418872",
1131
+ // Updated to user spec
1132
+ text: "#ffffff",
1133
+ hover: "rgba(65, 136, 114, 0.9)",
1134
+ subtle: "rgba(65, 136, 114, 0.12)"
1135
+ },
1136
+ ruby: {
1137
+ solid: "#ac0f0f",
1138
+ // Updated to user spec
1139
+ text: "#ffffff",
1140
+ hover: "rgba(172, 15, 15, 0.9)",
1141
+ subtle: "rgba(172, 15, 15, 0.12)"
1142
+ }
1143
+ };
1144
+ const selectedColor = colorStyles[color];
1145
+ const baseStyles = {
1146
+ display: "inline-flex",
1147
+ alignItems: "center",
1148
+ justifyContent: "center",
1149
+ whiteSpace: "nowrap",
1150
+ borderRadius: "0.5rem",
1151
+ fontSize: "0.875rem",
1152
+ lineHeight: "1.25rem",
1153
+ fontWeight: "600",
1154
+ transition: "all 0.15s cubic-bezier(0.4, 0, 0.2, 1)",
1155
+ cursor: disabled ? "not-allowed" : "pointer",
1156
+ opacity: disabled ? 0.5 : 1,
1157
+ pointerEvents: disabled ? "none" : "auto",
1158
+ outline: "none",
1159
+ border: "none",
1160
+ boxShadow: isHovered && !disabled ? "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)" : "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
1161
+ transform: isHovered && !disabled ? "translateY(-1px)" : "none"
1162
+ };
1163
+ const variantStyles = {
1164
+ primary: {
1165
+ normal: {
1166
+ backgroundColor: selectedColor.solid,
1167
+ color: selectedColor.text
1168
+ },
1169
+ hover: {
1170
+ backgroundColor: selectedColor.hover
1171
+ }
1172
+ },
1173
+ secondary: {
1174
+ normal: {
1175
+ backgroundColor: "#f3f4f6",
1176
+ color: "#111827"
1177
+ },
1178
+ hover: {
1179
+ backgroundColor: "rgba(243, 244, 246, 0.8)"
1180
+ }
1181
+ },
1182
+ outline: {
1183
+ normal: {
1184
+ backgroundColor: "#ffffff",
1185
+ color: selectedColor.solid,
1186
+ border: `1px solid ${selectedColor.solid}`
1187
+ },
1188
+ hover: {
1189
+ backgroundColor: selectedColor.subtle
1190
+ }
1191
+ },
1192
+ ghost: {
1193
+ normal: {
1194
+ backgroundColor: "transparent",
1195
+ color: selectedColor.solid
1196
+ },
1197
+ hover: {
1198
+ backgroundColor: selectedColor.subtle
1199
+ }
1200
+ }
1201
+ };
1202
+ const sizeStyles = {
1203
+ sm: { height: "2.25rem", padding: "0 0.75rem" },
1204
+ md: { height: "2.5rem", padding: "0.5rem 1rem" },
1205
+ lg: { height: "2.75rem", padding: "0 2rem" }
1206
+ };
1207
+ const currentVariant = variantStyles[variant];
1208
+ const combinedStyles = {
1209
+ ...baseStyles,
1210
+ ...currentVariant.normal,
1211
+ ...isHovered && !disabled ? currentVariant.hover : {},
1212
+ ...sizeStyles[size],
1213
+ ...style
1214
+ };
1125
1215
  return /* @__PURE__ */ jsx15(
1126
1216
  "button",
1127
1217
  {
1128
1218
  ref,
1129
- className: cn(
1130
- "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
1131
- {
1132
- "bg-gray-900 text-gray-50 hover:bg-gray-900/90": variant === "primary",
1133
- "bg-gray-100 text-gray-900 hover:bg-gray-100/80": variant === "secondary",
1134
- "border border-gray-200 bg-white hover:bg-gray-100 hover:text-gray-900": variant === "outline",
1135
- "hover:bg-gray-100 hover:text-gray-900": variant === "ghost",
1136
- "h-9 px-3": size === "sm",
1137
- "h-10 px-4 py-2": size === "md",
1138
- "h-11 px-8": size === "lg"
1139
- },
1140
- className
1141
- ),
1219
+ style: combinedStyles,
1220
+ onMouseEnter: () => setIsHovered(true),
1221
+ onMouseLeave: () => setIsHovered(false),
1222
+ disabled,
1142
1223
  ...props
1143
1224
  }
1144
1225
  );
1145
1226
  }
1146
1227
  );
1228
+ Button.displayName = "Button";
1147
1229
 
1148
1230
  // src/components/auth/UserProfile.tsx
1149
1231
  import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1150
- var UserProfile = () => {
1151
- const { user, logout, isAuthenticated } = usePrimusAuth();
1152
- if (!isAuthenticated || !user) {
1232
+ var UserProfile = ({
1233
+ user: userOverride,
1234
+ showLogout = true,
1235
+ onLogout
1236
+ }) => {
1237
+ const { user: contextUser, logout, isAuthenticated } = usePrimusAuth();
1238
+ const resolvedUser = userOverride ?? (isAuthenticated ? contextUser : null);
1239
+ if (!resolvedUser) {
1153
1240
  return null;
1154
1241
  }
1242
+ const handleLogout = async () => {
1243
+ if (onLogout) {
1244
+ onLogout();
1245
+ return;
1246
+ }
1247
+ await logout();
1248
+ };
1155
1249
  return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-4 p-4 rounded-lg bg-gray-50 border border-gray-200", children: [
1156
- /* @__PURE__ */ jsx16("div", { className: "h-10 w-10 rounded-full bg-primus-100 flex items-center justify-center text-primus-600 font-bold", children: user.name?.charAt(0) || "U" }),
1250
+ /* @__PURE__ */ jsx16("div", { className: "h-10 w-10 rounded-full bg-primus-100 flex items-center justify-center text-primus-600 font-bold", children: resolvedUser.name?.charAt(0) || "U" }),
1157
1251
  /* @__PURE__ */ jsxs13("div", { className: "flex-1", children: [
1158
- /* @__PURE__ */ jsx16("p", { className: "text-sm font-medium text-gray-900", children: user.name }),
1159
- /* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-500", children: user.email })
1252
+ /* @__PURE__ */ jsx16("p", { className: "text-sm font-medium text-gray-900", children: resolvedUser.name }),
1253
+ resolvedUser.email && /* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-500", children: resolvedUser.email })
1160
1254
  ] }),
1161
- /* @__PURE__ */ jsx16(Button, { variant: "outline", size: "sm", onClick: () => logout(), children: "Sign out" })
1255
+ showLogout && /* @__PURE__ */ jsx16(Button, { variant: "outline", size: "sm", onClick: handleLogout, children: "Sign out" })
1162
1256
  ] });
1163
1257
  };
1164
1258
 
1165
1259
  // src/hooks/useNotifications.ts
1166
- import { useState as useState15, useEffect as useEffect9 } from "react";
1167
- var useNotifications = (apiUrl = "http://localhost:5221") => {
1260
+ import { useState as useState15, useEffect as useEffect9, useMemo } from "react";
1261
+ var useNotifications = ({
1262
+ apiUrl = "http://localhost:5221",
1263
+ useMock = false,
1264
+ mockData = []
1265
+ } = {}) => {
1168
1266
  const [notifications, setNotifications] = useState15([]);
1169
1267
  const [unreadCount, setUnreadCount] = useState15(0);
1170
1268
  const [loading, setLoading] = useState15(true);
1269
+ const safeMockData = useMemo(() => mockData || [], [JSON.stringify(mockData)]);
1270
+ const DEFAULT_MOCK_DATA = [
1271
+ { id: "1", title: "Welcome", message: "Welcome to Primus UI", type: "info", timestamp: (/* @__PURE__ */ new Date()).toISOString(), read: false },
1272
+ { id: "2", title: "System Update", message: "Maintenance scheduled", type: "warning", timestamp: (/* @__PURE__ */ new Date()).toISOString(), read: false },
1273
+ { id: "3", title: "Payment Success", message: "Your payment was processed", type: "success", timestamp: (/* @__PURE__ */ new Date()).toISOString(), read: false }
1274
+ ];
1171
1275
  useEffect9(() => {
1276
+ if (useMock) {
1277
+ const data = safeMockData.length > 0 ? safeMockData : DEFAULT_MOCK_DATA;
1278
+ setNotifications(data);
1279
+ setUnreadCount(data.filter((n) => !n.read).length);
1280
+ setLoading(false);
1281
+ return;
1282
+ }
1172
1283
  fetchNotifications();
1173
- const interval = setInterval(fetchNotifications, 3e3);
1284
+ const interval = setInterval(fetchNotifications, 1e4);
1174
1285
  return () => clearInterval(interval);
1175
- }, []);
1286
+ }, [useMock, safeMockData]);
1176
1287
  const fetchNotifications = async () => {
1288
+ if (useMock) return;
1177
1289
  try {
1178
1290
  const response = await fetch(`${apiUrl}/notifications`);
1179
1291
  if (response.ok) {
1180
1292
  const data = await response.json();
1181
1293
  setNotifications(data);
1182
1294
  setUnreadCount(data.filter((n) => !n.read).length);
1295
+ } else {
1296
+ throw new Error("API unavailable");
1183
1297
  }
1184
1298
  } catch (error) {
1185
- console.error("Failed to fetch notifications:", error);
1299
+ console.warn("Failed to fetch notifications, using mock data:", error);
1300
+ setNotifications((prev) => prev.length === 0 ? DEFAULT_MOCK_DATA : prev);
1301
+ setUnreadCount((prev) => notifications.length === 0 ? DEFAULT_MOCK_DATA.filter((n) => !n.read).length : prev);
1186
1302
  } finally {
1187
1303
  setLoading(false);
1188
1304
  }
@@ -1209,7 +1325,7 @@ var useNotifications = (apiUrl = "http://localhost:5221") => {
1209
1325
  import { BellIcon, CheckCircleIcon, ExclamationTriangleIcon, InformationCircleIcon, XCircleIcon } from "@heroicons/react/24/outline";
1210
1326
  import { Popover, Transition } from "@headlessui/react";
1211
1327
  import { Fragment as Fragment2 } from "react";
1212
- import { clsx as clsx2 } from "clsx";
1328
+ import { clsx } from "clsx";
1213
1329
  import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
1214
1330
  var NotificationIcon = ({ type }) => {
1215
1331
  switch (type) {
@@ -1223,10 +1339,10 @@ var NotificationIcon = ({ type }) => {
1223
1339
  return /* @__PURE__ */ jsx17(InformationCircleIcon, { className: "h-6 w-6 text-blue-500" });
1224
1340
  }
1225
1341
  };
1226
- var NotificationFeed = () => {
1227
- const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotifications();
1228
- return /* @__PURE__ */ jsx17(Popover, { className: "relative", children: ({ open }) => /* @__PURE__ */ jsxs14(Fragment3, { children: [
1229
- /* @__PURE__ */ jsxs14(Popover.Button, { className: clsx2(
1342
+ var PrimusNotificationFeed = ({ useMock, mockData, apiUrl, className }) => {
1343
+ const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotifications({ useMock, mockData, apiUrl });
1344
+ return /* @__PURE__ */ jsx17(Popover, { className: clsx("relative", className), children: ({ open }) => /* @__PURE__ */ jsxs14(Fragment3, { children: [
1345
+ /* @__PURE__ */ jsxs14(Popover.Button, { className: clsx(
1230
1346
  "relative p-2 rounded-full hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primus-500",
1231
1347
  open && "bg-gray-100"
1232
1348
  ), children: [
@@ -1258,7 +1374,7 @@ var NotificationFeed = () => {
1258
1374
  /* @__PURE__ */ jsx17("div", { className: "max-h-96 overflow-y-auto", children: notifications.length === 0 ? /* @__PURE__ */ jsx17("div", { className: "px-4 py-6 text-center text-sm text-gray-500", children: "No new notifications" }) : /* @__PURE__ */ jsx17("div", { className: "divide-y divide-gray-100", children: notifications.map((notification) => /* @__PURE__ */ jsxs14(
1259
1375
  "div",
1260
1376
  {
1261
- className: clsx2(
1377
+ className: clsx(
1262
1378
  "flex gap-3 px-4 py-4 hover:bg-gray-50 transition-colors cursor-pointer",
1263
1379
  !notification.read && "bg-blue-50/50"
1264
1380
  ),
@@ -1287,7 +1403,13 @@ import { useState as useState16, useEffect as useEffect10, useCallback as useCal
1287
1403
  import { Bell, Send, X, Check, AlertTriangle, Info, AlertCircle } from "lucide-react";
1288
1404
  import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1289
1405
  var API_URL = "http://localhost:5222";
1290
- function PrimusNotificationCenter({ theme: themeOverride, apiUrl = API_URL }) {
1406
+ function PrimusNotificationCenter({
1407
+ theme: themeOverride,
1408
+ apiUrl = API_URL,
1409
+ pollInterval = 3e3,
1410
+ useMock = false,
1411
+ mockData
1412
+ }) {
1291
1413
  const themeContext = usePrimusTheme();
1292
1414
  const theme = themeOverride || themeContext.theme;
1293
1415
  const t = themeColors[theme];
@@ -1311,13 +1433,37 @@ function PrimusNotificationCenter({ theme: themeOverride, apiUrl = API_URL }) {
1311
1433
  }
1312
1434
  }, [apiUrl]);
1313
1435
  useEffect10(() => {
1436
+ if (useMock || mockData) {
1437
+ const next = mockData ?? [];
1438
+ setNotifications(next);
1439
+ setUnreadCount(next.filter((n) => !n.read).length);
1440
+ return;
1441
+ }
1314
1442
  fetchNotifications();
1315
- const interval = setInterval(fetchNotifications, 3e3);
1443
+ const interval = setInterval(fetchNotifications, pollInterval);
1316
1444
  return () => clearInterval(interval);
1317
- }, [fetchNotifications]);
1445
+ }, [fetchNotifications, pollInterval, useMock, mockData]);
1318
1446
  const sendNotification = async () => {
1319
1447
  if (!newTitle.trim() || !newMessage.trim()) return;
1320
1448
  setSending(true);
1449
+ if (useMock || mockData) {
1450
+ const next = {
1451
+ id: `mock-${Date.now()}`,
1452
+ title: newTitle,
1453
+ message: newMessage,
1454
+ type: newType,
1455
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1456
+ read: false
1457
+ };
1458
+ setNotifications((prev) => [next, ...prev]);
1459
+ setUnreadCount((prev) => prev + 1);
1460
+ setNewTitle("");
1461
+ setNewMessage("");
1462
+ setNewType("info");
1463
+ setShowSendForm(false);
1464
+ setSending(false);
1465
+ return;
1466
+ }
1321
1467
  try {
1322
1468
  const response = await fetch(`${apiUrl}/api/notifications`, {
1323
1469
  method: "POST",
@@ -1337,8 +1483,13 @@ function PrimusNotificationCenter({ theme: themeOverride, apiUrl = API_URL }) {
1337
1483
  setSending(false);
1338
1484
  };
1339
1485
  const markAsRead = async (id) => {
1486
+ if (useMock || mockData) {
1487
+ setNotifications((prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n));
1488
+ setUnreadCount((prev) => Math.max(0, prev - 1));
1489
+ return;
1490
+ }
1340
1491
  try {
1341
- await fetch(`${apiUrl}/api/notifications/${id}/read`, { method: "PUT" });
1492
+ await fetch(`${apiUrl}/api/notifications/${id}/read`, { method: "POST" });
1342
1493
  setNotifications((prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n));
1343
1494
  setUnreadCount((prev) => Math.max(0, prev - 1));
1344
1495
  } catch {
@@ -1578,32 +1729,81 @@ import { useState as useState18 } from "react";
1578
1729
 
1579
1730
  // src/components/shared/Input.tsx
1580
1731
  import React14 from "react";
1581
- import { clsx as clsx3 } from "clsx";
1582
- import { twMerge as twMerge2 } from "tailwind-merge";
1732
+ import { clsx as clsx2 } from "clsx";
1733
+ import { XMarkIcon } from "@heroicons/react/20/solid";
1583
1734
  import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1584
- function cn2(...inputs) {
1585
- return twMerge2(clsx3(inputs));
1586
- }
1735
+ var sizeClasses = {
1736
+ sm: "h-8 text-xs",
1737
+ md: "h-10 text-sm",
1738
+ lg: "h-12 text-base"
1739
+ };
1740
+ var iconSizeClasses = {
1741
+ sm: "w-4 h-4 [&>*]:w-full [&>*]:h-full",
1742
+ md: "w-5 h-5 [&>*]:w-full [&>*]:h-full",
1743
+ lg: "w-6 h-6 [&>*]:w-full [&>*]:h-full"
1744
+ };
1587
1745
  var Input = React14.forwardRef(
1588
- ({ className, label, error, ...props }, ref) => {
1589
- return /* @__PURE__ */ jsxs16("div", { className: "w-full", children: [
1590
- label && /* @__PURE__ */ jsx19("label", { className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 mb-2 block text-gray-700", children: label }),
1591
- /* @__PURE__ */ jsx19(
1592
- "input",
1593
- {
1594
- ref,
1595
- className: cn2(
1596
- "flex h-10 w-full rounded-md border border-gray-200 bg-white px-3 py-2 text-sm ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-gray-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
1597
- error && "border-red-500 focus-visible:ring-red-500",
1598
- className
1599
- ),
1600
- ...props
1601
- }
1602
- ),
1603
- error && /* @__PURE__ */ jsx19("p", { className: "text-sm text-red-500 mt-1", children: error })
1746
+ ({ className, style, label, error, disabled, startIcon, endIcon, onClear, value, onChange, size = "md", loading = false, ...props }, ref) => {
1747
+ const hasValue = value !== void 0 && value !== "" && value !== null;
1748
+ return /* @__PURE__ */ jsxs16("div", { className: clsx2("w-full", className), style, children: [
1749
+ label && /* @__PURE__ */ jsx19("label", { className: clsx2(
1750
+ "block font-medium mb-1.5",
1751
+ size === "sm" ? "text-xs" : "text-sm",
1752
+ disabled ? "text-gray-400 opacity-70" : "text-gray-700"
1753
+ ), children: label }),
1754
+ /* @__PURE__ */ jsxs16("div", { className: clsx2(
1755
+ "relative flex items-center w-full rounded-lg transition-all duration-200 ease-in-out bg-white overflow-hidden",
1756
+ "border",
1757
+ error ? "border-red-500 hover:border-red-600 focus-within:ring-2 focus-within:ring-red-500/20 focus-within:border-red-500" : "border-gray-200 hover:border-gray-300 focus-within:ring-2 focus-within:ring-primus-500/20 focus-within:border-primus-500",
1758
+ disabled && "bg-gray-50 opacity-60 cursor-not-allowed"
1759
+ ), children: [
1760
+ startIcon && /* @__PURE__ */ jsx19("div", { className: clsx2(
1761
+ "flex-shrink-0 pl-3 pr-2 text-gray-400 select-none pointer-events-none flex items-center justify-center",
1762
+ iconSizeClasses[size]
1763
+ ), children: startIcon }),
1764
+ /* @__PURE__ */ jsx19(
1765
+ "input",
1766
+ {
1767
+ ref,
1768
+ disabled,
1769
+ value,
1770
+ onChange,
1771
+ className: clsx2(
1772
+ "flex-1 w-full border-none bg-transparent p-0 placeholder:text-gray-400 focus:ring-0 outline-none",
1773
+ sizeClasses[size],
1774
+ // Adjust padding based on icon presence
1775
+ !startIcon && "pl-3",
1776
+ !endIcon && !onClear && !loading && "pr-3"
1777
+ ),
1778
+ ...props
1779
+ }
1780
+ ),
1781
+ onClear && hasValue && !disabled && !loading && /* @__PURE__ */ jsx19("div", { className: "flex-shrink-0 pr-2 flex items-center justify-center", children: /* @__PURE__ */ jsx19(
1782
+ "button",
1783
+ {
1784
+ type: "button",
1785
+ onClick: (e) => {
1786
+ e.stopPropagation();
1787
+ onClear();
1788
+ },
1789
+ className: "p-1 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors",
1790
+ children: /* @__PURE__ */ jsx19(XMarkIcon, { className: "h-4 w-4" })
1791
+ }
1792
+ ) }),
1793
+ loading && /* @__PURE__ */ jsx19("div", { className: "flex-shrink-0 pr-3 pl-2 flex items-center justify-center", children: /* @__PURE__ */ jsxs16("svg", { className: "animate-spin h-5 w-5 text-primus-500", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
1794
+ /* @__PURE__ */ jsx19("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1795
+ /* @__PURE__ */ jsx19("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
1796
+ ] }) }),
1797
+ endIcon && !loading && (onClear ? !hasValue : true) && /* @__PURE__ */ jsx19("div", { className: clsx2(
1798
+ "flex-shrink-0 pr-3 pl-2 text-gray-400 select-none pointer-events-none flex items-center justify-center",
1799
+ iconSizeClasses[size]
1800
+ ), children: endIcon })
1801
+ ] }),
1802
+ error && /* @__PURE__ */ jsx19("p", { className: "mt-1.5 text-xs text-red-500 flex items-center gap-1 animate-in slide-in-from-top-1 fade-in duration-200", children: error })
1604
1803
  ] });
1605
1804
  }
1606
1805
  );
1806
+ Input.displayName = "Input";
1607
1807
 
1608
1808
  // src/components/payments/CheckoutForm.tsx
1609
1809
  import { LockClosedIcon, CheckCircleIcon as CheckCircleIcon2, XCircleIcon as XCircleIcon2 } from "@heroicons/react/24/solid";
@@ -1749,22 +1949,22 @@ var CheckoutForm = ({
1749
1949
  import {
1750
1950
  DocumentArrowDownIcon,
1751
1951
  PrinterIcon,
1752
- XMarkIcon
1952
+ XMarkIcon as XMarkIcon2
1753
1953
  } from "@heroicons/react/24/outline";
1754
1954
  import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1755
1955
  var DocumentViewer = ({
1756
- document,
1956
+ document: document2,
1757
1957
  onClose,
1758
1958
  onDownload
1759
1959
  }) => {
1760
1960
  const renderContent = () => {
1761
- switch (document.type) {
1961
+ switch (document2.type) {
1762
1962
  case "image":
1763
1963
  return /* @__PURE__ */ jsx21(
1764
1964
  "img",
1765
1965
  {
1766
- src: document.url,
1767
- alt: document.name,
1966
+ src: document2.url,
1967
+ alt: document2.name,
1768
1968
  className: "max-w-full max-h-[80vh] object-contain mx-auto shadow-lg rounded"
1769
1969
  }
1770
1970
  );
@@ -1772,14 +1972,14 @@ var DocumentViewer = ({
1772
1972
  return /* @__PURE__ */ jsx21("div", { className: "bg-gray-100 p-8 rounded-lg text-center h-[600px] flex items-center justify-center border-2 border-dashed border-gray-300", children: /* @__PURE__ */ jsxs18("div", { className: "text-gray-500", children: [
1773
1973
  /* @__PURE__ */ jsx21(DocumentArrowDownIcon, { className: "h-16 w-16 mx-auto mb-4 text-gray-400" }),
1774
1974
  /* @__PURE__ */ jsx21("p", { className: "font-medium", children: "PDF Preview" }),
1775
- /* @__PURE__ */ jsx21("p", { className: "text-sm mt-2", children: document.name }),
1975
+ /* @__PURE__ */ jsx21("p", { className: "text-sm mt-2", children: document2.name }),
1776
1976
  /* @__PURE__ */ jsx21(Button, { variant: "outline", size: "sm", className: "mt-4", onClick: onDownload, children: "Download to view" })
1777
1977
  ] }) });
1778
1978
  default:
1779
1979
  return /* @__PURE__ */ jsxs18("div", { className: "bg-white p-8 rounded shadow border border-gray-200 h-[600px] overflow-auto font-mono text-sm leading-relaxed", children: [
1780
1980
  /* @__PURE__ */ jsxs18("p", { children: [
1781
1981
  "Document Content: ",
1782
- document.name
1982
+ document2.name
1783
1983
  ] }),
1784
1984
  /* @__PURE__ */ jsx21("p", { className: "mt-4 text-gray-500", children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." })
1785
1985
  ] });
@@ -1788,13 +1988,13 @@ var DocumentViewer = ({
1788
1988
  return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col h-full bg-gray-50 rounded-lg overflow-hidden border border-gray-200", children: [
1789
1989
  /* @__PURE__ */ jsxs18("div", { className: "bg-white border-b border-gray-200 px-4 py-3 flex items-center justify-between shadow-sm", children: [
1790
1990
  /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-3", children: [
1791
- /* @__PURE__ */ jsx21("div", { className: "h-8 w-8 bg-primus-100 rounded flex items-center justify-center text-primus-700", children: /* @__PURE__ */ jsx21("span", { className: "uppercase text-xs font-bold", children: document.type }) }),
1991
+ /* @__PURE__ */ jsx21("div", { className: "h-8 w-8 bg-primus-100 rounded flex items-center justify-center text-primus-700", children: /* @__PURE__ */ jsx21("span", { className: "uppercase text-xs font-bold", children: document2.type }) }),
1792
1992
  /* @__PURE__ */ jsxs18("div", { children: [
1793
- /* @__PURE__ */ jsx21("h3", { className: "text-sm font-semibold text-gray-900", children: document.name }),
1794
- document.size && /* @__PURE__ */ jsxs18("p", { className: "text-xs text-gray-500", children: [
1795
- document.size,
1993
+ /* @__PURE__ */ jsx21("h3", { className: "text-sm font-semibold text-gray-900", children: document2.name }),
1994
+ document2.size && /* @__PURE__ */ jsxs18("p", { className: "text-xs text-gray-500", children: [
1995
+ document2.size,
1796
1996
  " \u2022 ",
1797
- document.date
1997
+ document2.date
1798
1998
  ] })
1799
1999
  ] })
1800
2000
  ] }),
@@ -1802,7 +2002,7 @@ var DocumentViewer = ({
1802
2002
  /* @__PURE__ */ jsx21(Button, { variant: "ghost", size: "sm", onClick: () => window.print(), children: /* @__PURE__ */ jsx21(PrinterIcon, { className: "h-4 w-4" }) }),
1803
2003
  /* @__PURE__ */ jsx21(Button, { variant: "ghost", size: "sm", onClick: onDownload, children: /* @__PURE__ */ jsx21(DocumentArrowDownIcon, { className: "h-4 w-4" }) }),
1804
2004
  onClose && /* @__PURE__ */ jsx21("div", { className: "h-6 w-px bg-gray-200 mx-1" }),
1805
- onClose && /* @__PURE__ */ jsx21(Button, { variant: "ghost", size: "sm", onClick: onClose, className: "text-gray-400 hover:text-red-500", children: /* @__PURE__ */ jsx21(XMarkIcon, { className: "h-5 w-5" }) })
2005
+ onClose && /* @__PURE__ */ jsx21(Button, { variant: "ghost", size: "sm", onClick: onClose, className: "text-gray-400 hover:text-red-500", children: /* @__PURE__ */ jsx21(XMarkIcon2, { className: "h-5 w-5" }) })
1806
2006
  ] })
1807
2007
  ] }),
1808
2008
  /* @__PURE__ */ jsx21("div", { className: "flex-1 overflow-auto p-6 flex flex-col items-center justify-center", children: renderContent() })
@@ -1810,7 +2010,7 @@ var DocumentViewer = ({
1810
2010
  };
1811
2011
 
1812
2012
  // src/components/banking/cards/CreditCardVisual.tsx
1813
- import { clsx as clsx4 } from "clsx";
2013
+ import { clsx as clsx3 } from "clsx";
1814
2014
  import { WifiIcon } from "@heroicons/react/24/outline";
1815
2015
  import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
1816
2016
  var CreditCardVisual = ({
@@ -1832,7 +2032,7 @@ var CreditCardVisual = ({
1832
2032
  return "bg-gradient-to-br from-gray-900 to-gray-800";
1833
2033
  }
1834
2034
  };
1835
- return /* @__PURE__ */ jsxs19("div", { className: clsx4(
2035
+ return /* @__PURE__ */ jsxs19("div", { className: clsx3(
1836
2036
  "w-80 h-48 rounded-2xl p-6 text-white shadow-xl relative overflow-hidden transition-transform hover:scale-105 duration-300",
1837
2037
  getBackground()
1838
2038
  ), children: [
@@ -1866,7 +2066,7 @@ import {
1866
2066
  ArrowUpRightIcon,
1867
2067
  ShoppingBagIcon
1868
2068
  } from "@heroicons/react/24/outline";
1869
- import { clsx as clsx5 } from "clsx";
2069
+ import { clsx as clsx4 } from "clsx";
1870
2070
  import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
1871
2071
  var TransactionHistory = ({
1872
2072
  transactions,
@@ -1889,7 +2089,7 @@ var TransactionHistory = ({
1889
2089
  className: "px-6 py-4 flex items-center justify-between hover:bg-gray-50 cursor-pointer transition-colors",
1890
2090
  children: [
1891
2091
  /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-4", children: [
1892
- /* @__PURE__ */ jsx23("div", { className: clsx5(
2092
+ /* @__PURE__ */ jsx23("div", { className: clsx4(
1893
2093
  "h-10 w-10 rounded-full flex items-center justify-center",
1894
2094
  t.type === "credit" ? "bg-green-100" : "bg-gray-100"
1895
2095
  ), children: getIcon(t) }),
@@ -1899,7 +2099,7 @@ var TransactionHistory = ({
1899
2099
  ] })
1900
2100
  ] }),
1901
2101
  /* @__PURE__ */ jsxs20("div", { className: "text-right", children: [
1902
- /* @__PURE__ */ jsxs20("p", { className: clsx5(
2102
+ /* @__PURE__ */ jsxs20("p", { className: clsx4(
1903
2103
  "text-sm font-semibold",
1904
2104
  t.type === "credit" ? "text-green-600" : "text-gray-900"
1905
2105
  ), children: [
@@ -1916,7 +2116,7 @@ var TransactionHistory = ({
1916
2116
  };
1917
2117
 
1918
2118
  // src/components/insurance/policies/PolicyCard.tsx
1919
- import { clsx as clsx6 } from "clsx";
2119
+ import { clsx as clsx5 } from "clsx";
1920
2120
  import { ShieldCheckIcon, DocumentTextIcon } from "@heroicons/react/24/outline";
1921
2121
  import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
1922
2122
  var PolicyCard = ({
@@ -1936,7 +2136,7 @@ var PolicyCard = ({
1936
2136
  " Insurance"
1937
2137
  ] })
1938
2138
  ] }),
1939
- /* @__PURE__ */ jsx24("span", { className: clsx6(
2139
+ /* @__PURE__ */ jsx24("span", { className: clsx5(
1940
2140
  "px-2.5 py-0.5 rounded-full text-xs font-medium uppercase tracking-wide",
1941
2141
  status === "active" ? "bg-green-100 text-green-800" : status === "pending" ? "bg-yellow-100 text-yellow-800" : "bg-gray-100 text-gray-800"
1942
2142
  ), children: status })
@@ -1975,7 +2175,7 @@ var PolicyCard = ({
1975
2175
  };
1976
2176
 
1977
2177
  // src/components/insurance/claims/ClaimStatusTracker.tsx
1978
- import { clsx as clsx7 } from "clsx";
2178
+ import { clsx as clsx6 } from "clsx";
1979
2179
  import { CheckIcon } from "@heroicons/react/24/solid";
1980
2180
  import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
1981
2181
  var ClaimStatusTracker = ({
@@ -1990,14 +2190,14 @@ var ClaimStatusTracker = ({
1990
2190
  claimId
1991
2191
  ] })
1992
2192
  ] }),
1993
- /* @__PURE__ */ jsx25("nav", { "aria-label": "Progress", children: /* @__PURE__ */ jsx25("ol", { role: "list", className: "overflow-hidden", children: steps.map((step, stepIdx) => /* @__PURE__ */ jsxs22("li", { className: clsx7(
2193
+ /* @__PURE__ */ jsx25("nav", { "aria-label": "Progress", children: /* @__PURE__ */ jsx25("ol", { role: "list", className: "overflow-hidden", children: steps.map((step, stepIdx) => /* @__PURE__ */ jsxs22("li", { className: clsx6(
1994
2194
  "relative pb-10",
1995
2195
  stepIdx === steps.length - 1 ? "pb-0" : ""
1996
2196
  ), children: [
1997
2197
  stepIdx !== steps.length - 1 ? /* @__PURE__ */ jsx25(
1998
2198
  "div",
1999
2199
  {
2000
- className: clsx7(
2200
+ className: clsx6(
2001
2201
  "absolute top-4 left-4 -ml-px h-full w-0.5",
2002
2202
  step.status === "completed" ? "bg-primus-600" : "bg-gray-200"
2003
2203
  ),
@@ -2005,12 +2205,12 @@ var ClaimStatusTracker = ({
2005
2205
  }
2006
2206
  ) : null,
2007
2207
  /* @__PURE__ */ jsxs22("div", { className: "relative flex items-start group", children: [
2008
- /* @__PURE__ */ jsx25("span", { className: "h-9 flex items-center", children: /* @__PURE__ */ jsx25("span", { className: clsx7(
2208
+ /* @__PURE__ */ jsx25("span", { className: "h-9 flex items-center", children: /* @__PURE__ */ jsx25("span", { className: clsx6(
2009
2209
  "relative z-10 w-8 h-8 flex items-center justify-center rounded-full ring-1 ring-white",
2010
2210
  step.status === "completed" ? "bg-primus-600" : step.status === "current" ? "bg-white border-2 border-primus-600" : "bg-white border-2 border-gray-300"
2011
2211
  ), children: step.status === "completed" ? /* @__PURE__ */ jsx25(CheckIcon, { className: "w-5 h-5 text-white", "aria-hidden": "true" }) : step.status === "current" ? /* @__PURE__ */ jsx25("span", { className: "h-2.5 w-2.5 bg-primus-600 rounded-full" }) : null }) }),
2012
2212
  /* @__PURE__ */ jsxs22("span", { className: "ml-4 min-w-0 flex flex-col", children: [
2013
- /* @__PURE__ */ jsx25("span", { className: clsx7(
2213
+ /* @__PURE__ */ jsx25("span", { className: clsx6(
2014
2214
  "text-sm font-medium",
2015
2215
  step.status === "upcoming" ? "text-gray-500" : "text-gray-900"
2016
2216
  ), children: step.label }),
@@ -2166,9 +2366,14 @@ var PrimusSidebar = ({
2166
2366
  logo && /* @__PURE__ */ jsx29("div", { className: "h-20 flex items-center px-6 relative z-10 border-b border-white/5", children: logo }),
2167
2367
  /* @__PURE__ */ jsx29("nav", { className: "flex-1 py-6 px-3 overflow-y-auto relative z-10", children: /* @__PURE__ */ jsx29("ul", { className: "space-y-1", children: items.map((item) => {
2168
2368
  const isActive = activeId === item.id || item.active;
2369
+ const link = item.href ?? item.route;
2370
+ const Wrapper = link ? "a" : "button";
2169
2371
  return /* @__PURE__ */ jsx29("li", { children: /* @__PURE__ */ jsxs26(
2170
- "button",
2372
+ Wrapper,
2171
2373
  {
2374
+ href: link,
2375
+ target: item.target,
2376
+ rel: item.target === "_blank" ? "noreferrer" : void 0,
2172
2377
  onClick: () => {
2173
2378
  item.onClick?.();
2174
2379
  onItemClick?.(item);
@@ -2227,7 +2432,7 @@ var PrimusHeader = ({
2227
2432
  };
2228
2433
 
2229
2434
  // src/components/crud/PrimusDataTable.tsx
2230
- import { useState as useState21, useMemo } from "react";
2435
+ import { useState as useState21, useMemo as useMemo2 } from "react";
2231
2436
  import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
2232
2437
  function PrimusDataTable({
2233
2438
  data,
@@ -2241,12 +2446,17 @@ function PrimusDataTable({
2241
2446
  actions,
2242
2447
  emptyMessage = "No data available",
2243
2448
  searchPlaceholder = "Filter...",
2244
- searchable = true
2449
+ searchable = true,
2450
+ paginated = false,
2451
+ pageSize = 10,
2452
+ pageIndex,
2453
+ onPageChange
2245
2454
  }) {
2246
2455
  const [search, setSearch] = useState21("");
2247
2456
  const [sortKey, setSortKey] = useState21(null);
2248
2457
  const [sortDir, setSortDir] = useState21("asc");
2249
- const filteredData = useMemo(() => {
2458
+ const [internalPageIndex, setInternalPageIndex] = useState21(0);
2459
+ const filteredData = useMemo2(() => {
2250
2460
  let result = [...data];
2251
2461
  if (search) {
2252
2462
  const lowerSearch = search.toLowerCase();
@@ -2273,16 +2483,33 @@ function PrimusDataTable({
2273
2483
  setSortKey(key);
2274
2484
  setSortDir("asc");
2275
2485
  }
2486
+ if (paginated) {
2487
+ goToPage(0);
2488
+ }
2489
+ };
2490
+ const effectivePageIndex = pageIndex ?? internalPageIndex;
2491
+ const totalPages = Math.max(1, Math.ceil(filteredData.length / Math.max(pageSize, 1)));
2492
+ const currentPageIndex = Math.min(Math.max(effectivePageIndex, 0), totalPages - 1);
2493
+ const pageData = paginated ? filteredData.slice(currentPageIndex * pageSize, currentPageIndex * pageSize + pageSize) : filteredData;
2494
+ const selectionScope = paginated ? pageData : filteredData;
2495
+ const isScopeSelected = selectionScope.length > 0 && selectionScope.every((row) => selectedKeys.includes(row[rowKey]));
2496
+ const goToPage = (nextIndex) => {
2497
+ const clamped = Math.min(Math.max(nextIndex, 0), totalPages - 1);
2498
+ if (pageIndex === void 0) {
2499
+ setInternalPageIndex(clamped);
2500
+ }
2501
+ onPageChange?.({ pageIndex: clamped, pageSize });
2276
2502
  };
2277
2503
  const toggleSelect = (key) => {
2278
2504
  const newKeys = selectedKeys.includes(key) ? selectedKeys.filter((k) => k !== key) : [...selectedKeys, key];
2279
2505
  onSelectionChange?.(newKeys);
2280
2506
  };
2281
2507
  const toggleSelectAll = () => {
2282
- if (selectedKeys.length === filteredData.length) {
2508
+ const scopeKeys = selectionScope.map((row) => row[rowKey]);
2509
+ if (isScopeSelected) {
2283
2510
  onSelectionChange?.([]);
2284
2511
  } else {
2285
- onSelectionChange?.(filteredData.map((row) => row[rowKey]));
2512
+ onSelectionChange?.(scopeKeys);
2286
2513
  }
2287
2514
  };
2288
2515
  return /* @__PURE__ */ jsxs28("div", { className: "flex flex-col space-y-4", children: [
@@ -2294,7 +2521,12 @@ function PrimusDataTable({
2294
2521
  type: "text",
2295
2522
  placeholder: searchPlaceholder,
2296
2523
  value: search,
2297
- onChange: (e) => setSearch(e.target.value),
2524
+ onChange: (e) => {
2525
+ setSearch(e.target.value);
2526
+ if (paginated) {
2527
+ goToPage(0);
2528
+ }
2529
+ },
2298
2530
  className: "w-64 pl-10 pr-4 py-2 bg-white/5 border border-white/10 rounded-lg text-sm text-gray-200 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-purple-500/50 focus:bg-white/10 transition-all hover:bg-white/10"
2299
2531
  }
2300
2532
  )
@@ -2305,7 +2537,7 @@ function PrimusDataTable({
2305
2537
  "input",
2306
2538
  {
2307
2539
  type: "checkbox",
2308
- checked: selectedKeys.length === filteredData.length && filteredData.length > 0,
2540
+ checked: isScopeSelected,
2309
2541
  onChange: toggleSelectAll,
2310
2542
  className: "rounded border-gray-600 bg-gray-800 text-purple-600 focus:ring-offset-gray-900 focus:ring-purple-500 transition-colors cursor-pointer"
2311
2543
  }
@@ -2328,7 +2560,7 @@ function PrimusDataTable({
2328
2560
  /* @__PURE__ */ jsx31("tbody", { className: "divide-y divide-white/5", children: loading ? /* @__PURE__ */ jsx31("tr", { children: /* @__PURE__ */ jsx31("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center justify-center gap-3", children: [
2329
2561
  /* @__PURE__ */ jsx31("div", { className: "w-6 h-6 border-2 border-purple-500/50 border-t-purple-500 rounded-full animate-spin" }),
2330
2562
  /* @__PURE__ */ jsx31("span", { className: "text-sm font-medium", children: "Loading data..." })
2331
- ] }) }) }) : filteredData.length === 0 ? /* @__PURE__ */ jsx31("tr", { children: /* @__PURE__ */ jsx31("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ jsx31("p", { className: "text-sm", children: emptyMessage }) }) }) : filteredData.map((row) => /* @__PURE__ */ jsxs28(
2563
+ ] }) }) }) : filteredData.length === 0 ? /* @__PURE__ */ jsx31("tr", { children: /* @__PURE__ */ jsx31("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ jsx31("p", { className: "text-sm", children: emptyMessage }) }) }) : pageData.map((row) => /* @__PURE__ */ jsxs28(
2332
2564
  "tr",
2333
2565
  {
2334
2566
  onClick: () => onRowClick?.(row),
@@ -2353,7 +2585,35 @@ function PrimusDataTable({
2353
2585
  },
2354
2586
  String(row[rowKey])
2355
2587
  )) })
2356
- ] }) }) })
2588
+ ] }) }) }),
2589
+ paginated && totalPages > 1 && /* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between text-sm text-gray-400 px-2", children: [
2590
+ /* @__PURE__ */ jsx31(
2591
+ "button",
2592
+ {
2593
+ type: "button",
2594
+ onClick: () => goToPage(currentPageIndex - 1),
2595
+ disabled: currentPageIndex === 0,
2596
+ className: "px-3 py-2 rounded-lg border border-white/10 bg-white/5 hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed",
2597
+ children: "Previous"
2598
+ }
2599
+ ),
2600
+ /* @__PURE__ */ jsxs28("span", { children: [
2601
+ "Page ",
2602
+ currentPageIndex + 1,
2603
+ " of ",
2604
+ totalPages
2605
+ ] }),
2606
+ /* @__PURE__ */ jsx31(
2607
+ "button",
2608
+ {
2609
+ type: "button",
2610
+ onClick: () => goToPage(currentPageIndex + 1),
2611
+ disabled: currentPageIndex >= totalPages - 1,
2612
+ className: "px-3 py-2 rounded-lg border border-white/10 bg-white/5 hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed",
2613
+ children: "Next"
2614
+ }
2615
+ )
2616
+ ] })
2357
2617
  ] });
2358
2618
  }
2359
2619
 
@@ -2368,7 +2628,7 @@ var PrimusModal = ({
2368
2628
  size = "md"
2369
2629
  }) => {
2370
2630
  if (!open) return null;
2371
- const sizeClasses = {
2631
+ const sizeClasses2 = {
2372
2632
  sm: "max-w-sm",
2373
2633
  md: "max-w-md",
2374
2634
  lg: "max-w-lg",
@@ -2382,7 +2642,7 @@ var PrimusModal = ({
2382
2642
  onClick: onClose
2383
2643
  }
2384
2644
  ),
2385
- /* @__PURE__ */ jsxs29("div", { className: `relative w-full ${sizeClasses[size]} mx-4 bg-gray-800 rounded-xl border border-gray-700 shadow-2xl`, children: [
2645
+ /* @__PURE__ */ jsxs29("div", { className: `relative w-full ${sizeClasses2[size]} mx-4 bg-gray-800 rounded-xl border border-gray-700 shadow-2xl`, children: [
2386
2646
  title && /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-700", children: [
2387
2647
  /* @__PURE__ */ jsx32("h2", { className: "text-lg font-semibold text-white", children: title }),
2388
2648
  /* @__PURE__ */ jsx32(
@@ -2422,12 +2682,28 @@ var PrimusStatCard = ({
2422
2682
  neutral: "\u2192"
2423
2683
  };
2424
2684
  const renderSparkline = () => {
2425
- return /* @__PURE__ */ jsxs30("svg", { className: "w-full h-12 opacity-50 absolute bottom-0 left-0", preserveAspectRatio: "none", "data-trend": trend.join(","), children: [
2426
- /* @__PURE__ */ jsx33("path", { d: "M0 40 Q 20 20 40 40 T 80 40 T 120 40 T 160 30 V 50 H 0 Z", fill: `url(#gradient-${title.replace(/\s/g, "")})`, stroke: "none" }),
2427
- /* @__PURE__ */ jsx33("defs", { children: /* @__PURE__ */ jsxs30("linearGradient", { id: `gradient-${title.replace(/\s/g, "")}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2428
- /* @__PURE__ */ jsx33("stop", { offset: "0%", stopColor: "currentColor", stopOpacity: "0.2" }),
2685
+ if (!trend || trend.length === 0) {
2686
+ return null;
2687
+ }
2688
+ const max = Math.max(...trend);
2689
+ const min = Math.min(...trend);
2690
+ const range = max - min || 1;
2691
+ const divisor = trend.length > 1 ? trend.length - 1 : 1;
2692
+ const points = trend.map((value2, index) => {
2693
+ const x = index / divisor * 100;
2694
+ const y = 100 - (value2 - min) / range * 100;
2695
+ return { x, y };
2696
+ });
2697
+ const linePath = points.map((point, index) => `${index === 0 ? "M" : "L"} ${point.x} ${point.y}`).join(" ");
2698
+ const areaPath = `${linePath} L 100 100 L 0 100 Z`;
2699
+ const gradientId = `gradient-${title.replace(/\s/g, "")}`;
2700
+ return /* @__PURE__ */ jsxs30("svg", { className: "w-full h-12 opacity-60 absolute bottom-0 left-0", viewBox: "0 0 100 100", preserveAspectRatio: "none", "data-trend": trend.join(","), children: [
2701
+ /* @__PURE__ */ jsx33("defs", { children: /* @__PURE__ */ jsxs30("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2702
+ /* @__PURE__ */ jsx33("stop", { offset: "0%", stopColor: "currentColor", stopOpacity: "0.25" }),
2429
2703
  /* @__PURE__ */ jsx33("stop", { offset: "100%", stopColor: "currentColor", stopOpacity: "0" })
2430
- ] }) })
2704
+ ] }) }),
2705
+ /* @__PURE__ */ jsx33("path", { d: areaPath, fill: `url(#${gradientId})`, stroke: "none" }),
2706
+ /* @__PURE__ */ jsx33("path", { d: linePath, fill: "none", stroke: "currentColor", strokeWidth: "1.8", opacity: "0.6" })
2431
2707
  ] });
2432
2708
  };
2433
2709
  return /* @__PURE__ */ jsxs30("div", { className: "relative overflow-hidden bg-slate-900/40 backdrop-blur-md rounded-2xl border border-white/5 hover:border-white/10 transition-all duration-300 group", children: [
@@ -2481,12 +2757,1425 @@ var DashboardGrid = ({
2481
2757
  };
2482
2758
  return /* @__PURE__ */ jsx33("div", { className: `grid gap-6 ${colClasses[columns]}`, children });
2483
2759
  };
2760
+
2761
+ // src/components/dashboard/PrimusActivityFeed.tsx
2762
+ import { useMemo as useMemo3 } from "react";
2763
+ import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
2764
+ var statusClasses = {
2765
+ success: "bg-emerald-500/10 text-emerald-300 border-emerald-500/30",
2766
+ warning: "bg-amber-500/10 text-amber-300 border-amber-500/30",
2767
+ error: "bg-rose-500/10 text-rose-300 border-rose-500/30",
2768
+ info: "bg-blue-500/10 text-blue-300 border-blue-500/30"
2769
+ };
2770
+ var PrimusActivityFeed = ({
2771
+ items,
2772
+ maxItems = 10,
2773
+ showTimestamps = true,
2774
+ groupByDate = false,
2775
+ loading = false
2776
+ }) => {
2777
+ const visibleItems = useMemo3(() => items.slice(0, maxItems), [items, maxItems]);
2778
+ const groups = useMemo3(() => {
2779
+ if (!groupByDate) {
2780
+ return [{ label: "", items: visibleItems }];
2781
+ }
2782
+ const map = /* @__PURE__ */ new Map();
2783
+ visibleItems.forEach((item) => {
2784
+ const label = formatDate(item.timestamp);
2785
+ const list = map.get(label) ?? [];
2786
+ list.push(item);
2787
+ map.set(label, list);
2788
+ });
2789
+ return Array.from(map.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
2790
+ }, [groupByDate, visibleItems]);
2791
+ if (loading) {
2792
+ return /* @__PURE__ */ jsx34("div", { className: "rounded-xl border border-white/10 bg-slate-900/40 p-6 text-sm text-gray-400", children: "Loading activity..." });
2793
+ }
2794
+ return /* @__PURE__ */ jsx34("div", { className: "rounded-xl border border-white/10 bg-slate-900/40 p-6 space-y-6", children: groups.map((group, index) => /* @__PURE__ */ jsxs31("div", { children: [
2795
+ group.label && /* @__PURE__ */ jsx34("div", { className: "text-xs uppercase tracking-wide text-gray-500 mb-3", children: group.label }),
2796
+ /* @__PURE__ */ jsx34("div", { className: "space-y-4", children: group.items.map((item, itemIndex) => /* @__PURE__ */ jsxs31("div", { className: "flex items-start gap-4", children: [
2797
+ /* @__PURE__ */ jsx34("div", { className: `mt-1 h-2.5 w-2.5 rounded-full border ${statusClasses[item.status ?? "info"]}` }),
2798
+ /* @__PURE__ */ jsxs31("div", { className: "flex-1", children: [
2799
+ /* @__PURE__ */ jsxs31("div", { className: "flex items-center justify-between gap-4", children: [
2800
+ /* @__PURE__ */ jsx34("div", { className: "text-sm font-medium text-gray-100", children: item.title }),
2801
+ showTimestamps && /* @__PURE__ */ jsx34("div", { className: "text-xs text-gray-500", children: formatTime(item.timestamp) })
2802
+ ] }),
2803
+ item.description && /* @__PURE__ */ jsx34("div", { className: "text-xs text-gray-400 mt-1", children: item.description })
2804
+ ] })
2805
+ ] }, item.id ?? `${itemIndex}-${item.title}`)) })
2806
+ ] }, `${group.label}-${index}`)) });
2807
+ };
2808
+ var formatDate = (value) => {
2809
+ if (!value) {
2810
+ return "";
2811
+ }
2812
+ const date = value instanceof Date ? value : new Date(value);
2813
+ if (Number.isNaN(date.getTime())) {
2814
+ return String(value);
2815
+ }
2816
+ return date.toLocaleDateString();
2817
+ };
2818
+ var formatTime = (value) => {
2819
+ if (!value) {
2820
+ return "";
2821
+ }
2822
+ const date = value instanceof Date ? value : new Date(value);
2823
+ if (Number.isNaN(date.getTime())) {
2824
+ return "";
2825
+ }
2826
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
2827
+ };
2828
+
2829
+ // src/components/charts/PrimusChartBase.tsx
2830
+ import { useEffect as useEffect14, useMemo as useMemo4, useRef } from "react";
2831
+ import {
2832
+ Chart,
2833
+ registerables
2834
+ } from "chart.js";
2835
+ import { jsx as jsx35 } from "react/jsx-runtime";
2836
+ var registered = false;
2837
+ var ensureRegistered = () => {
2838
+ if (!registered) {
2839
+ Chart.register(...registerables);
2840
+ registered = true;
2841
+ }
2842
+ };
2843
+ var PrimusChartBase = ({
2844
+ type,
2845
+ data,
2846
+ labels = [],
2847
+ series = [],
2848
+ options,
2849
+ responsive = true,
2850
+ maintainAspectRatio = false,
2851
+ legend = true,
2852
+ height = 300,
2853
+ width,
2854
+ ariaLabel = "Chart",
2855
+ className,
2856
+ datasetTransform
2857
+ }) => {
2858
+ const canvasRef = useRef(null);
2859
+ const chartRef = useRef(null);
2860
+ const builtData = useMemo4(() => {
2861
+ if (data) {
2862
+ return data;
2863
+ }
2864
+ const datasets = series.map((item) => {
2865
+ const color = item.color ?? item.borderColor ?? "#3b82f6";
2866
+ const background = item.backgroundColor ?? color;
2867
+ let dataset = {
2868
+ label: item.name,
2869
+ data: item.data,
2870
+ borderColor: item.borderColor ?? color,
2871
+ backgroundColor: background,
2872
+ fill: item.fill
2873
+ };
2874
+ if (datasetTransform) {
2875
+ dataset = datasetTransform(dataset);
2876
+ }
2877
+ return dataset;
2878
+ });
2879
+ return {
2880
+ labels,
2881
+ datasets
2882
+ };
2883
+ }, [data, labels, series, datasetTransform]);
2884
+ const builtOptions = useMemo4(() => {
2885
+ const mergedPlugins = {
2886
+ ...options?.plugins ?? {},
2887
+ legend: {
2888
+ display: legend,
2889
+ ...options?.plugins?.legend ?? {}
2890
+ }
2891
+ };
2892
+ return {
2893
+ responsive,
2894
+ maintainAspectRatio,
2895
+ ...options ?? {},
2896
+ plugins: mergedPlugins,
2897
+ scales: {
2898
+ ...options?.scales ?? {}
2899
+ }
2900
+ };
2901
+ }, [options, responsive, maintainAspectRatio, legend]);
2902
+ useEffect14(() => {
2903
+ ensureRegistered();
2904
+ const canvas = canvasRef.current;
2905
+ if (!canvas) {
2906
+ return void 0;
2907
+ }
2908
+ const ctx = canvas.getContext("2d");
2909
+ if (!ctx) {
2910
+ return void 0;
2911
+ }
2912
+ if (chartRef.current) {
2913
+ chartRef.current.destroy();
2914
+ chartRef.current = null;
2915
+ }
2916
+ chartRef.current = new Chart(ctx, {
2917
+ type,
2918
+ data: builtData,
2919
+ options: builtOptions
2920
+ });
2921
+ return () => {
2922
+ chartRef.current?.destroy();
2923
+ chartRef.current = null;
2924
+ };
2925
+ }, [type, builtData, builtOptions]);
2926
+ return /* @__PURE__ */ jsx35("div", { className, style: { height, width }, children: /* @__PURE__ */ jsx35("canvas", { ref: canvasRef, "aria-label": ariaLabel, role: "img" }) });
2927
+ };
2928
+
2929
+ // src/components/charts/PrimusLineChart.tsx
2930
+ import { jsx as jsx36 } from "react/jsx-runtime";
2931
+ var PrimusLineChart = (props) => {
2932
+ return /* @__PURE__ */ jsx36(
2933
+ PrimusChartBase,
2934
+ {
2935
+ ...props,
2936
+ type: "line",
2937
+ datasetTransform: (dataset) => ({
2938
+ tension: 0.35,
2939
+ pointRadius: 2,
2940
+ pointHoverRadius: 4,
2941
+ borderWidth: 2,
2942
+ fill: dataset.fill ?? false,
2943
+ ...dataset
2944
+ })
2945
+ }
2946
+ );
2947
+ };
2948
+
2949
+ // src/components/charts/PrimusAreaChart.tsx
2950
+ import { jsx as jsx37 } from "react/jsx-runtime";
2951
+ var PrimusAreaChart = (props) => {
2952
+ return /* @__PURE__ */ jsx37(
2953
+ PrimusChartBase,
2954
+ {
2955
+ ...props,
2956
+ type: "line",
2957
+ datasetTransform: (dataset) => ({
2958
+ tension: 0.35,
2959
+ pointRadius: 2,
2960
+ pointHoverRadius: 4,
2961
+ borderWidth: 2,
2962
+ fill: dataset.fill ?? true,
2963
+ ...dataset
2964
+ })
2965
+ }
2966
+ );
2967
+ };
2968
+
2969
+ // src/components/charts/PrimusBarChart.tsx
2970
+ import { jsx as jsx38 } from "react/jsx-runtime";
2971
+ var PrimusBarChart = ({ stacked = false, options, ...props }) => {
2972
+ const mergedOptions = {
2973
+ ...options,
2974
+ scales: {
2975
+ x: { stacked, ...options?.scales?.x ?? {} },
2976
+ y: { stacked, ...options?.scales?.y ?? {} },
2977
+ ...options?.scales ?? {}
2978
+ }
2979
+ };
2980
+ return /* @__PURE__ */ jsx38(
2981
+ PrimusChartBase,
2982
+ {
2983
+ ...props,
2984
+ type: "bar",
2985
+ options: mergedOptions,
2986
+ datasetTransform: (dataset) => ({
2987
+ borderRadius: 6,
2988
+ borderSkipped: false,
2989
+ ...dataset
2990
+ })
2991
+ }
2992
+ );
2993
+ };
2994
+
2995
+ // src/components/charts/PrimusPieChart.tsx
2996
+ import { jsx as jsx39 } from "react/jsx-runtime";
2997
+ var PrimusPieChart = ({ donut = false, cutout = "55%", options, ...props }) => {
2998
+ const mergedOptions = {
2999
+ ...options,
3000
+ cutout: donut ? cutout : void 0
3001
+ };
3002
+ return /* @__PURE__ */ jsx39(
3003
+ PrimusChartBase,
3004
+ {
3005
+ ...props,
3006
+ type: donut ? "doughnut" : "pie",
3007
+ options: mergedOptions,
3008
+ datasetTransform: (dataset) => ({
3009
+ borderWidth: 1,
3010
+ borderColor: "transparent",
3011
+ ...dataset
3012
+ })
3013
+ }
3014
+ );
3015
+ };
3016
+
3017
+ // src/components/charts/PrimusSparkline.tsx
3018
+ import { useMemo as useMemo5 } from "react";
3019
+ import { jsx as jsx40, jsxs as jsxs32 } from "react/jsx-runtime";
3020
+ var PrimusSparkline = ({
3021
+ series = [],
3022
+ data,
3023
+ type = "line",
3024
+ height = 48,
3025
+ width = 160,
3026
+ strokeWidth = 2,
3027
+ className,
3028
+ ariaLabel = "Sparkline"
3029
+ }) => {
3030
+ const values = data ?? series[0]?.data ?? [];
3031
+ const color = series[0]?.color ?? series[0]?.borderColor ?? "#3b82f6";
3032
+ const { linePath, areaPath } = useMemo5(() => {
3033
+ if (!values.length) {
3034
+ return { linePath: "", areaPath: "" };
3035
+ }
3036
+ const max = Math.max(...values);
3037
+ const min = Math.min(...values);
3038
+ const range = max - min || 1;
3039
+ const divisor = values.length > 1 ? values.length - 1 : 1;
3040
+ const points = values.map((value, index) => {
3041
+ const x = index / divisor * 100;
3042
+ const y = 100 - (value - min) / range * 100;
3043
+ return { x, y };
3044
+ });
3045
+ const line = points.map((point, index) => `${index === 0 ? "M" : "L"} ${point.x} ${point.y}`).join(" ");
3046
+ const area = `${line} L 100 100 L 0 100 Z`;
3047
+ return { linePath: line, areaPath: area };
3048
+ }, [values]);
3049
+ if (!values.length) {
3050
+ return null;
3051
+ }
3052
+ return /* @__PURE__ */ jsxs32(
3053
+ "svg",
3054
+ {
3055
+ className,
3056
+ width,
3057
+ height,
3058
+ viewBox: "0 0 100 100",
3059
+ preserveAspectRatio: "none",
3060
+ "aria-label": ariaLabel,
3061
+ role: "img",
3062
+ children: [
3063
+ type === "area" && /* @__PURE__ */ jsx40("path", { d: areaPath, fill: color, opacity: 0.2, stroke: "none" }),
3064
+ /* @__PURE__ */ jsx40("path", { d: linePath, fill: "none", stroke: color, strokeWidth })
3065
+ ]
3066
+ }
3067
+ );
3068
+ };
3069
+
3070
+ // src/components/shared/Checkbox.tsx
3071
+ import React22 from "react";
3072
+ import { jsx as jsx41, jsxs as jsxs33 } from "react/jsx-runtime";
3073
+ var Checkbox = React22.forwardRef(
3074
+ ({ style, label, error, disabled, className, ...props }, ref) => {
3075
+ const containerStyles = {
3076
+ display: "flex",
3077
+ alignItems: "center",
3078
+ gap: "0.5rem"
3079
+ };
3080
+ const checkboxWrapperStyles = {
3081
+ position: "relative",
3082
+ display: "inline-flex",
3083
+ alignItems: "center",
3084
+ justifyContent: "center"
3085
+ };
3086
+ const checkboxStyles = {
3087
+ width: "1.25rem",
3088
+ height: "1.25rem",
3089
+ borderRadius: "0.25rem",
3090
+ border: error ? "2px solid #ef4444" : "2px solid #e5e7eb",
3091
+ cursor: disabled ? "not-allowed" : "pointer",
3092
+ opacity: disabled ? 0.5 : 1,
3093
+ accentColor: "#111827"
3094
+ };
3095
+ const labelStyles = {
3096
+ fontSize: "0.875rem",
3097
+ lineHeight: "1.25rem",
3098
+ color: "#374151",
3099
+ cursor: disabled ? "not-allowed" : "pointer",
3100
+ opacity: disabled ? 0.7 : 1,
3101
+ userSelect: "none"
3102
+ };
3103
+ const errorTextStyles = {
3104
+ fontSize: "0.875rem",
3105
+ lineHeight: "1.25rem",
3106
+ color: "#ef4444",
3107
+ marginTop: "0.25rem",
3108
+ marginLeft: "1.75rem"
3109
+ };
3110
+ return /* @__PURE__ */ jsxs33("div", { children: [
3111
+ /* @__PURE__ */ jsxs33("div", { style: containerStyles, children: [
3112
+ /* @__PURE__ */ jsx41("div", { style: checkboxWrapperStyles, children: /* @__PURE__ */ jsx41(
3113
+ "input",
3114
+ {
3115
+ ref,
3116
+ type: "checkbox",
3117
+ style: {
3118
+ ...checkboxStyles,
3119
+ ...style
3120
+ },
3121
+ disabled,
3122
+ ...props
3123
+ }
3124
+ ) }),
3125
+ label && /* @__PURE__ */ jsx41("label", { style: labelStyles, onClick: (e) => {
3126
+ if (!disabled) {
3127
+ const input = e.currentTarget.previousElementSibling?.querySelector("input");
3128
+ input?.click();
3129
+ }
3130
+ }, children: label })
3131
+ ] }),
3132
+ error && /* @__PURE__ */ jsx41("p", { style: errorTextStyles, children: error })
3133
+ ] });
3134
+ }
3135
+ );
3136
+ Checkbox.displayName = "Checkbox";
3137
+
3138
+ // src/components/shared/RadioGroup.tsx
3139
+ import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
3140
+ var RadioGroup = ({
3141
+ name,
3142
+ options,
3143
+ value,
3144
+ onChange,
3145
+ error,
3146
+ disabled,
3147
+ orientation = "vertical"
3148
+ }) => {
3149
+ const containerStyles = {
3150
+ display: "flex",
3151
+ flexDirection: orientation === "vertical" ? "column" : "row",
3152
+ gap: orientation === "vertical" ? "0.75rem" : "1.5rem"
3153
+ };
3154
+ const optionStyles = {
3155
+ display: "flex",
3156
+ alignItems: "center",
3157
+ gap: "0.5rem"
3158
+ };
3159
+ const radioStyles = {
3160
+ width: "1.25rem",
3161
+ height: "1.25rem",
3162
+ cursor: disabled ? "not-allowed" : "pointer",
3163
+ opacity: disabled ? 0.5 : 1,
3164
+ accentColor: "#111827"
3165
+ };
3166
+ const labelStyles = {
3167
+ fontSize: "0.875rem",
3168
+ lineHeight: "1.25rem",
3169
+ color: "#374151",
3170
+ cursor: disabled ? "not-allowed" : "pointer",
3171
+ userSelect: "none"
3172
+ };
3173
+ const errorTextStyles = {
3174
+ fontSize: "0.875rem",
3175
+ lineHeight: "1.25rem",
3176
+ color: "#ef4444",
3177
+ marginTop: "0.5rem"
3178
+ };
3179
+ return /* @__PURE__ */ jsxs34("div", { children: [
3180
+ /* @__PURE__ */ jsx42("div", { style: containerStyles, children: options.map((option) => /* @__PURE__ */ jsxs34("div", { style: optionStyles, children: [
3181
+ /* @__PURE__ */ jsx42(
3182
+ "input",
3183
+ {
3184
+ type: "radio",
3185
+ name,
3186
+ value: option.value,
3187
+ checked: value === option.value,
3188
+ onChange: () => onChange?.(option.value),
3189
+ disabled: disabled || option.disabled,
3190
+ style: radioStyles
3191
+ }
3192
+ ),
3193
+ /* @__PURE__ */ jsx42(
3194
+ "label",
3195
+ {
3196
+ style: {
3197
+ ...labelStyles,
3198
+ opacity: disabled || option.disabled ? 0.5 : 1
3199
+ },
3200
+ onClick: () => {
3201
+ if (!disabled && !option.disabled) {
3202
+ onChange?.(option.value);
3203
+ }
3204
+ },
3205
+ children: option.label
3206
+ }
3207
+ )
3208
+ ] }, option.value)) }),
3209
+ error && /* @__PURE__ */ jsx42("p", { style: errorTextStyles, children: error })
3210
+ ] });
3211
+ };
3212
+ RadioGroup.displayName = "RadioGroup";
3213
+
3214
+ // src/components/shared/Select.tsx
3215
+ import React23, { useState as useState22 } from "react";
3216
+ import { Combobox, Transition as Transition2 } from "@headlessui/react";
3217
+ import { CheckIcon as CheckIcon2, ChevronUpDownIcon, XMarkIcon as XMarkIcon3 } from "@heroicons/react/20/solid";
3218
+ import { clsx as clsx7 } from "clsx";
3219
+ import { Fragment as Fragment5, jsx as jsx43, jsxs as jsxs35 } from "react/jsx-runtime";
3220
+ var Select = ({
3221
+ label,
3222
+ error,
3223
+ options,
3224
+ placeholder = "Select option...",
3225
+ value,
3226
+ onChange,
3227
+ multiple = false,
3228
+ disabled = false,
3229
+ className
3230
+ }) => {
3231
+ const [query, setQuery] = useState22("");
3232
+ const filteredOptions = query === "" ? options : options.filter(
3233
+ (option) => option.label.toLowerCase().replace(/\s+/g, "").includes(query.toLowerCase().replace(/\s+/g, ""))
3234
+ );
3235
+ const getLabel = (val) => options.find((o) => o.value === val)?.label || val;
3236
+ const removeChip = (valToRemove) => {
3237
+ if (Array.isArray(value)) {
3238
+ onChange?.(value.filter((v) => v !== valToRemove));
3239
+ }
3240
+ };
3241
+ return /* @__PURE__ */ jsx43("div", { className: clsx7("w-full", className), children: /* @__PURE__ */ jsx43(
3242
+ Combobox,
3243
+ {
3244
+ value,
3245
+ onChange: (val) => {
3246
+ onChange?.(val);
3247
+ },
3248
+ multiple,
3249
+ disabled,
3250
+ children: ({}) => /* @__PURE__ */ jsxs35("div", { className: "relative", children: [
3251
+ label && /* @__PURE__ */ jsx43(Combobox.Label, { className: "block text-sm font-medium text-gray-700 mb-1", children: label }),
3252
+ /* @__PURE__ */ jsxs35("div", { className: clsx7(
3253
+ "relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left focus-within:ring-2 focus-within:ring-primus-500",
3254
+ "border transition-all duration-200 ease-in-out",
3255
+ error ? "border-red-500 focus-within:ring-red-500" : "border-gray-300",
3256
+ disabled && "opacity-50 cursor-not-allowed bg-gray-50"
3257
+ ), children: [
3258
+ /* @__PURE__ */ jsxs35("div", { className: clsx7(
3259
+ "flex flex-wrap items-center gap-1.5 w-full py-1.5 pl-3 pr-10 text-sm",
3260
+ "min-h-[2.5rem]"
3261
+ ), children: [
3262
+ multiple && Array.isArray(value) && value.map((val) => /* @__PURE__ */ jsxs35("span", { className: "inline-flex items-center gap-1 rounded bg-primus-50 px-2 py-0.5 text-xs font-medium text-primus-700 ring-1 ring-inset ring-primus-700/10 max-w-[150px]", children: [
3263
+ /* @__PURE__ */ jsx43("span", { className: "truncate", children: getLabel(val) }),
3264
+ /* @__PURE__ */ jsxs35(
3265
+ "button",
3266
+ {
3267
+ type: "button",
3268
+ className: "group relative -mr-1 h-3.5 w-3.5 rounded-sm hover:bg-primus-600/20 flex-shrink-0 cursor-pointer",
3269
+ onClick: (e) => {
3270
+ e.preventDefault();
3271
+ e.stopPropagation();
3272
+ removeChip(val);
3273
+ },
3274
+ onMouseDown: (e) => e.preventDefault(),
3275
+ children: [
3276
+ /* @__PURE__ */ jsx43("span", { className: "sr-only", children: "Remove" }),
3277
+ /* @__PURE__ */ jsx43(XMarkIcon3, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
3278
+ ]
3279
+ }
3280
+ )
3281
+ ] }, val)),
3282
+ /* @__PURE__ */ jsx43(
3283
+ Combobox.Input,
3284
+ {
3285
+ className: "border-none p-0 text-gray-900 focus:ring-0 outline-none placeholder:text-gray-400 bg-transparent min-w-[50px] flex-1 text-sm leading-5 py-0.5",
3286
+ displayValue: (val) => !multiple && val ? getLabel(val) : query,
3287
+ placeholder: multiple && Array.isArray(value) && value.length > 0 ? "" : placeholder,
3288
+ onChange: (event) => setQuery(event.target.value)
3289
+ }
3290
+ )
3291
+ ] }),
3292
+ /* @__PURE__ */ jsx43(Combobox.Button, { className: "absolute inset-y-0 right-0 flex items-center pr-2", children: /* @__PURE__ */ jsx43(
3293
+ ChevronUpDownIcon,
3294
+ {
3295
+ className: "h-5 w-5 text-gray-400",
3296
+ "aria-hidden": "true"
3297
+ }
3298
+ ) })
3299
+ ] }),
3300
+ /* @__PURE__ */ jsx43(
3301
+ Transition2,
3302
+ {
3303
+ as: React23.Fragment,
3304
+ leave: "transition ease-in duration-100",
3305
+ leaveFrom: "opacity-100",
3306
+ leaveTo: "opacity-0",
3307
+ afterLeave: () => setQuery(""),
3308
+ children: /* @__PURE__ */ jsx43(Combobox.Options, { className: "absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm", children: filteredOptions.length === 0 && query !== "" ? /* @__PURE__ */ jsx43("div", { className: "relative cursor-default select-none py-2 px-4 text-gray-700", children: "Nothing found." }) : filteredOptions.map((option) => /* @__PURE__ */ jsx43(
3309
+ Combobox.Option,
3310
+ {
3311
+ className: ({ active }) => clsx7(
3312
+ "relative cursor-default select-none py-2 pl-10 pr-4",
3313
+ active ? "bg-primus-600 text-white" : "text-gray-900"
3314
+ ),
3315
+ value: option.value,
3316
+ disabled: option.disabled,
3317
+ children: ({ selected, active }) => /* @__PURE__ */ jsxs35(Fragment5, { children: [
3318
+ /* @__PURE__ */ jsx43("span", { className: clsx7("block truncate", selected ? "font-medium" : "font-normal"), children: option.label }),
3319
+ selected ? /* @__PURE__ */ jsx43(
3320
+ "span",
3321
+ {
3322
+ className: clsx7(
3323
+ "absolute inset-y-0 left-0 flex items-center pl-3",
3324
+ active ? "text-white" : "text-primus-600"
3325
+ ),
3326
+ children: /* @__PURE__ */ jsx43(CheckIcon2, { className: "h-5 w-5", "aria-hidden": "true" })
3327
+ }
3328
+ ) : null
3329
+ ] })
3330
+ },
3331
+ option.value
3332
+ )) })
3333
+ }
3334
+ ),
3335
+ error && /* @__PURE__ */ jsx43("p", { className: "mt-1 text-sm text-red-500", children: error })
3336
+ ] })
3337
+ }
3338
+ ) });
3339
+ };
3340
+
3341
+ // src/components/shared/Toggle.tsx
3342
+ import React24 from "react";
3343
+ import { jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
3344
+ var Toggle = ({
3345
+ checked = false,
3346
+ onChange,
3347
+ disabled = false,
3348
+ label,
3349
+ size = "md"
3350
+ }) => {
3351
+ const [isHovered, setIsHovered] = React24.useState(false);
3352
+ const sizes = {
3353
+ sm: { width: "2.25rem", height: "1.25rem", thumbSize: "0.875rem" },
3354
+ md: { width: "2.75rem", height: "1.5rem", thumbSize: "1.125rem" },
3355
+ lg: { width: "3.5rem", height: "2rem", thumbSize: "1.625rem" }
3356
+ };
3357
+ const currentSize = sizes[size];
3358
+ const containerStyles = {
3359
+ display: "flex",
3360
+ alignItems: "center",
3361
+ gap: "0.75rem"
3362
+ };
3363
+ const switchStyles = {
3364
+ position: "relative",
3365
+ display: "inline-block",
3366
+ width: currentSize.width,
3367
+ height: currentSize.height,
3368
+ backgroundColor: checked ? "#111827" : "#e5e7eb",
3369
+ borderRadius: "9999px",
3370
+ cursor: disabled ? "not-allowed" : "pointer",
3371
+ transition: "background-color 0.2s ease",
3372
+ opacity: disabled ? 0.5 : isHovered ? 0.9 : 1
3373
+ };
3374
+ const thumbStyles = {
3375
+ position: "absolute",
3376
+ top: "50%",
3377
+ left: checked ? `calc(100% - ${currentSize.thumbSize} - 0.125rem)` : "0.125rem",
3378
+ transform: "translateY(-50%)",
3379
+ width: currentSize.thumbSize,
3380
+ height: currentSize.thumbSize,
3381
+ backgroundColor: "#ffffff",
3382
+ borderRadius: "50%",
3383
+ transition: "left 0.2s ease",
3384
+ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.1)"
3385
+ };
3386
+ const labelStyles = {
3387
+ fontSize: "0.875rem",
3388
+ lineHeight: "1.25rem",
3389
+ color: "#374151",
3390
+ cursor: disabled ? "not-allowed" : "pointer",
3391
+ userSelect: "none"
3392
+ };
3393
+ const handleClick = () => {
3394
+ if (!disabled) {
3395
+ onChange?.(!checked);
3396
+ }
3397
+ };
3398
+ return /* @__PURE__ */ jsxs36("div", { style: containerStyles, children: [
3399
+ /* @__PURE__ */ jsx44(
3400
+ "div",
3401
+ {
3402
+ style: switchStyles,
3403
+ onClick: handleClick,
3404
+ onMouseEnter: () => setIsHovered(true),
3405
+ onMouseLeave: () => setIsHovered(false),
3406
+ role: "switch",
3407
+ "aria-checked": checked,
3408
+ tabIndex: disabled ? -1 : 0,
3409
+ onKeyDown: (e) => {
3410
+ if (e.key === " " || e.key === "Enter") {
3411
+ e.preventDefault();
3412
+ handleClick();
3413
+ }
3414
+ },
3415
+ children: /* @__PURE__ */ jsx44("div", { style: thumbStyles })
3416
+ }
3417
+ ),
3418
+ label && /* @__PURE__ */ jsx44("label", { style: labelStyles, onClick: handleClick, children: label })
3419
+ ] });
3420
+ };
3421
+ Toggle.displayName = "Toggle";
3422
+
3423
+ // src/components/shared/Textarea.tsx
3424
+ import React25 from "react";
3425
+ import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
3426
+ var Textarea = React25.forwardRef(
3427
+ ({ style, label, error, disabled, resize = "vertical", ...props }, ref) => {
3428
+ const [isFocused, setIsFocused] = React25.useState(false);
3429
+ const containerStyles = {
3430
+ width: "100%"
3431
+ };
3432
+ const labelStyles = {
3433
+ fontSize: "0.875rem",
3434
+ lineHeight: "1.25rem",
3435
+ fontWeight: "500",
3436
+ marginBottom: "0.5rem",
3437
+ display: "block",
3438
+ color: "#374151",
3439
+ cursor: disabled ? "not-allowed" : "default",
3440
+ opacity: disabled ? 0.7 : 1
3441
+ };
3442
+ const textareaStyles = {
3443
+ display: "flex",
3444
+ minHeight: "5rem",
3445
+ width: "100%",
3446
+ borderRadius: "0.375rem",
3447
+ border: error ? "1px solid #ef4444" : "1px solid #e5e7eb",
3448
+ backgroundColor: "#ffffff",
3449
+ padding: "0.5rem 0.75rem",
3450
+ fontSize: "0.875rem",
3451
+ lineHeight: "1.5rem",
3452
+ outline: "none",
3453
+ transition: "all 0.2s ease",
3454
+ cursor: disabled ? "not-allowed" : "text",
3455
+ opacity: disabled ? 0.5 : 1,
3456
+ resize,
3457
+ fontFamily: "inherit",
3458
+ boxShadow: isFocused ? error ? "0 0 0 2px rgba(239, 68, 68, 0.2)" : "0 0 0 2px rgba(3, 7, 18, 0.1)" : "none"
3459
+ };
3460
+ const errorTextStyles = {
3461
+ fontSize: "0.875rem",
3462
+ lineHeight: "1.25rem",
3463
+ color: "#ef4444",
3464
+ marginTop: "0.25rem"
3465
+ };
3466
+ return /* @__PURE__ */ jsxs37("div", { style: containerStyles, children: [
3467
+ label && /* @__PURE__ */ jsx45("label", { style: labelStyles, children: label }),
3468
+ /* @__PURE__ */ jsx45(
3469
+ "textarea",
3470
+ {
3471
+ ref,
3472
+ style: {
3473
+ ...textareaStyles,
3474
+ ...style
3475
+ },
3476
+ onFocus: () => setIsFocused(true),
3477
+ onBlur: () => setIsFocused(false),
3478
+ disabled,
3479
+ ...props
3480
+ }
3481
+ ),
3482
+ error && /* @__PURE__ */ jsx45("p", { style: errorTextStyles, children: error })
3483
+ ] });
3484
+ }
3485
+ );
3486
+ Textarea.displayName = "Textarea";
3487
+
3488
+ // src/components/shared/Card.tsx
3489
+ import React26 from "react";
3490
+ import { jsx as jsx46 } from "react/jsx-runtime";
3491
+ var Card = React26.forwardRef(
3492
+ ({ style, variant = "default", padding = "md", children, ...props }, ref) => {
3493
+ const [isHovered, setIsHovered] = React26.useState(false);
3494
+ const paddingStyles = {
3495
+ none: "0",
3496
+ sm: "0.75rem",
3497
+ md: "1.5rem",
3498
+ lg: "2rem"
3499
+ };
3500
+ const variantStyles = {
3501
+ default: {
3502
+ normal: {
3503
+ backgroundColor: "#ffffff",
3504
+ border: "1px solid #e5e7eb",
3505
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)"
3506
+ },
3507
+ hover: {
3508
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
3509
+ }
3510
+ },
3511
+ outlined: {
3512
+ normal: {
3513
+ backgroundColor: "#ffffff",
3514
+ border: "2px solid #e5e7eb",
3515
+ boxShadow: "none"
3516
+ },
3517
+ hover: {
3518
+ borderColor: "#d1d5db"
3519
+ }
3520
+ },
3521
+ elevated: {
3522
+ normal: {
3523
+ backgroundColor: "#ffffff",
3524
+ border: "none",
3525
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
3526
+ },
3527
+ hover: {
3528
+ boxShadow: "0 10px 15px rgba(0, 0, 0, 0.15)",
3529
+ transform: "translateY(-2px)"
3530
+ }
3531
+ }
3532
+ };
3533
+ const baseStyles = {
3534
+ borderRadius: "0.5rem",
3535
+ padding: paddingStyles[padding],
3536
+ transition: "all 0.2s ease"
3537
+ };
3538
+ const currentVariant = variantStyles[variant];
3539
+ const combinedStyles = {
3540
+ ...baseStyles,
3541
+ ...currentVariant.normal,
3542
+ ...isHovered ? currentVariant.hover : {},
3543
+ ...style
3544
+ };
3545
+ return /* @__PURE__ */ jsx46(
3546
+ "div",
3547
+ {
3548
+ ref,
3549
+ style: combinedStyles,
3550
+ onMouseEnter: () => setIsHovered(true),
3551
+ onMouseLeave: () => setIsHovered(false),
3552
+ ...props,
3553
+ children
3554
+ }
3555
+ );
3556
+ }
3557
+ );
3558
+ Card.displayName = "Card";
3559
+
3560
+ // src/components/shared/Badge.tsx
3561
+ import React27 from "react";
3562
+ import { jsx as jsx47 } from "react/jsx-runtime";
3563
+ var Badge = React27.forwardRef(
3564
+ ({ style, variant = "default", size = "md", children, ...props }, ref) => {
3565
+ const variantStyles = {
3566
+ default: {
3567
+ backgroundColor: "#f3f4f6",
3568
+ color: "#374151"
3569
+ },
3570
+ success: {
3571
+ backgroundColor: "#d1fae5",
3572
+ color: "#065f46"
3573
+ },
3574
+ warning: {
3575
+ backgroundColor: "#fef3c7",
3576
+ color: "#92400e"
3577
+ },
3578
+ error: {
3579
+ backgroundColor: "#fee2e2",
3580
+ color: "#991b1b"
3581
+ },
3582
+ info: {
3583
+ backgroundColor: "#dbeafe",
3584
+ color: "#1e40af"
3585
+ }
3586
+ };
3587
+ const sizeStyles = {
3588
+ sm: {
3589
+ fontSize: "0.75rem",
3590
+ lineHeight: "1rem",
3591
+ padding: "0.125rem 0.5rem"
3592
+ },
3593
+ md: {
3594
+ fontSize: "0.875rem",
3595
+ lineHeight: "1.25rem",
3596
+ padding: "0.25rem 0.75rem"
3597
+ },
3598
+ lg: {
3599
+ fontSize: "1rem",
3600
+ lineHeight: "1.5rem",
3601
+ padding: "0.375rem 1rem"
3602
+ }
3603
+ };
3604
+ const baseStyles = {
3605
+ display: "inline-flex",
3606
+ alignItems: "center",
3607
+ borderRadius: "9999px",
3608
+ fontWeight: "500",
3609
+ whiteSpace: "nowrap"
3610
+ };
3611
+ const combinedStyles = {
3612
+ ...baseStyles,
3613
+ ...variantStyles[variant],
3614
+ ...sizeStyles[size],
3615
+ ...style
3616
+ };
3617
+ return /* @__PURE__ */ jsx47("span", { ref, style: combinedStyles, ...props, children });
3618
+ }
3619
+ );
3620
+ Badge.displayName = "Badge";
3621
+
3622
+ // src/components/shared/Table.tsx
3623
+ import React28 from "react";
3624
+ import { jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
3625
+ function Table({
3626
+ columns,
3627
+ data,
3628
+ striped = false,
3629
+ hoverable = true,
3630
+ bordered = true,
3631
+ style
3632
+ }) {
3633
+ const [hoveredRow, setHoveredRow] = React28.useState(null);
3634
+ const tableStyles = {
3635
+ width: "100%",
3636
+ borderCollapse: "collapse",
3637
+ fontSize: "0.875rem",
3638
+ lineHeight: "1.25rem",
3639
+ ...style
3640
+ };
3641
+ const theadStyles = {
3642
+ backgroundColor: "#f9fafb",
3643
+ borderBottom: "2px solid #e5e7eb"
3644
+ };
3645
+ const thStyles = {
3646
+ padding: "0.75rem 1rem",
3647
+ textAlign: "left",
3648
+ fontWeight: "600",
3649
+ color: "#374151",
3650
+ borderBottom: bordered ? "1px solid #e5e7eb" : "none"
3651
+ };
3652
+ const getTdStyles = (rowIndex) => ({
3653
+ padding: "0.75rem 1rem",
3654
+ borderBottom: bordered ? "1px solid #e5e7eb" : "none",
3655
+ backgroundColor: hoverable && hoveredRow === rowIndex ? "#f9fafb" : striped && rowIndex % 2 === 1 ? "#f9fafb" : "#ffffff",
3656
+ transition: "background-color 0.15s ease"
3657
+ });
3658
+ return /* @__PURE__ */ jsx48("div", { style: { overflowX: "auto", borderRadius: "0.5rem", border: bordered ? "1px solid #e5e7eb" : "none" }, children: /* @__PURE__ */ jsxs38("table", { style: tableStyles, children: [
3659
+ /* @__PURE__ */ jsx48("thead", { style: theadStyles, children: /* @__PURE__ */ jsx48("tr", { children: columns.map((column) => /* @__PURE__ */ jsx48(
3660
+ "th",
3661
+ {
3662
+ style: {
3663
+ ...thStyles,
3664
+ width: column.width
3665
+ },
3666
+ children: column.header
3667
+ },
3668
+ column.key
3669
+ )) }) }),
3670
+ /* @__PURE__ */ jsx48("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ jsx48(
3671
+ "tr",
3672
+ {
3673
+ onMouseEnter: () => hoverable && setHoveredRow(rowIndex),
3674
+ onMouseLeave: () => hoverable && setHoveredRow(null),
3675
+ children: columns.map((column) => /* @__PURE__ */ jsx48("td", { style: getTdStyles(rowIndex), children: column.render ? column.render(row) : row[column.key] }, column.key))
3676
+ },
3677
+ rowIndex
3678
+ )) })
3679
+ ] }) });
3680
+ }
3681
+ Table.displayName = "Table";
3682
+
3683
+ // src/components/shared/Container.tsx
3684
+ import React29 from "react";
3685
+ import { jsx as jsx49 } from "react/jsx-runtime";
3686
+ var Container = React29.forwardRef(
3687
+ ({ style, maxWidth = "lg", padding = "md", children, ...props }, ref) => {
3688
+ const maxWidthStyles = {
3689
+ sm: "640px",
3690
+ md: "768px",
3691
+ lg: "1024px",
3692
+ xl: "1280px",
3693
+ "2xl": "1536px",
3694
+ full: "100%"
3695
+ };
3696
+ const paddingStyles = {
3697
+ none: "0",
3698
+ sm: "1rem",
3699
+ md: "1.5rem",
3700
+ lg: "2rem"
3701
+ };
3702
+ const containerStyles = {
3703
+ width: "100%",
3704
+ maxWidth: maxWidthStyles[maxWidth],
3705
+ marginLeft: "auto",
3706
+ marginRight: "auto",
3707
+ paddingLeft: paddingStyles[padding],
3708
+ paddingRight: paddingStyles[padding],
3709
+ ...style
3710
+ };
3711
+ return /* @__PURE__ */ jsx49("div", { ref, style: containerStyles, ...props, children });
3712
+ }
3713
+ );
3714
+ Container.displayName = "Container";
3715
+
3716
+ // src/components/shared/Grid.tsx
3717
+ import React30 from "react";
3718
+ import { jsx as jsx50 } from "react/jsx-runtime";
3719
+ var Grid = React30.forwardRef(
3720
+ ({ style, columns = 3, rows, gap = "md", width = "100%", height = "auto", responsive = true, children, ...props }, ref) => {
3721
+ const gapStyles = {
3722
+ none: "0",
3723
+ sm: "0.5rem",
3724
+ md: "1rem",
3725
+ lg: "1.5rem",
3726
+ xl: "2rem"
3727
+ };
3728
+ const gridStyles = {
3729
+ display: "grid",
3730
+ gridTemplateColumns: responsive ? `repeat(auto-fit, minmax(${Math.floor(100 / columns)}%, 1fr))` : `repeat(${columns}, 1fr)`,
3731
+ gridTemplateRows: rows ? `repeat(${rows}, 1fr)` : void 0,
3732
+ gap: gapStyles[gap] || gap,
3733
+ width,
3734
+ height,
3735
+ ...style
3736
+ };
3737
+ return /* @__PURE__ */ jsx50("div", { ref, style: gridStyles, ...props, children });
3738
+ }
3739
+ );
3740
+ Grid.displayName = "Grid";
3741
+
3742
+ // src/components/shared/Stack.tsx
3743
+ import React31 from "react";
3744
+ import { jsx as jsx51 } from "react/jsx-runtime";
3745
+ var Stack = React31.forwardRef(
3746
+ ({ style, direction = "vertical", gap = "md", align = "stretch", justify = "start", children, ...props }, ref) => {
3747
+ const gapStyles = {
3748
+ none: "0",
3749
+ sm: "0.5rem",
3750
+ md: "1rem",
3751
+ lg: "1.5rem",
3752
+ xl: "2rem"
3753
+ };
3754
+ const alignStyles = {
3755
+ start: "flex-start",
3756
+ center: "center",
3757
+ end: "flex-end",
3758
+ stretch: "stretch"
3759
+ };
3760
+ const justifyStyles = {
3761
+ start: "flex-start",
3762
+ center: "center",
3763
+ end: "flex-end",
3764
+ between: "space-between",
3765
+ around: "space-around"
3766
+ };
3767
+ const stackStyles = {
3768
+ display: "flex",
3769
+ flexDirection: direction === "vertical" ? "column" : "row",
3770
+ gap: gapStyles[gap],
3771
+ alignItems: alignStyles[align],
3772
+ justifyContent: justifyStyles[justify],
3773
+ ...style
3774
+ };
3775
+ return /* @__PURE__ */ jsx51("div", { ref, style: stackStyles, ...props, children });
3776
+ }
3777
+ );
3778
+ Stack.displayName = "Stack";
3779
+
3780
+ // src/components/shared/Modal.tsx
3781
+ import React32 from "react";
3782
+ import { jsx as jsx52, jsxs as jsxs39 } from "react/jsx-runtime";
3783
+ var Modal = ({
3784
+ isOpen,
3785
+ onClose,
3786
+ title,
3787
+ children,
3788
+ size = "md",
3789
+ closeOnOverlayClick = true
3790
+ }) => {
3791
+ React32.useEffect(() => {
3792
+ if (isOpen) {
3793
+ document.body.style.overflow = "hidden";
3794
+ } else {
3795
+ document.body.style.overflow = "unset";
3796
+ }
3797
+ return () => {
3798
+ document.body.style.overflow = "unset";
3799
+ };
3800
+ }, [isOpen]);
3801
+ if (!isOpen) return null;
3802
+ const sizeStyles = {
3803
+ sm: "400px",
3804
+ md: "600px",
3805
+ lg: "800px",
3806
+ xl: "1000px"
3807
+ };
3808
+ const overlayStyles = {
3809
+ position: "fixed",
3810
+ top: 0,
3811
+ left: 0,
3812
+ right: 0,
3813
+ bottom: 0,
3814
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
3815
+ display: "flex",
3816
+ alignItems: "center",
3817
+ justifyContent: "center",
3818
+ zIndex: 1e3,
3819
+ padding: "1rem"
3820
+ };
3821
+ const modalStyles = {
3822
+ backgroundColor: "#ffffff",
3823
+ borderRadius: "0.5rem",
3824
+ boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
3825
+ width: "100%",
3826
+ maxWidth: sizeStyles[size],
3827
+ maxHeight: "90vh",
3828
+ display: "flex",
3829
+ flexDirection: "column"
3830
+ };
3831
+ const headerStyles = {
3832
+ padding: "1.5rem",
3833
+ borderBottom: "1px solid #e5e7eb",
3834
+ display: "flex",
3835
+ alignItems: "center",
3836
+ justifyContent: "space-between"
3837
+ };
3838
+ const titleStyles = {
3839
+ fontSize: "1.25rem",
3840
+ lineHeight: "1.75rem",
3841
+ fontWeight: "600",
3842
+ color: "#111827"
3843
+ };
3844
+ const closeButtonStyles = {
3845
+ padding: "0.5rem",
3846
+ borderRadius: "0.375rem",
3847
+ border: "none",
3848
+ backgroundColor: "transparent",
3849
+ cursor: "pointer",
3850
+ fontSize: "1.5rem",
3851
+ lineHeight: "1",
3852
+ color: "#6b7280",
3853
+ transition: "background-color 0.2s ease"
3854
+ };
3855
+ const contentStyles = {
3856
+ padding: "1.5rem",
3857
+ overflowY: "auto",
3858
+ flex: 1
3859
+ };
3860
+ return /* @__PURE__ */ jsx52(
3861
+ "div",
3862
+ {
3863
+ style: overlayStyles,
3864
+ onClick: closeOnOverlayClick ? onClose : void 0,
3865
+ children: /* @__PURE__ */ jsxs39(
3866
+ "div",
3867
+ {
3868
+ style: modalStyles,
3869
+ onClick: (e) => e.stopPropagation(),
3870
+ children: [
3871
+ title && /* @__PURE__ */ jsxs39("div", { style: headerStyles, children: [
3872
+ /* @__PURE__ */ jsx52("h2", { style: titleStyles, children: title }),
3873
+ /* @__PURE__ */ jsx52(
3874
+ "button",
3875
+ {
3876
+ style: closeButtonStyles,
3877
+ onClick: onClose,
3878
+ "aria-label": "Close modal",
3879
+ children: "\xD7"
3880
+ }
3881
+ )
3882
+ ] }),
3883
+ /* @__PURE__ */ jsx52("div", { style: contentStyles, children })
3884
+ ]
3885
+ }
3886
+ )
3887
+ }
3888
+ );
3889
+ };
3890
+ Modal.displayName = "Modal";
3891
+
3892
+ // src/components/shared/DateRangePicker.tsx
3893
+ import { useEffect as useEffect15, useMemo as useMemo6, useState as useState23 } from "react";
3894
+ import { jsx as jsx53, jsxs as jsxs40 } from "react/jsx-runtime";
3895
+ var PrimusDateRangePicker = ({
3896
+ startDate = null,
3897
+ endDate = null,
3898
+ ranges = [],
3899
+ min,
3900
+ max,
3901
+ disabled = false,
3902
+ onRangeChange
3903
+ }) => {
3904
+ const [start, setStart] = useState23(startDate ?? "");
3905
+ const [end, setEnd] = useState23(endDate ?? "");
3906
+ useEffect15(() => {
3907
+ setStart(startDate ?? "");
3908
+ }, [startDate]);
3909
+ useEffect15(() => {
3910
+ setEnd(endDate ?? "");
3911
+ }, [endDate]);
3912
+ const normalizedRanges = useMemo6(() => {
3913
+ return ranges.map((range) => typeof range === "string" ? resolvePreset(range) : range).filter((range) => !!range);
3914
+ }, [ranges]);
3915
+ const handleStartChange = (value) => {
3916
+ setStart(value);
3917
+ onRangeChange?.({ startDate: value || null, endDate: end || null });
3918
+ };
3919
+ const handleEndChange = (value) => {
3920
+ setEnd(value);
3921
+ onRangeChange?.({ startDate: start || null, endDate: value || null });
3922
+ };
3923
+ const applyRange = (range) => {
3924
+ const nextStart = toDateInputValue(range.start);
3925
+ const nextEnd = toDateInputValue(range.end);
3926
+ setStart(nextStart);
3927
+ setEnd(nextEnd);
3928
+ onRangeChange?.({ startDate: nextStart, endDate: nextEnd, label: range.label });
3929
+ };
3930
+ return /* @__PURE__ */ jsxs40("div", { className: "space-y-3", children: [
3931
+ normalizedRanges.length > 0 && /* @__PURE__ */ jsx53("div", { className: "flex flex-wrap gap-2", children: normalizedRanges.map((range) => /* @__PURE__ */ jsx53(
3932
+ "button",
3933
+ {
3934
+ type: "button",
3935
+ disabled,
3936
+ onClick: () => applyRange(range),
3937
+ className: "px-3 py-1.5 rounded-full text-xs font-medium border border-white/10 bg-white/5 text-gray-200 hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed",
3938
+ children: range.label
3939
+ },
3940
+ range.label
3941
+ )) }),
3942
+ /* @__PURE__ */ jsxs40("div", { className: "flex flex-col md:flex-row gap-3", children: [
3943
+ /* @__PURE__ */ jsx53(
3944
+ "input",
3945
+ {
3946
+ type: "date",
3947
+ value: start,
3948
+ min,
3949
+ max,
3950
+ disabled,
3951
+ onChange: (e) => handleStartChange(e.target.value),
3952
+ className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
3953
+ }
3954
+ ),
3955
+ /* @__PURE__ */ jsx53(
3956
+ "input",
3957
+ {
3958
+ type: "date",
3959
+ value: end,
3960
+ min,
3961
+ max,
3962
+ disabled,
3963
+ onChange: (e) => handleEndChange(e.target.value),
3964
+ className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
3965
+ }
3966
+ )
3967
+ ] })
3968
+ ] });
3969
+ };
3970
+ var resolvePreset = (label) => {
3971
+ const today = /* @__PURE__ */ new Date();
3972
+ const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
3973
+ switch (label.toLowerCase()) {
3974
+ case "today":
3975
+ return { label, start: startOfDay, end: startOfDay };
3976
+ case "last 7 days": {
3977
+ const start = new Date(startOfDay);
3978
+ start.setDate(start.getDate() - 6);
3979
+ return { label, start, end: startOfDay };
3980
+ }
3981
+ case "last 30 days": {
3982
+ const start = new Date(startOfDay);
3983
+ start.setDate(start.getDate() - 29);
3984
+ return { label, start, end: startOfDay };
3985
+ }
3986
+ case "this month": {
3987
+ const start = new Date(today.getFullYear(), today.getMonth(), 1);
3988
+ const end = new Date(today.getFullYear(), today.getMonth() + 1, 0);
3989
+ return { label, start, end };
3990
+ }
3991
+ default:
3992
+ return null;
3993
+ }
3994
+ };
3995
+ var toDateInputValue = (value) => {
3996
+ if (typeof value === "string") {
3997
+ return value;
3998
+ }
3999
+ const year = value.getFullYear();
4000
+ const month = String(value.getMonth() + 1).padStart(2, "0");
4001
+ const day = String(value.getDate()).padStart(2, "0");
4002
+ return `${year}-${month}-${day}`;
4003
+ };
4004
+
4005
+ // src/components/shared/FilterBar.tsx
4006
+ import { jsx as jsx54, jsxs as jsxs41 } from "react/jsx-runtime";
4007
+ var PrimusFilterBar = ({
4008
+ filters,
4009
+ activeFilters,
4010
+ onChange,
4011
+ children
4012
+ }) => {
4013
+ const updateFilter = (key, value) => {
4014
+ const next = {
4015
+ ...activeFilters,
4016
+ [key]: value
4017
+ };
4018
+ onChange?.(next);
4019
+ };
4020
+ return /* @__PURE__ */ jsxs41("div", { className: "flex flex-wrap gap-4 items-end", children: [
4021
+ filters.map((filter) => /* @__PURE__ */ jsxs41("div", { className: "min-w-[220px]", children: [
4022
+ filter.type === "select" && /* @__PURE__ */ jsx54(
4023
+ Select,
4024
+ {
4025
+ label: filter.label,
4026
+ placeholder: filter.placeholder,
4027
+ options: filter.options ?? [],
4028
+ value: activeFilters[filter.key] ?? "",
4029
+ onChange: (value) => updateFilter(filter.key, value)
4030
+ }
4031
+ ),
4032
+ filter.type === "toggle" && /* @__PURE__ */ jsx54(
4033
+ Toggle,
4034
+ {
4035
+ label: filter.label,
4036
+ checked: Boolean(activeFilters[filter.key]),
4037
+ onChange: (checked) => updateFilter(filter.key, checked)
4038
+ }
4039
+ ),
4040
+ filter.type === "search" && /* @__PURE__ */ jsx54(
4041
+ Input,
4042
+ {
4043
+ label: filter.label,
4044
+ placeholder: filter.placeholder ?? "Search...",
4045
+ value: activeFilters[filter.key] ?? "",
4046
+ onChange: (event) => updateFilter(filter.key, event.target.value)
4047
+ }
4048
+ )
4049
+ ] }, filter.key)),
4050
+ children
4051
+ ] });
4052
+ };
4053
+
4054
+ // src/components/shared/ExportMenu.tsx
4055
+ import { useEffect as useEffect16, useState as useState24 } from "react";
4056
+ import { jsx as jsx55, jsxs as jsxs42 } from "react/jsx-runtime";
4057
+ var PrimusExportMenu = ({
4058
+ formats = ["CSV", "PDF", "PNG", "JSON"],
4059
+ includeCharts = true,
4060
+ includeStats = true,
4061
+ includeTables = true,
4062
+ onExport
4063
+ }) => {
4064
+ const [format, setFormat] = useState24(formats[0] ?? "CSV");
4065
+ const [charts, setCharts] = useState24(includeCharts);
4066
+ const [stats, setStats] = useState24(includeStats);
4067
+ const [tables, setTables] = useState24(includeTables);
4068
+ useEffect16(() => {
4069
+ if (!formats.includes(format)) {
4070
+ setFormat(formats[0] ?? "CSV");
4071
+ }
4072
+ }, [formats, format]);
4073
+ const handleExport = () => {
4074
+ onExport?.({
4075
+ format,
4076
+ includeCharts: charts,
4077
+ includeStats: stats,
4078
+ includeTables: tables
4079
+ });
4080
+ };
4081
+ return /* @__PURE__ */ jsxs42("div", { className: "flex flex-wrap items-center gap-3", children: [
4082
+ /* @__PURE__ */ jsx55(
4083
+ "select",
4084
+ {
4085
+ value: format,
4086
+ onChange: (event) => setFormat(event.target.value),
4087
+ className: "px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm",
4088
+ children: formats.map((item) => /* @__PURE__ */ jsx55("option", { value: item, children: item }, item))
4089
+ }
4090
+ ),
4091
+ /* @__PURE__ */ jsxs42("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
4092
+ /* @__PURE__ */ jsx55("input", { type: "checkbox", checked: charts, onChange: (e) => setCharts(e.target.checked) }),
4093
+ "Charts"
4094
+ ] }),
4095
+ /* @__PURE__ */ jsxs42("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
4096
+ /* @__PURE__ */ jsx55("input", { type: "checkbox", checked: stats, onChange: (e) => setStats(e.target.checked) }),
4097
+ "Stats"
4098
+ ] }),
4099
+ /* @__PURE__ */ jsxs42("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
4100
+ /* @__PURE__ */ jsx55("input", { type: "checkbox", checked: tables, onChange: (e) => setTables(e.target.checked) }),
4101
+ "Tables"
4102
+ ] }),
4103
+ /* @__PURE__ */ jsx55(
4104
+ "button",
4105
+ {
4106
+ type: "button",
4107
+ onClick: handleExport,
4108
+ className: "px-4 py-2 rounded-lg bg-purple-600 text-white text-sm font-medium hover:bg-purple-500",
4109
+ children: "Export"
4110
+ }
4111
+ )
4112
+ ] });
4113
+ };
4114
+
4115
+ // src/components/shared/Search.tsx
4116
+ import { useEffect as useEffect17, useMemo as useMemo7, useState as useState25 } from "react";
4117
+ import { jsx as jsx56, jsxs as jsxs43 } from "react/jsx-runtime";
4118
+ var PrimusSearch = ({
4119
+ placeholder = "Search...",
4120
+ debounce = 300,
4121
+ value = "",
4122
+ showSuggestions = false,
4123
+ suggestions = [],
4124
+ onSearch
4125
+ }) => {
4126
+ const [query, setQuery] = useState25(value);
4127
+ useEffect17(() => {
4128
+ setQuery(value);
4129
+ }, [value]);
4130
+ useEffect17(() => {
4131
+ const handle = window.setTimeout(() => {
4132
+ onSearch?.(query);
4133
+ }, debounce);
4134
+ return () => window.clearTimeout(handle);
4135
+ }, [query, debounce, onSearch]);
4136
+ const visibleSuggestions = useMemo7(() => {
4137
+ if (!showSuggestions || !suggestions.length) {
4138
+ return [];
4139
+ }
4140
+ if (!query) {
4141
+ return suggestions.slice(0, 5);
4142
+ }
4143
+ return suggestions.filter((item) => item.toLowerCase().includes(query.toLowerCase())).slice(0, 5);
4144
+ }, [suggestions, query, showSuggestions]);
4145
+ return /* @__PURE__ */ jsxs43("div", { className: "relative", children: [
4146
+ /* @__PURE__ */ jsx56(
4147
+ "input",
4148
+ {
4149
+ type: "text",
4150
+ value: query,
4151
+ placeholder,
4152
+ onChange: (event) => setQuery(event.target.value),
4153
+ className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
4154
+ }
4155
+ ),
4156
+ visibleSuggestions.length > 0 && /* @__PURE__ */ jsx56("div", { className: "absolute mt-2 w-full rounded-lg border border-white/10 bg-slate-900/90 backdrop-blur-sm shadow-lg z-10", children: visibleSuggestions.map((item) => /* @__PURE__ */ jsx56(
4157
+ "button",
4158
+ {
4159
+ type: "button",
4160
+ onClick: () => setQuery(item),
4161
+ className: "w-full text-left px-3 py-2 text-sm text-gray-200 hover:bg-white/10",
4162
+ children: item
4163
+ },
4164
+ item
4165
+ )) })
4166
+ ] });
4167
+ };
2484
4168
  export {
2485
4169
  AICopilot,
2486
4170
  AccountDashboard,
2487
4171
  AgentDirectory,
4172
+ Badge,
4173
+ Button,
4174
+ Card,
4175
+ Checkbox,
2488
4176
  CheckoutForm,
2489
4177
  ClaimStatusTracker,
4178
+ Container,
2490
4179
  CreditCardVisual,
2491
4180
  CreditScoreCard,
2492
4181
  DashboardGrid,
@@ -2494,29 +4183,64 @@ export {
2494
4183
  FeatureFlagToggle,
2495
4184
  FileUploader,
2496
4185
  FraudDetectionDashboard,
4186
+ Grid,
4187
+ Input,
2497
4188
  KYCVerification,
2498
4189
  LoanCalculator,
2499
4190
  LogViewer,
2500
4191
  LoginPage,
4192
+ Modal,
2501
4193
  NotificationBell,
2502
- NotificationFeed,
4194
+ PrimusNotificationFeed as NotificationFeed,
2503
4195
  PolicyCard,
2504
4196
  PremiumCalculator,
4197
+ PrimusActivityFeed,
4198
+ PrimusAreaChart,
4199
+ Badge as PrimusBadge,
4200
+ PrimusBarChart,
4201
+ Button as PrimusButton,
4202
+ Card as PrimusCard,
4203
+ PrimusChartBase,
4204
+ Checkbox as PrimusCheckbox,
4205
+ Container as PrimusContainer,
2505
4206
  PrimusDashboard,
2506
4207
  PrimusDataTable,
4208
+ PrimusDateRangePicker,
4209
+ PrimusExportMenu,
4210
+ PrimusFilterBar,
4211
+ Grid as PrimusGrid,
2507
4212
  PrimusHeader,
4213
+ Input as PrimusInput,
2508
4214
  PrimusLayout,
4215
+ PrimusLineChart,
2509
4216
  PrimusLogin,
2510
4217
  PrimusModal,
4218
+ Modal as PrimusModalComponent,
2511
4219
  PrimusNotificationCenter,
4220
+ PrimusNotificationFeed,
2512
4221
  PrimusNotifications,
4222
+ PrimusPieChart,
2513
4223
  PrimusProvider,
4224
+ RadioGroup as PrimusRadioGroup,
4225
+ PrimusSearch,
4226
+ Select as PrimusSelect,
2514
4227
  PrimusSidebar,
4228
+ PrimusSparkline,
4229
+ Stack as PrimusStack,
2515
4230
  PrimusStatCard,
4231
+ Table as PrimusTable,
4232
+ Textarea as PrimusTextarea,
2516
4233
  PrimusThemeProvider,
2517
4234
  PrimusThemeToggle,
4235
+ Toggle as PrimusToggle,
2518
4236
  QuoteComparison,
4237
+ RadioGroup,
2519
4238
  SecurityDashboard,
4239
+ Select,
4240
+ Stack,
4241
+ Table,
4242
+ Textarea,
4243
+ Toggle,
2520
4244
  TransactionHistory,
2521
4245
  UserProfile,
2522
4246
  themeColors,