hazo_auth 4.0.0 → 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 (26) hide show
  1. package/README.md +82 -8
  2. package/SETUP_CHECKLIST.md +1 -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/profile_stamp_test/index.d.ts +10 -0
  7. package/dist/components/layouts/profile_stamp_test/index.d.ts.map +1 -0
  8. package/dist/components/layouts/profile_stamp_test/index.js +51 -0
  9. package/dist/components/layouts/shared/components/profile_stamp.d.ts +58 -0
  10. package/dist/components/layouts/shared/components/profile_stamp.d.ts.map +1 -0
  11. package/dist/components/layouts/shared/components/profile_stamp.js +72 -0
  12. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
  13. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +2 -2
  14. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +3 -0
  15. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -1
  16. package/dist/components/layouts/shared/hooks/use_auth_status.js +4 -0
  17. package/dist/components/layouts/shared/index.d.ts +2 -0
  18. package/dist/components/layouts/shared/index.d.ts.map +1 -1
  19. package/dist/components/layouts/shared/index.js +1 -0
  20. package/dist/components/ui/hover-card.d.ts +7 -0
  21. package/dist/components/ui/hover-card.d.ts.map +1 -0
  22. package/dist/components/ui/hover-card.js +29 -0
  23. package/dist/components/ui/index.d.ts +1 -0
  24. package/dist/components/ui/index.d.ts.map +1 -1
  25. package/dist/components/ui/index.js +1 -0
  26. package/package.json +2 -1
package/README.md CHANGED
@@ -198,11 +198,12 @@ import { MySettingsLayout } from "hazo_auth/components/layouts/my_settings";
198
198
  import { UserManagementLayout } from "hazo_auth/components/layouts/user_management";
199
199
 
200
200
  // Import shared components and hooks from barrel export
