@gov-components/layout-header-sidebar 1.0.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 +228 -0
- package/dist/index.d.mts +92 -0
- package/dist/index.d.ts +92 -0
- package/dist/index.js +214 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +206 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Gov Components Layout Header Sidebar
|
|
2
|
+
|
|
3
|
+
Reusable Header and Sidebar layout components designed for Next.js applications, pre-styled with Tailwind CSS. Perfect for government
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Responsive Sidebar**: Automatically collapses on mobile, togglable on desktop.
|
|
8
|
+
- **Notification System**: Built-in notification bell with dropdown list.
|
|
9
|
+
- **User Profile**: Display user avatar, name, and role.
|
|
10
|
+
- **Tailwind CSS**: Beautifully styled using Tailwind utility classes.
|
|
11
|
+
- **TypeScript**: Fully typed for excellent developer experience.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- React 18+
|
|
16
|
+
- Next.js 13+ (App Router recommended)
|
|
17
|
+
- TailwindCSS 3 (Optional, styles are bundled)
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Install the package via npm:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @gov-components/layout-header-sidebar @gov-components/design-tokens
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Setup (Important!)
|
|
28
|
+
|
|
29
|
+
This library relies on `@gov-components/design-tokens` for styling. Ensure you have imported the design tokens in your **root layout** (usually `app/layout.tsx`):
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
// app/layout.tsx
|
|
33
|
+
import "@gov-components/design-tokens/dist/tokens-core.css"; // Essential styles
|
|
34
|
+
import "@gov-components/design-tokens/dist/typography.css"; // Fonts & Typo
|
|
35
|
+
// ... other imports
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If you are using Next.js Transpile Packages (recommended for avoiding build errors):
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
// next.config.ts
|
|
42
|
+
const nextConfig = {
|
|
43
|
+
transpilePackages: ['@gov-components/layout-header-sidebar', '@gov-components/design-tokens'],
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage Guide
|
|
48
|
+
|
|
49
|
+
### 1. Basic Layout Setup
|
|
50
|
+
|
|
51
|
+
Combine `Header` and `SharedSidebar` to create a standard dashboard layout.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
// app/page.tsx
|
|
55
|
+
'use client';
|
|
56
|
+
|
|
57
|
+
import { Header, SharedSidebar, toggleSidebar, MenuItem } from '@gov-components/layout-header-sidebar';
|
|
58
|
+
import { useRouter } from 'next/navigation';
|
|
59
|
+
|
|
60
|
+
export default function Dashboard() {
|
|
61
|
+
const router = useRouter();
|
|
62
|
+
|
|
63
|
+
// 1. Define User Data
|
|
64
|
+
const user = {
|
|
65
|
+
firstName: 'John',
|
|
66
|
+
lastName: 'Doe',
|
|
67
|
+
pictureUrl: 'https://example.com/avatar.jpg',
|
|
68
|
+
role: 'ADMIN' // Optional role badge
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// 2. Define Menu Items
|
|
72
|
+
const menuItems: MenuItem[] = [
|
|
73
|
+
{
|
|
74
|
+
id: 'dashboard',
|
|
75
|
+
title: 'Dashboard',
|
|
76
|
+
path: '/dashboard',
|
|
77
|
+
icon: <span>📊</span> // Can be any React Node (SVG, Icon component)
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'settings',
|
|
81
|
+
title: 'Settings',
|
|
82
|
+
path: '/settings',
|
|
83
|
+
icon: <span>⚙️</span>
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className="min-h-screen bg-gray-50">
|
|
89
|
+
{/* Header Component */}
|
|
90
|
+
<Header
|
|
91
|
+
user={user}
|
|
92
|
+
sidebarId="main-sidebar" // Must match sidebarId in SharedSidebar
|
|
93
|
+
/>
|
|
94
|
+
|
|
95
|
+
{/* Sidebar Component */}
|
|
96
|
+
<SharedSidebar
|
|
97
|
+
user={user}
|
|
98
|
+
menuItems={menuItems}
|
|
99
|
+
sidebarId="main-sidebar"
|
|
100
|
+
profilePath="/profile"
|
|
101
|
+
roleLabel="Administrator"
|
|
102
|
+
roleColor="purple" // teal, purple, orange, blue, green
|
|
103
|
+
onNavigate={(path) => router.push(path)}
|
|
104
|
+
onLogout={() => console.log('User logged out')}
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
{/* Main Content Area */}
|
|
108
|
+
<main className="lg:pl-64 pt-20 p-8 transition-all duration-300">
|
|
109
|
+
<h1>Welcome to Dashboard</h1>
|
|
110
|
+
</main>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 2. Using Notifications
|
|
117
|
+
|
|
118
|
+
The Header component accepts a `notifications` array to display a dropdown.
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import { Header, NotificationItem } from '@gov-components/layout-header-sidebar';
|
|
122
|
+
|
|
123
|
+
const notifications: NotificationItem[] = [
|
|
124
|
+
{
|
|
125
|
+
id: 1,
|
|
126
|
+
title: 'System Update',
|
|
127
|
+
description: 'System maintenance scheduled at midnight.',
|
|
128
|
+
date: '10 mins ago',
|
|
129
|
+
type: 'info', // 'info' | 'success' | 'reminder'
|
|
130
|
+
isRead: false
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: 2,
|
|
134
|
+
title: 'Task Completed',
|
|
135
|
+
description: 'Your export task has finished successfully.',
|
|
136
|
+
date: '1 hour ago',
|
|
137
|
+
type: 'success',
|
|
138
|
+
isRead: true
|
|
139
|
+
}
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
// In your render:
|
|
143
|
+
<Header
|
|
144
|
+
user={user}
|
|
145
|
+
notifications={notifications}
|
|
146
|
+
/>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 3. Toggling Sidebar Programmatically
|
|
150
|
+
|
|
151
|
+
You can control the sidebar state from anywhere in your app using the `toggleSidebar` utility.
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { toggleSidebar } from '@gov-components/layout-header-sidebar';
|
|
155
|
+
|
|
156
|
+
// Toggle default sidebar ('sidebar', 'sidebar-overlay')
|
|
157
|
+
<button onClick={() => toggleSidebar()}>Menu</button>
|
|
158
|
+
|
|
159
|
+
// Toggle specific sidebar ID
|
|
160
|
+
<button onClick={() => toggleSidebar('main-sidebar')}>Menu</button>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## API Reference
|
|
164
|
+
|
|
165
|
+
### `<Header />`
|
|
166
|
+
|
|
167
|
+
Top navigation bar showing user profile, notification bell, and hamburger menu (mobile).
|
|
168
|
+
|
|
169
|
+
| Prop | Type | Default | Description |
|
|
170
|
+
|------|------|---------|-------------|
|
|
171
|
+
| `user` | `User` | - | User information object. |
|
|
172
|
+
| `notifications` | `NotificationItem[]` | `[]` | List of items for notification dropdown. |
|
|
173
|
+
| `sidebarId` | `string` | `'sidebar'` | ID used to toggle the sidebar. |
|
|
174
|
+
| `overlayId` | `string` | `'sidebar-overlay'` | ID used to toggle the overlay. |
|
|
175
|
+
| `notificationBell` | `ReactNode` | - | Custom component to replace the bell icon. |
|
|
176
|
+
|
|
177
|
+
### `<SharedSidebar />`
|
|
178
|
+
|
|
179
|
+
Responsive sidebar navigation with user profile section.
|
|
180
|
+
|
|
181
|
+
| Prop | Type | Default | Description |
|
|
182
|
+
|------|------|---------|-------------|
|
|
183
|
+
| `user` | `User` | - | User information object. |
|
|
184
|
+
| `menuItems` | `MenuItem[]` | `[]` | Array of navigation items. |
|
|
185
|
+
| `onNavigate` | `(path: string) => void` | - | Callback when a menu item is clicked. |
|
|
186
|
+
| `onLogout` | `() => void` | - | Callback when logout button is clicked. |
|
|
187
|
+
| `roleLabel` | `string` | - | Text to display below user name (e.g. "Admin"). |
|
|
188
|
+
| `roleColor` | `string` | `'orange'` | Badge color (`teal`, `blue`, `orange`, `purple`, `green`). |
|
|
189
|
+
| `profilePath` | `string` | - | URL path for the user profile page. |
|
|
190
|
+
| `sidebarId` | `string` | `'sidebar'` | DOM ID for the sidebar container. |
|
|
191
|
+
| `overlayId` | `string` | `'sidebar-overlay'` | DOM ID for the backdrop overlay. |
|
|
192
|
+
|
|
193
|
+
### Type Definitions
|
|
194
|
+
|
|
195
|
+
**User**
|
|
196
|
+
```ts
|
|
197
|
+
interface User {
|
|
198
|
+
firstName?: string;
|
|
199
|
+
lastName?: string;
|
|
200
|
+
pictureUrl?: string;
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**MenuItem**
|
|
205
|
+
```ts
|
|
206
|
+
interface MenuItem {
|
|
207
|
+
id: string;
|
|
208
|
+
title: string;
|
|
209
|
+
path: string;
|
|
210
|
+
icon?: React.ReactNode;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**NotificationItem**
|
|
215
|
+
```ts
|
|
216
|
+
interface NotificationItem {
|
|
217
|
+
id: string | number;
|
|
218
|
+
title: string;
|
|
219
|
+
description: string;
|
|
220
|
+
date: string;
|
|
221
|
+
type: 'reminder' | 'success' | 'info';
|
|
222
|
+
isRead?: boolean;
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface NotificationItem {
|
|
4
|
+
id: string | number;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
date: string;
|
|
8
|
+
type: 'info' | 'success' | 'warning' | 'error' | 'reminder';
|
|
9
|
+
isRead: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface MenuItem {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
path: string;
|
|
16
|
+
icon: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
interface MenuListProps {
|
|
19
|
+
menuItems: MenuItem[];
|
|
20
|
+
onItemClick: (path: string) => void;
|
|
21
|
+
itemClassName?: string;
|
|
22
|
+
}
|
|
23
|
+
declare function MenuList({ menuItems, onItemClick, itemClassName }: MenuListProps): react_jsx_runtime.JSX.Element;
|
|
24
|
+
|
|
25
|
+
interface User$1 {
|
|
26
|
+
id?: string | number;
|
|
27
|
+
firstName?: string;
|
|
28
|
+
lastName?: string;
|
|
29
|
+
pictureUrl?: string;
|
|
30
|
+
role?: string;
|
|
31
|
+
}
|
|
32
|
+
interface SharedSidebarProps {
|
|
33
|
+
user: User$1 | null;
|
|
34
|
+
menuItems: MenuItem[];
|
|
35
|
+
sidebarId?: string;
|
|
36
|
+
overlayId?: string;
|
|
37
|
+
roleLabel: string;
|
|
38
|
+
roleColor?: string;
|
|
39
|
+
onNavigate: (path: string) => void;
|
|
40
|
+
onLogout: () => void;
|
|
41
|
+
className?: string;
|
|
42
|
+
menuItemClassName?: string;
|
|
43
|
+
logoutButtonClassName?: string;
|
|
44
|
+
userProfileClassName?: string;
|
|
45
|
+
userAvatarClassName?: string;
|
|
46
|
+
userTextClassName?: string;
|
|
47
|
+
}
|
|
48
|
+
declare function SharedSidebar({ user, menuItems, sidebarId, overlayId, roleLabel, roleColor, onNavigate, onLogout, className, menuItemClassName, logoutButtonClassName, userProfileClassName, userAvatarClassName, userTextClassName }: SharedSidebarProps): react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
interface User {
|
|
51
|
+
id?: string | number;
|
|
52
|
+
firstName?: string;
|
|
53
|
+
lastName?: string;
|
|
54
|
+
pictureUrl?: string;
|
|
55
|
+
role?: string;
|
|
56
|
+
}
|
|
57
|
+
interface UserProfileProps {
|
|
58
|
+
user: User | null;
|
|
59
|
+
roleLabel: string;
|
|
60
|
+
roleColor?: string;
|
|
61
|
+
className?: string;
|
|
62
|
+
avatarClassName?: string;
|
|
63
|
+
textClassName?: string;
|
|
64
|
+
}
|
|
65
|
+
declare function UserProfile({ user, roleLabel, roleColor, className, avatarClassName, textClassName }: UserProfileProps): react_jsx_runtime.JSX.Element | null;
|
|
66
|
+
|
|
67
|
+
interface LogoutButtonProps {
|
|
68
|
+
onLogout: () => void;
|
|
69
|
+
className?: string;
|
|
70
|
+
}
|
|
71
|
+
declare function LogoutButton({ onLogout, className }: LogoutButtonProps): react_jsx_runtime.JSX.Element;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Toggle sidebar visibility (Right side)
|
|
75
|
+
* @param sidebarId - ID of the sidebar element
|
|
76
|
+
* @param overlayId - ID of the overlay element
|
|
77
|
+
*/
|
|
78
|
+
declare function toggleSidebar(sidebarId?: string, overlayId?: string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Close sidebar (Right side)
|
|
81
|
+
* @param sidebarId - ID of the sidebar element
|
|
82
|
+
* @param overlayId - ID of the overlay element
|
|
83
|
+
*/
|
|
84
|
+
declare function closeSidebar(sidebarId?: string, overlayId?: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Open sidebar (Right side)
|
|
87
|
+
* @param sidebarId - ID of the sidebar element
|
|
88
|
+
* @param overlayId - ID of the overlay element
|
|
89
|
+
*/
|
|
90
|
+
declare function openSidebar(sidebarId?: string, overlayId?: string): void;
|
|
91
|
+
|
|
92
|
+
export { LogoutButton, type MenuItem, MenuList, type NotificationItem, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface NotificationItem {
|
|
4
|
+
id: string | number;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
date: string;
|
|
8
|
+
type: 'info' | 'success' | 'warning' | 'error' | 'reminder';
|
|
9
|
+
isRead: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface MenuItem {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
path: string;
|
|
16
|
+
icon: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
interface MenuListProps {
|
|
19
|
+
menuItems: MenuItem[];
|
|
20
|
+
onItemClick: (path: string) => void;
|
|
21
|
+
itemClassName?: string;
|
|
22
|
+
}
|
|
23
|
+
declare function MenuList({ menuItems, onItemClick, itemClassName }: MenuListProps): react_jsx_runtime.JSX.Element;
|
|
24
|
+
|
|
25
|
+
interface User$1 {
|
|
26
|
+
id?: string | number;
|
|
27
|
+
firstName?: string;
|
|
28
|
+
lastName?: string;
|
|
29
|
+
pictureUrl?: string;
|
|
30
|
+
role?: string;
|
|
31
|
+
}
|
|
32
|
+
interface SharedSidebarProps {
|
|
33
|
+
user: User$1 | null;
|
|
34
|
+
menuItems: MenuItem[];
|
|
35
|
+
sidebarId?: string;
|
|
36
|
+
overlayId?: string;
|
|
37
|
+
roleLabel: string;
|
|
38
|
+
roleColor?: string;
|
|
39
|
+
onNavigate: (path: string) => void;
|
|
40
|
+
onLogout: () => void;
|
|
41
|
+
className?: string;
|
|
42
|
+
menuItemClassName?: string;
|
|
43
|
+
logoutButtonClassName?: string;
|
|
44
|
+
userProfileClassName?: string;
|
|
45
|
+
userAvatarClassName?: string;
|
|
46
|
+
userTextClassName?: string;
|
|
47
|
+
}
|
|
48
|
+
declare function SharedSidebar({ user, menuItems, sidebarId, overlayId, roleLabel, roleColor, onNavigate, onLogout, className, menuItemClassName, logoutButtonClassName, userProfileClassName, userAvatarClassName, userTextClassName }: SharedSidebarProps): react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
interface User {
|
|
51
|
+
id?: string | number;
|
|
52
|
+
firstName?: string;
|
|
53
|
+
lastName?: string;
|
|
54
|
+
pictureUrl?: string;
|
|
55
|
+
role?: string;
|
|
56
|
+
}
|
|
57
|
+
interface UserProfileProps {
|
|
58
|
+
user: User | null;
|
|
59
|
+
roleLabel: string;
|
|
60
|
+
roleColor?: string;
|
|
61
|
+
className?: string;
|
|
62
|
+
avatarClassName?: string;
|
|
63
|
+
textClassName?: string;
|
|
64
|
+
}
|
|
65
|
+
declare function UserProfile({ user, roleLabel, roleColor, className, avatarClassName, textClassName }: UserProfileProps): react_jsx_runtime.JSX.Element | null;
|
|
66
|
+
|
|
67
|
+
interface LogoutButtonProps {
|
|
68
|
+
onLogout: () => void;
|
|
69
|
+
className?: string;
|
|
70
|
+
}
|
|
71
|
+
declare function LogoutButton({ onLogout, className }: LogoutButtonProps): react_jsx_runtime.JSX.Element;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Toggle sidebar visibility (Right side)
|
|
75
|
+
* @param sidebarId - ID of the sidebar element
|
|
76
|
+
* @param overlayId - ID of the overlay element
|
|
77
|
+
*/
|
|
78
|
+
declare function toggleSidebar(sidebarId?: string, overlayId?: string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Close sidebar (Right side)
|
|
81
|
+
* @param sidebarId - ID of the sidebar element
|
|
82
|
+
* @param overlayId - ID of the overlay element
|
|
83
|
+
*/
|
|
84
|
+
declare function closeSidebar(sidebarId?: string, overlayId?: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Open sidebar (Right side)
|
|
87
|
+
* @param sidebarId - ID of the sidebar element
|
|
88
|
+
* @param overlayId - ID of the overlay element
|
|
89
|
+
*/
|
|
90
|
+
declare function openSidebar(sidebarId?: string, overlayId?: string): void;
|
|
91
|
+
|
|
92
|
+
export { LogoutButton, type MenuItem, MenuList, type NotificationItem, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('react');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
|
|
6
|
+
// src/header/Header.tsx
|
|
7
|
+
|
|
8
|
+
// src/sidebar/utils.ts
|
|
9
|
+
function toggleSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
10
|
+
const sidebar = document.getElementById(sidebarId);
|
|
11
|
+
const overlay = document.getElementById(overlayId);
|
|
12
|
+
if (sidebar && overlay) {
|
|
13
|
+
const isOpen = sidebar.classList.contains("translate-x-0");
|
|
14
|
+
if (isOpen) {
|
|
15
|
+
sidebar.classList.remove("translate-x-0");
|
|
16
|
+
sidebar.classList.add("translate-x-full");
|
|
17
|
+
overlay.classList.add("hidden");
|
|
18
|
+
} else {
|
|
19
|
+
sidebar.classList.remove("translate-x-full");
|
|
20
|
+
sidebar.classList.add("translate-x-0");
|
|
21
|
+
overlay.classList.remove("hidden");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function closeSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
26
|
+
const sidebar = document.getElementById(sidebarId);
|
|
27
|
+
const overlay = document.getElementById(overlayId);
|
|
28
|
+
if (sidebar) {
|
|
29
|
+
sidebar.classList.remove("translate-x-0");
|
|
30
|
+
sidebar.classList.add("translate-x-full");
|
|
31
|
+
}
|
|
32
|
+
if (overlay) {
|
|
33
|
+
overlay.classList.add("hidden");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function openSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
37
|
+
const sidebar = document.getElementById(sidebarId);
|
|
38
|
+
const overlay = document.getElementById(overlayId);
|
|
39
|
+
if (sidebar) {
|
|
40
|
+
sidebar.classList.remove("translate-x-full");
|
|
41
|
+
sidebar.classList.add("translate-x-0");
|
|
42
|
+
}
|
|
43
|
+
if (overlay) {
|
|
44
|
+
overlay.classList.remove("hidden");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function UserProfile({
|
|
48
|
+
user,
|
|
49
|
+
roleLabel,
|
|
50
|
+
roleColor = "orange",
|
|
51
|
+
className = "",
|
|
52
|
+
avatarClassName = "",
|
|
53
|
+
textClassName = ""
|
|
54
|
+
}) {
|
|
55
|
+
if (!user) return null;
|
|
56
|
+
const getFullName = () => {
|
|
57
|
+
if (user.firstName && user.lastName) {
|
|
58
|
+
return `${user.firstName} ${user.lastName}`;
|
|
59
|
+
}
|
|
60
|
+
return user.firstName || user.lastName || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
|
|
61
|
+
};
|
|
62
|
+
const getInitial = () => {
|
|
63
|
+
return user.firstName?.charAt(0) || user.lastName?.charAt(0) || "?";
|
|
64
|
+
};
|
|
65
|
+
const getRoleColorClass = () => {
|
|
66
|
+
const colors = {
|
|
67
|
+
orange: "bg-orange-500",
|
|
68
|
+
teal: "bg-teal-500",
|
|
69
|
+
blue: "bg-blue-500",
|
|
70
|
+
green: "bg-green-500",
|
|
71
|
+
purple: "bg-purple-500"
|
|
72
|
+
};
|
|
73
|
+
return colors[roleColor] || "bg-orange-500";
|
|
74
|
+
};
|
|
75
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `p-5 border-b border-gray-200 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
76
|
+
user.pictureUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
77
|
+
"img",
|
|
78
|
+
{
|
|
79
|
+
src: user.pictureUrl,
|
|
80
|
+
alt: getFullName(),
|
|
81
|
+
width: 56,
|
|
82
|
+
height: 56,
|
|
83
|
+
className: `w-14 h-14 rounded-full shadow-lg object-cover ${avatarClassName}`
|
|
84
|
+
}
|
|
85
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-14 h-14 bg-gradient-to-br from-teal-400 to-teal-600 rounded-full flex items-center justify-center text-white font-bold shadow-lg text-xl ${avatarClassName}`, children: getInitial() }),
|
|
86
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex-1 min-w-0 ${textClassName}`, children: [
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-bold text-gray-900 truncate text-base", children: getFullName() }),
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 flex items-center gap-1", children: [
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `w-2 h-2 ${getRoleColorClass()} rounded-full` }),
|
|
90
|
+
roleLabel
|
|
91
|
+
] })
|
|
92
|
+
] })
|
|
93
|
+
] }) });
|
|
94
|
+
}
|
|
95
|
+
function MenuList({ menuItems, onItemClick, itemClassName = "" }) {
|
|
96
|
+
return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex-1 p-5 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1", children: menuItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
97
|
+
"button",
|
|
98
|
+
{
|
|
99
|
+
onClick: () => onItemClick(item.path),
|
|
100
|
+
className: `w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors ${itemClassName}`,
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 flex items-center justify-center text-gray-600 flex-shrink-0", children: item.icon }),
|
|
103
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left font-medium text-base", children: item.title })
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
) }, item.id)) }) });
|
|
107
|
+
}
|
|
108
|
+
function LogoutButton({ onLogout, className = "" }) {
|
|
109
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-5 border-t border-gray-200", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
110
|
+
"button",
|
|
111
|
+
{
|
|
112
|
+
onClick: onLogout,
|
|
113
|
+
className: `w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-red-600 hover:bg-red-50 transition-colors ${className}`,
|
|
114
|
+
children: [
|
|
115
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
116
|
+
"path",
|
|
117
|
+
{
|
|
118
|
+
strokeLinecap: "round",
|
|
119
|
+
strokeLinejoin: "round",
|
|
120
|
+
strokeWidth: 2,
|
|
121
|
+
d: "M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
|
|
122
|
+
}
|
|
123
|
+
) }),
|
|
124
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left font-medium text-base", children: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A" })
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
) });
|
|
128
|
+
}
|
|
129
|
+
function SharedSidebar({
|
|
130
|
+
user,
|
|
131
|
+
menuItems,
|
|
132
|
+
sidebarId = "sidebar",
|
|
133
|
+
overlayId = "sidebar-overlay",
|
|
134
|
+
roleLabel,
|
|
135
|
+
roleColor = "orange",
|
|
136
|
+
onNavigate,
|
|
137
|
+
onLogout,
|
|
138
|
+
// Styles
|
|
139
|
+
className = "",
|
|
140
|
+
menuItemClassName = "",
|
|
141
|
+
logoutButtonClassName = "",
|
|
142
|
+
userProfileClassName = "",
|
|
143
|
+
userAvatarClassName = "",
|
|
144
|
+
userTextClassName = ""
|
|
145
|
+
}) {
|
|
146
|
+
const closeSidebar2 = () => {
|
|
147
|
+
const sidebar = document.getElementById(sidebarId);
|
|
148
|
+
if (sidebar) {
|
|
149
|
+
sidebar.classList.add("translate-x-full");
|
|
150
|
+
sidebar.classList.remove("translate-x-0");
|
|
151
|
+
}
|
|
152
|
+
const overlay = document.getElementById(overlayId);
|
|
153
|
+
if (overlay) {
|
|
154
|
+
overlay.classList.add("hidden");
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const handleMenuItemClick = (path) => {
|
|
158
|
+
onNavigate(path);
|
|
159
|
+
closeSidebar2();
|
|
160
|
+
};
|
|
161
|
+
const handleLogout = () => {
|
|
162
|
+
closeSidebar2();
|
|
163
|
+
onLogout();
|
|
164
|
+
};
|
|
165
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
166
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
167
|
+
"div",
|
|
168
|
+
{
|
|
169
|
+
id: overlayId,
|
|
170
|
+
className: "fixed inset-0 bg-black/50 z-40 hidden",
|
|
171
|
+
onClick: closeSidebar2
|
|
172
|
+
}
|
|
173
|
+
),
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
175
|
+
"aside",
|
|
176
|
+
{
|
|
177
|
+
id: sidebarId,
|
|
178
|
+
className: `fixed top-0 right-0 h-full w-[80vw] max-w-80 bg-white shadow-2xl z-50 transform translate-x-full transition-transform duration-300 flex flex-col ${className}`,
|
|
179
|
+
children: [
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
+
UserProfile,
|
|
182
|
+
{
|
|
183
|
+
user,
|
|
184
|
+
roleLabel,
|
|
185
|
+
roleColor,
|
|
186
|
+
className: userProfileClassName,
|
|
187
|
+
avatarClassName: userAvatarClassName,
|
|
188
|
+
textClassName: userTextClassName
|
|
189
|
+
}
|
|
190
|
+
),
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
192
|
+
MenuList,
|
|
193
|
+
{
|
|
194
|
+
menuItems,
|
|
195
|
+
onItemClick: handleMenuItemClick,
|
|
196
|
+
itemClassName: menuItemClassName
|
|
197
|
+
}
|
|
198
|
+
),
|
|
199
|
+
/* @__PURE__ */ jsxRuntime.jsx(LogoutButton, { onLogout: handleLogout, className: logoutButtonClassName })
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
] });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
exports.LogoutButton = LogoutButton;
|
|
207
|
+
exports.MenuList = MenuList;
|
|
208
|
+
exports.SharedSidebar = SharedSidebar;
|
|
209
|
+
exports.UserProfile = UserProfile;
|
|
210
|
+
exports.closeSidebar = closeSidebar;
|
|
211
|
+
exports.openSidebar = openSidebar;
|
|
212
|
+
exports.toggleSidebar = toggleSidebar;
|
|
213
|
+
//# sourceMappingURL=index.js.map
|
|
214
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sidebar/utils.ts","../src/sidebar/UserProfile.tsx","../src/sidebar/MenuList.tsx","../src/sidebar/LogoutButton.tsx","../src/sidebar/SharedSidebar.tsx"],"names":["jsx","jsxs","closeSidebar","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Toggle sidebar visibility (Right side)\r\n * @param sidebarId - ID of the sidebar element\r\n * @param overlayId - ID of the overlay element\r\n */\r\nexport function toggleSidebar(sidebarId: string = 'sidebar', overlayId: string = 'sidebar-overlay') {\r\n const sidebar = document.getElementById(sidebarId);\r\n const overlay = document.getElementById(overlayId);\r\n\r\n if (sidebar && overlay) {\r\n const isOpen = sidebar.classList.contains('translate-x-0');\r\n\r\n if (isOpen) {\r\n // Close sidebar (slide to right)\r\n sidebar.classList.remove('translate-x-0');\r\n sidebar.classList.add('translate-x-full');\r\n overlay.classList.add('hidden');\r\n } else {\r\n // Open sidebar (slide from right)\r\n sidebar.classList.remove('translate-x-full');\r\n sidebar.classList.add('translate-x-0');\r\n overlay.classList.remove('hidden');\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Close sidebar (Right side)\r\n * @param sidebarId - ID of the sidebar element\r\n * @param overlayId - ID of the overlay element\r\n */\r\nexport function closeSidebar(sidebarId: string = 'sidebar', overlayId: string = 'sidebar-overlay') {\r\n const sidebar = document.getElementById(sidebarId);\r\n const overlay = document.getElementById(overlayId);\r\n\r\n if (sidebar) {\r\n sidebar.classList.remove('translate-x-0');\r\n sidebar.classList.add('translate-x-full');\r\n }\r\n\r\n if (overlay) {\r\n overlay.classList.add('hidden');\r\n }\r\n}\r\n\r\n/**\r\n * Open sidebar (Right side)\r\n * @param sidebarId - ID of the sidebar element\r\n * @param overlayId - ID of the overlay element\r\n */\r\nexport function openSidebar(sidebarId: string = 'sidebar', overlayId: string = 'sidebar-overlay') {\r\n const sidebar = document.getElementById(sidebarId);\r\n const overlay = document.getElementById(overlayId);\r\n\r\n if (sidebar) {\r\n sidebar.classList.remove('translate-x-full');\r\n sidebar.classList.add('translate-x-0');\r\n }\r\n\r\n if (overlay) {\r\n overlay.classList.remove('hidden');\r\n }\r\n}\r\n","'use client';\r\n\r\ninterface User {\r\n id?: string | number;\r\n firstName?: string;\r\n lastName?: string;\r\n pictureUrl?: string;\r\n role?: string;\r\n}\r\n\r\ninterface UserProfileProps {\r\n user: User | null;\r\n roleLabel: string;\r\n roleColor?: string;\r\n // Styling\r\n className?: string;\r\n avatarClassName?: string;\r\n textClassName?: string;\r\n}\r\n\r\nexport default function UserProfile({\r\n user,\r\n roleLabel,\r\n roleColor = 'orange',\r\n className = '',\r\n avatarClassName = '',\r\n textClassName = ''\r\n}: UserProfileProps) {\r\n if (!user) return null;\r\n\r\n const getFullName = () => {\r\n if (user.firstName && user.lastName) {\r\n return `${user.firstName} ${user.lastName}`;\r\n }\r\n return user.firstName || user.lastName || 'ผู้ใช้';\r\n };\r\n\r\n const getInitial = () => {\r\n return user.firstName?.charAt(0) || user.lastName?.charAt(0) || '?';\r\n };\r\n\r\n const getRoleColorClass = () => {\r\n const colors: Record<string, string> = {\r\n orange: 'bg-orange-500',\r\n teal: 'bg-teal-500',\r\n blue: 'bg-blue-500',\r\n green: 'bg-green-500',\r\n purple: 'bg-purple-500',\r\n };\r\n return colors[roleColor] || 'bg-orange-500';\r\n };\r\n\r\n return (\r\n <div className={`p-5 border-b border-gray-200 ${className}`}>\r\n <div className=\"flex items-center gap-3\">\r\n {user.pictureUrl ? (\r\n <img\r\n src={user.pictureUrl}\r\n alt={getFullName()}\r\n width={56}\r\n height={56}\r\n className={`w-14 h-14 rounded-full shadow-lg object-cover ${avatarClassName}`}\r\n />\r\n ) : (\r\n <div className={`w-14 h-14 bg-gradient-to-br from-teal-400 to-teal-600 rounded-full flex items-center justify-center text-white font-bold shadow-lg text-xl ${avatarClassName}`}>\r\n {getInitial()}\r\n </div>\r\n )}\r\n <div className={`flex-1 min-w-0 ${textClassName}`}>\r\n <p className=\"font-bold text-gray-900 truncate text-base\">\r\n {getFullName()}\r\n </p>\r\n <p className=\"text-sm text-gray-500 flex items-center gap-1\">\r\n <span className={`w-2 h-2 ${getRoleColorClass()} rounded-full`}></span>\r\n {roleLabel}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","'use client';\r\n\r\nexport interface MenuItem {\r\n id: string;\r\n title: string;\r\n path: string;\r\n icon: React.ReactNode;\r\n}\r\n\r\ninterface MenuListProps {\r\n menuItems: MenuItem[];\r\n onItemClick: (path: string) => void;\r\n itemClassName?: string;\r\n}\r\n\r\nexport default function MenuList({ menuItems, onItemClick, itemClassName = '' }: MenuListProps) {\r\n return (\r\n <nav className=\"flex-1 p-5 overflow-y-auto\">\r\n <ul className=\"space-y-1\">\r\n {menuItems.map((item) => (\r\n <li key={item.id}>\r\n <button\r\n onClick={() => onItemClick(item.path)}\r\n className={`w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors ${itemClassName}`}\r\n >\r\n <div className=\"w-8 h-8 flex items-center justify-center text-gray-600 flex-shrink-0\">{item.icon}</div>\r\n <span className=\"flex-1 text-left font-medium text-base\">\r\n {item.title}\r\n </span>\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n </nav>\r\n );\r\n}\r\n","'use client';\r\n\r\ninterface LogoutButtonProps {\r\n onLogout: () => void;\r\n className?: string;\r\n}\r\n\r\nexport default function LogoutButton({ onLogout, className = '' }: LogoutButtonProps) {\r\n return (\r\n <div className=\"p-5 border-t border-gray-200\">\r\n <button\r\n onClick={onLogout}\r\n className={`w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-red-600 hover:bg-red-50 transition-colors ${className}`}\r\n >\r\n <svg className=\"w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1\"\r\n />\r\n </svg>\r\n <span className=\"flex-1 text-left font-medium text-base\">ออกจากระบบ</span>\r\n </button>\r\n </div>\r\n );\r\n}\r\n","'use client';\r\n\r\nimport UserProfile from './UserProfile';\r\n\r\nimport MenuList from './MenuList';\r\nimport LogoutButton from './LogoutButton';\r\nimport type { MenuItem } from './MenuList';\r\n\r\ninterface User {\r\n id?: string | number;\r\n firstName?: string;\r\n lastName?: string;\r\n pictureUrl?: string;\r\n role?: string;\r\n}\r\n\r\ninterface SharedSidebarProps {\r\n user: User | null;\r\n menuItems: MenuItem[];\r\n sidebarId?: string;\r\n overlayId?: string;\r\n\r\n roleLabel: string;\r\n roleColor?: string;\r\n onNavigate: (path: string) => void;\r\n onLogout: () => void;\r\n // Customization Props\r\n className?: string; // Sidebar container\r\n menuItemClassName?: string;\r\n logoutButtonClassName?: string;\r\n // UserProfile Customization via Sidebar\r\n userProfileClassName?: string;\r\n userAvatarClassName?: string;\r\n userTextClassName?: string;\r\n}\r\n\r\nexport default function SharedSidebar({\r\n user,\r\n menuItems,\r\n sidebarId = 'sidebar',\r\n overlayId = 'sidebar-overlay',\r\n\r\n roleLabel,\r\n roleColor = 'orange',\r\n onNavigate,\r\n onLogout,\r\n // Styles\r\n className = '',\r\n menuItemClassName = '',\r\n logoutButtonClassName = '',\r\n userProfileClassName = '',\r\n userAvatarClassName = '',\r\n userTextClassName = ''\r\n}: SharedSidebarProps) {\r\n\r\n const closeSidebar = () => {\r\n const sidebar = document.getElementById(sidebarId);\r\n if (sidebar) {\r\n sidebar.classList.add('translate-x-full');\r\n sidebar.classList.remove('translate-x-0');\r\n }\r\n const overlay = document.getElementById(overlayId);\r\n if (overlay) {\r\n overlay.classList.add('hidden');\r\n }\r\n };\r\n\r\n const handleMenuItemClick = (path: string) => {\r\n onNavigate(path);\r\n closeSidebar();\r\n };\r\n\r\n const handleLogout = () => {\r\n closeSidebar();\r\n onLogout();\r\n };\r\n\r\n return (\r\n <>\r\n {/* Overlay */}\r\n <div\r\n id={overlayId}\r\n className=\"fixed inset-0 bg-black/50 z-40 hidden\"\r\n onClick={closeSidebar}\r\n />\r\n\r\n {/* Sidebar - Hidden by default, opened via toggle button in header */}\r\n <aside\r\n id={sidebarId}\r\n className={`fixed top-0 right-0 h-full w-[80vw] max-w-80 bg-white shadow-2xl z-50 transform translate-x-full transition-transform duration-300 flex flex-col ${className}`}>\r\n\r\n {/* User Profile Section */}\r\n <UserProfile\r\n user={user}\r\n roleLabel={roleLabel}\r\n roleColor={roleColor}\r\n className={userProfileClassName}\r\n avatarClassName={userAvatarClassName}\r\n textClassName={userTextClassName}\r\n />\r\n\r\n {/* Menu Items */}\r\n <MenuList\r\n menuItems={menuItems}\r\n onItemClick={handleMenuItemClick}\r\n itemClassName={menuItemClassName}\r\n />\r\n\r\n {/* Logout Button */}\r\n <LogoutButton onLogout={handleLogout} className={logoutButtonClassName} />\r\n </aside>\r\n </>\r\n );\r\n}\r\n\r\n// Re-export MenuItem type for convenience\r\nexport type { MenuItem };\r\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import 'react';
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// src/header/Header.tsx
|
|
5
|
+
|
|
6
|
+
// src/sidebar/utils.ts
|
|
7
|
+
function toggleSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
8
|
+
const sidebar = document.getElementById(sidebarId);
|
|
9
|
+
const overlay = document.getElementById(overlayId);
|
|
10
|
+
if (sidebar && overlay) {
|
|
11
|
+
const isOpen = sidebar.classList.contains("translate-x-0");
|
|
12
|
+
if (isOpen) {
|
|
13
|
+
sidebar.classList.remove("translate-x-0");
|
|
14
|
+
sidebar.classList.add("translate-x-full");
|
|
15
|
+
overlay.classList.add("hidden");
|
|
16
|
+
} else {
|
|
17
|
+
sidebar.classList.remove("translate-x-full");
|
|
18
|
+
sidebar.classList.add("translate-x-0");
|
|
19
|
+
overlay.classList.remove("hidden");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function closeSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
24
|
+
const sidebar = document.getElementById(sidebarId);
|
|
25
|
+
const overlay = document.getElementById(overlayId);
|
|
26
|
+
if (sidebar) {
|
|
27
|
+
sidebar.classList.remove("translate-x-0");
|
|
28
|
+
sidebar.classList.add("translate-x-full");
|
|
29
|
+
}
|
|
30
|
+
if (overlay) {
|
|
31
|
+
overlay.classList.add("hidden");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function openSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
35
|
+
const sidebar = document.getElementById(sidebarId);
|
|
36
|
+
const overlay = document.getElementById(overlayId);
|
|
37
|
+
if (sidebar) {
|
|
38
|
+
sidebar.classList.remove("translate-x-full");
|
|
39
|
+
sidebar.classList.add("translate-x-0");
|
|
40
|
+
}
|
|
41
|
+
if (overlay) {
|
|
42
|
+
overlay.classList.remove("hidden");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function UserProfile({
|
|
46
|
+
user,
|
|
47
|
+
roleLabel,
|
|
48
|
+
roleColor = "orange",
|
|
49
|
+
className = "",
|
|
50
|
+
avatarClassName = "",
|
|
51
|
+
textClassName = ""
|
|
52
|
+
}) {
|
|
53
|
+
if (!user) return null;
|
|
54
|
+
const getFullName = () => {
|
|
55
|
+
if (user.firstName && user.lastName) {
|
|
56
|
+
return `${user.firstName} ${user.lastName}`;
|
|
57
|
+
}
|
|
58
|
+
return user.firstName || user.lastName || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
|
|
59
|
+
};
|
|
60
|
+
const getInitial = () => {
|
|
61
|
+
return user.firstName?.charAt(0) || user.lastName?.charAt(0) || "?";
|
|
62
|
+
};
|
|
63
|
+
const getRoleColorClass = () => {
|
|
64
|
+
const colors = {
|
|
65
|
+
orange: "bg-orange-500",
|
|
66
|
+
teal: "bg-teal-500",
|
|
67
|
+
blue: "bg-blue-500",
|
|
68
|
+
green: "bg-green-500",
|
|
69
|
+
purple: "bg-purple-500"
|
|
70
|
+
};
|
|
71
|
+
return colors[roleColor] || "bg-orange-500";
|
|
72
|
+
};
|
|
73
|
+
return /* @__PURE__ */ jsx("div", { className: `p-5 border-b border-gray-200 ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
74
|
+
user.pictureUrl ? /* @__PURE__ */ jsx(
|
|
75
|
+
"img",
|
|
76
|
+
{
|
|
77
|
+
src: user.pictureUrl,
|
|
78
|
+
alt: getFullName(),
|
|
79
|
+
width: 56,
|
|
80
|
+
height: 56,
|
|
81
|
+
className: `w-14 h-14 rounded-full shadow-lg object-cover ${avatarClassName}`
|
|
82
|
+
}
|
|
83
|
+
) : /* @__PURE__ */ jsx("div", { className: `w-14 h-14 bg-gradient-to-br from-teal-400 to-teal-600 rounded-full flex items-center justify-center text-white font-bold shadow-lg text-xl ${avatarClassName}`, children: getInitial() }),
|
|
84
|
+
/* @__PURE__ */ jsxs("div", { className: `flex-1 min-w-0 ${textClassName}`, children: [
|
|
85
|
+
/* @__PURE__ */ jsx("p", { className: "font-bold text-gray-900 truncate text-base", children: getFullName() }),
|
|
86
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 flex items-center gap-1", children: [
|
|
87
|
+
/* @__PURE__ */ jsx("span", { className: `w-2 h-2 ${getRoleColorClass()} rounded-full` }),
|
|
88
|
+
roleLabel
|
|
89
|
+
] })
|
|
90
|
+
] })
|
|
91
|
+
] }) });
|
|
92
|
+
}
|
|
93
|
+
function MenuList({ menuItems, onItemClick, itemClassName = "" }) {
|
|
94
|
+
return /* @__PURE__ */ jsx("nav", { className: "flex-1 p-5 overflow-y-auto", children: /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: menuItems.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
95
|
+
"button",
|
|
96
|
+
{
|
|
97
|
+
onClick: () => onItemClick(item.path),
|
|
98
|
+
className: `w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors ${itemClassName}`,
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ jsx("div", { className: "w-8 h-8 flex items-center justify-center text-gray-600 flex-shrink-0", children: item.icon }),
|
|
101
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left font-medium text-base", children: item.title })
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
) }, item.id)) }) });
|
|
105
|
+
}
|
|
106
|
+
function LogoutButton({ onLogout, className = "" }) {
|
|
107
|
+
return /* @__PURE__ */ jsx("div", { className: "p-5 border-t border-gray-200", children: /* @__PURE__ */ jsxs(
|
|
108
|
+
"button",
|
|
109
|
+
{
|
|
110
|
+
onClick: onLogout,
|
|
111
|
+
className: `w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-red-600 hover:bg-red-50 transition-colors ${className}`,
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ jsx("svg", { className: "w-5 h-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ jsx(
|
|
114
|
+
"path",
|
|
115
|
+
{
|
|
116
|
+
strokeLinecap: "round",
|
|
117
|
+
strokeLinejoin: "round",
|
|
118
|
+
strokeWidth: 2,
|
|
119
|
+
d: "M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
|
|
120
|
+
}
|
|
121
|
+
) }),
|
|
122
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left font-medium text-base", children: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A" })
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
) });
|
|
126
|
+
}
|
|
127
|
+
function SharedSidebar({
|
|
128
|
+
user,
|
|
129
|
+
menuItems,
|
|
130
|
+
sidebarId = "sidebar",
|
|
131
|
+
overlayId = "sidebar-overlay",
|
|
132
|
+
roleLabel,
|
|
133
|
+
roleColor = "orange",
|
|
134
|
+
onNavigate,
|
|
135
|
+
onLogout,
|
|
136
|
+
// Styles
|
|
137
|
+
className = "",
|
|
138
|
+
menuItemClassName = "",
|
|
139
|
+
logoutButtonClassName = "",
|
|
140
|
+
userProfileClassName = "",
|
|
141
|
+
userAvatarClassName = "",
|
|
142
|
+
userTextClassName = ""
|
|
143
|
+
}) {
|
|
144
|
+
const closeSidebar2 = () => {
|
|
145
|
+
const sidebar = document.getElementById(sidebarId);
|
|
146
|
+
if (sidebar) {
|
|
147
|
+
sidebar.classList.add("translate-x-full");
|
|
148
|
+
sidebar.classList.remove("translate-x-0");
|
|
149
|
+
}
|
|
150
|
+
const overlay = document.getElementById(overlayId);
|
|
151
|
+
if (overlay) {
|
|
152
|
+
overlay.classList.add("hidden");
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const handleMenuItemClick = (path) => {
|
|
156
|
+
onNavigate(path);
|
|
157
|
+
closeSidebar2();
|
|
158
|
+
};
|
|
159
|
+
const handleLogout = () => {
|
|
160
|
+
closeSidebar2();
|
|
161
|
+
onLogout();
|
|
162
|
+
};
|
|
163
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
164
|
+
/* @__PURE__ */ jsx(
|
|
165
|
+
"div",
|
|
166
|
+
{
|
|
167
|
+
id: overlayId,
|
|
168
|
+
className: "fixed inset-0 bg-black/50 z-40 hidden",
|
|
169
|
+
onClick: closeSidebar2
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
/* @__PURE__ */ jsxs(
|
|
173
|
+
"aside",
|
|
174
|
+
{
|
|
175
|
+
id: sidebarId,
|
|
176
|
+
className: `fixed top-0 right-0 h-full w-[80vw] max-w-80 bg-white shadow-2xl z-50 transform translate-x-full transition-transform duration-300 flex flex-col ${className}`,
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
UserProfile,
|
|
180
|
+
{
|
|
181
|
+
user,
|
|
182
|
+
roleLabel,
|
|
183
|
+
roleColor,
|
|
184
|
+
className: userProfileClassName,
|
|
185
|
+
avatarClassName: userAvatarClassName,
|
|
186
|
+
textClassName: userTextClassName
|
|
187
|
+
}
|
|
188
|
+
),
|
|
189
|
+
/* @__PURE__ */ jsx(
|
|
190
|
+
MenuList,
|
|
191
|
+
{
|
|
192
|
+
menuItems,
|
|
193
|
+
onItemClick: handleMenuItemClick,
|
|
194
|
+
itemClassName: menuItemClassName
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
/* @__PURE__ */ jsx(LogoutButton, { onLogout: handleLogout, className: logoutButtonClassName })
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
] });
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { LogoutButton, MenuList, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
|
205
|
+
//# sourceMappingURL=index.mjs.map
|
|
206
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sidebar/utils.ts","../src/sidebar/UserProfile.tsx","../src/sidebar/MenuList.tsx","../src/sidebar/LogoutButton.tsx","../src/sidebar/SharedSidebar.tsx"],"names":["jsx","jsxs","closeSidebar"],"mappings":";;;;;;AAKO,SAAS,aAAA,CAAc,SAAA,GAAoB,SAAA,EAAW,SAAA,GAAoB,iBAAA,EAAmB;AAChG,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AACjD,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AAEjD,EAAA,IAAI,WAAW,OAAA,EAAS;AACpB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,SAAA,CAAU,QAAA,CAAS,eAAe,CAAA;AAEzD,IAAA,IAAI,MAAA,EAAQ;AAER,MAAA,OAAA,CAAQ,SAAA,CAAU,OAAO,eAAe,CAAA;AACxC,MAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,kBAAkB,CAAA;AACxC,MAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,QAAQ,CAAA;AAAA,IAClC,CAAA,MAAO;AAEH,MAAA,OAAA,CAAQ,SAAA,CAAU,OAAO,kBAAkB,CAAA;AAC3C,MAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,eAAe,CAAA;AACrC,MAAA,OAAA,CAAQ,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,IACrC;AAAA,EACJ;AACJ;AAOO,SAAS,YAAA,CAAa,SAAA,GAAoB,SAAA,EAAW,SAAA,GAAoB,iBAAA,EAAmB;AAC/F,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AACjD,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AAEjD,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,OAAA,CAAQ,SAAA,CAAU,OAAO,eAAe,CAAA;AACxC,IAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,kBAAkB,CAAA;AAAA,EAC5C;AAEA,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,QAAQ,CAAA;AAAA,EAClC;AACJ;AAOO,SAAS,WAAA,CAAY,SAAA,GAAoB,SAAA,EAAW,SAAA,GAAoB,iBAAA,EAAmB;AAC9F,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AACjD,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AAEjD,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,OAAA,CAAQ,SAAA,CAAU,OAAO,kBAAkB,CAAA;AAC3C,IAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,eAAe,CAAA;AAAA,EACzC;AAEA,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,OAAA,CAAQ,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,EACrC;AACJ;AC1Ce,SAAR,WAAA,CAA6B;AAAA,EAChC,IAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA,GAAY,QAAA;AAAA,EACZ,SAAA,GAAY,EAAA;AAAA,EACZ,eAAA,GAAkB,EAAA;AAAA,EAClB,aAAA,GAAgB;AACpB,CAAA,EAAqB;AACjB,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,MAAM,cAAc,MAAM;AACtB,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,QAAA,EAAU;AACjC,MAAA,OAAO,CAAA,EAAG,IAAA,CAAK,SAAS,CAAA,CAAA,EAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,IAC7C;AACA,IAAA,OAAO,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,QAAA,IAAY,sCAAA;AAAA,EAC9C,CAAA;AAEA,EAAA,MAAM,aAAa,MAAM;AACrB,IAAA,OAAO,IAAA,CAAK,WAAW,MAAA,CAAO,CAAC,KAAK,IAAA,CAAK,QAAA,EAAU,MAAA,CAAO,CAAC,CAAA,IAAK,GAAA;AAAA,EACpE,CAAA;AAEA,EAAA,MAAM,oBAAoB,MAAM;AAC5B,IAAA,MAAM,MAAA,GAAiC;AAAA,MACnC,MAAA,EAAQ,eAAA;AAAA,MACR,IAAA,EAAM,aAAA;AAAA,MACN,IAAA,EAAM,aAAA;AAAA,MACN,KAAA,EAAO,cAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACZ;AACA,IAAA,OAAO,MAAA,CAAO,SAAS,CAAA,IAAK,eAAA;AAAA,EAChC,CAAA;AAEA,EAAA,uBACIA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,6BAAA,EAAgC,SAAS,CAAA,CAAA,EACrD,QAAA,kBAAAC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EACV,QAAA,EAAA;AAAA,IAAA,IAAA,CAAK,6BACFD,GAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACG,KAAK,IAAA,CAAK,UAAA;AAAA,QACV,KAAK,WAAA,EAAY;AAAA,QACjB,KAAA,EAAO,EAAA;AAAA,QACP,MAAA,EAAQ,EAAA;AAAA,QACR,SAAA,EAAW,iDAAiD,eAAe,CAAA;AAAA;AAAA,KAC/E,mBAEAA,GAAAA,CAAC,KAAA,EAAA,EAAI,WAAW,CAAA,2IAAA,EAA8I,eAAe,CAAA,CAAA,EACxK,QAAA,EAAA,UAAA,EAAW,EAChB,CAAA;AAAA,oBAEJC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,eAAA,EAAkB,aAAa,CAAA,CAAA,EAC3C,QAAA,EAAA;AAAA,sBAAAD,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4CAAA,EACR,uBAAY,EACjB,CAAA;AAAA,sBACAC,IAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,+CAAA,EACT,QAAA,EAAA;AAAA,wBAAAD,IAAC,MAAA,EAAA,EAAK,SAAA,EAAW,CAAA,QAAA,EAAW,iBAAA,EAAmB,CAAA,aAAA,CAAA,EAAiB,CAAA;AAAA,QAC/D;AAAA,OAAA,EACL;AAAA,KAAA,EACJ;AAAA,GAAA,EACJ,CAAA,EACJ,CAAA;AAER;ACjEe,SAAR,SAA0B,EAAE,SAAA,EAAW,WAAA,EAAa,aAAA,GAAgB,IAAG,EAAkB;AAC5F,EAAA,uBACIA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EACX,0BAAAA,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,WAAA,EACT,oBAAU,GAAA,CAAI,CAAC,yBACZA,GAAAA,CAAC,QACG,QAAA,kBAAAC,IAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACG,OAAA,EAAS,MAAM,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA;AAAA,MACpC,SAAA,EAAW,0GAA0G,aAAa,CAAA,CAAA;AAAA,MAElI,QAAA,EAAA;AAAA,wBAAAD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sEAAA,EAAwE,eAAK,IAAA,EAAK,CAAA;AAAA,wBACjGA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,wCAAA,EACX,eAAK,KAAA,EACV;AAAA;AAAA;AAAA,GACJ,EAAA,EATK,IAAA,CAAK,EAUd,CACH,GACL,CAAA,EACJ,CAAA;AAER;AC5Be,SAAR,YAAA,CAA8B,EAAE,QAAA,EAAU,SAAA,GAAY,IAAG,EAAsB;AAClF,EAAA,uBACIA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gCACX,QAAA,kBAAAC,IAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACG,OAAA,EAAS,QAAA;AAAA,MACT,SAAA,EAAW,wGAAwG,SAAS,CAAA,CAAA;AAAA,MAE5H,QAAA,EAAA;AAAA,wBAAAD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,SAAA,EAAU,OAAA,EAAQ,aAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAC5D,QAAA,kBAAAA,GAAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACG,aAAA,EAAc,OAAA;AAAA,YACd,cAAA,EAAe,OAAA;AAAA,YACf,WAAA,EAAa,CAAA;AAAA,YACb,CAAA,EAAE;AAAA;AAAA,SACN,EACJ,CAAA;AAAA,wBACAA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0CAAyC,QAAA,EAAA,8DAAA,EAAU;AAAA;AAAA;AAAA,GACvE,EACJ,CAAA;AAER;ACUe,SAAR,aAAA,CAA+B;AAAA,EAClC,IAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA,GAAY,SAAA;AAAA,EACZ,SAAA,GAAY,iBAAA;AAAA,EAEZ,SAAA;AAAA,EACA,SAAA,GAAY,QAAA;AAAA,EACZ,UAAA;AAAA,EACA,QAAA;AAAA;AAAA,EAEA,SAAA,GAAY,EAAA;AAAA,EACZ,iBAAA,GAAoB,EAAA;AAAA,EACpB,qBAAA,GAAwB,EAAA;AAAA,EACxB,oBAAA,GAAuB,EAAA;AAAA,EACvB,mBAAA,GAAsB,EAAA;AAAA,EACtB,iBAAA,GAAoB;AACxB,CAAA,EAAuB;AAEnB,EAAA,MAAME,gBAAe,MAAM;AACvB,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AACjD,IAAA,IAAI,OAAA,EAAS;AACT,MAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,kBAAkB,CAAA;AACxC,MAAA,OAAA,CAAQ,SAAA,CAAU,OAAO,eAAe,CAAA;AAAA,IAC5C;AACA,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA;AACjD,IAAA,IAAI,OAAA,EAAS;AACT,MAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,QAAQ,CAAA;AAAA,IAClC;AAAA,EACJ,CAAA;AAEA,EAAA,MAAM,mBAAA,GAAsB,CAAC,IAAA,KAAiB;AAC1C,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAAA,aAAAA,EAAa;AAAA,EACjB,CAAA;AAEA,EAAA,MAAM,eAAe,MAAM;AACvB,IAAAA,aAAAA,EAAa;AACb,IAAA,QAAA,EAAS;AAAA,EACb,CAAA;AAEA,EAAA,uBACID,KAAA,QAAA,EAAA,EAEI,QAAA,EAAA;AAAA,oBAAAD,GAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACG,EAAA,EAAI,SAAA;AAAA,QACJ,SAAA,EAAU,uCAAA;AAAA,QACV,OAAA,EAASE;AAAA;AAAA,KACb;AAAA,oBAGAD,IAAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACG,EAAA,EAAI,SAAA;AAAA,QACJ,SAAA,EAAW,oJAAoJ,SAAS,CAAA,CAAA;AAAA,QAGxK,QAAA,EAAA;AAAA,0BAAAD,GAAAA;AAAA,YAAC,WAAA;AAAA,YAAA;AAAA,cACG,IAAA;AAAA,cACA,SAAA;AAAA,cACA,SAAA;AAAA,cACA,SAAA,EAAW,oBAAA;AAAA,cACX,eAAA,EAAiB,mBAAA;AAAA,cACjB,aAAA,EAAe;AAAA;AAAA,WACnB;AAAA,0BAGAA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACG,SAAA;AAAA,cACA,WAAA,EAAa,mBAAA;AAAA,cACb,aAAA,EAAe;AAAA;AAAA,WACnB;AAAA,0BAGAA,GAAAA,CAAC,YAAA,EAAA,EAAa,QAAA,EAAU,YAAA,EAAc,WAAW,qBAAA,EAAuB;AAAA;AAAA;AAAA;AAC5E,GAAA,EACJ,CAAA;AAER","file":"index.mjs","sourcesContent":["/**\r\n * Toggle sidebar visibility (Right side)\r\n * @param sidebarId - ID of the sidebar element\r\n * @param overlayId - ID of the overlay element\r\n */\r\nexport function toggleSidebar(sidebarId: string = 'sidebar', overlayId: string = 'sidebar-overlay') {\r\n const sidebar = document.getElementById(sidebarId);\r\n const overlay = document.getElementById(overlayId);\r\n\r\n if (sidebar && overlay) {\r\n const isOpen = sidebar.classList.contains('translate-x-0');\r\n\r\n if (isOpen) {\r\n // Close sidebar (slide to right)\r\n sidebar.classList.remove('translate-x-0');\r\n sidebar.classList.add('translate-x-full');\r\n overlay.classList.add('hidden');\r\n } else {\r\n // Open sidebar (slide from right)\r\n sidebar.classList.remove('translate-x-full');\r\n sidebar.classList.add('translate-x-0');\r\n overlay.classList.remove('hidden');\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Close sidebar (Right side)\r\n * @param sidebarId - ID of the sidebar element\r\n * @param overlayId - ID of the overlay element\r\n */\r\nexport function closeSidebar(sidebarId: string = 'sidebar', overlayId: string = 'sidebar-overlay') {\r\n const sidebar = document.getElementById(sidebarId);\r\n const overlay = document.getElementById(overlayId);\r\n\r\n if (sidebar) {\r\n sidebar.classList.remove('translate-x-0');\r\n sidebar.classList.add('translate-x-full');\r\n }\r\n\r\n if (overlay) {\r\n overlay.classList.add('hidden');\r\n }\r\n}\r\n\r\n/**\r\n * Open sidebar (Right side)\r\n * @param sidebarId - ID of the sidebar element\r\n * @param overlayId - ID of the overlay element\r\n */\r\nexport function openSidebar(sidebarId: string = 'sidebar', overlayId: string = 'sidebar-overlay') {\r\n const sidebar = document.getElementById(sidebarId);\r\n const overlay = document.getElementById(overlayId);\r\n\r\n if (sidebar) {\r\n sidebar.classList.remove('translate-x-full');\r\n sidebar.classList.add('translate-x-0');\r\n }\r\n\r\n if (overlay) {\r\n overlay.classList.remove('hidden');\r\n }\r\n}\r\n","'use client';\r\n\r\ninterface User {\r\n id?: string | number;\r\n firstName?: string;\r\n lastName?: string;\r\n pictureUrl?: string;\r\n role?: string;\r\n}\r\n\r\ninterface UserProfileProps {\r\n user: User | null;\r\n roleLabel: string;\r\n roleColor?: string;\r\n // Styling\r\n className?: string;\r\n avatarClassName?: string;\r\n textClassName?: string;\r\n}\r\n\r\nexport default function UserProfile({\r\n user,\r\n roleLabel,\r\n roleColor = 'orange',\r\n className = '',\r\n avatarClassName = '',\r\n textClassName = ''\r\n}: UserProfileProps) {\r\n if (!user) return null;\r\n\r\n const getFullName = () => {\r\n if (user.firstName && user.lastName) {\r\n return `${user.firstName} ${user.lastName}`;\r\n }\r\n return user.firstName || user.lastName || 'ผู้ใช้';\r\n };\r\n\r\n const getInitial = () => {\r\n return user.firstName?.charAt(0) || user.lastName?.charAt(0) || '?';\r\n };\r\n\r\n const getRoleColorClass = () => {\r\n const colors: Record<string, string> = {\r\n orange: 'bg-orange-500',\r\n teal: 'bg-teal-500',\r\n blue: 'bg-blue-500',\r\n green: 'bg-green-500',\r\n purple: 'bg-purple-500',\r\n };\r\n return colors[roleColor] || 'bg-orange-500';\r\n };\r\n\r\n return (\r\n <div className={`p-5 border-b border-gray-200 ${className}`}>\r\n <div className=\"flex items-center gap-3\">\r\n {user.pictureUrl ? (\r\n <img\r\n src={user.pictureUrl}\r\n alt={getFullName()}\r\n width={56}\r\n height={56}\r\n className={`w-14 h-14 rounded-full shadow-lg object-cover ${avatarClassName}`}\r\n />\r\n ) : (\r\n <div className={`w-14 h-14 bg-gradient-to-br from-teal-400 to-teal-600 rounded-full flex items-center justify-center text-white font-bold shadow-lg text-xl ${avatarClassName}`}>\r\n {getInitial()}\r\n </div>\r\n )}\r\n <div className={`flex-1 min-w-0 ${textClassName}`}>\r\n <p className=\"font-bold text-gray-900 truncate text-base\">\r\n {getFullName()}\r\n </p>\r\n <p className=\"text-sm text-gray-500 flex items-center gap-1\">\r\n <span className={`w-2 h-2 ${getRoleColorClass()} rounded-full`}></span>\r\n {roleLabel}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","'use client';\r\n\r\nexport interface MenuItem {\r\n id: string;\r\n title: string;\r\n path: string;\r\n icon: React.ReactNode;\r\n}\r\n\r\ninterface MenuListProps {\r\n menuItems: MenuItem[];\r\n onItemClick: (path: string) => void;\r\n itemClassName?: string;\r\n}\r\n\r\nexport default function MenuList({ menuItems, onItemClick, itemClassName = '' }: MenuListProps) {\r\n return (\r\n <nav className=\"flex-1 p-5 overflow-y-auto\">\r\n <ul className=\"space-y-1\">\r\n {menuItems.map((item) => (\r\n <li key={item.id}>\r\n <button\r\n onClick={() => onItemClick(item.path)}\r\n className={`w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors ${itemClassName}`}\r\n >\r\n <div className=\"w-8 h-8 flex items-center justify-center text-gray-600 flex-shrink-0\">{item.icon}</div>\r\n <span className=\"flex-1 text-left font-medium text-base\">\r\n {item.title}\r\n </span>\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n </nav>\r\n );\r\n}\r\n","'use client';\r\n\r\ninterface LogoutButtonProps {\r\n onLogout: () => void;\r\n className?: string;\r\n}\r\n\r\nexport default function LogoutButton({ onLogout, className = '' }: LogoutButtonProps) {\r\n return (\r\n <div className=\"p-5 border-t border-gray-200\">\r\n <button\r\n onClick={onLogout}\r\n className={`w-full flex items-center gap-4 px-4 py-3.5 rounded-lg text-red-600 hover:bg-red-50 transition-colors ${className}`}\r\n >\r\n <svg className=\"w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1\"\r\n />\r\n </svg>\r\n <span className=\"flex-1 text-left font-medium text-base\">ออกจากระบบ</span>\r\n </button>\r\n </div>\r\n );\r\n}\r\n","'use client';\r\n\r\nimport UserProfile from './UserProfile';\r\n\r\nimport MenuList from './MenuList';\r\nimport LogoutButton from './LogoutButton';\r\nimport type { MenuItem } from './MenuList';\r\n\r\ninterface User {\r\n id?: string | number;\r\n firstName?: string;\r\n lastName?: string;\r\n pictureUrl?: string;\r\n role?: string;\r\n}\r\n\r\ninterface SharedSidebarProps {\r\n user: User | null;\r\n menuItems: MenuItem[];\r\n sidebarId?: string;\r\n overlayId?: string;\r\n\r\n roleLabel: string;\r\n roleColor?: string;\r\n onNavigate: (path: string) => void;\r\n onLogout: () => void;\r\n // Customization Props\r\n className?: string; // Sidebar container\r\n menuItemClassName?: string;\r\n logoutButtonClassName?: string;\r\n // UserProfile Customization via Sidebar\r\n userProfileClassName?: string;\r\n userAvatarClassName?: string;\r\n userTextClassName?: string;\r\n}\r\n\r\nexport default function SharedSidebar({\r\n user,\r\n menuItems,\r\n sidebarId = 'sidebar',\r\n overlayId = 'sidebar-overlay',\r\n\r\n roleLabel,\r\n roleColor = 'orange',\r\n onNavigate,\r\n onLogout,\r\n // Styles\r\n className = '',\r\n menuItemClassName = '',\r\n logoutButtonClassName = '',\r\n userProfileClassName = '',\r\n userAvatarClassName = '',\r\n userTextClassName = ''\r\n}: SharedSidebarProps) {\r\n\r\n const closeSidebar = () => {\r\n const sidebar = document.getElementById(sidebarId);\r\n if (sidebar) {\r\n sidebar.classList.add('translate-x-full');\r\n sidebar.classList.remove('translate-x-0');\r\n }\r\n const overlay = document.getElementById(overlayId);\r\n if (overlay) {\r\n overlay.classList.add('hidden');\r\n }\r\n };\r\n\r\n const handleMenuItemClick = (path: string) => {\r\n onNavigate(path);\r\n closeSidebar();\r\n };\r\n\r\n const handleLogout = () => {\r\n closeSidebar();\r\n onLogout();\r\n };\r\n\r\n return (\r\n <>\r\n {/* Overlay */}\r\n <div\r\n id={overlayId}\r\n className=\"fixed inset-0 bg-black/50 z-40 hidden\"\r\n onClick={closeSidebar}\r\n />\r\n\r\n {/* Sidebar - Hidden by default, opened via toggle button in header */}\r\n <aside\r\n id={sidebarId}\r\n className={`fixed top-0 right-0 h-full w-[80vw] max-w-80 bg-white shadow-2xl z-50 transform translate-x-full transition-transform duration-300 flex flex-col ${className}`}>\r\n\r\n {/* User Profile Section */}\r\n <UserProfile\r\n user={user}\r\n roleLabel={roleLabel}\r\n roleColor={roleColor}\r\n className={userProfileClassName}\r\n avatarClassName={userAvatarClassName}\r\n textClassName={userTextClassName}\r\n />\r\n\r\n {/* Menu Items */}\r\n <MenuList\r\n menuItems={menuItems}\r\n onItemClick={handleMenuItemClick}\r\n itemClassName={menuItemClassName}\r\n />\r\n\r\n {/* Logout Button */}\r\n <LogoutButton onLogout={handleLogout} className={logoutButtonClassName} />\r\n </aside>\r\n </>\r\n );\r\n}\r\n\r\n// Re-export MenuItem type for convenience\r\nexport type { MenuItem };\r\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gov-components/layout-header-sidebar",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Reusable Header and Sidebar components for React/Next.js projects",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"lint": "eslint ."
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"react",
|
|
25
|
+
"components",
|
|
26
|
+
"sidebar",
|
|
27
|
+
"header",
|
|
28
|
+
"tailwind"
|
|
29
|
+
],
|
|
30
|
+
"author": "Jakprim",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": ">=18",
|
|
34
|
+
"react-dom": ">=18"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.12.7",
|
|
38
|
+
"@types/react": "^18.3.1",
|
|
39
|
+
"autoprefixer": "^10.4.23",
|
|
40
|
+
"postcss": "^8.5.6",
|
|
41
|
+
"react": "^18.3.1",
|
|
42
|
+
"react-dom": "^18.3.1",
|
|
43
|
+
"tailwindcss": "^3.4.17",
|
|
44
|
+
"tsup": "^8.0.2",
|
|
45
|
+
"typescript": "^5.4.5"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@gov-components/design-tokens": "^1.0.13"
|
|
49
|
+
}
|
|
50
|
+
}
|