@gov-components/layout-header-sidebar 1.0.3 → 1.0.5
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 +9 -0
- package/dist/index.d.mts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +187 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +187 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -39,6 +39,15 @@ const nextConfig = {
|
|
|
39
39
|
};
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
### Tailwind CSS v4 Configuration
|
|
43
|
+
|
|
44
|
+
If you are using Tailwind CSS v4, you must explicitly include this package in your source detection. Add the `@source` directive to your main CSS file:
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
@import "tailwindcss";
|
|
48
|
+
@source "../node_modules/@gov-components/layout-header-sidebar";
|
|
49
|
+
```
|
|
50
|
+
|
|
42
51
|
## Usage Guide
|
|
43
52
|
|
|
44
53
|
### 1. Basic Layout Setup
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React$1 from 'react';
|
|
2
3
|
|
|
3
4
|
interface NotificationItem {
|
|
4
5
|
id: string | number;
|
|
@@ -9,6 +10,24 @@ interface NotificationItem {
|
|
|
9
10
|
isRead: boolean;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
interface HeaderProps {
|
|
14
|
+
user?: {
|
|
15
|
+
firstName?: string;
|
|
16
|
+
lastName?: string;
|
|
17
|
+
pictureUrl?: string;
|
|
18
|
+
};
|
|
19
|
+
sidebarId?: string;
|
|
20
|
+
overlayId?: string;
|
|
21
|
+
notificationBell?: React$1.ReactNode;
|
|
22
|
+
notifications?: NotificationItem[];
|
|
23
|
+
className?: string;
|
|
24
|
+
greetingClassName?: string;
|
|
25
|
+
userNameClassName?: string;
|
|
26
|
+
avatarClassName?: string;
|
|
27
|
+
notificationButtonClassName?: string;
|
|
28
|
+
}
|
|
29
|
+
declare function Header({ user, sidebarId, overlayId, notificationBell, notifications, className, greetingClassName, userNameClassName, avatarClassName, notificationButtonClassName }: HeaderProps): react_jsx_runtime.JSX.Element;
|
|
30
|
+
|
|
12
31
|
interface MenuItem {
|
|
13
32
|
id: string;
|
|
14
33
|
title: string;
|
|
@@ -89,4 +108,4 @@ declare function closeSidebar(sidebarId?: string, overlayId?: string): void;
|
|
|
89
108
|
*/
|
|
90
109
|
declare function openSidebar(sidebarId?: string, overlayId?: string): void;
|
|
91
110
|
|
|
92
|
-
export { LogoutButton, type MenuItem, MenuList, type NotificationItem, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
|
111
|
+
export { Header, LogoutButton, type MenuItem, MenuList, type NotificationItem, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React$1 from 'react';
|
|
2
3
|
|
|
3
4
|
interface NotificationItem {
|
|
4
5
|
id: string | number;
|
|
@@ -9,6 +10,24 @@ interface NotificationItem {
|
|
|
9
10
|
isRead: boolean;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
interface HeaderProps {
|
|
14
|
+
user?: {
|
|
15
|
+
firstName?: string;
|
|
16
|
+
lastName?: string;
|
|
17
|
+
pictureUrl?: string;
|
|
18
|
+
};
|
|
19
|
+
sidebarId?: string;
|
|
20
|
+
overlayId?: string;
|
|
21
|
+
notificationBell?: React$1.ReactNode;
|
|
22
|
+
notifications?: NotificationItem[];
|
|
23
|
+
className?: string;
|
|
24
|
+
greetingClassName?: string;
|
|
25
|
+
userNameClassName?: string;
|
|
26
|
+
avatarClassName?: string;
|
|
27
|
+
notificationButtonClassName?: string;
|
|
28
|
+
}
|
|
29
|
+
declare function Header({ user, sidebarId, overlayId, notificationBell, notifications, className, greetingClassName, userNameClassName, avatarClassName, notificationButtonClassName }: HeaderProps): react_jsx_runtime.JSX.Element;
|
|
30
|
+
|
|
12
31
|
interface MenuItem {
|
|
13
32
|
id: string;
|
|
14
33
|
title: string;
|
|
@@ -89,4 +108,4 @@ declare function closeSidebar(sidebarId?: string, overlayId?: string): void;
|
|
|
89
108
|
*/
|
|
90
109
|
declare function openSidebar(sidebarId?: string, overlayId?: string): void;
|
|
91
110
|
|
|
92
|
-
export { LogoutButton, type MenuItem, MenuList, type NotificationItem, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
|
111
|
+
export { Header, LogoutButton, type MenuItem, MenuList, type NotificationItem, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
require('
|
|
3
|
+
require('@gov-components/design-tokens');
|
|
4
|
+
var react = require('react');
|
|
4
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
6
|
|
|
6
|
-
// src/
|
|
7
|
+
// src/index.ts
|
|
7
8
|
|
|
8
9
|
// src/sidebar/utils.ts
|
|
9
10
|
function toggleSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
@@ -44,6 +45,189 @@ function openSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
|
44
45
|
overlay.classList.remove("hidden");
|
|
45
46
|
}
|
|
46
47
|
}
|
|
48
|
+
function NotificationList({
|
|
49
|
+
notifications,
|
|
50
|
+
isOpen,
|
|
51
|
+
onClose,
|
|
52
|
+
onMarkAllRead,
|
|
53
|
+
onViewAll
|
|
54
|
+
}) {
|
|
55
|
+
const listRef = react.useRef(null);
|
|
56
|
+
react.useEffect(() => {
|
|
57
|
+
const handleClickOutside = (event) => {
|
|
58
|
+
if (listRef.current && !listRef.current.contains(event.target)) {
|
|
59
|
+
onClose();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
if (isOpen) {
|
|
63
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
64
|
+
}
|
|
65
|
+
return () => {
|
|
66
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
67
|
+
};
|
|
68
|
+
}, [isOpen, onClose]);
|
|
69
|
+
if (!isOpen) return null;
|
|
70
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
71
|
+
"div",
|
|
72
|
+
{
|
|
73
|
+
ref: listRef,
|
|
74
|
+
className: "absolute right-0 mt-2 w-80 sm:w-96 bg-white rounded-xl shadow-lg ring-1 ring-black ring-opacity-5 z-50 overflow-hidden transform origin-top-right transition-all",
|
|
75
|
+
children: [
|
|
76
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-gray-100 flex items-center justify-between bg-gray-50/50", children: [
|
|
77
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-semibold text-gray-900", children: "\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19" }),
|
|
78
|
+
onMarkAllRead && /* @__PURE__ */ jsxRuntime.jsx(
|
|
79
|
+
"button",
|
|
80
|
+
{
|
|
81
|
+
onClick: onMarkAllRead,
|
|
82
|
+
className: "text-xs text-brand-primary hover:text-brand-secondary font-medium transition-colors",
|
|
83
|
+
children: "\u0E2D\u0E48\u0E32\u0E19\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14"
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
] }),
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[70vh] overflow-y-auto", children: notifications.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-8 text-center text-gray-500 flex flex-col items-center gap-3", children: [
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center text-2xl", children: "\u{1F514}" }),
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19\u0E43\u0E2B\u0E21\u0E48" })
|
|
90
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-gray-50", children: notifications.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
91
|
+
"div",
|
|
92
|
+
{
|
|
93
|
+
className: `p-4 hover:bg-gray-50 transition-colors cursor-pointer relative group ${!item.isRead ? "bg-blue-50/30" : ""}`,
|
|
94
|
+
children: [
|
|
95
|
+
!item.isRead && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-4 right-4 w-2 h-2 bg-red-500 rounded-full ring-2 ring-white" }),
|
|
96
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 items-start", children: [
|
|
97
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `mt-0.5 w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${getIconBgClass(item.type)}`, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: getIcon(item.type) }) }),
|
|
98
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
99
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-sm font-medium text-gray-900 mb-0.5 ${!item.isRead ? "font-semibold" : ""}`, children: item.title }),
|
|
100
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 line-clamp-2 mb-1.5 leading-relaxed", children: item.description }),
|
|
101
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-gray-400 font-medium", children: item.date })
|
|
102
|
+
] })
|
|
103
|
+
] })
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
item.id
|
|
107
|
+
)) }) }),
|
|
108
|
+
onViewAll && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 bg-gray-50 border-t border-gray-100 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
109
|
+
"button",
|
|
110
|
+
{
|
|
111
|
+
onClick: onViewAll,
|
|
112
|
+
className: "text-sm text-gray-600 hover:text-brand-primary font-medium transition-colors w-full py-1",
|
|
113
|
+
children: "\u0E14\u0E39\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14"
|
|
114
|
+
}
|
|
115
|
+
) })
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
function getIconBgClass(type) {
|
|
121
|
+
switch (type) {
|
|
122
|
+
case "success":
|
|
123
|
+
return "bg-green-100 text-green-600";
|
|
124
|
+
case "warning":
|
|
125
|
+
return "bg-yellow-100 text-yellow-600";
|
|
126
|
+
case "error":
|
|
127
|
+
return "bg-red-100 text-red-600";
|
|
128
|
+
case "reminder":
|
|
129
|
+
return "bg-purple-100 text-purple-600";
|
|
130
|
+
default:
|
|
131
|
+
return "bg-blue-100 text-blue-600";
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function getIcon(type) {
|
|
135
|
+
switch (type) {
|
|
136
|
+
case "success":
|
|
137
|
+
return "\u2713";
|
|
138
|
+
case "warning":
|
|
139
|
+
return "!";
|
|
140
|
+
case "error":
|
|
141
|
+
return "\u2715";
|
|
142
|
+
case "reminder":
|
|
143
|
+
return "\u23F0";
|
|
144
|
+
default:
|
|
145
|
+
return "i";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function Header({
|
|
149
|
+
user,
|
|
150
|
+
sidebarId = "sidebar",
|
|
151
|
+
overlayId = "sidebar-overlay",
|
|
152
|
+
notificationBell,
|
|
153
|
+
notifications = [],
|
|
154
|
+
// Styles
|
|
155
|
+
className = "",
|
|
156
|
+
greetingClassName = "",
|
|
157
|
+
userNameClassName = "",
|
|
158
|
+
avatarClassName = "",
|
|
159
|
+
notificationButtonClassName = ""
|
|
160
|
+
}) {
|
|
161
|
+
const displayName = `${user?.firstName || ""} ${user?.lastName || ""}`.trim() || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
|
|
162
|
+
const firstChar = user?.firstName?.charAt(0) || "\u0E1C";
|
|
163
|
+
const [isNotificationsOpen, setIsNotificationsOpen] = react.useState(false);
|
|
164
|
+
const notificationRef = react.useRef(null);
|
|
165
|
+
const handleToggleSidebar = () => {
|
|
166
|
+
toggleSidebar(sidebarId, overlayId);
|
|
167
|
+
};
|
|
168
|
+
react.useEffect(() => {
|
|
169
|
+
const handleClickOutside = (event) => {
|
|
170
|
+
if (notificationRef.current && !notificationRef.current.contains(event.target)) {
|
|
171
|
+
setIsNotificationsOpen(false);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
175
|
+
return () => {
|
|
176
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
177
|
+
};
|
|
178
|
+
}, []);
|
|
179
|
+
const unreadCount = notifications.filter((n) => !n.isRead).length;
|
|
180
|
+
return /* @__PURE__ */ jsxRuntime.jsx("header", { className: `bg-white shadow-sm sticky top-0 z-10 lg:static ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-5 py-3.5", children: [
|
|
181
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
182
|
+
user?.pictureUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
183
|
+
"img",
|
|
184
|
+
{
|
|
185
|
+
src: user.pictureUrl,
|
|
186
|
+
alt: displayName,
|
|
187
|
+
width: 44,
|
|
188
|
+
height: 44,
|
|
189
|
+
className: `rounded-full object-cover border-2 border-brand-surface w-[44px] h-[44px] ${avatarClassName}`
|
|
190
|
+
}
|
|
191
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-11 h-11 bg-gradient-to-br from-brand-secondary to-brand-primary rounded-full flex items-center justify-center shadow-sm ${avatarClassName}`, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white text-lg font-semibold", children: firstChar }) }),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-semibold text-brand-text-dark", children: [
|
|
193
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: greetingClassName, children: "\u0E2A\u0E27\u0E31\u0E2A\u0E14\u0E35," }),
|
|
194
|
+
" ",
|
|
195
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-brand-primary ${userNameClassName}`, children: displayName })
|
|
196
|
+
] }) })
|
|
197
|
+
] }),
|
|
198
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
199
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: notificationRef, children: [
|
|
200
|
+
notificationBell || /* @__PURE__ */ jsxRuntime.jsxs(
|
|
201
|
+
"button",
|
|
202
|
+
{
|
|
203
|
+
className: `p-2.5 rounded-lg transition-colors hover:bg-gray-100 relative ${notificationButtonClassName}`,
|
|
204
|
+
onClick: () => setIsNotificationsOpen(!isNotificationsOpen),
|
|
205
|
+
children: [
|
|
206
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "22", height: "24", viewBox: "0 0 22 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21.2321 13.4463L19.3618 6.71712C18.8136 4.74574 17.6222 3.01418 15.9769 1.79767C14.3316 0.581165 12.3269 -0.0504751 10.2814 0.00315377C8.23593 0.0567826 6.26708 0.792603 4.6878 2.09365C3.10852 3.3947 2.00945 5.18632 1.5653 7.18371L0.11728 13.6954C-0.0426654 14.4149 -0.0389674 15.1611 0.128101 15.879C0.29517 16.5969 0.621344 17.2681 1.08254 17.8431C1.54374 18.418 2.12818 18.8821 2.79272 19.2009C3.45727 19.5198 4.18494 19.6853 4.92202 19.6853H6.01861C6.24454 20.7979 6.84817 21.7982 7.72723 22.5167C8.60629 23.2352 9.70671 23.6277 10.842 23.6277C11.9774 23.6277 13.0778 23.2352 13.9569 22.5167C14.8359 21.7982 15.4396 20.7979 15.6655 19.6853H16.4904C17.2492 19.6853 17.9977 19.5099 18.6774 19.1728C19.3572 18.8357 19.9498 18.346 20.409 17.742C20.8682 17.1379 21.1815 16.4359 21.3245 15.6907C21.4674 14.9455 21.4352 14.1774 21.2321 13.4463ZM10.842 21.654C10.2334 21.6515 9.64049 21.461 9.1443 21.1086C8.6481 20.7562 8.27291 20.2591 8.07005 19.6853H13.614C13.4112 20.2591 13.036 20.7562 12.5398 21.1086C12.0436 21.461 11.4506 21.6515 10.842 21.654ZM18.8411 16.55C18.5668 16.9139 18.2114 17.2088 17.8032 17.4113C17.3949 17.6138 16.9451 17.7183 16.4894 17.7165H4.92202C4.47982 17.7164 4.04328 17.6171 3.64463 17.4257C3.24598 17.2344 2.89539 16.9559 2.61874 16.611C2.34208 16.266 2.14643 15.8633 2.04622 15.4326C1.94602 15.0019 1.94381 14.5542 2.03977 14.1226L3.4868 7.60994C3.83561 6.04105 4.69886 4.63379 5.93932 3.61186C7.17978 2.58992 8.72625 2.01197 10.3329 1.96988C11.9395 1.92779 13.5142 2.42398 14.8064 3.37956C16.0987 4.33515 17.0344 5.69528 17.4649 7.24376L19.3352 13.9729C19.4588 14.4114 19.4785 14.8725 19.3927 15.3199C19.3069 15.7672 19.1181 16.1884 18.8411 16.55Z", className: "fill-brand-text-dark" }) }),
|
|
207
|
+
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-1.5 right-1.5 min-w-[18px] h-[18px] bg-semantic-critical rounded-full flex items-center justify-center text-[10px] font-bold text-white px-1 border-2 border-white", children: unreadCount })
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
),
|
|
211
|
+
isNotificationsOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
212
|
+
NotificationList,
|
|
213
|
+
{
|
|
214
|
+
notifications,
|
|
215
|
+
isOpen: true,
|
|
216
|
+
onClose: () => setIsNotificationsOpen(false)
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
] }),
|
|
220
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
221
|
+
"button",
|
|
222
|
+
{
|
|
223
|
+
onClick: handleToggleSidebar,
|
|
224
|
+
className: "p-2.5 rounded-lg transition-colors hover:bg-gray-100",
|
|
225
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "27", height: "18", viewBox: "0 0 27 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1.1875 17.8426C0.851042 17.8426 0.569077 17.7287 0.341604 17.501C0.113868 17.2735 0 16.9914 0 16.6547C0 16.3182 0.113868 16.0363 0.341604 15.8088C0.569077 15.5816 0.851042 15.468 1.1875 15.468H25.7292C26.0656 15.468 26.3476 15.5817 26.5751 15.8092C26.8028 16.0369 26.9167 16.3192 26.9167 16.6559C26.9167 16.9923 26.8028 17.2743 26.5751 17.5018C26.3476 17.729 26.0656 17.8426 25.7292 17.8426H1.1875ZM1.1875 10.1088C0.851042 10.1088 0.569077 9.99492 0.341604 9.76719C0.113868 9.53945 0 9.25735 0 8.9209C0 8.58417 0.113868 8.30221 0.341604 8.075C0.569077 7.84753 0.851042 7.73379 1.1875 7.73379H25.7292C26.0656 7.73379 26.3476 7.84766 26.5751 8.0754C26.8028 8.30313 26.9167 8.58523 26.9167 8.92169C26.9167 9.25841 26.8028 9.54037 26.5751 9.76758C26.3476 9.99506 26.0656 10.1088 25.7292 10.1088H1.1875ZM1.1875 2.3746C0.851042 2.3746 0.569077 2.26087 0.341604 2.0334C0.113868 1.80566 0 1.52343 0 1.18671C0 0.850249 0.113868 0.568284 0.341604 0.340812C0.569077 0.113604 0.851042 0 1.1875 0H25.7292C26.0656 0 26.3476 0.113868 26.5751 0.341604C26.8028 0.569077 26.9167 0.851174 26.9167 1.1879C26.9167 1.52435 26.8028 1.80632 26.5751 2.03379C26.3476 2.261 26.0656 2.3746 25.7292 2.3746H1.1875Z", className: "fill-brand-text-dark" }) })
|
|
226
|
+
}
|
|
227
|
+
)
|
|
228
|
+
] })
|
|
229
|
+
] }) });
|
|
230
|
+
}
|
|
47
231
|
function UserProfile({
|
|
48
232
|
user,
|
|
49
233
|
roleLabel,
|
|
@@ -203,6 +387,7 @@ function SharedSidebar({
|
|
|
203
387
|
] });
|
|
204
388
|
}
|
|
205
389
|
|
|
390
|
+
exports.Header = Header;
|
|
206
391
|
exports.LogoutButton = LogoutButton;
|
|
207
392
|
exports.MenuList = MenuList;
|
|
208
393
|
exports.SharedSidebar = SharedSidebar;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["../src/sidebar/utils.ts","../src/header/NotificationList.tsx","../src/header/Header.tsx","../src/sidebar/UserProfile.tsx","../src/sidebar/MenuList.tsx","../src/sidebar/LogoutButton.tsx","../src/sidebar/SharedSidebar.tsx"],"names":["useRef","useEffect","jsxs","jsx","useState","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\nimport { useRef, useEffect } from 'react';\r\n\r\nexport interface NotificationItem {\r\n id: string | number;\r\n title: string;\r\n description: string;\r\n date: string;\r\n type: 'info' | 'success' | 'warning' | 'error' | 'reminder';\r\n isRead: boolean;\r\n}\r\n\r\ninterface NotificationListProps {\r\n notifications: NotificationItem[];\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onMarkAllRead?: () => void;\r\n onViewAll?: () => void;\r\n}\r\n\r\nexport default function NotificationList({\r\n notifications,\r\n isOpen,\r\n onClose,\r\n onMarkAllRead,\r\n onViewAll\r\n}: NotificationListProps) {\r\n const listRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (listRef.current && !listRef.current.contains(event.target as Node)) {\r\n onClose();\r\n }\r\n };\r\n\r\n if (isOpen) {\r\n document.addEventListener('mousedown', handleClickOutside);\r\n }\r\n\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside);\r\n };\r\n }, [isOpen, onClose]);\r\n\r\n if (!isOpen) return null;\r\n\r\n return (\r\n <div\r\n ref={listRef}\r\n className=\"absolute right-0 mt-2 w-80 sm:w-96 bg-white rounded-xl shadow-lg ring-1 ring-black ring-opacity-5 z-50 overflow-hidden transform origin-top-right transition-all\"\r\n >\r\n <div className=\"p-4 border-b border-gray-100 flex items-center justify-between bg-gray-50/50\">\r\n <h3 className=\"font-semibold text-gray-900\">การแจ้งเตือน</h3>\r\n {onMarkAllRead && (\r\n <button\r\n onClick={onMarkAllRead}\r\n className=\"text-xs text-brand-primary hover:text-brand-secondary font-medium transition-colors\"\r\n >\r\n อ่านทั้งหมด\r\n </button>\r\n )}\r\n </div>\r\n\r\n <div className=\"max-h-[70vh] overflow-y-auto\">\r\n {notifications.length === 0 ? (\r\n <div className=\"p-8 text-center text-gray-500 flex flex-col items-center gap-3\">\r\n <div className=\"w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center text-2xl\">\r\n 🔔\r\n </div>\r\n <p>ไม่มีการแจ้งเตือนใหม่</p>\r\n </div>\r\n ) : (\r\n <div className=\"divide-y divide-gray-50\">\r\n {notifications.map((item) => (\r\n <div\r\n key={item.id}\r\n className={`p-4 hover:bg-gray-50 transition-colors cursor-pointer relative group ${!item.isRead ? 'bg-blue-50/30' : ''}`}\r\n >\r\n {!item.isRead && (\r\n <span className=\"absolute top-4 right-4 w-2 h-2 bg-red-500 rounded-full ring-2 ring-white\"></span>\r\n )}\r\n <div className=\"flex gap-3 items-start\">\r\n <div className={`mt-0.5 w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${getIconBgClass(item.type)}`}>\r\n <span className=\"text-sm\">{getIcon(item.type)}</span>\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className={`text-sm font-medium text-gray-900 mb-0.5 ${!item.isRead ? 'font-semibold' : ''}`}>\r\n {item.title}\r\n </p>\r\n <p className=\"text-xs text-gray-500 line-clamp-2 mb-1.5 leading-relaxed\">\r\n {item.description}\r\n </p>\r\n <p className=\"text-[10px] text-gray-400 font-medium\">\r\n {item.date}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {onViewAll && (\r\n <div className=\"p-3 bg-gray-50 border-t border-gray-100 text-center\">\r\n <button\r\n onClick={onViewAll}\r\n className=\"text-sm text-gray-600 hover:text-brand-primary font-medium transition-colors w-full py-1\"\r\n >\r\n ดูทั้งหมด\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction getIconBgClass(type: NotificationItem['type']) {\r\n switch (type) {\r\n case 'success': return 'bg-green-100 text-green-600';\r\n case 'warning': return 'bg-yellow-100 text-yellow-600';\r\n case 'error': return 'bg-red-100 text-red-600';\r\n case 'reminder': return 'bg-purple-100 text-purple-600';\r\n default: return 'bg-blue-100 text-blue-600';\r\n }\r\n}\r\n\r\nfunction getIcon(type: NotificationItem['type']) {\r\n switch (type) {\r\n case 'success': return '✓';\r\n case 'warning': return '!';\r\n case 'error': return '✕';\r\n case 'reminder': return '⏰';\r\n default: return 'i';\r\n }\r\n}\r\n","'use client';\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport { toggleSidebar } from '../sidebar/utils';\r\nimport NotificationList, { NotificationItem } from './NotificationList';\r\nexport type { NotificationItem };\r\n\r\ninterface HeaderProps {\r\n user?: {\r\n firstName?: string;\r\n lastName?: string;\r\n pictureUrl?: string;\r\n };\r\n sidebarId?: string;\r\n overlayId?: string;\r\n notificationBell?: React.ReactNode;\r\n notifications?: NotificationItem[];\r\n // Customization Props\r\n className?: string; // Main container\r\n greetingClassName?: string; // \"สวัสดี,\" text\r\n userNameClassName?: string; // User's name\r\n avatarClassName?: string; // User's avatar/initials container\r\n notificationButtonClassName?: string; // Notification bell button\r\n}\r\n\r\nexport default function Header({\r\n user,\r\n sidebarId = 'sidebar',\r\n overlayId = 'sidebar-overlay',\r\n notificationBell,\r\n notifications = [],\r\n // Styles\r\n className = '',\r\n greetingClassName = '',\r\n userNameClassName = '',\r\n avatarClassName = '',\r\n notificationButtonClassName = ''\r\n}: HeaderProps) {\r\n const displayName = `${user?.firstName || ''} ${user?.lastName || ''}`.trim() || 'ผู้ใช้';\r\n const firstChar = user?.firstName?.charAt(0) || 'ผ';\r\n const [isNotificationsOpen, setIsNotificationsOpen] = useState(false);\r\n const notificationRef = useRef<HTMLDivElement>(null);\r\n\r\n const handleToggleSidebar = () => {\r\n toggleSidebar(sidebarId, overlayId);\r\n };\r\n\r\n // Close dropdown when clicking outside\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (notificationRef.current && !notificationRef.current.contains(event.target as Node)) {\r\n setIsNotificationsOpen(false);\r\n }\r\n };\r\n\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside);\r\n };\r\n }, []);\r\n\r\n const unreadCount = notifications.filter(n => !n.isRead).length;\r\n\r\n return (\r\n <header className={`bg-white shadow-sm sticky top-0 z-10 lg:static ${className}`}>\r\n <div className=\"flex items-center justify-between px-5 py-3.5\">\r\n {/* Avatar & Name */}\r\n <div className=\"flex items-center gap-3\">\r\n {user?.pictureUrl ? (\r\n <img\r\n src={user.pictureUrl}\r\n alt={displayName}\r\n width={44}\r\n height={44}\r\n className={`rounded-full object-cover border-2 border-brand-surface w-[44px] h-[44px] ${avatarClassName}`}\r\n />\r\n ) : (\r\n <div className={`w-11 h-11 bg-gradient-to-br from-brand-secondary to-brand-primary rounded-full flex items-center justify-center shadow-sm ${avatarClassName}`}>\r\n <span className=\"text-white text-lg font-semibold\">\r\n {firstChar}\r\n </span>\r\n </div>\r\n )}\r\n <div>\r\n <p className=\"text-sm font-semibold text-brand-text-dark\">\r\n <span className={greetingClassName}>สวัสดี,</span> <span className={`text-brand-primary ${userNameClassName}`}>{displayName}</span>\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Right Side Buttons */}\r\n <div className=\"flex items-center gap-1\">\r\n {/* Notification Bell (optional or default with dropdown) */}\r\n <div className=\"relative\" ref={notificationRef}>\r\n {notificationBell || (\r\n <button\r\n className={`p-2.5 rounded-lg transition-colors hover:bg-gray-100 relative ${notificationButtonClassName}`}\r\n onClick={() => setIsNotificationsOpen(!isNotificationsOpen)}\r\n >\r\n <svg width=\"22\" height=\"24\" viewBox=\"0 0 22 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M21.2321 13.4463L19.3618 6.71712C18.8136 4.74574 17.6222 3.01418 15.9769 1.79767C14.3316 0.581165 12.3269 -0.0504751 10.2814 0.00315377C8.23593 0.0567826 6.26708 0.792603 4.6878 2.09365C3.10852 3.3947 2.00945 5.18632 1.5653 7.18371L0.11728 13.6954C-0.0426654 14.4149 -0.0389674 15.1611 0.128101 15.879C0.29517 16.5969 0.621344 17.2681 1.08254 17.8431C1.54374 18.418 2.12818 18.8821 2.79272 19.2009C3.45727 19.5198 4.18494 19.6853 4.92202 19.6853H6.01861C6.24454 20.7979 6.84817 21.7982 7.72723 22.5167C8.60629 23.2352 9.70671 23.6277 10.842 23.6277C11.9774 23.6277 13.0778 23.2352 13.9569 22.5167C14.8359 21.7982 15.4396 20.7979 15.6655 19.6853H16.4904C17.2492 19.6853 17.9977 19.5099 18.6774 19.1728C19.3572 18.8357 19.9498 18.346 20.409 17.742C20.8682 17.1379 21.1815 16.4359 21.3245 15.6907C21.4674 14.9455 21.4352 14.1774 21.2321 13.4463ZM10.842 21.654C10.2334 21.6515 9.64049 21.461 9.1443 21.1086C8.6481 20.7562 8.27291 20.2591 8.07005 19.6853H13.614C13.4112 20.2591 13.036 20.7562 12.5398 21.1086C12.0436 21.461 11.4506 21.6515 10.842 21.654ZM18.8411 16.55C18.5668 16.9139 18.2114 17.2088 17.8032 17.4113C17.3949 17.6138 16.9451 17.7183 16.4894 17.7165H4.92202C4.47982 17.7164 4.04328 17.6171 3.64463 17.4257C3.24598 17.2344 2.89539 16.9559 2.61874 16.611C2.34208 16.266 2.14643 15.8633 2.04622 15.4326C1.94602 15.0019 1.94381 14.5542 2.03977 14.1226L3.4868 7.60994C3.83561 6.04105 4.69886 4.63379 5.93932 3.61186C7.17978 2.58992 8.72625 2.01197 10.3329 1.96988C11.9395 1.92779 13.5142 2.42398 14.8064 3.37956C16.0987 4.33515 17.0344 5.69528 17.4649 7.24376L19.3352 13.9729C19.4588 14.4114 19.4785 14.8725 19.3927 15.3199C19.3069 15.7672 19.1181 16.1884 18.8411 16.55Z\" className=\"fill-brand-text-dark\" />\r\n </svg>\r\n {unreadCount > 0 && (\r\n <span className=\"absolute top-1.5 right-1.5 min-w-[18px] h-[18px] bg-semantic-critical rounded-full flex items-center justify-center text-[10px] font-bold text-white px-1 border-2 border-white\">\r\n {unreadCount}\r\n </span>\r\n )}\r\n </button>\r\n )}\r\n\r\n {/* Dropdown */}\r\n {isNotificationsOpen && (\r\n <NotificationList\r\n notifications={notifications}\r\n isOpen={true}\r\n onClose={() => setIsNotificationsOpen(false)}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Menu Button */}\r\n <button\r\n onClick={handleToggleSidebar}\r\n className=\"p-2.5 rounded-lg transition-colors hover:bg-gray-100\"\r\n >\r\n <svg width=\"27\" height=\"18\" viewBox=\"0 0 27 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M1.1875 17.8426C0.851042 17.8426 0.569077 17.7287 0.341604 17.501C0.113868 17.2735 0 16.9914 0 16.6547C0 16.3182 0.113868 16.0363 0.341604 15.8088C0.569077 15.5816 0.851042 15.468 1.1875 15.468H25.7292C26.0656 15.468 26.3476 15.5817 26.5751 15.8092C26.8028 16.0369 26.9167 16.3192 26.9167 16.6559C26.9167 16.9923 26.8028 17.2743 26.5751 17.5018C26.3476 17.729 26.0656 17.8426 25.7292 17.8426H1.1875ZM1.1875 10.1088C0.851042 10.1088 0.569077 9.99492 0.341604 9.76719C0.113868 9.53945 0 9.25735 0 8.9209C0 8.58417 0.113868 8.30221 0.341604 8.075C0.569077 7.84753 0.851042 7.73379 1.1875 7.73379H25.7292C26.0656 7.73379 26.3476 7.84766 26.5751 8.0754C26.8028 8.30313 26.9167 8.58523 26.9167 8.92169C26.9167 9.25841 26.8028 9.54037 26.5751 9.76758C26.3476 9.99506 26.0656 10.1088 25.7292 10.1088H1.1875ZM1.1875 2.3746C0.851042 2.3746 0.569077 2.26087 0.341604 2.0334C0.113868 1.80566 0 1.52343 0 1.18671C0 0.850249 0.113868 0.568284 0.341604 0.340812C0.569077 0.113604 0.851042 0 1.1875 0H25.7292C26.0656 0 26.3476 0.113868 26.5751 0.341604C26.8028 0.569077 26.9167 0.851174 26.9167 1.1879C26.9167 1.52435 26.8028 1.80632 26.5751 2.03379C26.3476 2.261 26.0656 2.3746 25.7292 2.3746H1.1875Z\" className=\"fill-brand-text-dark\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n </header>\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
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import '
|
|
1
|
+
import '@gov-components/design-tokens';
|
|
2
|
+
import { useState, useRef, useEffect } from 'react';
|
|
2
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
4
|
|
|
4
|
-
// src/
|
|
5
|
+
// src/index.ts
|
|
5
6
|
|
|
6
7
|
// src/sidebar/utils.ts
|
|
7
8
|
function toggleSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
@@ -42,6 +43,189 @@ function openSidebar(sidebarId = "sidebar", overlayId = "sidebar-overlay") {
|
|
|
42
43
|
overlay.classList.remove("hidden");
|
|
43
44
|
}
|
|
44
45
|
}
|
|
46
|
+
function NotificationList({
|
|
47
|
+
notifications,
|
|
48
|
+
isOpen,
|
|
49
|
+
onClose,
|
|
50
|
+
onMarkAllRead,
|
|
51
|
+
onViewAll
|
|
52
|
+
}) {
|
|
53
|
+
const listRef = useRef(null);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const handleClickOutside = (event) => {
|
|
56
|
+
if (listRef.current && !listRef.current.contains(event.target)) {
|
|
57
|
+
onClose();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
if (isOpen) {
|
|
61
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
62
|
+
}
|
|
63
|
+
return () => {
|
|
64
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
65
|
+
};
|
|
66
|
+
}, [isOpen, onClose]);
|
|
67
|
+
if (!isOpen) return null;
|
|
68
|
+
return /* @__PURE__ */ jsxs(
|
|
69
|
+
"div",
|
|
70
|
+
{
|
|
71
|
+
ref: listRef,
|
|
72
|
+
className: "absolute right-0 mt-2 w-80 sm:w-96 bg-white rounded-xl shadow-lg ring-1 ring-black ring-opacity-5 z-50 overflow-hidden transform origin-top-right transition-all",
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4 border-b border-gray-100 flex items-center justify-between bg-gray-50/50", children: [
|
|
75
|
+
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-gray-900", children: "\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19" }),
|
|
76
|
+
onMarkAllRead && /* @__PURE__ */ jsx(
|
|
77
|
+
"button",
|
|
78
|
+
{
|
|
79
|
+
onClick: onMarkAllRead,
|
|
80
|
+
className: "text-xs text-brand-primary hover:text-brand-secondary font-medium transition-colors",
|
|
81
|
+
children: "\u0E2D\u0E48\u0E32\u0E19\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14"
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
] }),
|
|
85
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-[70vh] overflow-y-auto", children: notifications.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "p-8 text-center text-gray-500 flex flex-col items-center gap-3", children: [
|
|
86
|
+
/* @__PURE__ */ jsx("div", { className: "w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center text-2xl", children: "\u{1F514}" }),
|
|
87
|
+
/* @__PURE__ */ jsx("p", { children: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19\u0E43\u0E2B\u0E21\u0E48" })
|
|
88
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-50", children: notifications.map((item) => /* @__PURE__ */ jsxs(
|
|
89
|
+
"div",
|
|
90
|
+
{
|
|
91
|
+
className: `p-4 hover:bg-gray-50 transition-colors cursor-pointer relative group ${!item.isRead ? "bg-blue-50/30" : ""}`,
|
|
92
|
+
children: [
|
|
93
|
+
!item.isRead && /* @__PURE__ */ jsx("span", { className: "absolute top-4 right-4 w-2 h-2 bg-red-500 rounded-full ring-2 ring-white" }),
|
|
94
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 items-start", children: [
|
|
95
|
+
/* @__PURE__ */ jsx("div", { className: `mt-0.5 w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${getIconBgClass(item.type)}`, children: /* @__PURE__ */ jsx("span", { className: "text-sm", children: getIcon(item.type) }) }),
|
|
96
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
97
|
+
/* @__PURE__ */ jsx("p", { className: `text-sm font-medium text-gray-900 mb-0.5 ${!item.isRead ? "font-semibold" : ""}`, children: item.title }),
|
|
98
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 line-clamp-2 mb-1.5 leading-relaxed", children: item.description }),
|
|
99
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 font-medium", children: item.date })
|
|
100
|
+
] })
|
|
101
|
+
] })
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
item.id
|
|
105
|
+
)) }) }),
|
|
106
|
+
onViewAll && /* @__PURE__ */ jsx("div", { className: "p-3 bg-gray-50 border-t border-gray-100 text-center", children: /* @__PURE__ */ jsx(
|
|
107
|
+
"button",
|
|
108
|
+
{
|
|
109
|
+
onClick: onViewAll,
|
|
110
|
+
className: "text-sm text-gray-600 hover:text-brand-primary font-medium transition-colors w-full py-1",
|
|
111
|
+
children: "\u0E14\u0E39\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14"
|
|
112
|
+
}
|
|
113
|
+
) })
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
function getIconBgClass(type) {
|
|
119
|
+
switch (type) {
|
|
120
|
+
case "success":
|
|
121
|
+
return "bg-green-100 text-green-600";
|
|
122
|
+
case "warning":
|
|
123
|
+
return "bg-yellow-100 text-yellow-600";
|
|
124
|
+
case "error":
|
|
125
|
+
return "bg-red-100 text-red-600";
|
|
126
|
+
case "reminder":
|
|
127
|
+
return "bg-purple-100 text-purple-600";
|
|
128
|
+
default:
|
|
129
|
+
return "bg-blue-100 text-blue-600";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function getIcon(type) {
|
|
133
|
+
switch (type) {
|
|
134
|
+
case "success":
|
|
135
|
+
return "\u2713";
|
|
136
|
+
case "warning":
|
|
137
|
+
return "!";
|
|
138
|
+
case "error":
|
|
139
|
+
return "\u2715";
|
|
140
|
+
case "reminder":
|
|
141
|
+
return "\u23F0";
|
|
142
|
+
default:
|
|
143
|
+
return "i";
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function Header({
|
|
147
|
+
user,
|
|
148
|
+
sidebarId = "sidebar",
|
|
149
|
+
overlayId = "sidebar-overlay",
|
|
150
|
+
notificationBell,
|
|
151
|
+
notifications = [],
|
|
152
|
+
// Styles
|
|
153
|
+
className = "",
|
|
154
|
+
greetingClassName = "",
|
|
155
|
+
userNameClassName = "",
|
|
156
|
+
avatarClassName = "",
|
|
157
|
+
notificationButtonClassName = ""
|
|
158
|
+
}) {
|
|
159
|
+
const displayName = `${user?.firstName || ""} ${user?.lastName || ""}`.trim() || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
|
|
160
|
+
const firstChar = user?.firstName?.charAt(0) || "\u0E1C";
|
|
161
|
+
const [isNotificationsOpen, setIsNotificationsOpen] = useState(false);
|
|
162
|
+
const notificationRef = useRef(null);
|
|
163
|
+
const handleToggleSidebar = () => {
|
|
164
|
+
toggleSidebar(sidebarId, overlayId);
|
|
165
|
+
};
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
const handleClickOutside = (event) => {
|
|
168
|
+
if (notificationRef.current && !notificationRef.current.contains(event.target)) {
|
|
169
|
+
setIsNotificationsOpen(false);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
173
|
+
return () => {
|
|
174
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
175
|
+
};
|
|
176
|
+
}, []);
|
|
177
|
+
const unreadCount = notifications.filter((n) => !n.isRead).length;
|
|
178
|
+
return /* @__PURE__ */ jsx("header", { className: `bg-white shadow-sm sticky top-0 z-10 lg:static ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3.5", children: [
|
|
179
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
180
|
+
user?.pictureUrl ? /* @__PURE__ */ jsx(
|
|
181
|
+
"img",
|
|
182
|
+
{
|
|
183
|
+
src: user.pictureUrl,
|
|
184
|
+
alt: displayName,
|
|
185
|
+
width: 44,
|
|
186
|
+
height: 44,
|
|
187
|
+
className: `rounded-full object-cover border-2 border-brand-surface w-[44px] h-[44px] ${avatarClassName}`
|
|
188
|
+
}
|
|
189
|
+
) : /* @__PURE__ */ jsx("div", { className: `w-11 h-11 bg-gradient-to-br from-brand-secondary to-brand-primary rounded-full flex items-center justify-center shadow-sm ${avatarClassName}`, children: /* @__PURE__ */ jsx("span", { className: "text-white text-lg font-semibold", children: firstChar }) }),
|
|
190
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-brand-text-dark", children: [
|
|
191
|
+
/* @__PURE__ */ jsx("span", { className: greetingClassName, children: "\u0E2A\u0E27\u0E31\u0E2A\u0E14\u0E35," }),
|
|
192
|
+
" ",
|
|
193
|
+
/* @__PURE__ */ jsx("span", { className: `text-brand-primary ${userNameClassName}`, children: displayName })
|
|
194
|
+
] }) })
|
|
195
|
+
] }),
|
|
196
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
197
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", ref: notificationRef, children: [
|
|
198
|
+
notificationBell || /* @__PURE__ */ jsxs(
|
|
199
|
+
"button",
|
|
200
|
+
{
|
|
201
|
+
className: `p-2.5 rounded-lg transition-colors hover:bg-gray-100 relative ${notificationButtonClassName}`,
|
|
202
|
+
onClick: () => setIsNotificationsOpen(!isNotificationsOpen),
|
|
203
|
+
children: [
|
|
204
|
+
/* @__PURE__ */ jsx("svg", { width: "22", height: "24", viewBox: "0 0 22 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M21.2321 13.4463L19.3618 6.71712C18.8136 4.74574 17.6222 3.01418 15.9769 1.79767C14.3316 0.581165 12.3269 -0.0504751 10.2814 0.00315377C8.23593 0.0567826 6.26708 0.792603 4.6878 2.09365C3.10852 3.3947 2.00945 5.18632 1.5653 7.18371L0.11728 13.6954C-0.0426654 14.4149 -0.0389674 15.1611 0.128101 15.879C0.29517 16.5969 0.621344 17.2681 1.08254 17.8431C1.54374 18.418 2.12818 18.8821 2.79272 19.2009C3.45727 19.5198 4.18494 19.6853 4.92202 19.6853H6.01861C6.24454 20.7979 6.84817 21.7982 7.72723 22.5167C8.60629 23.2352 9.70671 23.6277 10.842 23.6277C11.9774 23.6277 13.0778 23.2352 13.9569 22.5167C14.8359 21.7982 15.4396 20.7979 15.6655 19.6853H16.4904C17.2492 19.6853 17.9977 19.5099 18.6774 19.1728C19.3572 18.8357 19.9498 18.346 20.409 17.742C20.8682 17.1379 21.1815 16.4359 21.3245 15.6907C21.4674 14.9455 21.4352 14.1774 21.2321 13.4463ZM10.842 21.654C10.2334 21.6515 9.64049 21.461 9.1443 21.1086C8.6481 20.7562 8.27291 20.2591 8.07005 19.6853H13.614C13.4112 20.2591 13.036 20.7562 12.5398 21.1086C12.0436 21.461 11.4506 21.6515 10.842 21.654ZM18.8411 16.55C18.5668 16.9139 18.2114 17.2088 17.8032 17.4113C17.3949 17.6138 16.9451 17.7183 16.4894 17.7165H4.92202C4.47982 17.7164 4.04328 17.6171 3.64463 17.4257C3.24598 17.2344 2.89539 16.9559 2.61874 16.611C2.34208 16.266 2.14643 15.8633 2.04622 15.4326C1.94602 15.0019 1.94381 14.5542 2.03977 14.1226L3.4868 7.60994C3.83561 6.04105 4.69886 4.63379 5.93932 3.61186C7.17978 2.58992 8.72625 2.01197 10.3329 1.96988C11.9395 1.92779 13.5142 2.42398 14.8064 3.37956C16.0987 4.33515 17.0344 5.69528 17.4649 7.24376L19.3352 13.9729C19.4588 14.4114 19.4785 14.8725 19.3927 15.3199C19.3069 15.7672 19.1181 16.1884 18.8411 16.55Z", className: "fill-brand-text-dark" }) }),
|
|
205
|
+
unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute top-1.5 right-1.5 min-w-[18px] h-[18px] bg-semantic-critical rounded-full flex items-center justify-center text-[10px] font-bold text-white px-1 border-2 border-white", children: unreadCount })
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
),
|
|
209
|
+
isNotificationsOpen && /* @__PURE__ */ jsx(
|
|
210
|
+
NotificationList,
|
|
211
|
+
{
|
|
212
|
+
notifications,
|
|
213
|
+
isOpen: true,
|
|
214
|
+
onClose: () => setIsNotificationsOpen(false)
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
] }),
|
|
218
|
+
/* @__PURE__ */ jsx(
|
|
219
|
+
"button",
|
|
220
|
+
{
|
|
221
|
+
onClick: handleToggleSidebar,
|
|
222
|
+
className: "p-2.5 rounded-lg transition-colors hover:bg-gray-100",
|
|
223
|
+
children: /* @__PURE__ */ jsx("svg", { width: "27", height: "18", viewBox: "0 0 27 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M1.1875 17.8426C0.851042 17.8426 0.569077 17.7287 0.341604 17.501C0.113868 17.2735 0 16.9914 0 16.6547C0 16.3182 0.113868 16.0363 0.341604 15.8088C0.569077 15.5816 0.851042 15.468 1.1875 15.468H25.7292C26.0656 15.468 26.3476 15.5817 26.5751 15.8092C26.8028 16.0369 26.9167 16.3192 26.9167 16.6559C26.9167 16.9923 26.8028 17.2743 26.5751 17.5018C26.3476 17.729 26.0656 17.8426 25.7292 17.8426H1.1875ZM1.1875 10.1088C0.851042 10.1088 0.569077 9.99492 0.341604 9.76719C0.113868 9.53945 0 9.25735 0 8.9209C0 8.58417 0.113868 8.30221 0.341604 8.075C0.569077 7.84753 0.851042 7.73379 1.1875 7.73379H25.7292C26.0656 7.73379 26.3476 7.84766 26.5751 8.0754C26.8028 8.30313 26.9167 8.58523 26.9167 8.92169C26.9167 9.25841 26.8028 9.54037 26.5751 9.76758C26.3476 9.99506 26.0656 10.1088 25.7292 10.1088H1.1875ZM1.1875 2.3746C0.851042 2.3746 0.569077 2.26087 0.341604 2.0334C0.113868 1.80566 0 1.52343 0 1.18671C0 0.850249 0.113868 0.568284 0.341604 0.340812C0.569077 0.113604 0.851042 0 1.1875 0H25.7292C26.0656 0 26.3476 0.113868 26.5751 0.341604C26.8028 0.569077 26.9167 0.851174 26.9167 1.1879C26.9167 1.52435 26.8028 1.80632 26.5751 2.03379C26.3476 2.261 26.0656 2.3746 25.7292 2.3746H1.1875Z", className: "fill-brand-text-dark" }) })
|
|
224
|
+
}
|
|
225
|
+
)
|
|
226
|
+
] })
|
|
227
|
+
] }) });
|
|
228
|
+
}
|
|
45
229
|
function UserProfile({
|
|
46
230
|
user,
|
|
47
231
|
roleLabel,
|
|
@@ -201,6 +385,6 @@ function SharedSidebar({
|
|
|
201
385
|
] });
|
|
202
386
|
}
|
|
203
387
|
|
|
204
|
-
export { LogoutButton, MenuList, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
|
388
|
+
export { Header, LogoutButton, MenuList, SharedSidebar, UserProfile, closeSidebar, openSidebar, toggleSidebar };
|
|
205
389
|
//# sourceMappingURL=index.mjs.map
|
|
206
390
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +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":"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","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"]}
|
|
1
|
+
{"version":3,"sources":["../src/sidebar/utils.ts","../src/header/NotificationList.tsx","../src/header/Header.tsx","../src/sidebar/UserProfile.tsx","../src/sidebar/MenuList.tsx","../src/sidebar/LogoutButton.tsx","../src/sidebar/SharedSidebar.tsx"],"names":["useRef","useEffect","jsx","jsxs","closeSidebar"],"mappings":"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","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\nimport { useRef, useEffect } from 'react';\r\n\r\nexport interface NotificationItem {\r\n id: string | number;\r\n title: string;\r\n description: string;\r\n date: string;\r\n type: 'info' | 'success' | 'warning' | 'error' | 'reminder';\r\n isRead: boolean;\r\n}\r\n\r\ninterface NotificationListProps {\r\n notifications: NotificationItem[];\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onMarkAllRead?: () => void;\r\n onViewAll?: () => void;\r\n}\r\n\r\nexport default function NotificationList({\r\n notifications,\r\n isOpen,\r\n onClose,\r\n onMarkAllRead,\r\n onViewAll\r\n}: NotificationListProps) {\r\n const listRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (listRef.current && !listRef.current.contains(event.target as Node)) {\r\n onClose();\r\n }\r\n };\r\n\r\n if (isOpen) {\r\n document.addEventListener('mousedown', handleClickOutside);\r\n }\r\n\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside);\r\n };\r\n }, [isOpen, onClose]);\r\n\r\n if (!isOpen) return null;\r\n\r\n return (\r\n <div\r\n ref={listRef}\r\n className=\"absolute right-0 mt-2 w-80 sm:w-96 bg-white rounded-xl shadow-lg ring-1 ring-black ring-opacity-5 z-50 overflow-hidden transform origin-top-right transition-all\"\r\n >\r\n <div className=\"p-4 border-b border-gray-100 flex items-center justify-between bg-gray-50/50\">\r\n <h3 className=\"font-semibold text-gray-900\">การแจ้งเตือน</h3>\r\n {onMarkAllRead && (\r\n <button\r\n onClick={onMarkAllRead}\r\n className=\"text-xs text-brand-primary hover:text-brand-secondary font-medium transition-colors\"\r\n >\r\n อ่านทั้งหมด\r\n </button>\r\n )}\r\n </div>\r\n\r\n <div className=\"max-h-[70vh] overflow-y-auto\">\r\n {notifications.length === 0 ? (\r\n <div className=\"p-8 text-center text-gray-500 flex flex-col items-center gap-3\">\r\n <div className=\"w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center text-2xl\">\r\n 🔔\r\n </div>\r\n <p>ไม่มีการแจ้งเตือนใหม่</p>\r\n </div>\r\n ) : (\r\n <div className=\"divide-y divide-gray-50\">\r\n {notifications.map((item) => (\r\n <div\r\n key={item.id}\r\n className={`p-4 hover:bg-gray-50 transition-colors cursor-pointer relative group ${!item.isRead ? 'bg-blue-50/30' : ''}`}\r\n >\r\n {!item.isRead && (\r\n <span className=\"absolute top-4 right-4 w-2 h-2 bg-red-500 rounded-full ring-2 ring-white\"></span>\r\n )}\r\n <div className=\"flex gap-3 items-start\">\r\n <div className={`mt-0.5 w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${getIconBgClass(item.type)}`}>\r\n <span className=\"text-sm\">{getIcon(item.type)}</span>\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className={`text-sm font-medium text-gray-900 mb-0.5 ${!item.isRead ? 'font-semibold' : ''}`}>\r\n {item.title}\r\n </p>\r\n <p className=\"text-xs text-gray-500 line-clamp-2 mb-1.5 leading-relaxed\">\r\n {item.description}\r\n </p>\r\n <p className=\"text-[10px] text-gray-400 font-medium\">\r\n {item.date}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {onViewAll && (\r\n <div className=\"p-3 bg-gray-50 border-t border-gray-100 text-center\">\r\n <button\r\n onClick={onViewAll}\r\n className=\"text-sm text-gray-600 hover:text-brand-primary font-medium transition-colors w-full py-1\"\r\n >\r\n ดูทั้งหมด\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction getIconBgClass(type: NotificationItem['type']) {\r\n switch (type) {\r\n case 'success': return 'bg-green-100 text-green-600';\r\n case 'warning': return 'bg-yellow-100 text-yellow-600';\r\n case 'error': return 'bg-red-100 text-red-600';\r\n case 'reminder': return 'bg-purple-100 text-purple-600';\r\n default: return 'bg-blue-100 text-blue-600';\r\n }\r\n}\r\n\r\nfunction getIcon(type: NotificationItem['type']) {\r\n switch (type) {\r\n case 'success': return '✓';\r\n case 'warning': return '!';\r\n case 'error': return '✕';\r\n case 'reminder': return '⏰';\r\n default: return 'i';\r\n }\r\n}\r\n","'use client';\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport { toggleSidebar } from '../sidebar/utils';\r\nimport NotificationList, { NotificationItem } from './NotificationList';\r\nexport type { NotificationItem };\r\n\r\ninterface HeaderProps {\r\n user?: {\r\n firstName?: string;\r\n lastName?: string;\r\n pictureUrl?: string;\r\n };\r\n sidebarId?: string;\r\n overlayId?: string;\r\n notificationBell?: React.ReactNode;\r\n notifications?: NotificationItem[];\r\n // Customization Props\r\n className?: string; // Main container\r\n greetingClassName?: string; // \"สวัสดี,\" text\r\n userNameClassName?: string; // User's name\r\n avatarClassName?: string; // User's avatar/initials container\r\n notificationButtonClassName?: string; // Notification bell button\r\n}\r\n\r\nexport default function Header({\r\n user,\r\n sidebarId = 'sidebar',\r\n overlayId = 'sidebar-overlay',\r\n notificationBell,\r\n notifications = [],\r\n // Styles\r\n className = '',\r\n greetingClassName = '',\r\n userNameClassName = '',\r\n avatarClassName = '',\r\n notificationButtonClassName = ''\r\n}: HeaderProps) {\r\n const displayName = `${user?.firstName || ''} ${user?.lastName || ''}`.trim() || 'ผู้ใช้';\r\n const firstChar = user?.firstName?.charAt(0) || 'ผ';\r\n const [isNotificationsOpen, setIsNotificationsOpen] = useState(false);\r\n const notificationRef = useRef<HTMLDivElement>(null);\r\n\r\n const handleToggleSidebar = () => {\r\n toggleSidebar(sidebarId, overlayId);\r\n };\r\n\r\n // Close dropdown when clicking outside\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (notificationRef.current && !notificationRef.current.contains(event.target as Node)) {\r\n setIsNotificationsOpen(false);\r\n }\r\n };\r\n\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside);\r\n };\r\n }, []);\r\n\r\n const unreadCount = notifications.filter(n => !n.isRead).length;\r\n\r\n return (\r\n <header className={`bg-white shadow-sm sticky top-0 z-10 lg:static ${className}`}>\r\n <div className=\"flex items-center justify-between px-5 py-3.5\">\r\n {/* Avatar & Name */}\r\n <div className=\"flex items-center gap-3\">\r\n {user?.pictureUrl ? (\r\n <img\r\n src={user.pictureUrl}\r\n alt={displayName}\r\n width={44}\r\n height={44}\r\n className={`rounded-full object-cover border-2 border-brand-surface w-[44px] h-[44px] ${avatarClassName}`}\r\n />\r\n ) : (\r\n <div className={`w-11 h-11 bg-gradient-to-br from-brand-secondary to-brand-primary rounded-full flex items-center justify-center shadow-sm ${avatarClassName}`}>\r\n <span className=\"text-white text-lg font-semibold\">\r\n {firstChar}\r\n </span>\r\n </div>\r\n )}\r\n <div>\r\n <p className=\"text-sm font-semibold text-brand-text-dark\">\r\n <span className={greetingClassName}>สวัสดี,</span> <span className={`text-brand-primary ${userNameClassName}`}>{displayName}</span>\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Right Side Buttons */}\r\n <div className=\"flex items-center gap-1\">\r\n {/* Notification Bell (optional or default with dropdown) */}\r\n <div className=\"relative\" ref={notificationRef}>\r\n {notificationBell || (\r\n <button\r\n className={`p-2.5 rounded-lg transition-colors hover:bg-gray-100 relative ${notificationButtonClassName}`}\r\n onClick={() => setIsNotificationsOpen(!isNotificationsOpen)}\r\n >\r\n <svg width=\"22\" height=\"24\" viewBox=\"0 0 22 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M21.2321 13.4463L19.3618 6.71712C18.8136 4.74574 17.6222 3.01418 15.9769 1.79767C14.3316 0.581165 12.3269 -0.0504751 10.2814 0.00315377C8.23593 0.0567826 6.26708 0.792603 4.6878 2.09365C3.10852 3.3947 2.00945 5.18632 1.5653 7.18371L0.11728 13.6954C-0.0426654 14.4149 -0.0389674 15.1611 0.128101 15.879C0.29517 16.5969 0.621344 17.2681 1.08254 17.8431C1.54374 18.418 2.12818 18.8821 2.79272 19.2009C3.45727 19.5198 4.18494 19.6853 4.92202 19.6853H6.01861C6.24454 20.7979 6.84817 21.7982 7.72723 22.5167C8.60629 23.2352 9.70671 23.6277 10.842 23.6277C11.9774 23.6277 13.0778 23.2352 13.9569 22.5167C14.8359 21.7982 15.4396 20.7979 15.6655 19.6853H16.4904C17.2492 19.6853 17.9977 19.5099 18.6774 19.1728C19.3572 18.8357 19.9498 18.346 20.409 17.742C20.8682 17.1379 21.1815 16.4359 21.3245 15.6907C21.4674 14.9455 21.4352 14.1774 21.2321 13.4463ZM10.842 21.654C10.2334 21.6515 9.64049 21.461 9.1443 21.1086C8.6481 20.7562 8.27291 20.2591 8.07005 19.6853H13.614C13.4112 20.2591 13.036 20.7562 12.5398 21.1086C12.0436 21.461 11.4506 21.6515 10.842 21.654ZM18.8411 16.55C18.5668 16.9139 18.2114 17.2088 17.8032 17.4113C17.3949 17.6138 16.9451 17.7183 16.4894 17.7165H4.92202C4.47982 17.7164 4.04328 17.6171 3.64463 17.4257C3.24598 17.2344 2.89539 16.9559 2.61874 16.611C2.34208 16.266 2.14643 15.8633 2.04622 15.4326C1.94602 15.0019 1.94381 14.5542 2.03977 14.1226L3.4868 7.60994C3.83561 6.04105 4.69886 4.63379 5.93932 3.61186C7.17978 2.58992 8.72625 2.01197 10.3329 1.96988C11.9395 1.92779 13.5142 2.42398 14.8064 3.37956C16.0987 4.33515 17.0344 5.69528 17.4649 7.24376L19.3352 13.9729C19.4588 14.4114 19.4785 14.8725 19.3927 15.3199C19.3069 15.7672 19.1181 16.1884 18.8411 16.55Z\" className=\"fill-brand-text-dark\" />\r\n </svg>\r\n {unreadCount > 0 && (\r\n <span className=\"absolute top-1.5 right-1.5 min-w-[18px] h-[18px] bg-semantic-critical rounded-full flex items-center justify-center text-[10px] font-bold text-white px-1 border-2 border-white\">\r\n {unreadCount}\r\n </span>\r\n )}\r\n </button>\r\n )}\r\n\r\n {/* Dropdown */}\r\n {isNotificationsOpen && (\r\n <NotificationList\r\n notifications={notifications}\r\n isOpen={true}\r\n onClose={() => setIsNotificationsOpen(false)}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Menu Button */}\r\n <button\r\n onClick={handleToggleSidebar}\r\n className=\"p-2.5 rounded-lg transition-colors hover:bg-gray-100\"\r\n >\r\n <svg width=\"27\" height=\"18\" viewBox=\"0 0 27 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M1.1875 17.8426C0.851042 17.8426 0.569077 17.7287 0.341604 17.501C0.113868 17.2735 0 16.9914 0 16.6547C0 16.3182 0.113868 16.0363 0.341604 15.8088C0.569077 15.5816 0.851042 15.468 1.1875 15.468H25.7292C26.0656 15.468 26.3476 15.5817 26.5751 15.8092C26.8028 16.0369 26.9167 16.3192 26.9167 16.6559C26.9167 16.9923 26.8028 17.2743 26.5751 17.5018C26.3476 17.729 26.0656 17.8426 25.7292 17.8426H1.1875ZM1.1875 10.1088C0.851042 10.1088 0.569077 9.99492 0.341604 9.76719C0.113868 9.53945 0 9.25735 0 8.9209C0 8.58417 0.113868 8.30221 0.341604 8.075C0.569077 7.84753 0.851042 7.73379 1.1875 7.73379H25.7292C26.0656 7.73379 26.3476 7.84766 26.5751 8.0754C26.8028 8.30313 26.9167 8.58523 26.9167 8.92169C26.9167 9.25841 26.8028 9.54037 26.5751 9.76758C26.3476 9.99506 26.0656 10.1088 25.7292 10.1088H1.1875ZM1.1875 2.3746C0.851042 2.3746 0.569077 2.26087 0.341604 2.0334C0.113868 1.80566 0 1.52343 0 1.18671C0 0.850249 0.113868 0.568284 0.341604 0.340812C0.569077 0.113604 0.851042 0 1.1875 0H25.7292C26.0656 0 26.3476 0.113868 26.5751 0.341604C26.8028 0.569077 26.9167 0.851174 26.9167 1.1879C26.9167 1.52435 26.8028 1.80632 26.5751 2.03379C26.3476 2.261 26.0656 2.3746 25.7292 2.3746H1.1875Z\" className=\"fill-brand-text-dark\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n </header>\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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gov-components/layout-header-sidebar",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Reusable Header and Sidebar components for React/Next.js projects",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsup",
|
|
20
20
|
"dev": "tsup --watch",
|
|
21
|
-
"lint": "eslint ."
|
|
21
|
+
"lint": "eslint .",
|
|
22
|
+
"prepublishOnly": "npm run build"
|
|
22
23
|
},
|
|
23
24
|
"keywords": [
|
|
24
25
|
"react",
|