@webdevarif/dashui 0.1.8 → 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.d.mts +144 -1
- package/dist/index.d.ts +144 -1
- package/dist/index.js +1086 -131
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1078 -133
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -503,9 +503,9 @@ var SelectContent = React9.forwardRef(({ className, children, position = "popper
|
|
|
503
503
|
SelectPrimitive.Content,
|
|
504
504
|
{
|
|
505
505
|
ref,
|
|
506
|
+
style: { background: "#ffffff", border: "1px solid #e5e7eb", borderRadius: 10, boxShadow: "0 8px 32px rgba(0,0,0,0.12)", zIndex: 9999, overflow: "hidden" },
|
|
506
507
|
className: cn(
|
|
507
|
-
|
|
508
|
-
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden",
|
|
508
|
+
"relative max-h-96 min-w-[8rem] overflow-hidden",
|
|
509
509
|
"rounded-lg border border-border bg-white text-foreground shadow-lg",
|
|
510
510
|
"dark:bg-zinc-900 dark:border-zinc-700",
|
|
511
511
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
@@ -966,8 +966,420 @@ function PageSection({
|
|
|
966
966
|
);
|
|
967
967
|
}
|
|
968
968
|
|
|
969
|
-
// src/components/
|
|
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__ */
|
|
1003
|
-
selection && selection.selected.length > 0 && actions && /* @__PURE__ */
|
|
1004
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1011
|
-
/* @__PURE__ */
|
|
1012
|
-
selection && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1035
|
-
selection && /* @__PURE__ */
|
|
1036
|
-
columns.map((col) => /* @__PURE__ */
|
|
1037
|
-
] }, i)) : data.length === 0 ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1079
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1089
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1130
|
-
/* @__PURE__ */
|
|
1131
|
-
description && /* @__PURE__ */
|
|
1132
|
-
action && /* @__PURE__ */
|
|
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
|
|
1551
|
+
import * as React19 from "react";
|
|
1140
1552
|
import { ChevronLeft, ChevronRight as ChevronRight3 } from "lucide-react";
|
|
1141
|
-
import { jsx as
|
|
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 =
|
|
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__ */
|
|
1165
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1583
|
+
children: /* @__PURE__ */ jsx28(ChevronLeft, { className: "h-4 w-4" })
|
|
1172
1584
|
}
|
|
1173
1585
|
),
|
|
1174
1586
|
pages.map(
|
|
1175
|
-
(p, i) => p === "ellipsis" ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
1614
|
+
import { jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1203
1615
|
function Stats({ stats, columns = 4, className }) {
|
|
1204
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1223
|
-
Icon2 && /* @__PURE__ */
|
|
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__ */
|
|
1226
|
-
/* @__PURE__ */
|
|
1227
|
-
stat.change && /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
1262
|
-
/* @__PURE__ */
|
|
2196
|
+
return /* @__PURE__ */ jsxs22("div", { className: cn("space-y-2", className), children: [
|
|
2197
|
+
/* @__PURE__ */ jsxs22(Label2, { children: [
|
|
1263
2198
|
label,
|
|
1264
|
-
required && /* @__PURE__ */
|
|
2199
|
+
required && /* @__PURE__ */ jsx36("span", { className: "ml-1 text-destructive", children: "*" })
|
|
1265
2200
|
] }),
|
|
1266
2201
|
children,
|
|
1267
|
-
hint && !error && /* @__PURE__ */
|
|
1268
|
-
error && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1290
|
-
title && /* @__PURE__ */
|
|
1291
|
-
description && /* @__PURE__ */
|
|
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__ */
|
|
1294
|
-
actions && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
1309
|
-
/* @__PURE__ */
|
|
1310
|
-
/* @__PURE__ */
|
|
1311
|
-
description && /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1360
|
-
title && /* @__PURE__ */
|
|
1361
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
1379
|
-
var
|
|
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__ */
|
|
2320
|
+
return /* @__PURE__ */ jsx40(
|
|
1386
2321
|
Loader2,
|
|
1387
2322
|
{
|
|
1388
|
-
className: cn("animate-spin text-muted-foreground",
|
|
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
|
|
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__ */
|
|
1407
|
-
/* @__PURE__ */
|
|
1408
|
-
/* @__PURE__ */
|
|
1409
|
-
description && /* @__PURE__ */
|
|
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__ */
|
|
1412
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2373
|
+
import { useState as useState5 } from "react";
|
|
1439
2374
|
function useDisclosure(initial = false) {
|
|
1440
|
-
const [isOpen, setIsOpen] =
|
|
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] =
|
|
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
|
|
2391
|
+
import { jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1457
2392
|
function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
1458
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2443
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
1509
2444
|
function AuthCard({ children, padding = "24px 28px" }) {
|
|
1510
|
-
return /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
1530
|
-
imageUrl ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2509
|
+
import { jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1575
2510
|
function AuthHeader({ title, description }) {
|
|
1576
|
-
return /* @__PURE__ */
|
|
1577
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2558
|
+
rightLabel && /* @__PURE__ */ jsx46("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
|
|
1624
2559
|
] }),
|
|
1625
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1656
|
-
hint && !error && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1717
|
-
/* @__PURE__ */
|
|
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
|
|
2673
|
+
import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
1739
2674
|
function AuthDivider({ label = "or" }) {
|
|
1740
|
-
return /* @__PURE__ */
|
|
1741
|
-
/* @__PURE__ */
|
|
1742
|
-
/* @__PURE__ */
|
|
1743
|
-
/* @__PURE__ */
|
|
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
|
|
2683
|
+
import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
1749
2684
|
function AuthFootnote({ text, linkText, linkHref }) {
|
|
1750
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
2711
|
+
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
1777
2712
|
function Skeleton2({ width = "100%", height = 16, rounded, style }) {
|
|
1778
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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
|