hazo_auth 3.0.4 → 4.1.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.
Files changed (82) hide show
  1. package/README.md +228 -8
  2. package/SETUP_CHECKLIST.md +370 -0
  3. package/dist/app/api/hazo_auth/me/route.d.ts +3 -0
  4. package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -1
  5. package/dist/app/api/hazo_auth/me/route.js +9 -1
  6. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts.map +1 -1
  7. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.js +2 -2
  8. package/dist/components/layouts/profile_stamp_test/index.d.ts +10 -0
  9. package/dist/components/layouts/profile_stamp_test/index.d.ts.map +1 -0
  10. package/dist/components/layouts/profile_stamp_test/index.js +51 -0
  11. package/dist/components/layouts/rbac_test/index.d.ts +15 -0
  12. package/dist/components/layouts/rbac_test/index.d.ts.map +1 -0
  13. package/dist/components/layouts/rbac_test/index.js +378 -0
  14. package/dist/components/layouts/shared/components/password_field.js +1 -1
  15. package/dist/components/layouts/shared/components/profile_stamp.d.ts +58 -0
  16. package/dist/components/layouts/shared/components/profile_stamp.d.ts.map +1 -0
  17. package/dist/components/layouts/shared/components/profile_stamp.js +72 -0
  18. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
  19. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +2 -2
  20. package/dist/components/layouts/shared/components/two_column_auth_layout.js +1 -1
  21. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +3 -0
  22. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -1
  23. package/dist/components/layouts/shared/hooks/use_auth_status.js +4 -0
  24. package/dist/components/layouts/shared/index.d.ts +2 -0
  25. package/dist/components/layouts/shared/index.d.ts.map +1 -1
  26. package/dist/components/layouts/shared/index.js +1 -0
  27. package/dist/components/layouts/user_management/components/roles_matrix.d.ts +2 -3
  28. package/dist/components/layouts/user_management/components/roles_matrix.d.ts.map +1 -1
  29. package/dist/components/layouts/user_management/components/roles_matrix.js +133 -8
  30. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.d.ts +12 -0
  31. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.d.ts.map +1 -0
  32. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.js +291 -0
  33. package/dist/components/layouts/user_management/components/scope_labels_tab.d.ts +13 -0
  34. package/dist/components/layouts/user_management/components/scope_labels_tab.d.ts.map +1 -0
  35. package/dist/components/layouts/user_management/components/scope_labels_tab.js +158 -0
  36. package/dist/components/layouts/user_management/components/user_scopes_tab.d.ts +11 -0
  37. package/dist/components/layouts/user_management/components/user_scopes_tab.d.ts.map +1 -0
  38. package/dist/components/layouts/user_management/components/user_scopes_tab.js +267 -0
  39. package/dist/components/layouts/user_management/index.d.ts +9 -2
  40. package/dist/components/layouts/user_management/index.d.ts.map +1 -1
  41. package/dist/components/layouts/user_management/index.js +22 -6
  42. package/dist/components/ui/hover-card.d.ts +7 -0
  43. package/dist/components/ui/hover-card.d.ts.map +1 -0
  44. package/dist/components/ui/hover-card.js +29 -0
  45. package/dist/components/ui/index.d.ts +1 -0
  46. package/dist/components/ui/index.d.ts.map +1 -1
  47. package/dist/components/ui/index.js +1 -0
  48. package/dist/components/ui/select.d.ts +14 -0
  49. package/dist/components/ui/select.d.ts.map +1 -0
  50. package/dist/components/ui/select.js +59 -0
  51. package/dist/components/ui/tree-view.d.ts +108 -0
  52. package/dist/components/ui/tree-view.d.ts.map +1 -0
  53. package/dist/components/ui/tree-view.js +194 -0
  54. package/dist/lib/auth/auth_types.d.ts +45 -0
  55. package/dist/lib/auth/auth_types.d.ts.map +1 -1
  56. package/dist/lib/auth/auth_types.js +13 -0
  57. package/dist/lib/auth/hazo_get_auth.server.d.ts +4 -2
  58. package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -1
  59. package/dist/lib/auth/hazo_get_auth.server.js +107 -3
  60. package/dist/lib/auth/scope_cache.d.ts +92 -0
  61. package/dist/lib/auth/scope_cache.d.ts.map +1 -0
  62. package/dist/lib/auth/scope_cache.js +171 -0
  63. package/dist/lib/scope_hierarchy_config.server.d.ts +39 -0
  64. package/dist/lib/scope_hierarchy_config.server.d.ts.map +1 -0
  65. package/dist/lib/scope_hierarchy_config.server.js +96 -0
  66. package/dist/lib/services/email_service.d.ts.map +1 -1
  67. package/dist/lib/services/email_service.js +7 -2
  68. package/dist/lib/services/profile_picture_service.d.ts +1 -7
  69. package/dist/lib/services/profile_picture_service.d.ts.map +1 -1
  70. package/dist/lib/services/profile_picture_service.js +77 -32
  71. package/dist/lib/services/registration_service.js +1 -1
  72. package/dist/lib/services/scope_labels_service.d.ts +48 -0
  73. package/dist/lib/services/scope_labels_service.d.ts.map +1 -0
  74. package/dist/lib/services/scope_labels_service.js +277 -0
  75. package/dist/lib/services/scope_service.d.ts +114 -0
  76. package/dist/lib/services/scope_service.d.ts.map +1 -0
  77. package/dist/lib/services/scope_service.js +582 -0
  78. package/dist/lib/services/user_scope_service.d.ts +74 -0
  79. package/dist/lib/services/user_scope_service.d.ts.map +1 -0
  80. package/dist/lib/services/user_scope_service.js +415 -0
  81. package/hazo_auth_config.example.ini +1 -1
  82. package/package.json +4 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_stamp.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/shared/components/profile_stamp.tsx"],"names":[],"mappings":"AAcA;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/B;;OAEG;IACH,aAAa,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC1C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAgB,EAChB,aAAkB,EAClB,SAAS,EACT,SAAgB,EAChB,UAAiB,GAClB,EAAE,iBAAiB,2CAwInB"}