201
- import {
202
- ProfilePicMenu,
201
+ import {
202
+ ProfilePicMenu,
203
203
  ProfilePicMenuWrapper,
204
- use_hazo_auth,
205
- use_auth_status
204
+ ProfileStamp,
205
+ use_hazo_auth,
206
+ use_auth_status
206
207
  } from "hazo_auth/components/layouts/shared";
207
208
 
208
209
  // Import server-side utilities
@@ -258,11 +259,12 @@ For client components (browser-safe, no Node.js dependencies):
258
259
 
259
260
  ```typescript
260
261
  // Use hazo_auth/client for client components
261
- import {
262
- ProfilePicMenu,
263
- use_auth_status,
262
+ import {
263
+ ProfilePicMenu,
264
+ ProfileStamp,
265
+ use_auth_status,
264
266
  use_hazo_auth,
265
- cn
267
+ cn
266
268
  } from "hazo_auth/client";
267
269
  ```
268
270
 
@@ -863,6 +865,10 @@ This is the **standardized endpoint** that ensures consistent response format ac
863
865
  last_logon: string | undefined,
864
866
  profile_picture_url: string | null,
865
867
  profile_source: "upload" | "library" | "gravatar" | "custom" | undefined,
868
+ // Profile picture aliases (for consuming app compatibility)
869
+ profile_image?: string, // Alias for profile_picture_url
870
+ avatar_url?: string, // Alias for profile_picture_url
871
+ image?: string, // Alias for profile_picture_url
866
872
  // Permissions (always included)
867
873
  user: {
868
874
  id: string,
@@ -1375,6 +1381,74 @@ The test tool uses the `/api/hazo_auth/rbac_test` endpoint which is included in
1375
1381
 
1376
1382
  ---
1377
1383
 
1384
+ ## ProfileStamp Component
1385
+
1386
+ The `ProfileStamp` component is a drop-in widget that displays a circular profile picture with a hover card showing user details. Perfect for adding profile attribution to notes, comments, or any user-generated content.
1387
+
1388
+ ### Features
1389
+
1390
+ - Displays user's profile picture or initials
1391
+ - Hover card with user name, email, and custom fields
1392
+ - Three sizes: sm (24px), default (32px), lg (40px)
1393
+ - Automatic loading state and unauthenticated fallback
1394
+ - Fully accessible with keyboard navigation
1395
+
1396
+ ### Usage
1397
+
1398
+ ```typescript
1399
+ import { ProfileStamp } from "hazo_auth/client";
1400
+
1401
+ // Basic usage
1402
+ <ProfileStamp />
1403
+
1404
+ // With custom size and fields
1405
+ <ProfileStamp
1406
+ size="lg"
1407
+ custom_fields={[
1408
+ { label: "Role", value: "Admin" },
1409
+ { label: "Department", value: "Engineering" }
1410
+ ]}
1411
+ />
1412
+
1413
+ // Hide default fields, only show custom fields
1414
+ <ProfileStamp
1415
+ show_name={false}
1416
+ show_email={false}
1417
+ custom_fields={[
1418
+ { label: "Posted", value: "2 hours ago" }
1419
+ ]}
1420
+ />
1421
+ ```
1422
+
1423
+ ### Props
1424
+
1425
+ | Prop | Type | Default | Description |
1426
+ |------|------|---------|-------------|
1427
+ | `size` | `"sm" \| "default" \| "lg"` | `"default"` | Avatar size (sm: 24px, default: 32px, lg: 40px) |
1428
+ | `custom_fields` | `ProfileStampCustomField[]` | `[]` | Custom fields to display in hover card |
1429
+ | `className` | `string` | `undefined` | Additional CSS classes |
1430
+ | `show_name` | `boolean` | `true` | Show user name in hover card |
1431
+ | `show_email` | `boolean` | `true` | Show email in hover card |
1432
+
1433
+ ### ProfileStampCustomField Type
1434
+
1435
+ ```typescript
1436
+ type ProfileStampCustomField = {
1437
+ label: string; // Field label (e.g., "Role", "Department")
1438
+ value: string; // Field value (e.g., "Admin", "Engineering")
1439
+ };
1440
+ ```
1441
+
1442
+ ### Test Page
1443
+
1444
+ Visit `/hazo_auth/profile_stamp_test` in your dev environment to see examples of ProfileStamp with various configurations:
1445
+ - Size variants
1446
+ - Custom fields
1447
+ - Display options (showing/hiding name and email)
1448
+ - Usage scenarios (notes, comments, activity feeds)
1449
+
1450
+ ---
1451
+
1378
1452
  ## Profile Picture Menu Widget
1379
1453
 
1380
1454
  The Profile Picture Menu is a versatile component for navbar or sidebar that automatically displays:
@@ -954,6 +954,7 @@ Visit each page and verify it loads:
954
954
  - [ ] `http://localhost:3000/hazo_auth/register` - Registration form displays
955
955
  - [ ] `http://localhost:3000/hazo_auth/forgot_password` - Forgot password form displays
956
956
  - [ ] `http://localhost:3000/hazo_auth/my_settings` - Settings page displays (after login)
957
+ - [ ] `http://localhost:3000/hazo_auth/profile_stamp_test` - ProfileStamp component examples display
957
958
 
958
959
  ---
959
960
 
@@ -14,6 +14,9 @@ import { NextRequest, NextResponse } from "next/server";
14
14
  * email_verified: boolean,
15
15
  * last_logon: string | undefined,
16
16
  * profile_picture_url: string | null,
17
+ * profile_image: string | null, // alias for profile_picture_url
18
+ * avatar_url: string | null, // alias for profile_picture_url
19
+ * image: string | null, // alias for profile_picture_url
17
20
  * profile_source: "upload" | "library" | "gravatar" | "custom" | undefined,
18
21
  * user: { id, email_address, name, is_active, profile_picture_url },
19
22
  * permissions: string[],
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/me/route.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;IA0E7C"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/me/route.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;IA+E7C"}
@@ -24,6 +24,9 @@ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_h
24
24
  * email_verified: boolean,
25
25
  * last_logon: string | undefined,
26
26
  * profile_picture_url: string | null,
27
+ * profile_image: string | null, // alias for profile_picture_url
28
+ * avatar_url: string | null, // alias for profile_picture_url
29
+ * image: string | null, // alias for profile_picture_url
27
30
  * profile_source: "upload" | "library" | "gravatar" | "custom" | undefined,
28
31
  * user: { id, email_address, name, is_active, profile_picture_url },
29
32
  * permissions: string[],
@@ -63,6 +66,7 @@ export async function GET(request) {
63
66
  const profile_source_db = user_db.profile_source;
64
67
  const profile_source_ui = profile_source_db ? map_db_source_to_ui(profile_source_db) : undefined;
65
68
  // Return unified format with all fields
69
+ const profile_pic = auth_result.user.profile_picture_url;
66
70
  return NextResponse.json({
67
71
  authenticated: true,
68
72
  // Top-level fields for backward compatibility
@@ -71,7 +75,11 @@ export async function GET(request) {
71
75
  name: auth_result.user.name,
72
76
  email_verified: user_db.email_verified === true,
73
77
  last_logon: user_db.last_logon || undefined,
74
- profile_picture_url: auth_result.user.profile_picture_url,
78
+ profile_picture_url: profile_pic,
79
+ // Aliases for profile_picture_url (for consuming app compatibility)
80
+ profile_image: profile_pic,
81
+ avatar_url: profile_pic,
82
+ image: profile_pic,
75
83
  profile_source: profile_source_ui,
76
84
  // Permissions and user object (always included)
77
85
  user: auth_result.user,
@@ -0,0 +1,10 @@
1
+ export type ProfileStampTestLayoutProps = {
2
+ className?: string;
3
+ };
4
+ /**
5
+ * ProfileStampTestLayout - Test page for ProfileStamp component
6
+ * Demonstrates various scenarios and configurations
7
+ */
8
+ export declare function ProfileStampTestLayout({ className }: ProfileStampTestLayoutProps): import("react/jsx-runtime").JSX.Element;
9
+ export default ProfileStampTestLayout;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/profile_stamp_test/index.tsx"],"names":[],"mappings":"AAYA,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAGF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,SAAS,EAAE,EAAE,2BAA2B,2CAkNhF;AAED,eAAe,sBAAsB,CAAC"}
@@ -0,0 +1,51 @@
1
+ // file_description: Test page layout for ProfileStamp component demonstrating various scenarios
2
+ // section: client_directive
3
+ "use client";
4
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
+ // section: imports
6
+ import { useState } from "react";
7
+ import { ProfileStamp } from "../shared/components/profile_stamp";
8
+ import { use_auth_status } from "../shared/hooks/use_auth_status";
9
+ import { Button } from "../../ui/button";
10
+ import { Card } from "../../ui/card";
11
+ // section: component
12
+ /**
13
+ * ProfileStampTestLayout - Test page for ProfileStamp component
14
+ * Demonstrates various scenarios and configurations
15
+ */
16
+ export function ProfileStampTestLayout({ className }) {
17
+ const authStatus = use_auth_status();
18
+ const [showCustomFields, setShowCustomFields] = useState(true);
19
+ // Sample custom fields for testing
20
+ const sampleCustomFields = [
21
+ { label: "Role", value: "Administrator" },
22
+ { label: "Department", value: "Engineering" },
23
+ { label: "Joined", value: "Jan 2024" },
24
+ ];
25
+ return (_jsxs("div", { className: `cls_profile_stamp_test_layout w-full max-w-4xl mx-auto p-6 ${className || ""}`, children: [_jsx("h1", { className: "text-2xl font-bold mb-6", children: "ProfileStamp Component Test" }), _jsxs(Card, { className: "p-4 mb-6", children: [_jsx("h2", { className: "text-lg font-semibold mb-2", children: "Current Auth Status" }), _jsxs("div", { className: "grid grid-cols-2 gap-2 text-sm", children: [_jsx("div", { children: "Authenticated:" }), _jsx("div", { className: authStatus.authenticated ? "text-green-600" : "text-red-600", children: authStatus.authenticated ? "Yes" : "No" }), _jsx("div", { children: "User ID:" }), _jsx("div", { children: authStatus.user_id || "N/A" }), _jsx("div", { children: "Name:" }), _jsx("div", { children: authStatus.name || "N/A" }), _jsx("div", { children: "Email:" }), _jsx("div", { children: authStatus.email || "N/A" }), _jsx("div", { children: "Profile Picture URL:" }), _jsx("div", { className: "truncate", children: authStatus.profile_picture_url || "N/A" }), _jsx("div", { children: "Profile Source:" }), _jsx("div", { children: authStatus.profile_source || "N/A" })] })] }), _jsxs(Card, { className: "p-4 mb-6", children: [_jsx("h2", { className: "text-lg font-semibold mb-4", children: "Size Variants" }), _jsxs("div", { className: "flex items-end gap-6", children: [_jsxs("div", { className: "flex flex-col items-center gap-2", children: [_jsx(ProfileStamp, { size: "sm" }), _jsx("span", { className: "text-xs text-muted-foreground", children: "sm (24px)" })] }), _jsxs("div", { className: "flex flex-col items-center gap-2", children: [_jsx(ProfileStamp, { size: "default" }), _jsx("span", { className: "text-xs text-muted-foreground", children: "default (32px)" })] }), _jsxs("div", { className: "flex flex-col items-center gap-2", children: [_jsx(ProfileStamp, { size: "lg" }), _jsx("span", { className: "text-xs text-muted-foreground", children: "lg (40px)" })] })] })] }), _jsxs(Card, { className: "p-4 mb-6", children: [_jsx("h2", { className: "text-lg font-semibold mb-4", children: "With Custom Fields" }), _jsx("div", { className: "flex items-center gap-4 mb-4", children: _jsx(Button, { variant: showCustomFields ? "default" : "outline", size: "sm", onClick: () => setShowCustomFields(!showCustomFields), children: showCustomFields ? "Hide Custom Fields" : "Show Custom Fields" }) }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(ProfileStamp, { size: "lg", custom_fields: showCustomFields ? sampleCustomFields : [] }), _jsxs("span", { className: "text-sm text-muted-foreground", children: ["Hover to see ", showCustomFields ? "name, email, and custom fields" : "name and email only"] })] }), showCustomFields && (_jsx("div", { className: "mt-4 p-3 bg-muted rounded-md", children: _jsxs("div", { className: "text-xs font-mono", children: ["custom_fields=", JSON.stringify(sampleCustomFields, null, 2)] }) }))] }), _jsxs(Card, { className: "p-4 mb-6", children: [_jsx("h2", { className: "text-lg font-semibold mb-4", children: "Display Options" }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx(ProfileStamp, { show_name: true, show_email: true }), _jsx("span", { className: "text-sm text-muted-foreground", children: "show_name=true, show_email=true (default)" })] }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(ProfileStamp, { show_name: true, show_email: false }), _jsx("span", { className: "text-sm text-muted-foreground", children: "show_name=true, show_email=false" })] }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(ProfileStamp, { show_name: false, show_email: true }), _jsx("span", { className: "text-sm text-muted-foreground", children: "show_name=false, show_email=true" })] }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(ProfileStamp, { show_name: false, show_email: false }), _jsx("span", { className: "text-sm text-muted-foreground", children: "show_name=false, show_email=false (no hover card)" })] })] })] }), _jsxs(Card, { className: "p-4 mb-6", children: [_jsx("h2", { className: "text-lg font-semibold mb-4", children: "Inline Usage Example (Note Attribution)" }), _jsx("div", { className: "border rounded-lg p-4 bg-background", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(ProfileStamp, { size: "default" }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [_jsx("span", { className: "font-medium text-sm", children: authStatus.name || "User" }), _jsx("span", { className: "text-xs text-muted-foreground", children: "2 hours ago" })] }), _jsx("p", { className: "text-sm text-foreground", children: "This is an example note with a ProfileStamp component showing who added it. Hover over the profile picture to see more details about the user." })] })] }) })] }), _jsxs(Card, { className: "p-4 mb-6", children: [_jsx("h2", { className: "text-lg font-semibold mb-4", children: "Comment Thread Example" }), _jsx("div", { className: "space-y-4", children: [
26
+ { time: "3 hours ago", text: "Great progress on the project!" },
27
+ { time: "2 hours ago", text: "I agree, the new features look amazing." },
28
+ { time: "1 hour ago", text: "Let me know if you need any help with the deployment." },
29
+ ].map((comment, index) => (_jsxs("div", { className: "flex items-start gap-3 border-b pb-4 last:border-b-0", children: [_jsx(ProfileStamp, { size: "sm", custom_fields: [{ label: "Comment", value: `#${index + 1}` }] }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [_jsx("span", { className: "font-medium text-sm", children: authStatus.name || "User" }), _jsx("span", { className: "text-xs text-muted-foreground", children: comment.time })] }), _jsx("p", { className: "text-sm text-foreground", children: comment.text })] })] }, index))) })] }), _jsxs(Card, { className: "p-4 mb-6", children: [_jsx("h2", { className: "text-lg font-semibold mb-4", children: "API Response Fields" }), _jsx("p", { className: "text-sm text-muted-foreground mb-3", children: "The /api/hazo_auth/me endpoint now returns these profile picture fields:" }), _jsx("div", { className: "p-3 bg-muted rounded-md font-mono text-xs", children: _jsx("pre", { children: `{
30
+ "profile_picture_url": "${authStatus.profile_picture_url || "null"}",
31
+ "profile_image": "${authStatus.profile_image || "null"}", // alias
32
+ "avatar_url": "${authStatus.avatar_url || "null"}", // alias
33
+ "image": "${authStatus.image || "null"}" // alias
34
+ }` }) })] }), _jsxs(Card, { className: "p-4", children: [_jsx("h2", { className: "text-lg font-semibold mb-4", children: "Usage Code Example" }), _jsx("div", { className: "p-3 bg-muted rounded-md font-mono text-xs overflow-x-auto", children: _jsx("pre", { children: `// Basic usage
35
+ import { ProfileStamp } from "hazo_auth/client";
36
+
37
+ <ProfileStamp />
38
+
39
+ // With all options
40
+ <ProfileStamp
41
+ size="lg"
42
+ show_name={true}
43
+ show_email={true}
44
+ custom_fields={[
45
+ { label: "Role", value: "Admin" },
46
+ { label: "Department", value: "IT" }
47
+ ]}
48
+ className="my-custom-class"
49
+ />` }) })] })] }));
50
+ }
51
+ export default ProfileStampTestLayout;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Custom field to display in the hover card
3
+ */
4
+ export type ProfileStampCustomField = {
5
+ label: string;
6
+ value: string;
7
+ };
8
+ /**
9
+ * Props for the ProfileStamp component
10
+ */
11
+ export type ProfileStampProps = {
12
+ /**
13
+ * Size variant for the avatar
14
+ * - sm: h-6 w-6 (24px)
15
+ * - default: h-8 w-8 (32px)
16
+ * - lg: h-10 w-10 (40px)
17
+ */
18
+ size?: "sm" | "default" | "lg";
19
+ /**
20
+ * Custom fields to display in the hover card
21
+ */
22
+ custom_fields?: ProfileStampCustomField[];
23
+ /**
24
+ * Additional CSS classes to apply to the wrapper
25
+ */
26
+ className?: string;
27
+ /**
28
+ * Whether to show the user's name in the hover card (default: true)
29
+ */
30
+ show_name?: boolean;
31
+ /**
32
+ * Whether to show the user's email in the hover card (default: true)
33
+ */
34
+ show_email?: boolean;
35
+ };
36
+ /**
37
+ * ProfileStamp component - displays a circular profile picture with a hover card
38
+ * showing the user's name, email, and any custom fields.
39
+ *
40
+ * Use this component to add profile attribution to notes, comments, or any
41
+ * user-generated content in your application.
42
+ *
43
+ * @example
44
+ * // Basic usage
45
+ * <ProfileStamp />
46
+ *
47
+ * @example
48
+ * // With custom fields
49
+ * <ProfileStamp
50
+ * size="lg"
51
+ * custom_fields={[
52
+ * { label: "Role", value: "Admin" },
53
+ * { label: "Department", value: "Engineering" }
54
+ * ]}
55
+ * />
56
+ */
57
+ export declare function ProfileStamp({ size, custom_fields, className, show_name, show_email, }: ProfileStampProps): import("react/jsx-runtime").JSX.Element;
58
+ //# sourceMappingURL=profile_stamp.d.ts.map
@@ -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,2CAqL3E"}
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, ShieldCheck } 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(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(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
  }
@@ -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";
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
3
+ declare const HoverCard: React.FC<HoverCardPrimitive.HoverCardProps>;
4
+ declare const HoverCardTrigger: React.ForwardRefExoticComponent<HoverCardPrimitive.HoverCardTriggerProps & React.RefAttributes<HTMLAnchorElement>>;
5
+ declare const HoverCardContent: React.ForwardRefExoticComponent<Omit<HoverCardPrimitive.HoverCardContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
6
+ export { HoverCard, HoverCardTrigger, HoverCardContent };
7
+ //# sourceMappingURL=hover-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hover-card.d.ts","sourceRoot":"","sources":["../../../src/components/ui/hover-card.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,kBAAkB,MAAM,4BAA4B,CAAA;AAKhE,QAAA,MAAM,SAAS,6CAA0B,CAAA;AAEzC,QAAA,MAAM,gBAAgB,oHAA6B,CAAA;AAEnD,QAAA,MAAM,gBAAgB,oKAcpB,CAAA;AAIF,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAA"}
@@ -0,0 +1,29 @@
1
+ // file_description: HoverCard component from shadcn/ui using Radix UI
2
+ // section: client_directive
3
+ "use client";
4
+ var __rest = (this && this.__rest) || function (s, e) {
5
+ var t = {};
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
7
+ t[p] = s[p];
8
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
9
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
10
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
11
+ t[p[i]] = s[p[i]];
12
+ }
13
+ return t;
14
+ };
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+ // section: imports
17
+ import * as React from "react";
18
+ import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
19
+ import { cn } from "../../lib/utils";
20
+ // section: components
21
+ const HoverCard = HoverCardPrimitive.Root;
22
+ const HoverCardTrigger = HoverCardPrimitive.Trigger;
23
+ const HoverCardContent = React.forwardRef((_a, ref) => {
24
+ var { className, align = "center", sideOffset = 4 } = _a, props = __rest(_a, ["className", "align", "sideOffset"]);
25
+ return (_jsx(HoverCardPrimitive.Content, Object.assign({ ref: ref, align: align, sideOffset: sideOffset, className: cn("z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]", className) }, props)));
26
+ });
27
+ HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
28
+ // section: exports
29
+ export { HoverCard, HoverCardTrigger, HoverCardContent };
@@ -5,6 +5,7 @@ export * from "./checkbox";
5
5
  export * from "./dialog";
6
6
  export * from "./dropdown-menu";
7
7
  export * from "./hazo_ui_tooltip";
8
+ export * from "./hover-card";
8
9
  export * from "./input";
9
10
  export * from "./label";
10
11
  export * from "./separator";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"AAEA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"AAEA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC"}
@@ -7,6 +7,7 @@ export * from "./checkbox";
7
7
  export * from "./dialog";
8
8
  export * from "./dropdown-menu";
9
9
  export * from "./hazo_ui_tooltip";
10
+ export * from "./hover-card";
10
11
  export * from "./input";
11
12
  export * from "./label";
12
13
  export * from "./separator";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -150,6 +150,7 @@
150
150
  "@radix-ui/react-checkbox": "^1.3.3",
151
151
  "@radix-ui/react-dialog": "^1.1.15",
152
152
  "@radix-ui/react-dropdown-menu": "^2.1.16",
153
+ "@radix-ui/react-hover-card": "^1.1.15",
153
154
  "@radix-ui/react-label": "^2.1.8",
154
155
  "@radix-ui/react-select": "^2.2.6",
155
156
  "@radix-ui/react-separator": "^1.1.8",