@greatapps/greatauth-ui 0.3.12 → 0.3.14
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.ts +2 -0
- package/dist/index.js +236 -97
- package/dist/index.js.map +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +6 -1
- package/dist/ui.js.map +1 -1
- package/package.json +1 -1
- package/src/components/app-header.tsx +54 -13
- package/src/components/app-sidebar.tsx +29 -11
- package/src/components/login-form.tsx +131 -81
- package/src/components/ui/collapsible.tsx +7 -0
- package/src/components/ui/sidebar.tsx +1 -1
- package/src/components/users/users-page.tsx +1 -1
- package/src/theme.css +65 -34
- package/src/types/index.ts +2 -0
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -362,7 +362,7 @@ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
|
362
362
|
var SIDEBAR_STORAGE_KEY = "sidebar_state";
|
|
363
363
|
var SIDEBAR_WIDTH = "16rem";
|
|
364
364
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
365
|
-
var SIDEBAR_WIDTH_ICON = "
|
|
365
|
+
var SIDEBAR_WIDTH_ICON = "3.5rem";
|
|
366
366
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
367
367
|
var SidebarContext = React.createContext(null);
|
|
368
368
|
function useSidebar() {
|
|
@@ -572,6 +572,30 @@ function SidebarTrigger({
|
|
|
572
572
|
}
|
|
573
573
|
);
|
|
574
574
|
}
|
|
575
|
+
function SidebarRail({ className, ...props }) {
|
|
576
|
+
const { toggleSidebar } = useSidebar();
|
|
577
|
+
return /* @__PURE__ */ jsx7(
|
|
578
|
+
"button",
|
|
579
|
+
{
|
|
580
|
+
"data-sidebar": "rail",
|
|
581
|
+
"data-slot": "sidebar-rail",
|
|
582
|
+
"aria-label": "Toggle Sidebar",
|
|
583
|
+
tabIndex: -1,
|
|
584
|
+
onClick: toggleSidebar,
|
|
585
|
+
title: "Toggle Sidebar",
|
|
586
|
+
className: cn(
|
|
587
|
+
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2",
|
|
588
|
+
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
|
589
|
+
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
|
590
|
+
"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
|
|
591
|
+
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
|
592
|
+
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
|
593
|
+
className
|
|
594
|
+
),
|
|
595
|
+
...props
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
}
|
|
575
599
|
function SidebarInset({ className, ...props }) {
|
|
576
600
|
return /* @__PURE__ */ jsx7(
|
|
577
601
|
"main",
|
|
@@ -757,7 +781,7 @@ function SidebarMenuButton({
|
|
|
757
781
|
// src/components/app-sidebar.tsx
|
|
758
782
|
import { usePathname, useRouter } from "next/navigation";
|
|
759
783
|
import Link from "next/link";
|
|
760
|
-
import {
|
|
784
|
+
import { ChevronsUpDown, ChevronRight as ChevronRight2, LogOut } from "lucide-react";
|
|
761
785
|
|
|
762
786
|
// src/components/ui/collapsible.tsx
|
|
763
787
|
import { Collapsible as CollapsiblePrimitive } from "radix-ui";
|
|
@@ -779,12 +803,17 @@ function CollapsibleTrigger({
|
|
|
779
803
|
);
|
|
780
804
|
}
|
|
781
805
|
function CollapsibleContent({
|
|
806
|
+
className,
|
|
782
807
|
...props
|
|
783
808
|
}) {
|
|
784
809
|
return /* @__PURE__ */ jsx8(
|
|
785
810
|
CollapsiblePrimitive.CollapsibleContent,
|
|
786
811
|
{
|
|
787
812
|
"data-slot": "collapsible-content",
|
|
813
|
+
className: cn(
|
|
814
|
+
"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
|
|
815
|
+
className
|
|
816
|
+
),
|
|
788
817
|
...props
|
|
789
818
|
}
|
|
790
819
|
);
|
|
@@ -981,23 +1010,35 @@ function getUserInitials(name, email) {
|
|
|
981
1010
|
return parts[0][0].toUpperCase();
|
|
982
1011
|
}
|
|
983
1012
|
function SimpleMenuItem({ item, pathname }) {
|
|
984
|
-
const isActive = pathname.startsWith(item.href);
|
|
1013
|
+
const isActive = item.isActive ?? pathname.startsWith(item.href);
|
|
985
1014
|
const Icon = item.icon;
|
|
986
|
-
return /* @__PURE__ */ jsx12(SidebarMenuItem, { children: /* @__PURE__ */ jsx12(SidebarMenuButton, { asChild: true, isActive, tooltip: item.label, children: /* @__PURE__ */ jsxs5(Link, { href: item.href, onClick: item.onClick, children: [
|
|
1015
|
+
return /* @__PURE__ */ jsx12(SidebarMenuItem, { children: /* @__PURE__ */ jsx12(SidebarMenuButton, { asChild: true, isActive, tooltip: item.label, children: /* @__PURE__ */ jsxs5(Link, { href: item.href, onClick: item.onClick, "aria-current": isActive ? "page" : void 0, children: [
|
|
987
1016
|
/* @__PURE__ */ jsx12(Icon, { className: "size-4" }),
|
|
988
|
-
/* @__PURE__ */ jsx12("span", { children: item.label })
|
|
1017
|
+
/* @__PURE__ */ jsx12("span", { children: item.label }),
|
|
1018
|
+
item.badge != null && /* @__PURE__ */ jsx12("span", { className: "ml-auto flex h-5 min-w-5 items-center justify-center rounded-full bg-primary/10 px-1.5 text-[10px] font-semibold text-primary tabular-nums", children: item.badge })
|
|
989
1019
|
] }) }) });
|
|
990
1020
|
}
|
|
991
1021
|
function CollapsibleMenuItem({ item, pathname }) {
|
|
992
1022
|
const Icon = item.icon;
|
|
993
|
-
const
|
|
994
|
-
|
|
995
|
-
|
|
1023
|
+
const isParentActive = pathname.startsWith(item.href);
|
|
1024
|
+
const isChildActive = item.children?.some(
|
|
1025
|
+
(child) => child.isActive !== void 0 ? child.isActive : pathname.startsWith(child.href)
|
|
1026
|
+
) ?? false;
|
|
1027
|
+
return /* @__PURE__ */ jsx12(Collapsible, { defaultOpen: isParentActive || isChildActive, className: "group/collapsible", children: /* @__PURE__ */ jsxs5(SidebarMenuItem, { children: [
|
|
1028
|
+
/* @__PURE__ */ jsx12(SidebarMenuButton, { asChild: true, isActive: isParentActive, tooltip: item.label, children: /* @__PURE__ */ jsxs5(Link, { href: item.href, onClick: item.onClick, children: [
|
|
996
1029
|
/* @__PURE__ */ jsx12(Icon, { className: "size-4" }),
|
|
997
|
-
/* @__PURE__ */ jsx12("span", { children: item.label })
|
|
998
|
-
/* @__PURE__ */ jsx12(ChevronRight2, { className: "ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" })
|
|
1030
|
+
/* @__PURE__ */ jsx12("span", { children: item.label })
|
|
999
1031
|
] }) }),
|
|
1000
|
-
/* @__PURE__ */ jsx12(
|
|
1032
|
+
/* @__PURE__ */ jsx12(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsx12(
|
|
1033
|
+
"button",
|
|
1034
|
+
{
|
|
1035
|
+
"data-sidebar": "menu-action",
|
|
1036
|
+
className: "absolute right-1 top-1.5 flex h-5 w-5 items-center justify-center rounded-md text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground outline-hidden focus-visible:ring-2 ring-sidebar-ring transition-colors group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 md:after:hidden",
|
|
1037
|
+
"aria-label": "Expandir submenu",
|
|
1038
|
+
children: /* @__PURE__ */ jsx12(ChevronRight2, { className: "size-3.5 shrink-0 transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" })
|
|
1039
|
+
}
|
|
1040
|
+
) }),
|
|
1041
|
+
/* @__PURE__ */ jsx12(CollapsibleContent, { children: /* @__PURE__ */ jsx12(SidebarMenu, { className: "ml-4 border-l pl-2", children: item.children?.map((child) => /* @__PURE__ */ jsx12(SimpleMenuItem, { item: child, pathname }, child.href + child.label)) }) })
|
|
1001
1042
|
] }) });
|
|
1002
1043
|
}
|
|
1003
1044
|
function AppSidebar({ config }) {
|
|
@@ -1034,7 +1075,7 @@ function AppSidebar({ config }) {
|
|
|
1034
1075
|
/* @__PURE__ */ jsx12("span", { className: "truncate font-semibold", children: userName }),
|
|
1035
1076
|
/* @__PURE__ */ jsx12("span", { className: "truncate text-xs text-muted-foreground", children: userEmail })
|
|
1036
1077
|
] }),
|
|
1037
|
-
/* @__PURE__ */ jsx12(
|
|
1078
|
+
/* @__PURE__ */ jsx12(ChevronsUpDown, { className: "ml-auto size-4 group-data-[collapsible=icon]:hidden" })
|
|
1038
1079
|
] }) }),
|
|
1039
1080
|
/* @__PURE__ */ jsxs5(
|
|
1040
1081
|
DropdownMenuContent,
|
|
@@ -1057,13 +1098,15 @@ function AppSidebar({ config }) {
|
|
|
1057
1098
|
]
|
|
1058
1099
|
}
|
|
1059
1100
|
)
|
|
1060
|
-
] }) }) }) })
|
|
1101
|
+
] }) }) }) }),
|
|
1102
|
+
/* @__PURE__ */ jsx12(SidebarRail, {})
|
|
1061
1103
|
] });
|
|
1062
1104
|
}
|
|
1063
1105
|
|
|
1064
1106
|
// src/components/app-header.tsx
|
|
1065
|
-
import { Fragment } from "react";
|
|
1107
|
+
import { Fragment, useMemo as useMemo2 } from "react";
|
|
1066
1108
|
import { usePathname as usePathname2 } from "next/navigation";
|
|
1109
|
+
import Link2 from "next/link";
|
|
1067
1110
|
|
|
1068
1111
|
// src/components/ui/breadcrumb.tsx
|
|
1069
1112
|
import { Slot as Slot4 } from "radix-ui";
|
|
@@ -1103,6 +1146,21 @@ function BreadcrumbItem({ className, ...props }) {
|
|
|
1103
1146
|
}
|
|
1104
1147
|
);
|
|
1105
1148
|
}
|
|
1149
|
+
function BreadcrumbLink({
|
|
1150
|
+
asChild,
|
|
1151
|
+
className,
|
|
1152
|
+
...props
|
|
1153
|
+
}) {
|
|
1154
|
+
const Comp = asChild ? Slot4.Root : "a";
|
|
1155
|
+
return /* @__PURE__ */ jsx13(
|
|
1156
|
+
Comp,
|
|
1157
|
+
{
|
|
1158
|
+
"data-slot": "breadcrumb-link",
|
|
1159
|
+
className: cn("hover:text-foreground transition-colors", className),
|
|
1160
|
+
...props
|
|
1161
|
+
}
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1106
1164
|
function BreadcrumbPage({ className, ...props }) {
|
|
1107
1165
|
return /* @__PURE__ */ jsx13(
|
|
1108
1166
|
"span",
|
|
@@ -1133,6 +1191,28 @@ function BreadcrumbSeparator({
|
|
|
1133
1191
|
}
|
|
1134
1192
|
);
|
|
1135
1193
|
}
|
|
1194
|
+
function BreadcrumbEllipsis({
|
|
1195
|
+
className,
|
|
1196
|
+
...props
|
|
1197
|
+
}) {
|
|
1198
|
+
return /* @__PURE__ */ jsxs6(
|
|
1199
|
+
"span",
|
|
1200
|
+
{
|
|
1201
|
+
"data-slot": "breadcrumb-ellipsis",
|
|
1202
|
+
role: "presentation",
|
|
1203
|
+
"aria-hidden": "true",
|
|
1204
|
+
className: cn(
|
|
1205
|
+
"size-5 [&>svg]:size-4 flex items-center justify-center",
|
|
1206
|
+
className
|
|
1207
|
+
),
|
|
1208
|
+
...props,
|
|
1209
|
+
children: [
|
|
1210
|
+
/* @__PURE__ */ jsx13(MoreHorizontal, {}),
|
|
1211
|
+
/* @__PURE__ */ jsx13("span", { className: "sr-only", children: "More" })
|
|
1212
|
+
]
|
|
1213
|
+
}
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1136
1216
|
|
|
1137
1217
|
// src/components/theme-toggle.tsx
|
|
1138
1218
|
import { useTheme } from "next-themes";
|
|
@@ -1166,26 +1246,47 @@ function ThemeToggle() {
|
|
|
1166
1246
|
}
|
|
1167
1247
|
|
|
1168
1248
|
// src/components/app-header.tsx
|
|
1169
|
-
import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1249
|
+
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1170
1250
|
function AppHeader({ config }) {
|
|
1171
1251
|
const pathname = usePathname2();
|
|
1252
|
+
const { state } = useSidebar();
|
|
1172
1253
|
const segments = pathname.split("/").filter(Boolean);
|
|
1173
|
-
const breadcrumbs =
|
|
1254
|
+
const breadcrumbs = useMemo2(() => {
|
|
1255
|
+
const items = [];
|
|
1256
|
+
for (let i = 0; i < segments.length; i++) {
|
|
1257
|
+
const label = config.routeLabels[segments[i]];
|
|
1258
|
+
if (label) {
|
|
1259
|
+
const href = "/" + segments.slice(0, i + 1).join("/");
|
|
1260
|
+
items.push({ label, href });
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
return items;
|
|
1264
|
+
}, [segments, config.routeLabels]);
|
|
1265
|
+
const isLast = (i) => i === breadcrumbs.length - 1;
|
|
1266
|
+
const showEllipsis = breadcrumbs.length > 2;
|
|
1174
1267
|
return /* @__PURE__ */ jsxs8("header", { className: "flex h-14 shrink-0 items-center gap-2 border-b px-4", children: [
|
|
1175
1268
|
/* @__PURE__ */ jsx15(SidebarTrigger, { className: "-ml-1" }),
|
|
1269
|
+
state === "collapsed" && config.appIcon && /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1270
|
+
/* @__PURE__ */ jsx15(Separator, { orientation: "vertical", className: "!h-4" }),
|
|
1271
|
+
/* @__PURE__ */ jsx15("div", { className: "shrink-0 text-sidebar-foreground", children: config.appIcon })
|
|
1272
|
+
] }),
|
|
1176
1273
|
/* @__PURE__ */ jsx15(Separator, { orientation: "vertical", className: "mr-2 !h-4" }),
|
|
1177
|
-
/* @__PURE__ */ jsx15(Breadcrumb, { className: "flex-1", children: /* @__PURE__ */ jsx15(BreadcrumbList, { children: breadcrumbs.length > 0 ? breadcrumbs.map((
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1274
|
+
/* @__PURE__ */ jsx15(Breadcrumb, { className: "flex-1", children: /* @__PURE__ */ jsx15(BreadcrumbList, { children: breadcrumbs.length > 0 ? breadcrumbs.map((crumb, i) => {
|
|
1275
|
+
const hiddenOnMobile = showEllipsis && i < breadcrumbs.length - 2;
|
|
1276
|
+
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
1277
|
+
showEllipsis && i === breadcrumbs.length - 2 && /* @__PURE__ */ jsx15(BreadcrumbItem, { className: "sm:hidden", children: /* @__PURE__ */ jsx15(BreadcrumbEllipsis, {}) }),
|
|
1278
|
+
i > 0 && /* @__PURE__ */ jsx15(BreadcrumbSeparator, { className: hiddenOnMobile ? "hidden sm:flex" : void 0 }),
|
|
1279
|
+
/* @__PURE__ */ jsx15(BreadcrumbItem, { className: hiddenOnMobile ? "hidden sm:flex" : void 0, children: isLast(i) ? /* @__PURE__ */ jsx15(BreadcrumbPage, { children: crumb.label }) : /* @__PURE__ */ jsx15(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx15(Link2, { href: crumb.href, children: crumb.label }) }) })
|
|
1280
|
+
] }, i);
|
|
1281
|
+
}) : config.defaultBreadcrumb ? /* @__PURE__ */ jsx15(BreadcrumbItem, { children: /* @__PURE__ */ jsx15(BreadcrumbPage, { children: config.defaultBreadcrumb }) }) : null }) }),
|
|
1181
1282
|
/* @__PURE__ */ jsx15(ThemeToggle, {})
|
|
1182
1283
|
] });
|
|
1183
1284
|
}
|
|
1184
1285
|
|
|
1185
1286
|
// src/components/app-shell.tsx
|
|
1186
|
-
import { Fragment as
|
|
1287
|
+
import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1187
1288
|
function AppShell({ config, children, renderAbove }) {
|
|
1188
|
-
return /* @__PURE__ */ jsxs9(
|
|
1289
|
+
return /* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
1189
1290
|
renderAbove,
|
|
1190
1291
|
/* @__PURE__ */ jsx16(TooltipProvider, { children: /* @__PURE__ */ jsxs9(SidebarProvider, { className: "!h-svh !overflow-hidden", children: [
|
|
1191
1292
|
/* @__PURE__ */ jsx16(AppSidebar, { config }),
|
|
@@ -1200,7 +1301,7 @@ function AppShell({ config, children, renderAbove }) {
|
|
|
1200
1301
|
// src/components/login-form.tsx
|
|
1201
1302
|
import { useState as useState3 } from "react";
|
|
1202
1303
|
import { useRouter as useRouter2, useSearchParams } from "next/navigation";
|
|
1203
|
-
import { Loader2, Mail, Lock, AlertCircle } from "lucide-react";
|
|
1304
|
+
import { Loader2, Mail, Lock, AlertCircle, Eye, EyeOff } from "lucide-react";
|
|
1204
1305
|
|
|
1205
1306
|
// src/components/ui/label.tsx
|
|
1206
1307
|
import { Label as LabelPrimitive } from "radix-ui";
|
|
@@ -1223,7 +1324,7 @@ function Label({
|
|
|
1223
1324
|
}
|
|
1224
1325
|
|
|
1225
1326
|
// src/components/login-form.tsx
|
|
1226
|
-
import { Fragment as
|
|
1327
|
+
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1227
1328
|
function LoginForm({ config }) {
|
|
1228
1329
|
const router = useRouter2();
|
|
1229
1330
|
const searchParams = useSearchParams();
|
|
@@ -1232,6 +1333,7 @@ function LoginForm({ config }) {
|
|
|
1232
1333
|
const [password, setPassword] = useState3("");
|
|
1233
1334
|
const [loading, setLoading] = useState3(false);
|
|
1234
1335
|
const [error, setError] = useState3("");
|
|
1336
|
+
const [showPassword, setShowPassword] = useState3(false);
|
|
1235
1337
|
const handleSubmit = async (e) => {
|
|
1236
1338
|
e.preventDefault();
|
|
1237
1339
|
if (loading) return;
|
|
@@ -1262,73 +1364,110 @@ function LoginForm({ config }) {
|
|
|
1262
1364
|
setLoading(false);
|
|
1263
1365
|
}
|
|
1264
1366
|
};
|
|
1265
|
-
return /* @__PURE__ */
|
|
1266
|
-
/* @__PURE__ */
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
required: true
|
|
1294
|
-
}
|
|
1295
|
-
)
|
|
1296
|
-
] })
|
|
1297
|
-
] }),
|
|
1298
|
-
/* @__PURE__ */ jsxs10("div", { className: "space-y-1.5", children: [
|
|
1299
|
-
/* @__PURE__ */ jsx18(Label, { htmlFor: "login-password", className: "text-sm font-medium", children: "Senha" }),
|
|
1300
|
-
/* @__PURE__ */ jsxs10("div", { className: "relative", children: [
|
|
1301
|
-
/* @__PURE__ */ jsx18(Lock, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
1302
|
-
/* @__PURE__ */ jsx18(
|
|
1303
|
-
Input,
|
|
1304
|
-
{
|
|
1305
|
-
id: "login-password",
|
|
1306
|
-
type: "password",
|
|
1307
|
-
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
1308
|
-
value: password,
|
|
1309
|
-
onChange: (e) => setPassword(e.target.value),
|
|
1310
|
-
className: "pl-9",
|
|
1311
|
-
autoComplete: "current-password",
|
|
1312
|
-
required: true
|
|
1313
|
-
}
|
|
1314
|
-
)
|
|
1315
|
-
] })
|
|
1367
|
+
return /* @__PURE__ */ jsxs10("div", { className: "relative flex min-h-svh", children: [
|
|
1368
|
+
/* @__PURE__ */ jsx18("div", { className: "fixed top-4 right-4 z-50", children: /* @__PURE__ */ jsx18(ThemeToggle, {}) }),
|
|
1369
|
+
/* @__PURE__ */ jsxs10(
|
|
1370
|
+
"div",
|
|
1371
|
+
{
|
|
1372
|
+
className: "relative hidden items-center justify-center overflow-hidden bg-primary md:flex md:w-1/2",
|
|
1373
|
+
style: {
|
|
1374
|
+
backgroundImage: "radial-gradient(circle, rgba(255,255,255,0.1) 1px, transparent 1px)",
|
|
1375
|
+
backgroundSize: "24px 24px"
|
|
1376
|
+
},
|
|
1377
|
+
children: [
|
|
1378
|
+
/* @__PURE__ */ jsx18("div", { className: "absolute inset-0 bg-gradient-to-br from-primary/80 via-primary to-primary/90" }),
|
|
1379
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative z-10 flex flex-col items-center gap-4 px-8 text-center text-primary-foreground", children: [
|
|
1380
|
+
/* @__PURE__ */ jsx18("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl bg-primary-foreground/15 shadow-lg backdrop-blur-sm", children: config.icon }),
|
|
1381
|
+
/* @__PURE__ */ jsx18("h2", { className: "text-3xl font-bold tracking-tight", children: config.appName }),
|
|
1382
|
+
/* @__PURE__ */ jsx18("p", { className: "max-w-xs text-base text-primary-foreground/80", children: config.description })
|
|
1383
|
+
] })
|
|
1384
|
+
]
|
|
1385
|
+
}
|
|
1386
|
+
),
|
|
1387
|
+
/* @__PURE__ */ jsx18("div", { className: "flex w-full items-center justify-center bg-background p-4 md:w-1/2", children: /* @__PURE__ */ jsxs10("div", { className: "w-full max-w-sm", children: [
|
|
1388
|
+
/* @__PURE__ */ jsxs10("div", { className: "mb-8 text-center", children: [
|
|
1389
|
+
/* @__PURE__ */ jsx18("div", { className: "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-primary text-primary-foreground shadow-sm md:hidden", children: config.icon }),
|
|
1390
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-center gap-2", children: [
|
|
1391
|
+
/* @__PURE__ */ jsx18("h1", { className: "text-3xl font-bold tracking-tight", children: config.appName }),
|
|
1392
|
+
config.appBadge && /* @__PURE__ */ jsx18(Badge, { variant: config.appBadge.variant, className: "text-xs", children: config.appBadge.text })
|
|
1393
|
+
] }),
|
|
1394
|
+
/* @__PURE__ */ jsx18("p", { className: "mt-1.5 text-base text-muted-foreground", children: config.description })
|
|
1316
1395
|
] }),
|
|
1317
|
-
/* @__PURE__ */ jsx18(
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
"
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1396
|
+
/* @__PURE__ */ jsx18("div", { className: "rounded-xl border bg-card p-6 shadow-sm", children: /* @__PURE__ */ jsxs10("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
1397
|
+
error && /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm text-destructive", children: [
|
|
1398
|
+
/* @__PURE__ */ jsx18(AlertCircle, { className: "h-4 w-4 shrink-0" }),
|
|
1399
|
+
error
|
|
1400
|
+
] }),
|
|
1401
|
+
/* @__PURE__ */ jsxs10("div", { className: "space-y-1.5", children: [
|
|
1402
|
+
/* @__PURE__ */ jsx18(Label, { htmlFor: "login-email", className: "text-sm font-medium", children: "Email" }),
|
|
1403
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative", children: [
|
|
1404
|
+
/* @__PURE__ */ jsx18(Mail, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
1405
|
+
/* @__PURE__ */ jsx18(
|
|
1406
|
+
Input,
|
|
1407
|
+
{
|
|
1408
|
+
id: "login-email",
|
|
1409
|
+
type: "email",
|
|
1410
|
+
placeholder: "email@exemplo.com",
|
|
1411
|
+
value: email,
|
|
1412
|
+
onChange: (e) => setEmail(e.target.value),
|
|
1413
|
+
className: "pl-9",
|
|
1414
|
+
autoComplete: "email",
|
|
1415
|
+
required: true
|
|
1416
|
+
}
|
|
1417
|
+
)
|
|
1418
|
+
] })
|
|
1419
|
+
] }),
|
|
1420
|
+
/* @__PURE__ */ jsxs10("div", { className: "space-y-1.5", children: [
|
|
1421
|
+
/* @__PURE__ */ jsx18(Label, { htmlFor: "login-password", className: "text-sm font-medium", children: "Senha" }),
|
|
1422
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative", children: [
|
|
1423
|
+
/* @__PURE__ */ jsx18(Lock, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
1424
|
+
/* @__PURE__ */ jsx18(
|
|
1425
|
+
Input,
|
|
1426
|
+
{
|
|
1427
|
+
id: "login-password",
|
|
1428
|
+
type: showPassword ? "text" : "password",
|
|
1429
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
1430
|
+
value: password,
|
|
1431
|
+
onChange: (e) => setPassword(e.target.value),
|
|
1432
|
+
className: "pl-9 pr-10",
|
|
1433
|
+
autoComplete: "current-password",
|
|
1434
|
+
required: true
|
|
1435
|
+
}
|
|
1436
|
+
),
|
|
1437
|
+
/* @__PURE__ */ jsx18(
|
|
1438
|
+
"button",
|
|
1439
|
+
{
|
|
1440
|
+
type: "button",
|
|
1441
|
+
onClick: () => setShowPassword(!showPassword),
|
|
1442
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
|
|
1443
|
+
"aria-label": showPassword ? "Ocultar senha" : "Mostrar senha",
|
|
1444
|
+
children: showPassword ? /* @__PURE__ */ jsx18(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx18(Eye, { className: "h-4 w-4" })
|
|
1445
|
+
}
|
|
1446
|
+
)
|
|
1447
|
+
] })
|
|
1448
|
+
] }),
|
|
1449
|
+
/* @__PURE__ */ jsx18(
|
|
1450
|
+
Button,
|
|
1451
|
+
{
|
|
1452
|
+
type: "submit",
|
|
1453
|
+
className: cn("w-full", loading && "cursor-wait"),
|
|
1454
|
+
disabled: loading,
|
|
1455
|
+
children: loading ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
1456
|
+
/* @__PURE__ */ jsx18(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
1457
|
+
"A entrar..."
|
|
1458
|
+
] }) : "Entrar"
|
|
1459
|
+
}
|
|
1460
|
+
)
|
|
1461
|
+
] }) }),
|
|
1462
|
+
/* @__PURE__ */ jsx18("p", { className: "mt-6 text-center text-xs text-muted-foreground", children: config.footerText || "Acesso restrito a utilizadores autorizados" }),
|
|
1463
|
+
/* @__PURE__ */ jsxs10("p", { className: "mt-1 text-center text-xs text-muted-foreground", children: [
|
|
1464
|
+
"\xA9 ",
|
|
1465
|
+
(/* @__PURE__ */ new Date()).getFullYear(),
|
|
1466
|
+
" ",
|
|
1467
|
+
config.appName
|
|
1468
|
+
] })
|
|
1469
|
+
] }) })
|
|
1470
|
+
] });
|
|
1332
1471
|
}
|
|
1333
1472
|
|
|
1334
1473
|
// src/components/entity-avatar.tsx
|
|
@@ -1891,14 +2030,14 @@ function useResetPassword(config) {
|
|
|
1891
2030
|
}
|
|
1892
2031
|
|
|
1893
2032
|
// src/components/users/users-page.tsx
|
|
1894
|
-
import { useMemo as
|
|
2033
|
+
import { useMemo as useMemo4, useState as useState7 } from "react";
|
|
1895
2034
|
|
|
1896
2035
|
// src/components/users/user-form-dialog.tsx
|
|
1897
2036
|
import { useEffect as useEffect3, useState as useState5 } from "react";
|
|
1898
2037
|
|
|
1899
2038
|
// src/components/ui/select.tsx
|
|
1900
2039
|
import { Select as SelectPrimitive } from "radix-ui";
|
|
1901
|
-
import { ChevronsUpDown, Check as Check2, ChevronUp
|
|
2040
|
+
import { ChevronsUpDown as ChevronsUpDown2, Check as Check2, ChevronUp, ChevronDown } from "lucide-react";
|
|
1902
2041
|
import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1903
2042
|
function Select({
|
|
1904
2043
|
...props
|
|
@@ -1928,7 +2067,7 @@ function SelectTrigger({
|
|
|
1928
2067
|
...props,
|
|
1929
2068
|
children: [
|
|
1930
2069
|
children,
|
|
1931
|
-
/* @__PURE__ */ jsx23(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx23(
|
|
2070
|
+
/* @__PURE__ */ jsx23(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx23(ChevronsUpDown2, { className: "text-muted-foreground size-4 pointer-events-none" }) })
|
|
1932
2071
|
]
|
|
1933
2072
|
}
|
|
1934
2073
|
);
|
|
@@ -1998,7 +2137,7 @@ function SelectScrollUpButton({
|
|
|
1998
2137
|
"data-slot": "select-scroll-up-button",
|
|
1999
2138
|
className: cn("bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4", className),
|
|
2000
2139
|
...props,
|
|
2001
|
-
children: /* @__PURE__ */ jsx23(
|
|
2140
|
+
children: /* @__PURE__ */ jsx23(ChevronUp, {})
|
|
2002
2141
|
}
|
|
2003
2142
|
);
|
|
2004
2143
|
}
|
|
@@ -2580,7 +2719,7 @@ function UsersPage({ config, renderPhones }) {
|
|
|
2580
2719
|
const [search, setSearch] = useState7("");
|
|
2581
2720
|
const [profileFilter, setProfileFilter] = useState7("all");
|
|
2582
2721
|
const [page, setPage] = useState7(1);
|
|
2583
|
-
const queryParams =
|
|
2722
|
+
const queryParams = useMemo4(() => {
|
|
2584
2723
|
const params = {
|
|
2585
2724
|
limit: String(PAGE_SIZE),
|
|
2586
2725
|
page: String(page)
|
|
@@ -2597,7 +2736,7 @@ function UsersPage({ config, renderPhones }) {
|
|
|
2597
2736
|
const [resetUser, setResetUser] = useState7(null);
|
|
2598
2737
|
const users = data?.data || [];
|
|
2599
2738
|
const total = data?.total || 0;
|
|
2600
|
-
const filtered =
|
|
2739
|
+
const filtered = useMemo4(() => {
|
|
2601
2740
|
if (!search) return users;
|
|
2602
2741
|
const term = search.toLowerCase();
|
|
2603
2742
|
return users.filter(
|
|
@@ -2635,7 +2774,7 @@ function UsersPage({ config, renderPhones }) {
|
|
|
2635
2774
|
}
|
|
2636
2775
|
});
|
|
2637
2776
|
}
|
|
2638
|
-
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-4 p-4", children: [
|
|
2777
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-4 p-4 md:p-6", children: [
|
|
2639
2778
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between", children: [
|
|
2640
2779
|
/* @__PURE__ */ jsxs19("div", { children: [
|
|
2641
2780
|
/* @__PURE__ */ jsx29("h1", { className: "text-xl font-semibold", children: "Usu\xE1rios" }),
|