@webdevarif/dashui 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -966,8 +966,420 @@ function PageSection({
966
966
  );
967
967
  }
968
968
 
969
- // src/components/data/data-table.tsx
969
+ // src/components/layout/search-bar.tsx
970
970
  import { jsx as jsx22, jsxs as jsxs9 } from "react/jsx-runtime";
971
+ function SearchBar({
972
+ value,
973
+ onChange,
974
+ placeholder = "Search\u2026",
975
+ shortcut,
976
+ className,
977
+ width = "max-w-xs"
978
+ }) {
979
+ const shortcuts = shortcut ? shortcut.split(" ") : [];
980
+ return /* @__PURE__ */ jsxs9("div", { className: cn("relative flex items-center", width, className), children: [
981
+ /* @__PURE__ */ jsxs9(
982
+ "svg",
983
+ {
984
+ className: "pointer-events-none absolute left-2.5 h-3.5 w-3.5 text-muted-foreground",
985
+ xmlns: "http://www.w3.org/2000/svg",
986
+ viewBox: "0 0 24 24",
987
+ fill: "none",
988
+ stroke: "currentColor",
989
+ strokeWidth: "2",
990
+ strokeLinecap: "round",
991
+ strokeLinejoin: "round",
992
+ children: [
993
+ /* @__PURE__ */ jsx22("circle", { cx: "11", cy: "11", r: "8" }),
994
+ /* @__PURE__ */ jsx22("path", { d: "m21 21-4.35-4.35" })
995
+ ]
996
+ }
997
+ ),
998
+ /* @__PURE__ */ jsx22(
999
+ "input",
1000
+ {
1001
+ type: "search",
1002
+ value,
1003
+ onChange: (e) => onChange?.(e.target.value),
1004
+ placeholder,
1005
+ className: cn(
1006
+ "h-8 w-full rounded-lg border border-input bg-muted/50 pl-8 text-sm outline-none transition-colors",
1007
+ "placeholder:text-muted-foreground",
1008
+ "focus:border-primary focus:ring-1 focus:ring-primary",
1009
+ shortcut ? "pr-16" : "pr-3"
1010
+ )
1011
+ }
1012
+ ),
1013
+ shortcuts.length > 0 && /* @__PURE__ */ jsx22("div", { className: "pointer-events-none absolute right-2 flex items-center gap-0.5", children: shortcuts.map((key, i) => /* @__PURE__ */ jsx22(
1014
+ "kbd",
1015
+ {
1016
+ className: "inline-flex h-5 items-center rounded border border-border bg-background px-1 font-mono text-[10px] text-muted-foreground",
1017
+ children: key
1018
+ },
1019
+ i
1020
+ )) })
1021
+ ] });
1022
+ }
1023
+
1024
+ // src/components/layout/notification-bell.tsx
1025
+ import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
1026
+ function NotificationBell({
1027
+ count = 0,
1028
+ onClick,
1029
+ className
1030
+ }) {
1031
+ return /* @__PURE__ */ jsxs10(
1032
+ "button",
1033
+ {
1034
+ onClick,
1035
+ className: cn(
1036
+ "relative flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
1037
+ className
1038
+ ),
1039
+ "aria-label": count > 0 ? `${count} unread notifications` : "Notifications",
1040
+ children: [
1041
+ /* @__PURE__ */ jsxs10(
1042
+ "svg",
1043
+ {
1044
+ className: "h-4 w-4",
1045
+ xmlns: "http://www.w3.org/2000/svg",
1046
+ viewBox: "0 0 24 24",
1047
+ fill: "none",
1048
+ stroke: "currentColor",
1049
+ strokeWidth: "2",
1050
+ strokeLinecap: "round",
1051
+ strokeLinejoin: "round",
1052
+ children: [
1053
+ /* @__PURE__ */ jsx23("path", { d: "M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" }),
1054
+ /* @__PURE__ */ jsx23("path", { d: "M10.3 21a1.94 1.94 0 0 0 3.4 0" })
1055
+ ]
1056
+ }
1057
+ ),
1058
+ count > 0 && /* @__PURE__ */ jsx23("span", { className: "absolute right-1.5 top-1.5 h-2 w-2 rounded-full bg-green-500" })
1059
+ ]
1060
+ }
1061
+ );
1062
+ }
1063
+
1064
+ // src/components/layout/theme-toggle.tsx
1065
+ import * as React17 from "react";
1066
+ import { useTheme } from "next-themes";
1067
+ import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
1068
+ function ThemeToggle({ className }) {
1069
+ const { resolvedTheme, setTheme } = useTheme();
1070
+ const [mounted, setMounted] = React17.useState(false);
1071
+ React17.useEffect(() => {
1072
+ setMounted(true);
1073
+ }, []);
1074
+ if (!mounted) {
1075
+ return /* @__PURE__ */ jsx24(
1076
+ "button",
1077
+ {
1078
+ className: cn(
1079
+ "flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground",
1080
+ className
1081
+ ),
1082
+ "aria-label": "Toggle theme",
1083
+ children: /* @__PURE__ */ jsx24("span", { className: "h-4 w-4" })
1084
+ }
1085
+ );
1086
+ }
1087
+ const isDark = resolvedTheme === "dark";
1088
+ return /* @__PURE__ */ jsx24(
1089
+ "button",
1090
+ {
1091
+ onClick: () => setTheme(isDark ? "light" : "dark"),
1092
+ className: cn(
1093
+ "flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
1094
+ className
1095
+ ),
1096
+ "aria-label": isDark ? "Switch to light mode" : "Switch to dark mode",
1097
+ children: isDark ? (
1098
+ /* Sun icon */
1099
+ /* @__PURE__ */ jsxs11(
1100
+ "svg",
1101
+ {
1102
+ className: "h-4 w-4",
1103
+ xmlns: "http://www.w3.org/2000/svg",
1104
+ viewBox: "0 0 24 24",
1105
+ fill: "none",
1106
+ stroke: "currentColor",
1107
+ strokeWidth: "2",
1108
+ strokeLinecap: "round",
1109
+ strokeLinejoin: "round",
1110
+ children: [
1111
+ /* @__PURE__ */ jsx24("circle", { cx: "12", cy: "12", r: "4" }),
1112
+ /* @__PURE__ */ jsx24("path", { d: "M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" })
1113
+ ]
1114
+ }
1115
+ )
1116
+ ) : (
1117
+ /* Moon icon */
1118
+ /* @__PURE__ */ jsx24(
1119
+ "svg",
1120
+ {
1121
+ className: "h-4 w-4",
1122
+ xmlns: "http://www.w3.org/2000/svg",
1123
+ viewBox: "0 0 24 24",
1124
+ fill: "none",
1125
+ stroke: "currentColor",
1126
+ strokeWidth: "2",
1127
+ strokeLinecap: "round",
1128
+ strokeLinejoin: "round",
1129
+ children: /* @__PURE__ */ jsx24("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })
1130
+ }
1131
+ )
1132
+ )
1133
+ }
1134
+ );
1135
+ }
1136
+
1137
+ // src/components/layout/dashboard-layout.tsx
1138
+ import * as React18 from "react";
1139
+ import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
1140
+ function isActive(itemHref, activeHref) {
1141
+ if (!activeHref) return false;
1142
+ return activeHref === itemHref || activeHref.startsWith(itemHref + "/");
1143
+ }
1144
+ function NavItemRow({
1145
+ item,
1146
+ collapsed,
1147
+ activeHref,
1148
+ onNavigate,
1149
+ depth = 0
1150
+ }) {
1151
+ const active = isActive(item.href, activeHref);
1152
+ const hasChildren = item.children && item.children.length > 0;
1153
+ const childActive = hasChildren && item.children.some((c) => isActive(c.href, activeHref));
1154
+ const [open, setOpen] = React18.useState(active || childActive);
1155
+ const handleClick = (e) => {
1156
+ if (onNavigate) {
1157
+ e.preventDefault();
1158
+ onNavigate(item.href);
1159
+ }
1160
+ if (hasChildren) {
1161
+ e.preventDefault();
1162
+ setOpen((v) => !v);
1163
+ }
1164
+ };
1165
+ const rowClasses = cn(
1166
+ "flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium transition-colors",
1167
+ active ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
1168
+ depth > 0 && "py-1.5"
1169
+ );
1170
+ return /* @__PURE__ */ jsxs12("div", { children: [
1171
+ /* @__PURE__ */ jsxs12(
1172
+ "a",
1173
+ {
1174
+ href: item.href,
1175
+ onClick: hasChildren ? (e) => {
1176
+ e.preventDefault();
1177
+ setOpen((v) => !v);
1178
+ } : onNavigate ? handleClick : void 0,
1179
+ className: rowClasses,
1180
+ title: collapsed ? item.label : void 0,
1181
+ children: [
1182
+ item.icon && /* @__PURE__ */ jsx25("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center", children: item.icon }),
1183
+ !collapsed && /* @__PURE__ */ jsxs12(Fragment3, { children: [
1184
+ /* @__PURE__ */ jsx25("span", { className: "flex-1 truncate", children: item.label }),
1185
+ item.badge !== void 0 && !hasChildren && /* @__PURE__ */ jsx25("span", { className: "rounded-full bg-primary/15 px-2 py-0.5 text-[11px] font-semibold text-primary", children: item.badge }),
1186
+ hasChildren && /* @__PURE__ */ jsx25(
1187
+ "svg",
1188
+ {
1189
+ className: cn("h-3.5 w-3.5 shrink-0 transition-transform text-sidebar-foreground/50", open && "rotate-180"),
1190
+ xmlns: "http://www.w3.org/2000/svg",
1191
+ viewBox: "0 0 24 24",
1192
+ fill: "none",
1193
+ stroke: "currentColor",
1194
+ strokeWidth: "2",
1195
+ strokeLinecap: "round",
1196
+ strokeLinejoin: "round",
1197
+ children: /* @__PURE__ */ jsx25("path", { d: "m6 9 6 6 6-6" })
1198
+ }
1199
+ )
1200
+ ] })
1201
+ ]
1202
+ }
1203
+ ),
1204
+ hasChildren && open && !collapsed && /* @__PURE__ */ jsx25("div", { className: "mt-0.5 ml-[22px] space-y-0.5 border-l border-sidebar-border/60 pl-3", children: item.children.map((child) => /* @__PURE__ */ jsx25(
1205
+ NavItemRow,
1206
+ {
1207
+ item: child,
1208
+ collapsed,
1209
+ activeHref,
1210
+ onNavigate,
1211
+ depth: depth + 1
1212
+ },
1213
+ child.href
1214
+ )) })
1215
+ ] });
1216
+ }
1217
+ function UserAvatar({ user, size = "sm" }) {
1218
+ const initials = user.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
1219
+ const sizeClass = size === "md" ? "h-8 w-8 text-xs" : "h-7 w-7 text-[10px]";
1220
+ return /* @__PURE__ */ jsx25("div", { className: cn("flex shrink-0 items-center justify-center rounded-full bg-primary font-semibold text-primary-foreground overflow-hidden", sizeClass), children: user.avatar ? /* @__PURE__ */ jsx25("img", { src: user.avatar, alt: user.name, className: "h-full w-full object-cover" }) : initials });
1221
+ }
1222
+ function DashboardLayout({
1223
+ logo,
1224
+ appName = "Dashboard",
1225
+ navItems,
1226
+ bottomNavItems,
1227
+ activeHref,
1228
+ onNavigate,
1229
+ searchPlaceholder,
1230
+ searchShortcut,
1231
+ notificationCount,
1232
+ onNotificationClick,
1233
+ user,
1234
+ onSignOut,
1235
+ children,
1236
+ defaultCollapsed = false,
1237
+ footerContent
1238
+ }) {
1239
+ const [collapsed, setCollapsed] = React18.useState(defaultCollapsed);
1240
+ const [userMenuOpen, setUserMenuOpen] = React18.useState(false);
1241
+ const [searchValue, setSearchValue] = React18.useState("");
1242
+ const userMenuRef = React18.useRef(null);
1243
+ React18.useEffect(() => {
1244
+ function handler(e) {
1245
+ if (userMenuRef.current && !userMenuRef.current.contains(e.target)) {
1246
+ setUserMenuOpen(false);
1247
+ }
1248
+ }
1249
+ document.addEventListener("mousedown", handler);
1250
+ return () => document.removeEventListener("mousedown", handler);
1251
+ }, []);
1252
+ const ToggleIcon = () => /* @__PURE__ */ jsxs12(
1253
+ "svg",
1254
+ {
1255
+ className: "h-4 w-4",
1256
+ xmlns: "http://www.w3.org/2000/svg",
1257
+ viewBox: "0 0 24 24",
1258
+ fill: "none",
1259
+ stroke: "currentColor",
1260
+ strokeWidth: "2",
1261
+ strokeLinecap: "round",
1262
+ strokeLinejoin: "round",
1263
+ children: [
1264
+ /* @__PURE__ */ jsx25("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
1265
+ /* @__PURE__ */ jsx25("line", { x1: "3", y1: "12", x2: "21", y2: "12" }),
1266
+ /* @__PURE__ */ jsx25("line", { x1: "3", y1: "18", x2: "21", y2: "18" })
1267
+ ]
1268
+ }
1269
+ );
1270
+ return /* @__PURE__ */ jsxs12("div", { className: "flex h-screen overflow-hidden bg-background", children: [
1271
+ /* @__PURE__ */ jsxs12(
1272
+ "aside",
1273
+ {
1274
+ className: cn(
1275
+ "flex shrink-0 flex-col border-r bg-sidebar transition-all duration-200 ease-in-out",
1276
+ collapsed ? "w-16" : "w-80"
1277
+ ),
1278
+ children: [
1279
+ /* @__PURE__ */ jsx25("div", { className: "flex h-14 shrink-0 items-center border-b border-sidebar-border px-4", children: collapsed ? /* @__PURE__ */ jsx25("div", { className: "flex h-8 w-8 items-center justify-center rounded-md bg-primary/10", children: /* @__PURE__ */ jsx25("span", { className: "text-sm font-bold text-primary", children: appName?.[0] ?? "D" }) }) : logo ?? /* @__PURE__ */ jsx25("span", { className: "text-base font-semibold text-sidebar-foreground", children: appName }) }),
1280
+ /* @__PURE__ */ jsx25("nav", { className: "flex-1 space-y-0.5 overflow-y-auto p-2", children: navItems.map((item) => /* @__PURE__ */ jsx25(
1281
+ NavItemRow,
1282
+ {
1283
+ item,
1284
+ collapsed,
1285
+ activeHref,
1286
+ onNavigate
1287
+ },
1288
+ item.href
1289
+ )) }),
1290
+ /* @__PURE__ */ jsxs12("div", { className: "border-t border-sidebar-border p-2", children: [
1291
+ bottomNavItems && bottomNavItems.length > 0 && /* @__PURE__ */ jsx25("div", { className: "mb-2 space-y-0.5", children: bottomNavItems.map((item) => /* @__PURE__ */ jsx25(
1292
+ NavItemRow,
1293
+ {
1294
+ item,
1295
+ collapsed,
1296
+ activeHref,
1297
+ onNavigate
1298
+ },
1299
+ item.href
1300
+ )) }),
1301
+ footerContent && !collapsed && /* @__PURE__ */ jsx25("div", { className: "mb-2", children: footerContent }),
1302
+ user && /* @__PURE__ */ jsxs12("div", { className: "relative", ref: userMenuRef, children: [
1303
+ /* @__PURE__ */ jsxs12(
1304
+ "button",
1305
+ {
1306
+ onClick: () => setUserMenuOpen((v) => !v),
1307
+ className: "flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-sidebar-accent/60",
1308
+ children: [
1309
+ /* @__PURE__ */ jsx25(UserAvatar, { user }),
1310
+ !collapsed && /* @__PURE__ */ jsxs12("div", { className: "flex-1 overflow-hidden text-left", children: [
1311
+ /* @__PURE__ */ jsx25("div", { className: "truncate text-xs font-medium text-sidebar-foreground", children: user.name }),
1312
+ /* @__PURE__ */ jsx25("div", { className: "truncate text-[11px] text-sidebar-foreground/60", children: user.email })
1313
+ ] })
1314
+ ]
1315
+ }
1316
+ ),
1317
+ userMenuOpen && /* @__PURE__ */ jsxs12("div", { className: cn(
1318
+ "absolute bottom-full mb-1 z-50 min-w-[180px] rounded-md border bg-popover shadow-md",
1319
+ collapsed ? "left-full ml-2 bottom-0" : "left-0"
1320
+ ), children: [
1321
+ /* @__PURE__ */ jsxs12("div", { className: "px-3 py-2 border-b", children: [
1322
+ /* @__PURE__ */ jsx25("p", { className: "text-xs font-medium", children: user.name }),
1323
+ /* @__PURE__ */ jsx25("p", { className: "text-[11px] text-muted-foreground truncate", children: user.email })
1324
+ ] }),
1325
+ onSignOut && /* @__PURE__ */ jsxs12(
1326
+ "button",
1327
+ {
1328
+ onClick: () => {
1329
+ setUserMenuOpen(false);
1330
+ onSignOut();
1331
+ },
1332
+ className: "flex w-full items-center gap-2 px-3 py-2 text-sm text-destructive hover:bg-accent transition-colors",
1333
+ children: [
1334
+ /* @__PURE__ */ jsxs12("svg", { className: "h-3.5 w-3.5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1335
+ /* @__PURE__ */ jsx25("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
1336
+ /* @__PURE__ */ jsx25("polyline", { points: "16 17 21 12 16 7" }),
1337
+ /* @__PURE__ */ jsx25("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
1338
+ ] }),
1339
+ "Sign out"
1340
+ ]
1341
+ }
1342
+ )
1343
+ ] })
1344
+ ] })
1345
+ ] })
1346
+ ]
1347
+ }
1348
+ ),
1349
+ /* @__PURE__ */ jsxs12("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
1350
+ /* @__PURE__ */ jsxs12("header", { className: "flex h-14 shrink-0 items-center gap-3 border-b bg-background px-4", children: [
1351
+ /* @__PURE__ */ jsx25(
1352
+ "button",
1353
+ {
1354
+ onClick: () => setCollapsed((v) => !v),
1355
+ className: "flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
1356
+ "aria-label": "Toggle sidebar",
1357
+ children: /* @__PURE__ */ jsx25(ToggleIcon, {})
1358
+ }
1359
+ ),
1360
+ /* @__PURE__ */ jsx25("div", { className: "flex flex-1 items-center gap-2", children: /* @__PURE__ */ jsx25(
1361
+ SearchBar,
1362
+ {
1363
+ value: searchValue,
1364
+ onChange: setSearchValue,
1365
+ placeholder: searchPlaceholder,
1366
+ shortcut: searchShortcut,
1367
+ width: "max-w-sm"
1368
+ }
1369
+ ) }),
1370
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
1371
+ /* @__PURE__ */ jsx25(ThemeToggle, {}),
1372
+ /* @__PURE__ */ jsx25(NotificationBell, { count: notificationCount, onClick: onNotificationClick }),
1373
+ user && /* @__PURE__ */ jsx25("div", { className: "ml-1", children: /* @__PURE__ */ jsx25(UserAvatar, { user, size: "md" }) })
1374
+ ] })
1375
+ ] }),
1376
+ /* @__PURE__ */ jsx25("main", { className: "flex-1 overflow-y-auto bg-muted/30 p-6", children })
1377
+ ] })
1378
+ ] });
1379
+ }
1380
+
1381
+ // src/components/data/data-table.tsx
1382
+ import { jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
971
1383
  function DataTable({
972
1384
  columns,
973
1385
  data,
@@ -999,17 +1411,17 @@ function DataTable({
999
1411
  }
1000
1412
  }
1001
1413
  const totalPages = pagination ? Math.ceil(pagination.total / pagination.pageSize) : 1;
1002
- return /* @__PURE__ */ jsxs9("div", { className: "space-y-4", children: [
1003
- selection && selection.selected.length > 0 && actions && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 rounded-md border bg-muted/50 p-2", children: [
1004
- /* @__PURE__ */ jsxs9("span", { className: "text-sm text-muted-foreground", children: [
1414
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
1415
+ selection && selection.selected.length > 0 && actions && /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 rounded-md border bg-muted/50 p-2", children: [
1416
+ /* @__PURE__ */ jsxs13("span", { className: "text-sm text-muted-foreground", children: [
1005
1417
  selection.selected.length,
1006
1418
  " selected"
1007
1419
  ] }),
1008
1420
  actions
1009
1421
  ] }),
1010
- /* @__PURE__ */ jsx22("div", { className: "rounded-md border", children: /* @__PURE__ */ jsx22("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs9("table", { className: "w-full text-sm", children: [
1011
- /* @__PURE__ */ jsx22("thead", { children: /* @__PURE__ */ jsxs9("tr", { className: "border-b bg-muted/50", children: [
1012
- selection && /* @__PURE__ */ jsx22("th", { className: "w-12 px-4 py-3", children: /* @__PURE__ */ jsx22(
1422
+ /* @__PURE__ */ jsx26("div", { className: "rounded-md border", children: /* @__PURE__ */ jsx26("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs13("table", { className: "w-full text-sm", children: [
1423
+ /* @__PURE__ */ jsx26("thead", { children: /* @__PURE__ */ jsxs13("tr", { className: "border-b bg-muted/50", children: [
1424
+ selection && /* @__PURE__ */ jsx26("th", { className: "w-12 px-4 py-3", children: /* @__PURE__ */ jsx26(
1013
1425
  Checkbox,
1014
1426
  {
1015
1427
  checked: allSelected,
@@ -1021,7 +1433,7 @@ function DataTable({
1021
1433
  onCheckedChange: toggleAll
1022
1434
  }
1023
1435
  ) }),
1024
- columns.map((col) => /* @__PURE__ */ jsx22(
1436
+ columns.map((col) => /* @__PURE__ */ jsx26(
1025
1437
  "th",
1026
1438
  {
1027
1439
  className: "px-4 py-3 text-left font-medium text-muted-foreground",
@@ -1031,20 +1443,20 @@ function DataTable({
1031
1443
  String(col.key)
1032
1444
  ))
1033
1445
  ] }) }),
1034
- /* @__PURE__ */ jsx22("tbody", { children: loading ? Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs9("tr", { className: "border-b", children: [
1035
- selection && /* @__PURE__ */ jsx22("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx22(Skeleton, { className: "h-4 w-4" }) }),
1036
- columns.map((col) => /* @__PURE__ */ jsx22("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx22(Skeleton, { className: "h-4 w-24" }) }, String(col.key)))
1037
- ] }, i)) : data.length === 0 ? /* @__PURE__ */ jsx22("tr", { children: /* @__PURE__ */ jsx22(
1446
+ /* @__PURE__ */ jsx26("tbody", { children: loading ? Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs13("tr", { className: "border-b", children: [
1447
+ selection && /* @__PURE__ */ jsx26("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx26(Skeleton, { className: "h-4 w-4" }) }),
1448
+ columns.map((col) => /* @__PURE__ */ jsx26("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx26(Skeleton, { className: "h-4 w-24" }) }, String(col.key)))
1449
+ ] }, i)) : data.length === 0 ? /* @__PURE__ */ jsx26("tr", { children: /* @__PURE__ */ jsx26(
1038
1450
  "td",
1039
1451
  {
1040
1452
  colSpan: columns.length + (selection ? 1 : 0),
1041
1453
  className: "py-12 text-center",
1042
- children: emptyState || /* @__PURE__ */ jsx22("p", { className: "text-muted-foreground", children: "No data found" })
1454
+ children: emptyState || /* @__PURE__ */ jsx26("p", { className: "text-muted-foreground", children: "No data found" })
1043
1455
  }
1044
1456
  ) }) : data.map((row, idx) => {
1045
1457
  const rowId = String(row[idKey] ?? idx);
1046
1458
  const isSelected = selection?.selected.includes(rowId);
1047
- return /* @__PURE__ */ jsxs9(
1459
+ return /* @__PURE__ */ jsxs13(
1048
1460
  "tr",
1049
1461
  {
1050
1462
  className: cn(
@@ -1054,12 +1466,12 @@ function DataTable({
1054
1466
  ),
1055
1467
  onClick: () => onRowClick?.(row),
1056
1468
  children: [
1057
- selection && /* @__PURE__ */ jsx22(
1469
+ selection && /* @__PURE__ */ jsx26(
1058
1470
  "td",
1059
1471
  {
1060
1472
  className: "px-4 py-3",
1061
1473
  onClick: (e) => e.stopPropagation(),
1062
- children: /* @__PURE__ */ jsx22(
1474
+ children: /* @__PURE__ */ jsx26(
1063
1475
  Checkbox,
1064
1476
  {
1065
1477
  checked: isSelected,
@@ -1068,15 +1480,15 @@ function DataTable({
1068
1480
  )
1069
1481
  }
1070
1482
  ),
1071
- columns.map((col) => /* @__PURE__ */ jsx22("td", { className: "px-4 py-3", children: col.cell ? col.cell(row) : String(row[col.key] ?? "") }, String(col.key)))
1483
+ columns.map((col) => /* @__PURE__ */ jsx26("td", { className: "px-4 py-3", children: col.cell ? col.cell(row) : String(row[col.key] ?? "") }, String(col.key)))
1072
1484
  ]
1073
1485
  },
1074
1486
  rowId
1075
1487
  );
1076
1488
  }) })
1077
1489
  ] }) }) }),
1078
- pagination && totalPages > 1 && /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between px-2", children: [
1079
- /* @__PURE__ */ jsxs9("div", { className: "text-sm text-muted-foreground", children: [
1490
+ pagination && totalPages > 1 && /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between px-2", children: [
1491
+ /* @__PURE__ */ jsxs13("div", { className: "text-sm text-muted-foreground", children: [
1080
1492
  "Page ",
1081
1493
  pagination.page,
1082
1494
  " of ",
@@ -1085,8 +1497,8 @@ function DataTable({
1085
1497
  pagination.total,
1086
1498
  " total)"
1087
1499
  ] }),
1088
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
1089
- /* @__PURE__ */ jsx22(
1500
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
1501
+ /* @__PURE__ */ jsx26(
1090
1502
  "button",
1091
1503
  {
1092
1504
  className: "rounded-md border px-3 py-1.5 text-sm disabled:opacity-50",
@@ -1095,7 +1507,7 @@ function DataTable({
1095
1507
  children: "Previous"
1096
1508
  }
1097
1509
  ),
1098
- /* @__PURE__ */ jsx22(
1510
+ /* @__PURE__ */ jsx26(
1099
1511
  "button",
1100
1512
  {
1101
1513
  className: "rounded-md border px-3 py-1.5 text-sm disabled:opacity-50",
@@ -1110,7 +1522,7 @@ function DataTable({
1110
1522
  }
1111
1523
 
1112
1524
  // src/components/data/empty-state.tsx
1113
- import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
1525
+ import { jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
1114
1526
  function EmptyState({
1115
1527
  icon: Icon2,
1116
1528
  title,
@@ -1118,7 +1530,7 @@ function EmptyState({
1118
1530
  action,
1119
1531
  className
1120
1532
  }) {
1121
- return /* @__PURE__ */ jsxs10(
1533
+ return /* @__PURE__ */ jsxs14(
1122
1534
  "div",
1123
1535
  {
1124
1536
  className: cn(
@@ -1126,26 +1538,26 @@ function EmptyState({
1126
1538
  className
1127
1539
  ),
1128
1540
  children: [
1129
- Icon2 && /* @__PURE__ */ jsx23("div", { className: "mb-4 rounded-full bg-muted p-3", children: /* @__PURE__ */ jsx23(Icon2, { className: "h-6 w-6 text-muted-foreground" }) }),
1130
- /* @__PURE__ */ jsx23("h3", { className: "text-lg font-semibold", children: title }),
1131
- description && /* @__PURE__ */ jsx23("p", { className: "mt-1 max-w-sm text-sm text-muted-foreground", children: description }),
1132
- action && /* @__PURE__ */ jsx23("div", { className: "mt-4", children: action })
1541
+ Icon2 && /* @__PURE__ */ jsx27("div", { className: "mb-4 rounded-full bg-muted p-3", children: /* @__PURE__ */ jsx27(Icon2, { className: "h-6 w-6 text-muted-foreground" }) }),
1542
+ /* @__PURE__ */ jsx27("h3", { className: "text-lg font-semibold", children: title }),
1543
+ description && /* @__PURE__ */ jsx27("p", { className: "mt-1 max-w-sm text-sm text-muted-foreground", children: description }),
1544
+ action && /* @__PURE__ */ jsx27("div", { className: "mt-4", children: action })
1133
1545
  ]
1134
1546
  }
1135
1547
  );
1136
1548
  }
1137
1549
 
1138
1550
  // src/components/data/pagination.tsx
1139
- import * as React17 from "react";
1551
+ import * as React19 from "react";
1140
1552
  import { ChevronLeft, ChevronRight as ChevronRight3 } from "lucide-react";
1141
- import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
1553
+ import { jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
1142
1554
  function Pagination({
1143
1555
  page,
1144
1556
  totalPages,
1145
1557
  onPageChange,
1146
1558
  className
1147
1559
  }) {
1148
- const pages = React17.useMemo(() => {
1560
+ const pages = React19.useMemo(() => {
1149
1561
  const items = [];
1150
1562
  if (totalPages <= 7) {
1151
1563
  for (let i = 1; i <= totalPages; i++) items.push(i);
@@ -1161,18 +1573,18 @@ function Pagination({
1161
1573
  return items;
1162
1574
  }, [page, totalPages]);
1163
1575
  if (totalPages <= 1) return null;
1164
- return /* @__PURE__ */ jsxs11("nav", { className: cn("flex items-center gap-1", className), children: [
1165
- /* @__PURE__ */ jsx24(
1576
+ return /* @__PURE__ */ jsxs15("nav", { className: cn("flex items-center gap-1", className), children: [
1577
+ /* @__PURE__ */ jsx28(
1166
1578
  "button",
1167
1579
  {
1168
1580
  className: "inline-flex h-9 w-9 items-center justify-center rounded-md border text-sm disabled:opacity-50",
1169
1581
  disabled: page <= 1,
1170
1582
  onClick: () => onPageChange(page - 1),
1171
- children: /* @__PURE__ */ jsx24(ChevronLeft, { className: "h-4 w-4" })
1583
+ children: /* @__PURE__ */ jsx28(ChevronLeft, { className: "h-4 w-4" })
1172
1584
  }
1173
1585
  ),
1174
1586
  pages.map(
1175
- (p, i) => p === "ellipsis" ? /* @__PURE__ */ jsx24("span", { className: "px-2 text-muted-foreground", children: "..." }, `e-${i}`) : /* @__PURE__ */ jsx24(
1587
+ (p, i) => p === "ellipsis" ? /* @__PURE__ */ jsx28("span", { className: "px-2 text-muted-foreground", children: "..." }, `e-${i}`) : /* @__PURE__ */ jsx28(
1176
1588
  "button",
1177
1589
  {
1178
1590
  className: cn(
@@ -1185,13 +1597,13 @@ function Pagination({
1185
1597
  p
1186
1598
  )
1187
1599
  ),
1188
- /* @__PURE__ */ jsx24(
1600
+ /* @__PURE__ */ jsx28(
1189
1601
  "button",
1190
1602
  {
1191
1603
  className: "inline-flex h-9 w-9 items-center justify-center rounded-md border text-sm disabled:opacity-50",
1192
1604
  disabled: page >= totalPages,
1193
1605
  onClick: () => onPageChange(page + 1),
1194
- children: /* @__PURE__ */ jsx24(ChevronRight3, { className: "h-4 w-4" })
1606
+ children: /* @__PURE__ */ jsx28(ChevronRight3, { className: "h-4 w-4" })
1195
1607
  }
1196
1608
  )
1197
1609
  ] });
@@ -1199,9 +1611,9 @@ function Pagination({
1199
1611
 
1200
1612
  // src/components/data/stats.tsx
1201
1613
  import { ArrowDown, ArrowUp } from "lucide-react";
1202
- import { jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
1614
+ import { jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
1203
1615
  function Stats({ stats, columns = 4, className }) {
1204
- return /* @__PURE__ */ jsx25(
1616
+ return /* @__PURE__ */ jsx29(
1205
1617
  "div",
1206
1618
  {
1207
1619
  className: cn(
@@ -1213,18 +1625,18 @@ function Stats({ stats, columns = 4, className }) {
1213
1625
  ),
1214
1626
  children: stats.map((stat, index) => {
1215
1627
  const Icon2 = stat.icon;
1216
- return /* @__PURE__ */ jsxs12(
1628
+ return /* @__PURE__ */ jsxs16(
1217
1629
  "div",
1218
1630
  {
1219
1631
  className: "rounded-lg border bg-card p-6 text-card-foreground shadow-sm",
1220
1632
  children: [
1221
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between", children: [
1222
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: stat.label }),
1223
- Icon2 && /* @__PURE__ */ jsx25(Icon2, { className: "h-4 w-4 text-muted-foreground" })
1633
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
1634
+ /* @__PURE__ */ jsx29("p", { className: "text-sm font-medium text-muted-foreground", children: stat.label }),
1635
+ Icon2 && /* @__PURE__ */ jsx29(Icon2, { className: "h-4 w-4 text-muted-foreground" })
1224
1636
  ] }),
1225
- /* @__PURE__ */ jsxs12("div", { className: "mt-2 flex items-baseline gap-2", children: [
1226
- /* @__PURE__ */ jsx25("p", { className: "text-2xl font-bold", children: stat.value }),
1227
- stat.change && /* @__PURE__ */ jsxs12(
1637
+ /* @__PURE__ */ jsxs16("div", { className: "mt-2 flex items-baseline gap-2", children: [
1638
+ /* @__PURE__ */ jsx29("p", { className: "text-2xl font-bold", children: stat.value }),
1639
+ stat.change && /* @__PURE__ */ jsxs16(
1228
1640
  "span",
1229
1641
  {
1230
1642
  className: cn(
@@ -1232,7 +1644,7 @@ function Stats({ stats, columns = 4, className }) {
1232
1644
  stat.change.type === "increase" ? "text-green-600 dark:text-green-400" : "text-red-600 dark:text-red-400"
1233
1645
  ),
1234
1646
  children: [
1235
- stat.change.type === "increase" ? /* @__PURE__ */ jsx25(ArrowUp, { className: "mr-0.5 h-3 w-3" }) : /* @__PURE__ */ jsx25(ArrowDown, { className: "mr-0.5 h-3 w-3" }),
1647
+ stat.change.type === "increase" ? /* @__PURE__ */ jsx29(ArrowUp, { className: "mr-0.5 h-3 w-3" }) : /* @__PURE__ */ jsx29(ArrowDown, { className: "mr-0.5 h-3 w-3" }),
1236
1648
  stat.change.value,
1237
1649
  "%"
1238
1650
  ]
@@ -1248,8 +1660,531 @@ function Stats({ stats, columns = 4, className }) {
1248
1660
  );
1249
1661
  }
1250
1662
 
1663
+ // src/components/data/plan-badge.tsx
1664
+ import { jsx as jsx30 } from "react/jsx-runtime";
1665
+ var PLAN_STYLES = {
1666
+ BASIC: "bg-muted text-muted-foreground",
1667
+ GROW: "bg-primary text-primary-foreground",
1668
+ ADVANCED: "bg-zinc-900 text-amber-400 dark:bg-zinc-800"
1669
+ };
1670
+ function PlanBadge({ plan, size = "md", className }) {
1671
+ const colorClass = PLAN_STYLES[plan.toUpperCase()] ?? "bg-muted text-muted-foreground";
1672
+ return /* @__PURE__ */ jsx30(
1673
+ "span",
1674
+ {
1675
+ className: cn(
1676
+ "inline-flex items-center rounded font-semibold uppercase tracking-wide",
1677
+ colorClass,
1678
+ size === "sm" ? "px-1.5 py-0.5 text-[10px]" : "px-2 py-1 text-xs",
1679
+ className
1680
+ ),
1681
+ children: plan
1682
+ }
1683
+ );
1684
+ }
1685
+
1686
+ // src/components/data/storage-bar.tsx
1687
+ import { jsx as jsx31, jsxs as jsxs17 } from "react/jsx-runtime";
1688
+ function formatBytes(bytes) {
1689
+ if (bytes < 1024) return `${bytes} B`;
1690
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1691
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1692
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
1693
+ }
1694
+ function getBarColor(pct) {
1695
+ if (pct >= 90) return "bg-destructive";
1696
+ if (pct >= 70) return "bg-amber-500";
1697
+ return "bg-primary";
1698
+ }
1699
+ function StorageIcon({ className }) {
1700
+ return /* @__PURE__ */ jsxs17(
1701
+ "svg",
1702
+ {
1703
+ className,
1704
+ xmlns: "http://www.w3.org/2000/svg",
1705
+ viewBox: "0 0 24 24",
1706
+ fill: "none",
1707
+ stroke: "currentColor",
1708
+ strokeWidth: "2",
1709
+ strokeLinecap: "round",
1710
+ strokeLinejoin: "round",
1711
+ children: [
1712
+ /* @__PURE__ */ jsx31("ellipse", { cx: "12", cy: "5", rx: "9", ry: "3" }),
1713
+ /* @__PURE__ */ jsx31("path", { d: "M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5" }),
1714
+ /* @__PURE__ */ jsx31("path", { d: "M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3" })
1715
+ ]
1716
+ }
1717
+ );
1718
+ }
1719
+ function StorageBar({
1720
+ used,
1721
+ limit,
1722
+ plan,
1723
+ collapsed = false,
1724
+ className
1725
+ }) {
1726
+ const pct = limit ? Math.min(100, used / limit * 100) : 0;
1727
+ const barColor = getBarColor(pct);
1728
+ if (collapsed) {
1729
+ return /* @__PURE__ */ jsx31("div", { className: cn("flex justify-center", className), children: /* @__PURE__ */ jsx31(StorageIcon, { className: "h-4 w-4 text-muted-foreground" }) });
1730
+ }
1731
+ return /* @__PURE__ */ jsxs17("div", { className: cn("space-y-1.5 px-1", className), children: [
1732
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1.5", children: [
1733
+ /* @__PURE__ */ jsx31(StorageIcon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
1734
+ limit === null ? /* @__PURE__ */ jsxs17("p", { className: "text-[11px] text-muted-foreground", children: [
1735
+ /* @__PURE__ */ jsx31("span", { className: "font-medium text-foreground", children: formatBytes(used) }),
1736
+ " \xB7 Unlimited"
1737
+ ] }) : /* @__PURE__ */ jsxs17("p", { className: "text-[11px] text-muted-foreground", children: [
1738
+ /* @__PURE__ */ jsx31("span", { className: "font-medium text-foreground", children: formatBytes(used) }),
1739
+ " / ",
1740
+ formatBytes(limit)
1741
+ ] })
1742
+ ] }),
1743
+ limit !== null && /* @__PURE__ */ jsx31("div", { className: "h-1 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx31(
1744
+ "div",
1745
+ {
1746
+ className: cn("h-full rounded-full transition-all duration-300", barColor),
1747
+ style: { width: `${pct}%` }
1748
+ }
1749
+ ) }),
1750
+ plan && /* @__PURE__ */ jsx31("p", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: plan })
1751
+ ] });
1752
+ }
1753
+
1754
+ // src/components/media/media-card.tsx
1755
+ import { jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
1756
+ function stripExtension(name) {
1757
+ return name.replace(/\.[^/.]+$/, "");
1758
+ }
1759
+ function getFileEmoji(mimeType) {
1760
+ if (mimeType.startsWith("video/")) return "\u{1F3AC}";
1761
+ if (mimeType.startsWith("audio/")) return "\u{1F3B5}";
1762
+ if (mimeType === "application/pdf") return "\u{1F4C4}";
1763
+ return "\u{1F4CE}";
1764
+ }
1765
+ function MediaCard({ file, selected = false, onClick, className }) {
1766
+ const isImage = file.mimeType.startsWith("image/");
1767
+ const displayName = stripExtension(file.name);
1768
+ return /* @__PURE__ */ jsxs18(
1769
+ "div",
1770
+ {
1771
+ role: "button",
1772
+ tabIndex: 0,
1773
+ onClick,
1774
+ onKeyDown: (e) => {
1775
+ if (e.key === "Enter" || e.key === " ") onClick?.();
1776
+ },
1777
+ className: cn(
1778
+ "group relative aspect-square cursor-pointer rounded-xl overflow-hidden border-2 transition-all duration-150",
1779
+ selected ? "border-[color:var(--primary)] shadow-[0_0_0_2px_rgba(40,127,113,0.2)]" : "border-transparent hover:border-[color:var(--primary)]/40",
1780
+ className
1781
+ ),
1782
+ children: [
1783
+ isImage ? /* @__PURE__ */ jsx32(
1784
+ "img",
1785
+ {
1786
+ src: file.url,
1787
+ alt: file.name,
1788
+ className: "h-full w-full object-cover transition-transform duration-150 group-hover:scale-[1.03]",
1789
+ loading: "lazy"
1790
+ }
1791
+ ) : /* @__PURE__ */ jsx32("div", { className: "flex h-full w-full items-center justify-center bg-muted text-4xl", children: getFileEmoji(file.mimeType) }),
1792
+ /* @__PURE__ */ jsx32("div", { className: "absolute inset-0 flex items-end bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 transition-opacity duration-150 group-hover:opacity-100", children: /* @__PURE__ */ jsx32("p", { className: "truncate px-2 pb-2 text-[11px] font-medium text-white", children: displayName }) }),
1793
+ selected && /* @__PURE__ */ jsx32("div", { className: "absolute right-1.5 top-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-primary shadow", children: /* @__PURE__ */ jsx32(
1794
+ "svg",
1795
+ {
1796
+ className: "h-3 w-3 text-white",
1797
+ xmlns: "http://www.w3.org/2000/svg",
1798
+ viewBox: "0 0 24 24",
1799
+ fill: "none",
1800
+ stroke: "currentColor",
1801
+ strokeWidth: "3",
1802
+ strokeLinecap: "round",
1803
+ strokeLinejoin: "round",
1804
+ children: /* @__PURE__ */ jsx32("polyline", { points: "20 6 9 17 4 12" })
1805
+ }
1806
+ ) })
1807
+ ]
1808
+ }
1809
+ );
1810
+ }
1811
+
1812
+ // src/components/media/media-grid.tsx
1813
+ import { jsx as jsx33, jsxs as jsxs19 } from "react/jsx-runtime";
1814
+ var columnsClass = {
1815
+ 4: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4",
1816
+ 5: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5",
1817
+ 6: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6"
1818
+ };
1819
+ function MediaGrid({
1820
+ files,
1821
+ selected,
1822
+ onSelect,
1823
+ loading = false,
1824
+ columns = 5,
1825
+ emptyMessage = "No files yet.",
1826
+ onUploadClick,
1827
+ className
1828
+ }) {
1829
+ if (loading) {
1830
+ return /* @__PURE__ */ jsx33("div", { className: cn("grid gap-2", columnsClass[columns] ?? columnsClass[5], className), children: Array.from({ length: columns * 2 }).map((_, i) => /* @__PURE__ */ jsx33(
1831
+ "div",
1832
+ {
1833
+ className: "aspect-square animate-pulse rounded-xl bg-muted"
1834
+ },
1835
+ i
1836
+ )) });
1837
+ }
1838
+ if (files.length === 0) {
1839
+ return /* @__PURE__ */ jsxs19("div", { className: cn("flex flex-col items-center justify-center gap-3 py-16 text-center", className), children: [
1840
+ /* @__PURE__ */ jsx33("div", { className: "flex h-14 w-14 items-center justify-center rounded-full bg-muted", children: /* @__PURE__ */ jsxs19(
1841
+ "svg",
1842
+ {
1843
+ className: "h-7 w-7 text-muted-foreground",
1844
+ xmlns: "http://www.w3.org/2000/svg",
1845
+ viewBox: "0 0 24 24",
1846
+ fill: "none",
1847
+ stroke: "currentColor",
1848
+ strokeWidth: "1.5",
1849
+ strokeLinecap: "round",
1850
+ strokeLinejoin: "round",
1851
+ children: [
1852
+ /* @__PURE__ */ jsx33("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
1853
+ /* @__PURE__ */ jsx33("circle", { cx: "9", cy: "9", r: "2" }),
1854
+ /* @__PURE__ */ jsx33("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
1855
+ ]
1856
+ }
1857
+ ) }),
1858
+ /* @__PURE__ */ jsx33("p", { className: "text-sm text-muted-foreground", children: emptyMessage }),
1859
+ onUploadClick && /* @__PURE__ */ jsx33(
1860
+ "button",
1861
+ {
1862
+ onClick: onUploadClick,
1863
+ className: "rounded-md bg-primary px-4 py-1.5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90",
1864
+ children: "Upload files"
1865
+ }
1866
+ )
1867
+ ] });
1868
+ }
1869
+ return /* @__PURE__ */ jsx33("div", { className: cn("grid gap-2", columnsClass[columns] ?? columnsClass[5], className), children: files.map((file) => /* @__PURE__ */ jsx33(
1870
+ MediaCard,
1871
+ {
1872
+ file,
1873
+ selected: selected?.has(file.id),
1874
+ onClick: () => onSelect?.(file)
1875
+ },
1876
+ file.id
1877
+ )) });
1878
+ }
1879
+
1880
+ // src/components/media/media-picker-dialog.tsx
1881
+ import * as React20 from "react";
1882
+ import { Fragment as Fragment4, jsx as jsx34, jsxs as jsxs20 } from "react/jsx-runtime";
1883
+ var TYPE_OPTIONS = [
1884
+ { value: "", label: "All" },
1885
+ { value: "image", label: "Images" },
1886
+ { value: "video", label: "Videos" },
1887
+ { value: "audio", label: "Audio" },
1888
+ { value: "document", label: "Docs" }
1889
+ ];
1890
+ function MediaPickerDialog({
1891
+ open,
1892
+ onOpenChange,
1893
+ title = "Media Library",
1894
+ files,
1895
+ folders = [],
1896
+ loading = false,
1897
+ total,
1898
+ uploads = [],
1899
+ typeFilter = "",
1900
+ onTypeChange,
1901
+ search = "",
1902
+ onSearch,
1903
+ activeFolderId,
1904
+ onFolderChange,
1905
+ onUpload,
1906
+ onLoadMore,
1907
+ hasMore = false,
1908
+ multiple = false,
1909
+ accept = "all",
1910
+ onSelect
1911
+ }) {
1912
+ const [localSelected, setLocalSelected] = React20.useState(/* @__PURE__ */ new Set());
1913
+ const fileInputRef = React20.useRef(null);
1914
+ const handleFileSelect = (file) => {
1915
+ if (multiple) {
1916
+ setLocalSelected((prev) => {
1917
+ const next = new Set(prev);
1918
+ if (next.has(file.id)) {
1919
+ next.delete(file.id);
1920
+ } else {
1921
+ next.add(file.id);
1922
+ }
1923
+ return next;
1924
+ });
1925
+ } else {
1926
+ const selected = files.filter((f) => f.id === file.id);
1927
+ onSelect(selected);
1928
+ onOpenChange(false);
1929
+ }
1930
+ };
1931
+ const handleConfirm = () => {
1932
+ const selected = files.filter((f) => localSelected.has(f.id));
1933
+ onSelect(selected);
1934
+ onOpenChange(false);
1935
+ };
1936
+ const handleUploadChange = (e) => {
1937
+ if (e.target.files && onUpload) {
1938
+ onUpload(e.target.files);
1939
+ }
1940
+ };
1941
+ const activeUploads = uploads.filter((u) => u.status === "uploading");
1942
+ return /* @__PURE__ */ jsx34(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs20(DialogContent, { className: "flex h-[85vh] max-h-[700px] max-w-4xl flex-col gap-0 p-0", children: [
1943
+ /* @__PURE__ */ jsxs20(DialogHeader, { className: "flex-row items-center justify-between border-b px-5 py-3", children: [
1944
+ /* @__PURE__ */ jsx34(DialogTitle, { className: "text-base", children: title }),
1945
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
1946
+ /* @__PURE__ */ jsxs20("span", { className: "text-xs text-muted-foreground", children: [
1947
+ total,
1948
+ " files"
1949
+ ] }),
1950
+ onUpload && /* @__PURE__ */ jsxs20(Fragment4, { children: [
1951
+ /* @__PURE__ */ jsx34(
1952
+ "input",
1953
+ {
1954
+ ref: fileInputRef,
1955
+ type: "file",
1956
+ className: "hidden",
1957
+ multiple: true,
1958
+ accept: accept === "images" ? "image/*" : void 0,
1959
+ onChange: handleUploadChange
1960
+ }
1961
+ ),
1962
+ /* @__PURE__ */ jsxs20(
1963
+ "button",
1964
+ {
1965
+ onClick: () => fileInputRef.current?.click(),
1966
+ className: "flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-opacity hover:opacity-90",
1967
+ children: [
1968
+ /* @__PURE__ */ jsxs20("svg", { className: "h-3.5 w-3.5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1969
+ /* @__PURE__ */ jsx34("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1970
+ /* @__PURE__ */ jsx34("polyline", { points: "17 8 12 3 7 8" }),
1971
+ /* @__PURE__ */ jsx34("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1972
+ ] }),
1973
+ "Upload"
1974
+ ]
1975
+ }
1976
+ )
1977
+ ] })
1978
+ ] })
1979
+ ] }),
1980
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-1 overflow-hidden", children: [
1981
+ folders.length > 0 && /* @__PURE__ */ jsxs20("aside", { className: "flex w-44 shrink-0 flex-col gap-0.5 overflow-y-auto border-r p-2", children: [
1982
+ /* @__PURE__ */ jsxs20(
1983
+ "button",
1984
+ {
1985
+ onClick: () => onFolderChange?.(""),
1986
+ className: cn(
1987
+ "flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm transition-colors",
1988
+ !activeFolderId ? "bg-primary/10 font-medium text-primary" : "text-muted-foreground hover:bg-accent"
1989
+ ),
1990
+ children: [
1991
+ /* @__PURE__ */ jsx34("svg", { className: "h-3.5 w-3.5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx34("path", { d: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }) }),
1992
+ "All files"
1993
+ ]
1994
+ }
1995
+ ),
1996
+ folders.map((folder) => /* @__PURE__ */ jsxs20(
1997
+ "button",
1998
+ {
1999
+ onClick: () => onFolderChange?.(folder.id),
2000
+ className: cn(
2001
+ "flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm transition-colors",
2002
+ activeFolderId === folder.id ? "bg-primary/10 font-medium text-primary" : "text-muted-foreground hover:bg-accent"
2003
+ ),
2004
+ children: [
2005
+ /* @__PURE__ */ jsx34("span", { className: "text-base leading-none", children: folder.icon ?? "\u{1F4C1}" }),
2006
+ /* @__PURE__ */ jsx34("span", { className: "truncate", children: folder.name })
2007
+ ]
2008
+ },
2009
+ folder.id
2010
+ ))
2011
+ ] }),
2012
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
2013
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 border-b px-4 py-2", children: [
2014
+ /* @__PURE__ */ jsxs20("div", { className: "relative flex-1", children: [
2015
+ /* @__PURE__ */ jsxs20("svg", { className: "pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2016
+ /* @__PURE__ */ jsx34("circle", { cx: "11", cy: "11", r: "8" }),
2017
+ /* @__PURE__ */ jsx34("path", { d: "m21 21-4.35-4.35" })
2018
+ ] }),
2019
+ /* @__PURE__ */ jsx34(
2020
+ "input",
2021
+ {
2022
+ type: "search",
2023
+ value: search,
2024
+ onChange: (e) => onSearch?.(e.target.value),
2025
+ placeholder: "Search files\u2026",
2026
+ className: "h-7 w-full rounded-md border border-input bg-muted/50 pl-8 pr-3 text-xs outline-none focus:border-primary focus:ring-1 focus:ring-primary"
2027
+ }
2028
+ )
2029
+ ] }),
2030
+ /* @__PURE__ */ jsx34("div", { className: "flex gap-1", children: TYPE_OPTIONS.filter((o) => accept === "images" ? o.value === "" || o.value === "image" : true).map((opt) => /* @__PURE__ */ jsx34(
2031
+ "button",
2032
+ {
2033
+ onClick: () => onTypeChange?.(opt.value),
2034
+ className: cn(
2035
+ "rounded px-2 py-1 text-xs transition-colors",
2036
+ typeFilter === opt.value ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-accent"
2037
+ ),
2038
+ children: opt.label
2039
+ },
2040
+ opt.value
2041
+ )) })
2042
+ ] }),
2043
+ activeUploads.length > 0 && /* @__PURE__ */ jsx34("div", { className: "border-b px-4 py-2 space-y-1.5", children: activeUploads.map((u, i) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
2044
+ /* @__PURE__ */ jsx34("span", { className: "flex-1 truncate text-xs text-muted-foreground", children: u.name }),
2045
+ /* @__PURE__ */ jsx34("div", { className: "h-1.5 w-24 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx34(
2046
+ "div",
2047
+ {
2048
+ className: "h-full rounded-full bg-primary transition-all",
2049
+ style: { width: `${u.progress}%` }
2050
+ }
2051
+ ) }),
2052
+ /* @__PURE__ */ jsxs20("span", { className: "text-[10px] text-muted-foreground", children: [
2053
+ u.progress,
2054
+ "%"
2055
+ ] })
2056
+ ] }, i)) }),
2057
+ /* @__PURE__ */ jsxs20("div", { className: "flex-1 overflow-y-auto p-4", children: [
2058
+ /* @__PURE__ */ jsx34(
2059
+ MediaGrid,
2060
+ {
2061
+ files,
2062
+ selected: localSelected,
2063
+ onSelect: handleFileSelect,
2064
+ loading,
2065
+ columns: 5,
2066
+ onUploadClick: onUpload ? () => fileInputRef.current?.click() : void 0
2067
+ }
2068
+ ),
2069
+ hasMore && /* @__PURE__ */ jsx34("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx34(
2070
+ "button",
2071
+ {
2072
+ onClick: onLoadMore,
2073
+ className: "rounded-md border px-4 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent",
2074
+ children: "Load more"
2075
+ }
2076
+ ) })
2077
+ ] }),
2078
+ multiple && localSelected.size > 0 && /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between border-t px-4 py-3", children: [
2079
+ /* @__PURE__ */ jsxs20("span", { className: "text-sm text-muted-foreground", children: [
2080
+ localSelected.size,
2081
+ " selected"
2082
+ ] }),
2083
+ /* @__PURE__ */ jsxs20("div", { className: "flex gap-2", children: [
2084
+ /* @__PURE__ */ jsx34(
2085
+ "button",
2086
+ {
2087
+ onClick: () => setLocalSelected(/* @__PURE__ */ new Set()),
2088
+ className: "rounded-md px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:bg-accent",
2089
+ children: "Clear"
2090
+ }
2091
+ ),
2092
+ /* @__PURE__ */ jsxs20(
2093
+ "button",
2094
+ {
2095
+ onClick: handleConfirm,
2096
+ className: "rounded-md bg-primary px-4 py-1.5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90",
2097
+ children: [
2098
+ "Insert ",
2099
+ localSelected.size,
2100
+ " file",
2101
+ localSelected.size !== 1 ? "s" : ""
2102
+ ]
2103
+ }
2104
+ )
2105
+ ] })
2106
+ ] })
2107
+ ] })
2108
+ ] })
2109
+ ] }) });
2110
+ }
2111
+
2112
+ // src/components/media/image-picker-field.tsx
2113
+ import { jsx as jsx35, jsxs as jsxs21 } from "react/jsx-runtime";
2114
+ var sizeMap = {
2115
+ sm: { box: "h-12 w-12", icon: "h-4 w-4", text: "text-[9px]" },
2116
+ md: { box: "h-20 w-20", icon: "h-5 w-5", text: "text-[10px]" },
2117
+ lg: { box: "h-24 w-24", icon: "h-6 w-6", text: "text-xs" }
2118
+ };
2119
+ function ImagePickerField({
2120
+ value,
2121
+ filename,
2122
+ onPickerOpen,
2123
+ onRemove,
2124
+ size = "md",
2125
+ emptyLabel = "Click to select",
2126
+ className
2127
+ }) {
2128
+ const sz = sizeMap[size];
2129
+ return /* @__PURE__ */ jsxs21("div", { className: cn("relative inline-flex shrink-0", className), children: [
2130
+ /* @__PURE__ */ jsx35(
2131
+ "button",
2132
+ {
2133
+ type: "button",
2134
+ onClick: onPickerOpen,
2135
+ className: cn(
2136
+ "group flex items-center justify-center rounded-lg border-2 border-dashed transition-all duration-150",
2137
+ sz.box,
2138
+ value ? "border-border overflow-hidden" : "border-border hover:border-[color:var(--primary)] hover:bg-primary/5"
2139
+ ),
2140
+ children: value ? /* @__PURE__ */ jsx35(
2141
+ "img",
2142
+ {
2143
+ src: value,
2144
+ alt: filename ?? "Selected image",
2145
+ className: "h-full w-full rounded-md object-cover"
2146
+ }
2147
+ ) : /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-1", children: [
2148
+ /* @__PURE__ */ jsxs21(
2149
+ "svg",
2150
+ {
2151
+ className: cn(sz.icon, "text-muted-foreground transition-colors group-hover:text-primary"),
2152
+ xmlns: "http://www.w3.org/2000/svg",
2153
+ viewBox: "0 0 24 24",
2154
+ fill: "none",
2155
+ stroke: "currentColor",
2156
+ strokeWidth: "1.5",
2157
+ strokeLinecap: "round",
2158
+ strokeLinejoin: "round",
2159
+ children: [
2160
+ /* @__PURE__ */ jsx35("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
2161
+ /* @__PURE__ */ jsx35("circle", { cx: "9", cy: "9", r: "2" }),
2162
+ /* @__PURE__ */ jsx35("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
2163
+ ]
2164
+ }
2165
+ ),
2166
+ size !== "sm" && /* @__PURE__ */ jsx35("span", { className: cn(sz.text, "text-muted-foreground text-center leading-tight transition-colors group-hover:text-primary"), children: emptyLabel })
2167
+ ] })
2168
+ }
2169
+ ),
2170
+ value && onRemove && /* @__PURE__ */ jsx35(
2171
+ "button",
2172
+ {
2173
+ type: "button",
2174
+ onClick: (e) => {
2175
+ e.stopPropagation();
2176
+ onRemove();
2177
+ },
2178
+ className: "absolute -right-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-destructive text-destructive-foreground shadow-sm transition-opacity hover:opacity-90",
2179
+ "aria-label": "Remove image",
2180
+ children: /* @__PURE__ */ jsx35("svg", { className: "h-2.5 w-2.5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx35("path", { d: "M18 6 6 18M6 6l12 12" }) })
2181
+ }
2182
+ )
2183
+ ] });
2184
+ }
2185
+
1251
2186
  // src/components/form/form-field.tsx
1252
- import { jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
2187
+ import { jsx as jsx36, jsxs as jsxs22 } from "react/jsx-runtime";
1253
2188
  function FormField({
1254
2189
  label,
1255
2190
  error,
@@ -1258,19 +2193,19 @@ function FormField({
1258
2193
  children,
1259
2194
  className
1260
2195
  }) {
1261
- return /* @__PURE__ */ jsxs13("div", { className: cn("space-y-2", className), children: [
1262
- /* @__PURE__ */ jsxs13(Label2, { children: [
2196
+ return /* @__PURE__ */ jsxs22("div", { className: cn("space-y-2", className), children: [
2197
+ /* @__PURE__ */ jsxs22(Label2, { children: [
1263
2198
  label,
1264
- required && /* @__PURE__ */ jsx26("span", { className: "ml-1 text-destructive", children: "*" })
2199
+ required && /* @__PURE__ */ jsx36("span", { className: "ml-1 text-destructive", children: "*" })
1265
2200
  ] }),
1266
2201
  children,
1267
- hint && !error && /* @__PURE__ */ jsx26("p", { className: "text-sm text-muted-foreground", children: hint }),
1268
- error && /* @__PURE__ */ jsx26("p", { className: "text-sm text-destructive", children: error })
2202
+ hint && !error && /* @__PURE__ */ jsx36("p", { className: "text-sm text-muted-foreground", children: hint }),
2203
+ error && /* @__PURE__ */ jsx36("p", { className: "text-sm text-destructive", children: error })
1269
2204
  ] });
1270
2205
  }
1271
2206
 
1272
2207
  // src/components/form/form-layout.tsx
1273
- import { jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
2208
+ import { jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
1274
2209
  function FormLayout({
1275
2210
  title,
1276
2211
  description,
@@ -1278,7 +2213,7 @@ function FormLayout({
1278
2213
  actions,
1279
2214
  className
1280
2215
  }) {
1281
- return /* @__PURE__ */ jsxs14(
2216
+ return /* @__PURE__ */ jsxs23(
1282
2217
  "div",
1283
2218
  {
1284
2219
  className: cn(
@@ -1286,37 +2221,37 @@ function FormLayout({
1286
2221
  className
1287
2222
  ),
1288
2223
  children: [
1289
- (title || description) && /* @__PURE__ */ jsxs14("div", { className: "border-b p-6", children: [
1290
- title && /* @__PURE__ */ jsx27("h3", { className: "text-lg font-semibold", children: title }),
1291
- description && /* @__PURE__ */ jsx27("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
2224
+ (title || description) && /* @__PURE__ */ jsxs23("div", { className: "border-b p-6", children: [
2225
+ title && /* @__PURE__ */ jsx37("h3", { className: "text-lg font-semibold", children: title }),
2226
+ description && /* @__PURE__ */ jsx37("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
1292
2227
  ] }),
1293
- /* @__PURE__ */ jsx27("div", { className: "space-y-6 p-6", children }),
1294
- actions && /* @__PURE__ */ jsx27("div", { className: "flex items-center justify-end gap-2 border-t px-6 py-4", children: actions })
2228
+ /* @__PURE__ */ jsx37("div", { className: "space-y-6 p-6", children }),
2229
+ actions && /* @__PURE__ */ jsx37("div", { className: "flex items-center justify-end gap-2 border-t px-6 py-4", children: actions })
1295
2230
  ]
1296
2231
  }
1297
2232
  );
1298
2233
  }
1299
2234
 
1300
2235
  // src/components/form/form-section.tsx
1301
- import { jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
2236
+ import { jsx as jsx38, jsxs as jsxs24 } from "react/jsx-runtime";
1302
2237
  function FormSection({
1303
2238
  title,
1304
2239
  description,
1305
2240
  children,
1306
2241
  className
1307
2242
  }) {
1308
- return /* @__PURE__ */ jsxs15("div", { className: cn("space-y-4", className), children: [
1309
- /* @__PURE__ */ jsxs15("div", { children: [
1310
- /* @__PURE__ */ jsx28("h4", { className: "text-sm font-medium", children: title }),
1311
- description && /* @__PURE__ */ jsx28("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
2243
+ return /* @__PURE__ */ jsxs24("div", { className: cn("space-y-4", className), children: [
2244
+ /* @__PURE__ */ jsxs24("div", { children: [
2245
+ /* @__PURE__ */ jsx38("h4", { className: "text-sm font-medium", children: title }),
2246
+ description && /* @__PURE__ */ jsx38("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
1312
2247
  ] }),
1313
- /* @__PURE__ */ jsx28("div", { className: "space-y-4", children })
2248
+ /* @__PURE__ */ jsx38("div", { className: "space-y-4", children })
1314
2249
  ] });
1315
2250
  }
1316
2251
 
1317
2252
  // src/components/feedback/alert.tsx
1318
2253
  import { AlertCircle, CheckCircle2, Info, AlertTriangle, X as X2 } from "lucide-react";
1319
- import { jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
2254
+ import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
1320
2255
  var variantConfig = {
1321
2256
  info: {
1322
2257
  icon: Info,
@@ -1345,7 +2280,7 @@ function Alert({
1345
2280
  }) {
1346
2281
  const config = variantConfig[variant];
1347
2282
  const Icon2 = config.icon;
1348
- return /* @__PURE__ */ jsxs16(
2283
+ return /* @__PURE__ */ jsxs25(
1349
2284
  "div",
1350
2285
  {
1351
2286
  className: cn(
@@ -1355,17 +2290,17 @@ function Alert({
1355
2290
  ),
1356
2291
  role: "alert",
1357
2292
  children: [
1358
- /* @__PURE__ */ jsx29(Icon2, { className: "mt-0.5 h-5 w-5 shrink-0" }),
1359
- /* @__PURE__ */ jsxs16("div", { className: "flex-1", children: [
1360
- title && /* @__PURE__ */ jsx29("p", { className: "font-medium", children: title }),
1361
- /* @__PURE__ */ jsx29("div", { className: cn("text-sm", title && "mt-1"), children })
2293
+ /* @__PURE__ */ jsx39(Icon2, { className: "mt-0.5 h-5 w-5 shrink-0" }),
2294
+ /* @__PURE__ */ jsxs25("div", { className: "flex-1", children: [
2295
+ title && /* @__PURE__ */ jsx39("p", { className: "font-medium", children: title }),
2296
+ /* @__PURE__ */ jsx39("div", { className: cn("text-sm", title && "mt-1"), children })
1362
2297
  ] }),
1363
- dismissible && /* @__PURE__ */ jsx29(
2298
+ dismissible && /* @__PURE__ */ jsx39(
1364
2299
  "button",
1365
2300
  {
1366
2301
  onClick: onDismiss,
1367
2302
  className: "absolute right-3 top-3 rounded-md p-1 opacity-70 hover:opacity-100",
1368
- children: /* @__PURE__ */ jsx29(X2, { className: "h-4 w-4" })
2303
+ children: /* @__PURE__ */ jsx39(X2, { className: "h-4 w-4" })
1369
2304
  }
1370
2305
  )
1371
2306
  ]
@@ -1375,23 +2310,23 @@ function Alert({
1375
2310
 
1376
2311
  // src/components/feedback/loading-spinner.tsx
1377
2312
  import { Loader2 } from "lucide-react";
1378
- import { jsx as jsx30 } from "react/jsx-runtime";
1379
- var sizeMap = {
2313
+ import { jsx as jsx40 } from "react/jsx-runtime";
2314
+ var sizeMap2 = {
1380
2315
  sm: "h-4 w-4",
1381
2316
  md: "h-6 w-6",
1382
2317
  lg: "h-8 w-8"
1383
2318
  };
1384
2319
  function LoadingSpinner({ size = "md", className }) {
1385
- return /* @__PURE__ */ jsx30(
2320
+ return /* @__PURE__ */ jsx40(
1386
2321
  Loader2,
1387
2322
  {
1388
- className: cn("animate-spin text-muted-foreground", sizeMap[size], className)
2323
+ className: cn("animate-spin text-muted-foreground", sizeMap2[size], className)
1389
2324
  }
1390
2325
  );
1391
2326
  }
1392
2327
 
1393
2328
  // src/components/feedback/confirm-dialog.tsx
1394
- import { jsx as jsx31, jsxs as jsxs17 } from "react/jsx-runtime";
2329
+ import { jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
1395
2330
  function ConfirmDialog({
1396
2331
  open,
1397
2332
  onOpenChange,
@@ -1403,13 +2338,13 @@ function ConfirmDialog({
1403
2338
  loading,
1404
2339
  variant = "default"
1405
2340
  }) {
1406
- return /* @__PURE__ */ jsx31(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs17(DialogContent, { children: [
1407
- /* @__PURE__ */ jsxs17(DialogHeader, { children: [
1408
- /* @__PURE__ */ jsx31(DialogTitle, { children: title }),
1409
- description && /* @__PURE__ */ jsx31(DialogDescription, { children: description })
2341
+ return /* @__PURE__ */ jsx41(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs26(DialogContent, { children: [
2342
+ /* @__PURE__ */ jsxs26(DialogHeader, { children: [
2343
+ /* @__PURE__ */ jsx41(DialogTitle, { children: title }),
2344
+ description && /* @__PURE__ */ jsx41(DialogDescription, { children: description })
1410
2345
  ] }),
1411
- /* @__PURE__ */ jsxs17(DialogFooter, { children: [
1412
- /* @__PURE__ */ jsx31(
2346
+ /* @__PURE__ */ jsxs26(DialogFooter, { children: [
2347
+ /* @__PURE__ */ jsx41(
1413
2348
  Button,
1414
2349
  {
1415
2350
  variant: "outline",
@@ -1418,14 +2353,14 @@ function ConfirmDialog({
1418
2353
  children: cancelLabel
1419
2354
  }
1420
2355
  ),
1421
- /* @__PURE__ */ jsxs17(
2356
+ /* @__PURE__ */ jsxs26(
1422
2357
  Button,
1423
2358
  {
1424
2359
  variant: variant === "destructive" ? "destructive" : "default",
1425
2360
  onClick: onConfirm,
1426
2361
  disabled: loading,
1427
2362
  children: [
1428
- loading && /* @__PURE__ */ jsx31(LoadingSpinner, { size: "sm", className: "mr-2" }),
2363
+ loading && /* @__PURE__ */ jsx41(LoadingSpinner, { size: "sm", className: "mr-2" }),
1429
2364
  confirmLabel
1430
2365
  ]
1431
2366
  }
@@ -1435,9 +2370,9 @@ function ConfirmDialog({
1435
2370
  }
1436
2371
 
1437
2372
  // src/hooks/index.ts
1438
- import { useState as useState2 } from "react";
2373
+ import { useState as useState5 } from "react";
1439
2374
  function useDisclosure(initial = false) {
1440
- const [isOpen, setIsOpen] = useState2(initial);
2375
+ const [isOpen, setIsOpen] = useState5(initial);
1441
2376
  return {
1442
2377
  isOpen,
1443
2378
  open: () => setIsOpen(true),
@@ -1447,15 +2382,15 @@ function useDisclosure(initial = false) {
1447
2382
  };
1448
2383
  }
1449
2384
  function usePagination(total, pageSize = 20) {
1450
- const [page, setPage] = useState2(1);
2385
+ const [page, setPage] = useState5(1);
1451
2386
  const totalPages = Math.ceil(total / pageSize);
1452
2387
  return { page, setPage, pageSize, total, totalPages };
1453
2388
  }
1454
2389
 
1455
2390
  // src/components/auth/AuthShell.tsx
1456
- import { jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
2391
+ import { jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
1457
2392
  function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
1458
- return /* @__PURE__ */ jsxs18(
2393
+ return /* @__PURE__ */ jsxs27(
1459
2394
  "div",
1460
2395
  {
1461
2396
  style: {
@@ -1470,7 +2405,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
1470
2405
  overflow: "hidden"
1471
2406
  },
1472
2407
  children: [
1473
- pattern === "dots" && /* @__PURE__ */ jsx32(
2408
+ pattern === "dots" && /* @__PURE__ */ jsx42(
1474
2409
  "div",
1475
2410
  {
1476
2411
  "aria-hidden": true,
@@ -1484,7 +2419,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
1484
2419
  }
1485
2420
  }
1486
2421
  ),
1487
- pattern === "grid" && /* @__PURE__ */ jsx32(
2422
+ pattern === "grid" && /* @__PURE__ */ jsx42(
1488
2423
  "div",
1489
2424
  {
1490
2425
  "aria-hidden": true,
@@ -1498,16 +2433,16 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
1498
2433
  }
1499
2434
  }
1500
2435
  ),
1501
- /* @__PURE__ */ jsx32("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
2436
+ /* @__PURE__ */ jsx42("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
1502
2437
  ]
1503
2438
  }
1504
2439
  );
1505
2440
  }
1506
2441
 
1507
2442
  // src/components/auth/AuthCard.tsx
1508
- import { jsx as jsx33 } from "react/jsx-runtime";
2443
+ import { jsx as jsx43 } from "react/jsx-runtime";
1509
2444
  function AuthCard({ children, padding = "24px 28px" }) {
1510
- return /* @__PURE__ */ jsx33(
2445
+ return /* @__PURE__ */ jsx43(
1511
2446
  "div",
1512
2447
  {
1513
2448
  style: {
@@ -1524,10 +2459,10 @@ function AuthCard({ children, padding = "24px 28px" }) {
1524
2459
  }
1525
2460
 
1526
2461
  // src/components/auth/AuthLogo.tsx
1527
- import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
2462
+ import { jsx as jsx44, jsxs as jsxs28 } from "react/jsx-runtime";
1528
2463
  function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }) {
1529
- return /* @__PURE__ */ jsxs19("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
1530
- imageUrl ? /* @__PURE__ */ jsx34(
2464
+ return /* @__PURE__ */ jsxs28("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
2465
+ imageUrl ? /* @__PURE__ */ jsx44(
1531
2466
  "img",
1532
2467
  {
1533
2468
  src: imageUrl,
@@ -1536,7 +2471,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
1536
2471
  height: size,
1537
2472
  style: { borderRadius: "calc(var(--radius, 0.5rem) * 1.2)", flexShrink: 0, display: "block" }
1538
2473
  }
1539
- ) : /* @__PURE__ */ jsx34(
2474
+ ) : /* @__PURE__ */ jsx44(
1540
2475
  "div",
1541
2476
  {
1542
2477
  style: {
@@ -1555,7 +2490,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
1555
2490
  children: letter
1556
2491
  }
1557
2492
  ),
1558
- /* @__PURE__ */ jsx34(
2493
+ /* @__PURE__ */ jsx44(
1559
2494
  "span",
1560
2495
  {
1561
2496
  style: {
@@ -1571,10 +2506,10 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
1571
2506
  }
1572
2507
 
1573
2508
  // src/components/auth/AuthHeader.tsx
1574
- import { jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
2509
+ import { jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
1575
2510
  function AuthHeader({ title, description }) {
1576
- return /* @__PURE__ */ jsxs20("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
1577
- /* @__PURE__ */ jsx35(
2511
+ return /* @__PURE__ */ jsxs29("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
2512
+ /* @__PURE__ */ jsx45(
1578
2513
  "h1",
1579
2514
  {
1580
2515
  style: {
@@ -1587,7 +2522,7 @@ function AuthHeader({ title, description }) {
1587
2522
  children: title
1588
2523
  }
1589
2524
  ),
1590
- description && /* @__PURE__ */ jsx35(
2525
+ description && /* @__PURE__ */ jsx45(
1591
2526
  "p",
1592
2527
  {
1593
2528
  style: {
@@ -1603,12 +2538,12 @@ function AuthHeader({ title, description }) {
1603
2538
  }
1604
2539
 
1605
2540
  // src/components/auth/AuthField.tsx
1606
- import { jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
2541
+ import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
1607
2542
  function AuthField({ label, error, hint, rightLabel, id, ...props }) {
1608
2543
  const fieldId = id ?? label.toLowerCase().replace(/\s+/g, "-");
1609
- return /* @__PURE__ */ jsxs21("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
1610
- /* @__PURE__ */ jsxs21("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
1611
- /* @__PURE__ */ jsx36(
2544
+ return /* @__PURE__ */ jsxs30("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
2545
+ /* @__PURE__ */ jsxs30("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
2546
+ /* @__PURE__ */ jsx46(
1612
2547
  "label",
1613
2548
  {
1614
2549
  htmlFor: fieldId,
@@ -1620,9 +2555,9 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
1620
2555
  children: label
1621
2556
  }
1622
2557
  ),
1623
- rightLabel && /* @__PURE__ */ jsx36("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
2558
+ rightLabel && /* @__PURE__ */ jsx46("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
1624
2559
  ] }),
1625
- /* @__PURE__ */ jsx36(
2560
+ /* @__PURE__ */ jsx46(
1626
2561
  "input",
1627
2562
  {
1628
2563
  id: fieldId,
@@ -1652,13 +2587,13 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
1652
2587
  ...props
1653
2588
  }
1654
2589
  ),
1655
- error && /* @__PURE__ */ jsx36("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
1656
- hint && !error && /* @__PURE__ */ jsx36("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
2590
+ error && /* @__PURE__ */ jsx46("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
2591
+ hint && !error && /* @__PURE__ */ jsx46("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
1657
2592
  ] });
1658
2593
  }
1659
2594
 
1660
2595
  // src/components/auth/AuthButton.tsx
1661
- import { Fragment as Fragment3, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
2596
+ import { Fragment as Fragment5, jsx as jsx47, jsxs as jsxs31 } from "react/jsx-runtime";
1662
2597
  function AuthButton({
1663
2598
  loading,
1664
2599
  variant = "primary",
@@ -1701,7 +2636,7 @@ function AuthButton({
1701
2636
  color: "var(--foreground)"
1702
2637
  }
1703
2638
  };
1704
- return /* @__PURE__ */ jsx37(
2639
+ return /* @__PURE__ */ jsx47(
1705
2640
  "button",
1706
2641
  {
1707
2642
  disabled: loading || disabled,
@@ -1713,8 +2648,8 @@ function AuthButton({
1713
2648
  e.currentTarget.style.filter = "none";
1714
2649
  },
1715
2650
  ...props,
1716
- children: loading ? /* @__PURE__ */ jsxs22(Fragment3, { children: [
1717
- /* @__PURE__ */ jsx37(
2651
+ children: loading ? /* @__PURE__ */ jsxs31(Fragment5, { children: [
2652
+ /* @__PURE__ */ jsx47(
1718
2653
  "span",
1719
2654
  {
1720
2655
  style: {
@@ -1735,19 +2670,19 @@ function AuthButton({
1735
2670
  }
1736
2671
 
1737
2672
  // src/components/auth/AuthDivider.tsx
1738
- import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
2673
+ import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
1739
2674
  function AuthDivider({ label = "or" }) {
1740
- return /* @__PURE__ */ jsxs23("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
1741
- /* @__PURE__ */ jsx38("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
1742
- /* @__PURE__ */ jsx38("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
1743
- /* @__PURE__ */ jsx38("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
2675
+ return /* @__PURE__ */ jsxs32("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
2676
+ /* @__PURE__ */ jsx48("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
2677
+ /* @__PURE__ */ jsx48("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
2678
+ /* @__PURE__ */ jsx48("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
1744
2679
  ] });
1745
2680
  }
1746
2681
 
1747
2682
  // src/components/auth/AuthFootnote.tsx
1748
- import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
2683
+ import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
1749
2684
  function AuthFootnote({ text, linkText, linkHref }) {
1750
- return /* @__PURE__ */ jsxs24("p", { style: {
2685
+ return /* @__PURE__ */ jsxs33("p", { style: {
1751
2686
  textAlign: "center",
1752
2687
  marginTop: "20px",
1753
2688
  fontSize: "0.8125rem",
@@ -1755,7 +2690,7 @@ function AuthFootnote({ text, linkText, linkHref }) {
1755
2690
  }, children: [
1756
2691
  text,
1757
2692
  " ",
1758
- /* @__PURE__ */ jsx39(
2693
+ /* @__PURE__ */ jsx49(
1759
2694
  "a",
1760
2695
  {
1761
2696
  href: linkHref,
@@ -1773,9 +2708,9 @@ function AuthFootnote({ text, linkText, linkHref }) {
1773
2708
  }
1774
2709
 
1775
2710
  // src/components/Skeleton.tsx
1776
- import { jsx as jsx40 } from "react/jsx-runtime";
2711
+ import { jsx as jsx50 } from "react/jsx-runtime";
1777
2712
  function Skeleton2({ width = "100%", height = 16, rounded, style }) {
1778
- return /* @__PURE__ */ jsx40(
2713
+ return /* @__PURE__ */ jsx50(
1779
2714
  "div",
1780
2715
  {
1781
2716
  style: {
@@ -1788,7 +2723,7 @@ function Skeleton2({ width = "100%", height = 16, rounded, style }) {
1788
2723
  flexShrink: 0,
1789
2724
  ...style
1790
2725
  },
1791
- children: /* @__PURE__ */ jsx40(
2726
+ children: /* @__PURE__ */ jsx50(
1792
2727
  "div",
1793
2728
  {
1794
2729
  style: {
@@ -1804,7 +2739,7 @@ function Skeleton2({ width = "100%", height = 16, rounded, style }) {
1804
2739
  }
1805
2740
 
1806
2741
  // src/index.ts
1807
- import { ThemeProvider, useTheme } from "next-themes";
2742
+ import { ThemeProvider, useTheme as useTheme2 } from "next-themes";
1808
2743
  export {
1809
2744
  Alert,
1810
2745
  AppShell,
@@ -1826,6 +2761,7 @@ export {
1826
2761
  CardTitle,
1827
2762
  Checkbox,
1828
2763
  ConfirmDialog,
2764
+ DashboardLayout,
1829
2765
  DataTable,
1830
2766
  Dialog,
1831
2767
  DialogClose,
@@ -1856,15 +2792,22 @@ export {
1856
2792
  FormField,
1857
2793
  FormLayout,
1858
2794
  FormSection,
2795
+ ImagePickerField,
1859
2796
  Input,
1860
2797
  Label2 as Label,
1861
2798
  LoadingSpinner,
2799
+ MediaCard,
2800
+ MediaGrid,
2801
+ MediaPickerDialog,
2802
+ NotificationBell,
1862
2803
  Page,
1863
2804
  PageSection,
1864
2805
  Pagination,
2806
+ PlanBadge,
1865
2807
  Popover,
1866
2808
  PopoverContent,
1867
2809
  PopoverTrigger,
2810
+ SearchBar,
1868
2811
  Select,
1869
2812
  SelectContent,
1870
2813
  SelectGroup,
@@ -1879,6 +2822,7 @@ export {
1879
2822
  Sidebar,
1880
2823
  Skeleton2 as Skeleton,
1881
2824
  Stats,
2825
+ StorageBar,
1882
2826
  Switch,
1883
2827
  Tabs,
1884
2828
  TabsContent,
@@ -1886,6 +2830,7 @@ export {
1886
2830
  TabsTrigger,
1887
2831
  Textarea,
1888
2832
  ThemeProvider,
2833
+ ThemeToggle,
1889
2834
  Tooltip,
1890
2835
  TooltipContent,
1891
2836
  TooltipProvider,
@@ -1896,6 +2841,6 @@ export {
1896
2841
  cn,
1897
2842
  useDisclosure,
1898
2843
  usePagination,
1899
- useTheme
2844
+ useTheme2 as useTheme
1900
2845
  };
1901
2846
  //# sourceMappingURL=index.mjs.map