@@ -0,0 +1,72 @@
1
+ // file_description: ProfileStamp component - circular profile picture with hover card showing user details
2
+ // section: client_directive
3
+ "use client";
4
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
+ // section: imports
6
+ import { Avatar, AvatarImage, AvatarFallback } from "../../../ui/avatar";
7
+ import { HoverCard, HoverCardTrigger, HoverCardContent, } from "../../../ui/hover-card";
8
+ import { use_auth_status } from "../hooks/use_auth_status";
9
+ // section: component
10
+ /**
11
+ * ProfileStamp component - displays a circular profile picture with a hover card
12
+ * showing the user's name, email, and any custom fields.
13
+ *
14
+ * Use this component to add profile attribution to notes, comments, or any
15
+ * user-generated content in your application.
16
+ *
17
+ * @example
18
+ * // Basic usage
19
+ * <ProfileStamp />
20
+ *
21
+ * @example
22
+ * // With custom fields
23
+ * <ProfileStamp
24
+ * size="lg"
25
+ * custom_fields={[
26
+ * { label: "Role", value: "Admin" },
27
+ * { label: "Department", value: "Engineering" }
28
+ * ]}
29
+ * />
30
+ */
31
+ export function ProfileStamp({ size = "default", custom_fields = [], className, show_name = true, show_email = true, }) {
32
+ const authStatus = use_auth_status();
33
+ // Avatar size classes
34
+ const avatarSizeClasses = {
35
+ sm: "h-6 w-6",
36
+ default: "h-8 w-8",
37
+ lg: "h-10 w-10",
38
+ };
39
+ // Get initials from name or email
40
+ const getInitials = () => {
41
+ var _a, _b;
42
+ if (authStatus.name) {
43
+ const parts = authStatus.name.trim().split(" ");
44
+ if (parts.length >= 2) {
45
+ return `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
46
+ }
47
+ return ((_a = authStatus.name[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || "";
48
+ }
49
+ if (authStatus.email) {
50
+ return ((_b = authStatus.email[0]) === null || _b === void 0 ? void 0 : _b.toUpperCase()) || "";
51
+ }
52
+ return "?";
53
+ };
54
+ // Show loading skeleton
55
+ if (authStatus.loading) {
56
+ return (_jsx("div", { className: `cls_profile_stamp inline-block ${className || ""}`, children: _jsx("div", { className: `${avatarSizeClasses[size]} rounded-full bg-[var(--hazo-bg-emphasis)] animate-pulse`, "aria-label": "Loading profile" }) }));
57
+ }
58
+ // Not authenticated - show placeholder
59
+ if (!authStatus.authenticated) {
60
+ return (_jsx("div", { className: `cls_profile_stamp inline-block ${className || ""}`, children: _jsx(Avatar, { className: `cls_profile_stamp_avatar ${avatarSizeClasses[size]}`, children: _jsx(AvatarFallback, { className: "cls_profile_stamp_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)]", children: "?" }) }) }));
61
+ }
62
+ // Check if there's any content to show in the hover card
63
+ const hasHoverContent = (show_name && authStatus.name) ||
64
+ (show_email && authStatus.email) ||
65
+ custom_fields.length > 0;
66
+ // If no hover content, just show the avatar without hover card
67
+ if (!hasHoverContent) {
68
+ return (_jsx("div", { className: `cls_profile_stamp inline-block ${className || ""}`, children: _jsxs(Avatar, { className: `cls_profile_stamp_avatar ${avatarSizeClasses[size]}`, children: [_jsx(AvatarImage, { src: authStatus.profile_picture_url, alt: authStatus.name ? `Profile picture of ${authStatus.name}` : "Profile picture", className: "cls_profile_stamp_image" }), _jsx(AvatarFallback, { className: "cls_profile_stamp_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)]", children: getInitials() })] }) }));
69
+ }
70
+ // Authenticated with hover content - show avatar with hover card
71
+ return (_jsx("div", { className: `cls_profile_stamp inline-block ${className || ""}`, children: _jsxs(HoverCard, { children: [_jsx(HoverCardTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "cls_profile_stamp_trigger cursor-pointer focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary rounded-full", "aria-label": `View profile information for ${authStatus.name || authStatus.email || "user"}`, children: _jsxs(Avatar, { className: `cls_profile_stamp_avatar ${avatarSizeClasses[size]}`, children: [_jsx(AvatarImage, { src: authStatus.profile_picture_url, alt: authStatus.name ? `Profile picture of ${authStatus.name}` : "Profile picture", className: "cls_profile_stamp_image" }), _jsx(AvatarFallback, { className: "cls_profile_stamp_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)]", children: getInitials() })] }) }) }), _jsx(HoverCardContent, { align: "start", className: "cls_profile_stamp_hover_card w-auto min-w-[200px]", children: _jsxs("div", { className: "cls_profile_stamp_hover_content flex flex-col gap-2", children: [show_name && authStatus.name && (_jsx("div", { className: "cls_profile_stamp_name text-sm font-semibold text-foreground", children: authStatus.name })), show_email && authStatus.email && (_jsx("div", { className: "cls_profile_stamp_email text-sm text-muted-foreground", children: authStatus.email })), custom_fields.length > 0 && (_jsx("div", { className: "cls_profile_stamp_custom_fields flex flex-col gap-1 pt-2 border-t", children: custom_fields.map((field, index) => (_jsxs("div", { className: "cls_profile_stamp_custom_field flex justify-between gap-4 text-sm", children: [_jsxs("span", { className: "cls_profile_stamp_field_label text-muted-foreground", children: [field.label, ":"] }), _jsx("span", { className: "cls_profile_stamp_field_value text-foreground font-medium", children: field.value })] }, `${field.label}-${index}`))) }))] }) })] }) }));
72
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar_layout_wrapper.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/shared/components/sidebar_layout_wrapper.tsx"],"names":[],"mappings":"AAwBA,KAAK,yBAAyB,GAAG;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAGF,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,EAAE,yBAAyB,2CAyK3E"}
1
+ {"version":3,"file":"sidebar_layout_wrapper.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/shared/components/sidebar_layout_wrapper.tsx"],"names":[],"mappings":"AAwBA,KAAK,yBAAyB,GAAG;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAGF,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,EAAE,yBAAyB,2CAiM3E"}
@@ -5,11 +5,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  // section: imports
6
6
  import Link from "next/link";
7
7
  import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarTrigger, SidebarInset, } from "../../../ui/sidebar";
8
- import { LogIn, UserPlus, BookOpen, ExternalLink, Database, KeyRound, MailCheck, Key, User } from "lucide-react";
8
+ import { LogIn, UserPlus, BookOpen, ExternalLink, Database, KeyRound, MailCheck, Key, User, ShieldCheck, CircleUserRound } from "lucide-react";
9
9
  import { use_auth_status } from "../hooks/use_auth_status";
10
10
  import { ProfilePicMenu } from "./profile_pic_menu";
11
11
  // section: component
12
12
  export function SidebarLayoutWrapper({ children }) {
13
13
  const authStatus = use_auth_status();
14
- return (_jsx(SidebarProvider, { children: _jsxs("div", { className: "cls_sidebar_layout_wrapper flex min-h-screen w-full", children: [_jsxs(Sidebar, { children: [_jsx(SidebarHeader, { className: "cls_sidebar_layout_header", children: _jsx("div", { className: "cls_sidebar_layout_title flex items-center gap-2 px-2 py-4", children: _jsx("h1", { className: "cls_sidebar_layout_title_text text-lg font-semibold text-sidebar-foreground", children: "hazo auth" }) }) }), _jsxs(SidebarContent, { className: "cls_sidebar_layout_content", children: [_jsxs(SidebarGroup, { className: "cls_sidebar_layout_test_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Test components" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_test_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_login_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/login", className: "cls_sidebar_layout_test_login_link flex items-center gap-2", "aria-label": "Test login layout component", children: [_jsx(LogIn, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test login" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_register_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/register", className: "cls_sidebar_layout_test_register_link flex items-center gap-2", "aria-label": "Test register layout component", children: [_jsx(UserPlus, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test register" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_forgot_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/forgot_password", className: "cls_sidebar_layout_test_forgot_password_link flex items-center gap-2", "aria-label": "Test forgot password layout component", children: [_jsx(KeyRound, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test forgot password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_reset_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/reset_password", className: "cls_sidebar_layout_test_reset_password_link flex items-center gap-2", "aria-label": "Test reset password layout component", children: [_jsx(Key, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test reset password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_email_verification_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/verify_email", className: "cls_sidebar_layout_test_email_verification_link flex items-center gap-2", "aria-label": "Test email verification layout component", children: [_jsx(MailCheck, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test email verification" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_sqlite_admin_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_connect/sqlite_admin", className: "cls_sidebar_layout_sqlite_admin_link flex items-center gap-2", "aria-label": "Open SQLite admin UI to browse and edit database", children: [_jsx(Database, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "SQLite Admin" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_user_management_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/user_management", className: "cls_sidebar_layout_user_management_link flex items-center gap-2", "aria-label": "Open User Management to manage users, roles, and permissions", children: [_jsx(User, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "User Management" })] }) }) })] })] }), _jsx(ProfilePicMenu, { variant: "sidebar", avatar_size: "sm", className: "cls_sidebar_layout_profile_menu", sidebar_group_label: "Account" }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_resources_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Resources" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_resources_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_storybook_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "http://localhost:6006", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_storybook_link flex items-center gap-2", "aria-label": "Open Storybook preview for reusable components", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Storybook" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_docs_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "https://ui.shadcn.com/docs", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_docs_link flex items-center gap-2", "aria-label": "Review shadcn documentation for styling guidance", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Shadcn docs" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) })] })] })] })] }), _jsxs(SidebarInset, { className: "cls_sidebar_layout_inset", children: [_jsxs("header", { className: "cls_sidebar_layout_main_header flex h-16 shrink-0 items-center gap-2 border-b px-4", children: [_jsx(SidebarTrigger, { className: "cls_sidebar_layout_trigger" }), _jsx("div", { className: "cls_sidebar_layout_main_header_content flex flex-1 items-center gap-2", children: _jsx("h2", { className: "cls_sidebar_layout_main_title text-lg font-semibold text-foreground", children: "hazo reusable ui library workspace" }) }), _jsx(ProfilePicMenu, { className: "cls_sidebar_layout_auth_status", avatar_size: "sm" })] }), _jsx("main", { className: "cls_sidebar_layout_main_content flex flex-1 items-center justify-center p-6", children: children })] })] }) }));
14
+ return (_jsx(SidebarProvider, { children: _jsxs("div", { className: "cls_sidebar_layout_wrapper flex min-h-screen w-full", children: [_jsxs(Sidebar, { children: [_jsx(SidebarHeader, { className: "cls_sidebar_layout_header", children: _jsx("div", { className: "cls_sidebar_layout_title flex items-center gap-2 px-2 py-4", children: _jsx("h1", { className: "cls_sidebar_layout_title_text text-lg font-semibold text-sidebar-foreground", children: "hazo auth" }) }) }), _jsxs(SidebarContent, { className: "cls_sidebar_layout_content", children: [_jsxs(SidebarGroup, { className: "cls_sidebar_layout_test_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Test components" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_test_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_login_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/login", className: "cls_sidebar_layout_test_login_link flex items-center gap-2", "aria-label": "Test login layout component", children: [_jsx(LogIn, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test login" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_register_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/register", className: "cls_sidebar_layout_test_register_link flex items-center gap-2", "aria-label": "Test register layout component", children: [_jsx(UserPlus, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test register" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_forgot_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/forgot_password", className: "cls_sidebar_layout_test_forgot_password_link flex items-center gap-2", "aria-label": "Test forgot password layout component", children: [_jsx(KeyRound, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test forgot password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_reset_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/reset_password", className: "cls_sidebar_layout_test_reset_password_link flex items-center gap-2", "aria-label": "Test reset password layout component", children: [_jsx(Key, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test reset password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_email_verification_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/verify_email", className: "cls_sidebar_layout_test_email_verification_link flex items-center gap-2", "aria-label": "Test email verification layout component", children: [_jsx(MailCheck, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test email verification" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_sqlite_admin_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_connect/sqlite_admin", className: "cls_sidebar_layout_sqlite_admin_link flex items-center gap-2", "aria-label": "Open SQLite admin UI to browse and edit database", children: [_jsx(Database, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "SQLite Admin" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_user_management_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/user_management", className: "cls_sidebar_layout_user_management_link flex items-center gap-2", "aria-label": "Open User Management to manage users, roles, and permissions", children: [_jsx(User, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "User Management" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_rbac_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/rbac_test", className: "cls_sidebar_layout_rbac_test_link flex items-center gap-2", "aria-label": "Test RBAC and HRBAC access control", children: [_jsx(ShieldCheck, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "RBAC/HRBAC Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_profile_stamp_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/profile_stamp_test", className: "cls_sidebar_layout_profile_stamp_test_link flex items-center gap-2", "aria-label": "Test ProfileStamp component", children: [_jsx(CircleUserRound, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "ProfileStamp Test" })] }) }) })] })] }), _jsx(ProfilePicMenu, { variant: "sidebar", avatar_size: "sm", className: "cls_sidebar_layout_profile_menu", sidebar_group_label: "Account" }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_resources_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Resources" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_resources_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_storybook_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "http://localhost:6006", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_storybook_link flex items-center gap-2", "aria-label": "Open Storybook preview for reusable components", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Storybook" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_docs_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "https://ui.shadcn.com/docs", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_docs_link flex items-center gap-2", "aria-label": "Review shadcn documentation for styling guidance", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Shadcn docs" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) })] })] })] })] }), _jsxs(SidebarInset, { className: "cls_sidebar_layout_inset", children: [_jsxs("header", { className: "cls_sidebar_layout_main_header flex h-16 shrink-0 items-center gap-2 border-b px-4", children: [_jsx(SidebarTrigger, { className: "cls_sidebar_layout_trigger" }), _jsx("div", { className: "cls_sidebar_layout_main_header_content flex flex-1 items-center gap-2", children: _jsx("h2", { className: "cls_sidebar_layout_main_title text-lg font-semibold text-foreground", children: "hazo reusable ui library workspace" }) }), _jsx(ProfilePicMenu, { className: "cls_sidebar_layout_auth_status", avatar_size: "sm" })] }), _jsx("main", { className: "cls_sidebar_layout_main_content flex flex-1 items-center justify-center p-6", children: children })] })] }) }));
15
15
  }
@@ -4,5 +4,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  import { VisualPanel } from "./visual_panel";
5
5
  // section: component
6
6
  export function TwoColumnAuthLayout({ imageSrc, imageAlt, imageBackgroundColor, formContent, className, visualPanelClassName, formContainerClassName, }) {
7
- return (_jsxs("div", { className: `cls_two_column_auth_layout mx-auto grid w-full max-w-5xl grid-cols-1 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm md:grid-cols-2 md:min-h-[520px] ${className !== null && className !== void 0 ? className : ""}`, children: [_jsx(VisualPanel, { imageSrc: imageSrc, imageAlt: imageAlt, backgroundColor: imageBackgroundColor, className: visualPanelClassName }), _jsx("div", { className: `cls_two_column_auth_layout_form_container flex flex-col gap-6 p-8 ${formContainerClassName !== null && formContainerClassName !== void 0 ? formContainerClassName : ""}`, children: formContent })] }));
7
+ return (_jsxs("div", { className: `cls_two_column_auth_layout mx-4 my-8 grid w-full max-w-5xl grid-cols-1 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm md:mx-auto md:my-12 md:grid-cols-2 md:min-h-[520px] ${className !== null && className !== void 0 ? className : ""}`, children: [_jsx(VisualPanel, { imageSrc: imageSrc, imageAlt: imageAlt, backgroundColor: imageBackgroundColor, className: visualPanelClassName }), _jsx("div", { className: `cls_two_column_auth_layout_form_container flex flex-col gap-6 p-8 ${formContainerClassName !== null && formContainerClassName !== void 0 ? formContainerClassName : ""}`, children: formContent })] }));
8
8
  }
@@ -6,6 +6,9 @@ export type AuthStatusData = {
6
6
  email_verified?: boolean;
7
7
  last_logon?: string;
8
8
  profile_picture_url?: string;
9
+ profile_image?: string;
10
+ avatar_url?: string;
11
+ image?: string;
9
12
  profile_source?: "upload" | "library" | "gravatar" | "custom";
10
13
  permissions?: string[];
11
14
  permission_ok?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"use_auth_status.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/shared/hooks/use_auth_status.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC9D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAMF;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAIlD;AAGD,wBAAgB,eAAe,IAAI,UAAU,CAmE5C"}
1
+ {"version":3,"file":"use_auth_status.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/shared/hooks/use_auth_status.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC9D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAMF;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAIlD;AAGD,wBAAgB,eAAe,IAAI,UAAU,CAuE5C"}
@@ -40,6 +40,10 @@ export function use_auth_status() {
40
40
  email_verified: data.email_verified,
41
41
  last_logon: data.last_logon,
42
42
  profile_picture_url: data.profile_picture_url,
43
+ // Populate aliases for profile_picture_url
44
+ profile_image: data.profile_image,
45
+ avatar_url: data.avatar_url,
46
+ image: data.image,
43
47
  profile_source: data.profile_source,
44
48
  permissions: data.permissions || [],
45
49
  permission_ok: (_a = data.permission_ok) !== null && _a !== void 0 ? _a : true,
@@ -6,6 +6,8 @@ export { FormHeader } from "./components/form_header";
6
6
  export { LogoutButton } from "./components/logout_button";
7
7
  export { PasswordField } from "./components/password_field";
8
8
  export { ProfilePicMenu } from "./components/profile_pic_menu";
9
+ export { ProfileStamp } from "./components/profile_stamp";
10
+ export type { ProfileStampProps, ProfileStampCustomField } from "./components/profile_stamp";
9
11
  export { StandaloneLayoutWrapper } from "./components/standalone_layout_wrapper";
10
12
  export { TwoColumnAuthLayout } from "./components/two_column_auth_layout";
11
13
  export { UnauthorizedGuard } from "./components/unauthorized_guard";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/shared/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACjF,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGnF,cAAc,+BAA+B,CAAC;AAG9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/shared/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,YAAY,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAE7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACjF,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGnF,cAAc,+BAA+B,CAAC;AAG9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,oBAAoB,CAAC"}
@@ -10,6 +10,7 @@ export { LogoutButton } from "./components/logout_button";
10
10
  export { PasswordField } from "./components/password_field";
11
11
  // ProfilePicMenuWrapper - NOT exported (server component - imports .server files)
12
12
  export { ProfilePicMenu } from "./components/profile_pic_menu";
13
+ export { ProfileStamp } from "./components/profile_stamp";
13
14
  // SidebarLayoutWrapper - NOT exported (test workspace component only)
14
15
  export { StandaloneLayoutWrapper } from "./components/standalone_layout_wrapper";
15
16
  export { TwoColumnAuthLayout } from "./components/two_column_auth_layout";
@@ -18,9 +18,8 @@ export type RolesMatrixProps = {
18
18
  className?: string;
19
19
  };
20
20
  /**
21
- * Roles matrix component - reusable internal component for roles-permissions matrix
22
- * Shows data table with permissions as columns and roles as rows
23
- * Checkboxes in cells indicate role-permission mappings
21
+ * Roles matrix component - reusable internal component for roles-permissions management
22
+ * Shows roles with permission tags and an edit button to modify permissions via dialog
24
23
  * Changes are stored locally and only saved when Save button is pressed
25
24
  * @param props - Component props including button enable flags and save callback
26
25
  * @returns Roles matrix component
@@ -1 +1 @@
1
- {"version":3,"file":"roles_matrix.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/user_management/components/roles_matrix.tsx"],"names":[],"mappings":"AAgCA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,KAAK,CAAC;QACX,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC,CAAC;CACJ,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAGF;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAC1B,kBAAyB,EACzB,2BAAkC,EAClC,qBAA6B,EAC7B,gBAAuB,EACvB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,eAAe,EACf,SAAS,GACV,EAAE,gBAAgB,2CAwhBlB"}
1
+ {"version":3,"file":"roles_matrix.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/user_management/components/roles_matrix.tsx"],"names":[],"mappings":"AAgCA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,KAAK,CAAC;QACX,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC,CAAC;CACJ,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,kBAAyB,EACzB,2BAAkC,EAClC,qBAA6B,EAC7B,gBAAuB,EACvB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,eAAe,EACf,SAAS,GACV,EAAE,gBAAgB,2CA4xBlB"}
@@ -1,4 +1,4 @@
1
- // file_description: internal reusable component for roles-permissions matrix with data table
1
+ // file_description: internal reusable component for roles-permissions management with tag-based UI
2
2
  // section: client_directive
3
3
  "use client";
4
4
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
@@ -10,30 +10,36 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "
10
10
  import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "../../../ui/dialog";
11
11
  import { Input } from "../../../ui/input";
12
12
  import { Label } from "../../../ui/label";
13
- import { Plus, Loader2, CircleCheck, CircleX } from "lucide-react";
13
+ import { Plus, Loader2, CircleCheck, CircleX, Pencil } from "lucide-react";
14
14
  import { toast } from "sonner";
15
15
  import { Avatar, AvatarImage, AvatarFallback } from "../../../ui/avatar";
16
16
  import { useHazoAuthConfig } from "../../../../contexts/hazo_auth_provider";
17
17
  // section: component
18
18
  /**
19
- * Roles matrix component - reusable internal component for roles-permissions matrix
20
- * Shows data table with permissions as columns and roles as rows
21
- * Checkboxes in cells indicate role-permission mappings
19
+ * Roles matrix component - reusable internal component for roles-permissions management
20
+ * Shows roles with permission tags and an edit button to modify permissions via dialog
22
21
  * Changes are stored locally and only saved when Save button is pressed
23
22
  * @param props - Component props including button enable flags and save callback
24
23
  * @returns Roles matrix component
25
24
  */
26
25
  export function RolesMatrix({ add_button_enabled = true, role_name_selection_enabled = true, permissions_read_only = false, show_save_cancel = true, user_id, onSave, onCancel, onRoleSelection, className, }) {
26
+ var _a;
27
27
  const { apiBasePath } = useHazoAuthConfig();
28
28
  const [roles, setRoles] = useState([]);
29
29
  const [originalRoles, setOriginalRoles] = useState([]);
30
30
  const [permissions, setPermissions] = useState([]);
31
+ const [permissionsWithDescriptions, setPermissionsWithDescriptions] = useState([]);
31
32
  const [loading, setLoading] = useState(true);
32
33
  const [saving, setSaving] = useState(false);
33
34
  const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
34
35
  const [newRoleName, setNewRoleName] = useState("");
35
36
  const [userInfo, setUserInfo] = useState(null);
36
37
  const [userRoleIds, setUserRoleIds] = useState([]);
38
+ // Edit permissions dialog state
39
+ const [editPermissionsDialogOpen, setEditPermissionsDialogOpen] = useState(false);
40
+ const [editingRoleIndex, setEditingRoleIndex] = useState(null);
41
+ // Track which roles have expanded permission tags (for read-only mode)
42
+ const [expandedRoles, setExpandedRoles] = useState(new Set());
37
43
  // Load roles and permissions on mount
38
44
  useEffect(() => {
39
45
  const loadData = async () => {
@@ -48,6 +54,44 @@ export function RolesMatrix({ add_button_enabled = true, role_name_selection_ena
48
54
  return;
49
55
  }
50
56
  setPermissions(roles_data.permissions.map((p) => p.permission_name));
57
+ // Also fetch permission descriptions from the permissions endpoint
58
+ try {
59
+ const perms_response = await fetch(`${apiBasePath}/user_management/permissions`);
60
+ const perms_data = await perms_response.json();
61
+ if (perms_data.success) {
62
+ // Combine DB permissions and config permissions with descriptions
63
+ const all_perms_with_desc = [];
64
+ // DB permissions have descriptions
65
+ if (Array.isArray(perms_data.db_permissions)) {
66
+ perms_data.db_permissions.forEach((p) => {
67
+ all_perms_with_desc.push({
68
+ permission_name: p.permission_name,
69
+ description: p.description || "",
70
+ });
71
+ });
72
+ }
73
+ // Config permissions don't have descriptions in the API
74
+ if (Array.isArray(perms_data.config_permissions)) {
75
+ perms_data.config_permissions.forEach((name) => {
76
+ // Only add if not already in db_permissions
77
+ if (!all_perms_with_desc.some(p => p.permission_name === name)) {
78
+ all_perms_with_desc.push({
79
+ permission_name: name,
80
+ description: "",
81
+ });
82
+ }
83
+ });
84
+ }
85
+ setPermissionsWithDescriptions(all_perms_with_desc);
86
+ }
87
+ }
88
+ catch (_a) {
89
+ // If we can't get descriptions, use permissions without descriptions
90
+ setPermissionsWithDescriptions(roles_data.permissions.map((p) => ({
91
+ permission_name: p.permission_name,
92
+ description: "",
93
+ })));
94
+ }
51
95
  // Initialize roles with permissions as Sets
52
96
  const roles_with_permissions = roles_data.roles.map((role) => ({
53
97
  role_id: role.role_id,
@@ -105,7 +149,7 @@ export function RolesMatrix({ add_button_enabled = true, role_name_selection_ena
105
149
  }
106
150
  };
107
151
  void loadData();
108
- }, [user_id]);
152
+ }, [user_id, apiBasePath]);
109
153
  // Handle checkbox change for role-permission mapping
110
154
  const handlePermissionToggle = (role_index, permission_name) => {
111
155
  setRoles((prev) => {
@@ -264,6 +308,53 @@ export function RolesMatrix({ add_button_enabled = true, role_name_selection_ena
264
308
  setSaving(false);
265
309
  }
266
310
  };
311
+ // Handle opening the edit permissions dialog
312
+ const handleOpenEditPermissions = (role_index) => {
313
+ setEditingRoleIndex(role_index);
314
+ setEditPermissionsDialogOpen(true);
315
+ };
316
+ // Handle toggling expanded state for a role's permission tags
317
+ const handleToggleExpandedPermissions = (role_index) => {
318
+ setExpandedRoles((prev) => {
319
+ const updated = new Set(prev);
320
+ if (updated.has(role_index)) {
321
+ updated.delete(role_index);
322
+ }
323
+ else {
324
+ updated.add(role_index);
325
+ }
326
+ return updated;
327
+ });
328
+ };
329
+ // Handle select all permissions for the editing role
330
+ const handleSelectAllPermissions = () => {
331
+ if (editingRoleIndex === null)
332
+ return;
333
+ setRoles((prev) => {
334
+ const updated = [...prev];
335
+ const role = Object.assign({}, updated[editingRoleIndex]);
336
+ role.permissions = new Set(permissions);
337
+ updated[editingRoleIndex] = role;
338
+ return updated;
339
+ });
340
+ };
341
+ // Handle unselect all permissions for the editing role
342
+ const handleUnselectAllPermissions = () => {
343
+ if (editingRoleIndex === null)
344
+ return;
345
+ setRoles((prev) => {
346
+ const updated = [...prev];
347
+ const role = Object.assign({}, updated[editingRoleIndex]);
348
+ role.permissions = new Set();
349
+ updated[editingRoleIndex] = role;
350
+ return updated;
351
+ });
352
+ };
353
+ // Get description for a permission
354
+ const getPermissionDescription = (permission_name) => {
355
+ const perm = permissionsWithDescriptions.find(p => p.permission_name === permission_name);
356
+ return (perm === null || perm === void 0 ? void 0 : perm.description) || "";
357
+ };
267
358
  if (loading) {
268
359
  return (_jsx("div", { className: `cls_roles_matrix flex items-center justify-center p-8 ${className || ""}`, children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-slate-400" }) }));
269
360
  }
@@ -278,12 +369,46 @@ export function RolesMatrix({ add_button_enabled = true, role_name_selection_ena
278
369
  }
279
370
  return email.substring(0, 2).toUpperCase();
280
371
  };
281
- return (_jsxs("div", { className: `cls_roles_matrix flex flex-col gap-4 w-full ${className || ""}`, children: [user_id && userInfo && (_jsxs("div", { className: "cls_roles_matrix_user_info flex items-center gap-4 p-4 border rounded-lg bg-muted/50", children: [_jsxs(Avatar, { className: "cls_roles_matrix_user_avatar h-12 w-12", children: [_jsx(AvatarImage, { src: userInfo.profile_picture_url || undefined, alt: userInfo.name ? `Profile picture of ${userInfo.name}` : "Profile picture", className: "cls_roles_matrix_user_avatar_image" }), _jsx(AvatarFallback, { className: "cls_roles_matrix_user_avatar_fallback bg-slate-200 text-slate-600", children: getUserInitials(userInfo.name, userInfo.email_address) })] }), _jsxs("div", { className: "cls_roles_matrix_user_info_details flex flex-col", children: [_jsx("span", { className: "cls_roles_matrix_user_name font-semibold text-lg", children: userInfo.name || userInfo.email_address }), userInfo.name && (_jsx("span", { className: "cls_roles_matrix_user_email text-sm text-muted-foreground", children: userInfo.email_address }))] })] })), _jsx("div", { className: "cls_roles_matrix_header flex items-center justify-between", children: _jsx("div", { className: "cls_roles_matrix_header_left", children: add_button_enabled && (_jsxs(Button, { onClick: () => setIsAddDialogOpen(true), variant: "default", size: "sm", className: "cls_roles_matrix_add_button", children: [_jsx(Plus, { className: "h-4 w-4 mr-2" }), "Add Role"] })) }) }), _jsx("div", { className: "cls_roles_matrix_table_container border rounded-lg overflow-auto w-full", children: _jsxs(Table, { className: "cls_roles_matrix_table w-full", children: [_jsx(TableHeader, { className: "cls_roles_matrix_table_header", children: _jsxs(TableRow, { className: "cls_roles_matrix_table_header_row", children: [role_name_selection_enabled && (_jsx(TableHead, { className: "cls_roles_matrix_table_header_role_checkbox w-12" })), _jsx(TableHead, { className: "cls_roles_matrix_table_header_role_name", children: "Role Name" }), permissions.map((permission_name) => (_jsx(TableHead, { className: "cls_roles_matrix_table_header_permission text-center", children: permission_name }, permission_name)))] }) }), _jsx(TableBody, { className: "cls_roles_matrix_table_body", children: roles.length === 0 ? (_jsx(TableRow, { className: "cls_roles_matrix_table_row_empty", children: _jsx(TableCell, { colSpan: permissions.length + (role_name_selection_enabled ? 2 : 1), className: "text-center text-muted-foreground py-8", children: "No roles found. Add a role to get started." }) })) : (roles.map((role, role_index) => (_jsxs(TableRow, { className: "cls_roles_matrix_table_row", children: [role_name_selection_enabled && (_jsx(TableCell, { className: "cls_roles_matrix_table_cell_role_checkbox text-center", children: _jsx("div", { className: "cls_roles_matrix_role_checkbox_wrapper flex items-center justify-center", children: _jsx(Checkbox, { checked: role.selected, onCheckedChange: () => handleRoleSelectionToggle(role_index), className: "cls_roles_matrix_role_checkbox" }) }) })), _jsx(TableCell, { className: "cls_roles_matrix_table_cell_role_name font-medium", children: role.role_name }), permissions.map((permission_name) => (_jsx(TableCell, { className: "cls_roles_matrix_table_cell_permission text-center", children: _jsx("div", { className: "cls_roles_matrix_permission_checkbox_wrapper flex items-center justify-center", children: _jsx(Checkbox, { checked: role.permissions.has(permission_name), onCheckedChange: () => handlePermissionToggle(role_index, permission_name), disabled: permissions_read_only, className: "cls_roles_matrix_permission_checkbox" }) }) }, permission_name)))] }, role_index)))) })] }) }), show_save_cancel && (_jsxs("div", { className: "cls_roles_matrix_footer flex items-center justify-end gap-2", children: [_jsx(Button, { onClick: handleSave, disabled: saving, variant: "default", size: "sm", className: "cls_roles_matrix_save_button", children: saving ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Saving..."] })) : (_jsxs(_Fragment, { children: [_jsx(CircleCheck, { className: "h-4 w-4 mr-2" }), "Save"] })) }), _jsxs(Button, { onClick: handleCancel, variant: "outline", size: "sm", className: "cls_roles_matrix_cancel_button", children: [_jsx(CircleX, { className: "h-4 w-4 mr-2" }), "Cancel"] })] })), _jsx(Dialog, { open: isAddDialogOpen, onOpenChange: setIsAddDialogOpen, children: _jsxs(DialogContent, { className: "cls_roles_matrix_add_dialog", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Add New Role" }), _jsx(DialogDescription, { children: "Enter a name for the new role. You can assign permissions after creating the role." })] }), _jsx("div", { className: "cls_roles_matrix_add_dialog_content flex flex-col gap-4 py-4", children: _jsxs("div", { className: "cls_roles_matrix_add_dialog_field flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "role_name", className: "cls_roles_matrix_add_dialog_label", children: "Role Name" }), _jsx(Input, { id: "role_name", value: newRoleName, onChange: (e) => setNewRoleName(e.target.value), placeholder: "Enter role name", className: "cls_roles_matrix_add_dialog_input", onKeyDown: (e) => {
372
+ // Number of permission tags to show before truncating
373
+ const MAX_VISIBLE_TAGS = 4;
374
+ return (_jsxs("div", { className: `cls_roles_matrix flex flex-col gap-4 w-full ${className || ""}`, children: [user_id && userInfo && (_jsxs("div", { className: "cls_roles_matrix_user_info flex items-center gap-4 p-4 border rounded-lg bg-muted/50", children: [_jsxs(Avatar, { className: "cls_roles_matrix_user_avatar h-12 w-12", children: [_jsx(AvatarImage, { src: userInfo.profile_picture_url || undefined, alt: userInfo.name ? `Profile picture of ${userInfo.name}` : "Profile picture", className: "cls_roles_matrix_user_avatar_image" }), _jsx(AvatarFallback, { className: "cls_roles_matrix_user_avatar_fallback bg-slate-200 text-slate-600", children: getUserInitials(userInfo.name, userInfo.email_address) })] }), _jsxs("div", { className: "cls_roles_matrix_user_info_details flex flex-col", children: [_jsx("span", { className: "cls_roles_matrix_user_name font-semibold text-lg", children: userInfo.name || userInfo.email_address }), userInfo.name && (_jsx("span", { className: "cls_roles_matrix_user_email text-sm text-muted-foreground", children: userInfo.email_address }))] })] })), _jsx("div", { className: "cls_roles_matrix_header flex items-center justify-between", children: _jsx("div", { className: "cls_roles_matrix_header_left", children: add_button_enabled && (_jsxs(Button, { onClick: () => setIsAddDialogOpen(true), variant: "default", size: "sm", className: "cls_roles_matrix_add_button", children: [_jsx(Plus, { className: "h-4 w-4 mr-2" }), "Add Role"] })) }) }), _jsx("div", { className: "cls_roles_matrix_table_container border rounded-lg overflow-auto w-full", children: _jsxs(Table, { className: "cls_roles_matrix_table w-full", children: [_jsx(TableHeader, { className: "cls_roles_matrix_table_header", children: _jsxs(TableRow, { className: "cls_roles_matrix_table_header_row", children: [role_name_selection_enabled && (_jsx(TableHead, { className: "cls_roles_matrix_table_header_role_checkbox w-12" })), _jsx(TableHead, { className: "cls_roles_matrix_table_header_role_name w-48", children: "Role Name" }), _jsx(TableHead, { className: "cls_roles_matrix_table_header_permissions", children: "Permissions" }), !permissions_read_only && (_jsx(TableHead, { className: "cls_roles_matrix_table_header_actions w-24 text-center", children: "Actions" }))] }) }), _jsx(TableBody, { className: "cls_roles_matrix_table_body", children: roles.length === 0 ? (_jsx(TableRow, { className: "cls_roles_matrix_table_row_empty", children: _jsx(TableCell, { colSpan: role_name_selection_enabled ? 4 : 3, className: "text-center text-muted-foreground py-8", children: "No roles found. Add a role to get started." }) })) : (roles.map((role, role_index) => {
375
+ const permission_array = Array.from(role.permissions);
376
+ const is_expanded = expandedRoles.has(role_index);
377
+ const visible_permissions = is_expanded
378
+ ? permission_array
379
+ : permission_array.slice(0, MAX_VISIBLE_TAGS);
380
+ const remaining_count = permission_array.length - MAX_VISIBLE_TAGS;
381
+ return (_jsxs(TableRow, { className: "cls_roles_matrix_table_row", children: [role_name_selection_enabled && (_jsx(TableCell, { className: "cls_roles_matrix_table_cell_role_checkbox text-center", children: _jsx("div", { className: "cls_roles_matrix_role_checkbox_wrapper flex items-center justify-center", children: _jsx(Checkbox, { checked: role.selected, onCheckedChange: () => handleRoleSelectionToggle(role_index), className: "cls_roles_matrix_role_checkbox" }) }) })), _jsx(TableCell, { className: "cls_roles_matrix_table_cell_role_name font-medium", children: role.role_name }), _jsx(TableCell, { className: "cls_roles_matrix_table_cell_permissions", children: _jsx("div", { className: "cls_roles_matrix_permission_tags flex flex-wrap items-center gap-1.5", children: permission_array.length === 0 ? (_jsx("span", { className: "text-muted-foreground text-sm italic", children: "No permissions assigned" })) : (_jsxs(_Fragment, { children: [visible_permissions.map((perm_name) => (_jsx("span", { className: "cls_roles_matrix_permission_tag bg-blue-100 text-blue-700 px-2 py-0.5 rounded text-xs font-medium", title: getPermissionDescription(perm_name) || perm_name, children: perm_name }, perm_name))), remaining_count > 0 && !is_expanded && (_jsxs("span", { className: "cls_roles_matrix_permission_tag_more bg-slate-100 text-slate-600 px-2 py-0.5 rounded text-xs font-medium cursor-pointer hover:bg-slate-200", onClick: () => {
382
+ if (permissions_read_only) {
383
+ handleToggleExpandedPermissions(role_index);
384
+ }
385
+ else {
386
+ handleOpenEditPermissions(role_index);
387
+ }
388
+ }, title: permissions_read_only ? `Click to expand all ${permission_array.length} permissions` : `Click to edit all ${permission_array.length} permissions`, children: ["+", remaining_count, " more"] })), is_expanded && remaining_count > 0 && (_jsx("span", { className: "cls_roles_matrix_permission_tag_collapse bg-slate-100 text-slate-600 px-2 py-0.5 rounded text-xs font-medium cursor-pointer hover:bg-slate-200", onClick: () => handleToggleExpandedPermissions(role_index), title: "Click to collapse", children: "Show less" }))] })) }) }), !permissions_read_only && (_jsx(TableCell, { className: "cls_roles_matrix_table_cell_actions text-center", children: _jsx(Button, { onClick: () => handleOpenEditPermissions(role_index), variant: "ghost", size: "sm", className: "cls_roles_matrix_edit_button h-8 w-8 p-0", title: "Edit permissions", children: _jsx(Pencil, { className: "h-4 w-4" }) }) }))] }, role_index));
389
+ })) })] }) }), show_save_cancel && (_jsxs("div", { className: "cls_roles_matrix_footer flex items-center justify-end gap-2", children: [_jsx(Button, { onClick: handleSave, disabled: saving, variant: "default", size: "sm", className: "cls_roles_matrix_save_button", children: saving ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Saving..."] })) : (_jsxs(_Fragment, { children: [_jsx(CircleCheck, { className: "h-4 w-4 mr-2" }), "Save"] })) }), _jsxs(Button, { onClick: handleCancel, variant: "outline", size: "sm", className: "cls_roles_matrix_cancel_button", children: [_jsx(CircleX, { className: "h-4 w-4 mr-2" }), "Cancel"] })] })), _jsx(Dialog, { open: isAddDialogOpen, onOpenChange: setIsAddDialogOpen, children: _jsxs(DialogContent, { className: "cls_roles_matrix_add_dialog", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Add New Role" }), _jsx(DialogDescription, { children: "Enter a name for the new role. You can assign permissions after creating the role." })] }), _jsx("div", { className: "cls_roles_matrix_add_dialog_content flex flex-col gap-4 py-4", children: _jsxs("div", { className: "cls_roles_matrix_add_dialog_field flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "role_name", className: "cls_roles_matrix_add_dialog_label", children: "Role Name" }), _jsx(Input, { id: "role_name", value: newRoleName, onChange: (e) => setNewRoleName(e.target.value), placeholder: "Enter role name", className: "cls_roles_matrix_add_dialog_input", onKeyDown: (e) => {
282
390
  if (e.key === "Enter") {
283
391
  handleAddRole();
284
392
  }
285
393
  } })] }) }), _jsxs(DialogFooter, { className: "cls_roles_matrix_add_dialog_footer", children: [_jsx(Button, { onClick: handleAddRole, variant: "default", className: "cls_roles_matrix_add_dialog_save", children: "Add Role" }), _jsx(Button, { onClick: () => {
286
394
  setIsAddDialogOpen(false);
287
395
  setNewRoleName("");
288
- }, variant: "outline", className: "cls_roles_matrix_add_dialog_cancel", children: "Cancel" })] })] }) })] }));
396
+ }, variant: "outline", className: "cls_roles_matrix_add_dialog_cancel", children: "Cancel" })] })] }) }), _jsx(Dialog, { open: editPermissionsDialogOpen, onOpenChange: setEditPermissionsDialogOpen, children: _jsxs(DialogContent, { className: "cls_roles_matrix_edit_permissions_dialog max-w-lg max-h-[80vh] flex flex-col", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: ["Edit Permissions for: ", editingRoleIndex !== null ? (_a = roles[editingRoleIndex]) === null || _a === void 0 ? void 0 : _a.role_name : ""] }), _jsx(DialogDescription, { children: "Select which permissions to assign to this role." })] }), _jsxs("div", { className: "cls_roles_matrix_edit_permissions_actions flex items-center gap-2 py-2 border-b", children: [_jsx(Button, { onClick: handleSelectAllPermissions, variant: "outline", size: "sm", className: "cls_roles_matrix_select_all_button", children: "Select All" }), _jsx(Button, { onClick: handleUnselectAllPermissions, variant: "outline", size: "sm", className: "cls_roles_matrix_unselect_all_button", children: "Unselect All" })] }), _jsx("div", { className: "cls_roles_matrix_edit_permissions_list flex-1 overflow-y-auto py-2 min-h-0", children: _jsx("div", { className: "flex flex-col gap-3", children: permissionsWithDescriptions.map((perm) => {
397
+ var _a;
398
+ const is_checked = editingRoleIndex !== null && ((_a = roles[editingRoleIndex]) === null || _a === void 0 ? void 0 : _a.permissions.has(perm.permission_name));
399
+ return (_jsxs("div", { className: "cls_roles_matrix_permission_item flex items-start gap-3 p-2 rounded hover:bg-muted/50 cursor-pointer", onClick: () => editingRoleIndex !== null && handlePermissionToggle(editingRoleIndex, perm.permission_name), children: [_jsx(Checkbox, { checked: is_checked, onCheckedChange: () => editingRoleIndex !== null && handlePermissionToggle(editingRoleIndex, perm.permission_name), className: "cls_roles_matrix_permission_checkbox mt-0.5" }), _jsxs("div", { className: "cls_roles_matrix_permission_info flex flex-col gap-0.5", children: [_jsx("span", { className: "cls_roles_matrix_permission_name font-medium text-sm", children: perm.permission_name }), perm.description && (_jsx("span", { className: "cls_roles_matrix_permission_description text-xs text-muted-foreground italic", children: perm.description }))] })] }, perm.permission_name));
400
+ }) }) }), _jsxs(DialogFooter, { className: "cls_roles_matrix_edit_permissions_footer border-t pt-4", children: [_jsxs(Button, { onClick: () => setEditPermissionsDialogOpen(false), variant: "default", className: "cls_roles_matrix_edit_permissions_done", children: [_jsx(CircleCheck, { className: "h-4 w-4 mr-2" }), "Done"] }), _jsxs(Button, { onClick: () => {
401
+ // Reset this role's permissions to original state
402
+ if (editingRoleIndex !== null) {
403
+ const original_role = originalRoles.find(r => r.role_name === roles[editingRoleIndex].role_name);
404
+ if (original_role) {
405
+ setRoles((prev) => {
406
+ const updated = [...prev];
407
+ updated[editingRoleIndex] = Object.assign(Object.assign({}, updated[editingRoleIndex]), { permissions: new Set(original_role.permissions) });
408
+ return updated;
409
+ });
410
+ }
411
+ }
412
+ setEditPermissionsDialogOpen(false);
413
+ }, variant: "outline", className: "cls_roles_matrix_edit_permissions_cancel", children: [_jsx(CircleX, { className: "h-4 w-4 mr-2" }), "Cancel"] })] })] }) })] }));
289
414
  }
@@ -0,0 +1,12 @@
1
+ export type ScopeHierarchyTabProps = {
2
+ className?: string;
3
+ defaultOrg?: string;
4
+ };
5
+ /**
6
+ * Scope Hierarchy tab component for managing HRBAC scopes
7
+ * Displays scopes in a tree view for intuitive hierarchy configuration
8
+ * @param props - Component props
9
+ * @returns Scope Hierarchy tab component
10
+ */
11
+ export declare function ScopeHierarchyTab({ className, defaultOrg, }: ScopeHierarchyTabProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=scope_hierarchy_tab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope_hierarchy_tab.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/user_management/components/scope_hierarchy_tab.tsx"],"names":[],"mappings":"AA2CA,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AA8HF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,UAAe,GAChB,EAAE,sBAAsB,2CA2fxB"}