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.
- package/README.md +82 -8
- package/SETUP_CHECKLIST.md +1 -0
- package/dist/app/api/hazo_auth/me/route.d.ts +3 -0
- package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/me/route.js +9 -1
- package/dist/components/layouts/profile_stamp_test/index.d.ts +10 -0
- package/dist/components/layouts/profile_stamp_test/index.d.ts.map +1 -0
- package/dist/components/layouts/profile_stamp_test/index.js +51 -0
- package/dist/components/layouts/shared/components/profile_stamp.d.ts +58 -0
- package/dist/components/layouts/shared/components/profile_stamp.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/profile_stamp.js +72 -0
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +2 -2
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +3 -0
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -1
- package/dist/components/layouts/shared/hooks/use_auth_status.js +4 -0
- package/dist/components/layouts/shared/index.d.ts +2 -0
- package/dist/components/layouts/shared/index.d.ts.map +1 -1
- package/dist/components/layouts/shared/index.js +1 -0
- package/dist/components/ui/hover-card.d.ts +7 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/hover-card.js +29 -0
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +1 -0
- 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
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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:
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -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
|
|
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:
|
|
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,
|
|
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;
|
|
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;
|
|
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 };
|
|
@@ -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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hazo_auth",
|
|
3
|
-
"version": "4.
|
|
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",
|