gov-layout 1.3.1 → 1.3.4
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 +1 -0
- package/dist/index.js +86 -93
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -222,6 +222,7 @@ const menuItems: MenuItem[] = [
|
|
|
222
222
|
- ✅ Default ตั้งค่าระบบ + ช่วยเหลือ (override ได้)
|
|
223
223
|
- ✅ โปรไฟล์ + ออกจากระบบ ล่างสุดเสมอ
|
|
224
224
|
- ✅ `dividerAfter` เส้นคั่นระหว่างกลุ่ม
|
|
225
|
+
- ✅ ใช้ Standard Avatar Placeholder กรณีที่ไม่มีรูปโปรไฟล์หรือโหลดรูปไม่สำเร็จ (v1.3.2+) 🆕
|
|
225
226
|
|
|
226
227
|
---
|
|
227
228
|
|
package/dist/index.js
CHANGED
|
@@ -625,6 +625,25 @@ function ProfileIcon() {
|
|
|
625
625
|
}
|
|
626
626
|
);
|
|
627
627
|
}
|
|
628
|
+
function AvatarPlaceholder({ size = 40 }) {
|
|
629
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
630
|
+
"div",
|
|
631
|
+
{
|
|
632
|
+
style: {
|
|
633
|
+
width: `${size}px`,
|
|
634
|
+
height: `${size}px`,
|
|
635
|
+
borderRadius: "50%",
|
|
636
|
+
backgroundColor: "#f1f5f9",
|
|
637
|
+
display: "flex",
|
|
638
|
+
alignItems: "center",
|
|
639
|
+
justifyContent: "center",
|
|
640
|
+
flexShrink: 0,
|
|
641
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.05)"
|
|
642
|
+
},
|
|
643
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size * 0.6, height: size * 0.6, viewBox: "0 0 24 24", fill: "#94a3b8", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }) })
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
}
|
|
628
647
|
function SidebarUserProfile({
|
|
629
648
|
user,
|
|
630
649
|
roleLabel,
|
|
@@ -633,6 +652,10 @@ function SidebarUserProfile({
|
|
|
633
652
|
onProfile
|
|
634
653
|
}) {
|
|
635
654
|
const isDark = useDarkMode();
|
|
655
|
+
const [imgError, setImgError] = react.useState(false);
|
|
656
|
+
react.useEffect(() => {
|
|
657
|
+
setImgError(false);
|
|
658
|
+
}, [user?.pictureUrl]);
|
|
636
659
|
if (!user) return null;
|
|
637
660
|
const getFullName = () => {
|
|
638
661
|
if (user.firstName && user.lastName) {
|
|
@@ -640,9 +663,6 @@ function SidebarUserProfile({
|
|
|
640
663
|
}
|
|
641
664
|
return user.firstName || user.lastName || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
|
|
642
665
|
};
|
|
643
|
-
const getInitial = () => {
|
|
644
|
-
return user.firstName?.charAt(0) || user.lastName?.charAt(0) || "?";
|
|
645
|
-
};
|
|
646
666
|
if (collapsed) {
|
|
647
667
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
648
668
|
padding: "12px 8px",
|
|
@@ -658,36 +678,21 @@ function SidebarUserProfile({
|
|
|
658
678
|
onClick: onProfile,
|
|
659
679
|
title: onProfile ? "\u0E14\u0E39\u0E42\u0E1B\u0E23\u0E44\u0E1F\u0E25\u0E4C" : getFullName(),
|
|
660
680
|
style: { cursor: onProfile ? "pointer" : "default" },
|
|
661
|
-
children: user.pictureUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
681
|
+
children: user.pictureUrl && !imgError ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
662
682
|
"img",
|
|
663
683
|
{
|
|
664
684
|
src: user.pictureUrl,
|
|
665
685
|
alt: getFullName(),
|
|
686
|
+
onError: () => setImgError(true),
|
|
666
687
|
style: {
|
|
667
688
|
width: "36px",
|
|
668
689
|
height: "36px",
|
|
669
690
|
borderRadius: "50%",
|
|
670
|
-
objectFit: "cover"
|
|
691
|
+
objectFit: "cover",
|
|
692
|
+
flexShrink: 0
|
|
671
693
|
}
|
|
672
694
|
}
|
|
673
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
674
|
-
"div",
|
|
675
|
-
{
|
|
676
|
-
style: {
|
|
677
|
-
width: "36px",
|
|
678
|
-
height: "36px",
|
|
679
|
-
borderRadius: "50%",
|
|
680
|
-
background: "var(--color-alias-color-brand-primary, #1e7d55)",
|
|
681
|
-
display: "flex",
|
|
682
|
-
alignItems: "center",
|
|
683
|
-
justifyContent: "center",
|
|
684
|
-
color: "#fff",
|
|
685
|
-
fontWeight: 700,
|
|
686
|
-
fontSize: "14px"
|
|
687
|
-
},
|
|
688
|
-
children: getInitial()
|
|
689
|
-
}
|
|
690
|
-
)
|
|
695
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(AvatarPlaceholder, { size: 36 })
|
|
691
696
|
}
|
|
692
697
|
),
|
|
693
698
|
onProfile && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -777,11 +782,12 @@ function SidebarUserProfile({
|
|
|
777
782
|
transition: "opacity 0.15s ease"
|
|
778
783
|
},
|
|
779
784
|
children: [
|
|
780
|
-
user.pictureUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
785
|
+
user.pictureUrl && !imgError ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
781
786
|
"img",
|
|
782
787
|
{
|
|
783
788
|
src: user.pictureUrl,
|
|
784
789
|
alt: getFullName(),
|
|
790
|
+
onError: () => setImgError(true),
|
|
785
791
|
style: {
|
|
786
792
|
width: "40px",
|
|
787
793
|
height: "40px",
|
|
@@ -790,25 +796,7 @@ function SidebarUserProfile({
|
|
|
790
796
|
flexShrink: 0
|
|
791
797
|
}
|
|
792
798
|
}
|
|
793
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
794
|
-
"div",
|
|
795
|
-
{
|
|
796
|
-
style: {
|
|
797
|
-
width: "40px",
|
|
798
|
-
height: "40px",
|
|
799
|
-
borderRadius: "50%",
|
|
800
|
-
background: "var(--color-alias-color-brand-primary, #1e7d55)",
|
|
801
|
-
display: "flex",
|
|
802
|
-
alignItems: "center",
|
|
803
|
-
justifyContent: "center",
|
|
804
|
-
color: "#fff",
|
|
805
|
-
fontWeight: 700,
|
|
806
|
-
fontSize: "16px",
|
|
807
|
-
flexShrink: 0
|
|
808
|
-
},
|
|
809
|
-
children: getInitial()
|
|
810
|
-
}
|
|
811
|
-
),
|
|
799
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(AvatarPlaceholder, { size: 40 }),
|
|
812
800
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
813
801
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: {
|
|
814
802
|
fontWeight: 600,
|
|
@@ -1100,6 +1088,25 @@ function HamburgerIcon() {
|
|
|
1100
1088
|
function MessageOutlinedIcon(props) {
|
|
1101
1089
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", fill: "currentColor", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4h16v12H5.17L4 17.17zm0-2c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm2 10h12v2H6zm0-3h12v2H6zm0-3h12v2H6z" }) });
|
|
1102
1090
|
}
|
|
1091
|
+
function AvatarPlaceholder2({ size = 44 }) {
|
|
1092
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1093
|
+
"div",
|
|
1094
|
+
{
|
|
1095
|
+
style: {
|
|
1096
|
+
width: `${size}px`,
|
|
1097
|
+
height: `${size}px`,
|
|
1098
|
+
borderRadius: "50%",
|
|
1099
|
+
backgroundColor: "#f1f5f9",
|
|
1100
|
+
display: "flex",
|
|
1101
|
+
alignItems: "center",
|
|
1102
|
+
justifyContent: "center",
|
|
1103
|
+
flexShrink: 0,
|
|
1104
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.05)"
|
|
1105
|
+
},
|
|
1106
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size * 0.6, height: size * 0.6, viewBox: "0 0 24 24", fill: "#94a3b8", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }) })
|
|
1107
|
+
}
|
|
1108
|
+
);
|
|
1109
|
+
}
|
|
1103
1110
|
function getNotifBg(type) {
|
|
1104
1111
|
const map = {
|
|
1105
1112
|
success: "#dcfce7",
|
|
@@ -1131,11 +1138,14 @@ function UserHeader({
|
|
|
1131
1138
|
className
|
|
1132
1139
|
}) {
|
|
1133
1140
|
const displayName = `${user?.firstName || ""} ${user?.lastName || ""}`.trim() || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
|
|
1134
|
-
const firstChar = user?.firstName?.charAt(0) || "\u0E1C";
|
|
1135
1141
|
const [isNotifOpen, setIsNotifOpen] = react.useState(false);
|
|
1136
1142
|
const [activeFilter, setActiveFilter] = react.useState("all");
|
|
1137
1143
|
const notifRef = react.useRef(null);
|
|
1138
1144
|
const isDark = useDarkMode();
|
|
1145
|
+
const [imgError, setImgError] = react.useState(false);
|
|
1146
|
+
react.useEffect(() => {
|
|
1147
|
+
setImgError(false);
|
|
1148
|
+
}, [user?.pictureUrl]);
|
|
1139
1149
|
react.useEffect(() => {
|
|
1140
1150
|
const handleClickOutside = (e) => {
|
|
1141
1151
|
if (notifRef.current && !notifRef.current.contains(e.target)) {
|
|
@@ -1198,42 +1208,22 @@ function UserHeader({
|
|
|
1198
1208
|
overflow: "hidden"
|
|
1199
1209
|
},
|
|
1200
1210
|
children: [
|
|
1201
|
-
user?.pictureUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1211
|
+
user?.pictureUrl && !imgError ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1202
1212
|
"img",
|
|
1203
1213
|
{
|
|
1204
1214
|
src: user.pictureUrl,
|
|
1205
1215
|
alt: displayName,
|
|
1216
|
+
onError: () => setImgError(true),
|
|
1206
1217
|
style: {
|
|
1207
1218
|
width: "44px",
|
|
1208
1219
|
height: "44px",
|
|
1209
1220
|
borderRadius: "50%",
|
|
1210
1221
|
objectFit: "cover",
|
|
1211
|
-
border: "2px solid rgba(255,255,255,0.7)"
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1215
|
-
"div",
|
|
1216
|
-
{
|
|
1217
|
-
style: {
|
|
1218
|
-
width: "44px",
|
|
1219
|
-
height: "44px",
|
|
1220
|
-
borderRadius: "50%",
|
|
1221
|
-
background: "rgba(255,255,255,0.2)",
|
|
1222
1222
|
border: "2px solid rgba(255,255,255,0.7)",
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
justifyContent: "center",
|
|
1226
|
-
boxShadow: "0 1px 3px rgba(0,0,0,0.1)"
|
|
1227
|
-
},
|
|
1228
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1229
|
-
"span",
|
|
1230
|
-
{
|
|
1231
|
-
style: { color: "#fff", fontSize: "18px", fontWeight: 600 },
|
|
1232
|
-
children: firstChar
|
|
1233
|
-
}
|
|
1234
|
-
)
|
|
1223
|
+
flexShrink: 0
|
|
1224
|
+
}
|
|
1235
1225
|
}
|
|
1236
|
-
),
|
|
1226
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(AvatarPlaceholder2, { size: 44 }),
|
|
1237
1227
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1238
1228
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1239
1229
|
"p",
|
|
@@ -1625,6 +1615,25 @@ function ProfileIcon2() {
|
|
|
1625
1615
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "7", r: "4" })
|
|
1626
1616
|
] });
|
|
1627
1617
|
}
|
|
1618
|
+
function AvatarPlaceholder3({ size = 56 }) {
|
|
1619
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1620
|
+
"div",
|
|
1621
|
+
{
|
|
1622
|
+
style: {
|
|
1623
|
+
width: `${size}px`,
|
|
1624
|
+
height: `${size}px`,
|
|
1625
|
+
borderRadius: "50%",
|
|
1626
|
+
backgroundColor: "#f1f5f9",
|
|
1627
|
+
display: "flex",
|
|
1628
|
+
alignItems: "center",
|
|
1629
|
+
justifyContent: "center",
|
|
1630
|
+
flexShrink: 0,
|
|
1631
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.05)"
|
|
1632
|
+
},
|
|
1633
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size * 0.6, height: size * 0.6, viewBox: "0 0 24 24", fill: "#94a3b8", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }) })
|
|
1634
|
+
}
|
|
1635
|
+
);
|
|
1636
|
+
}
|
|
1628
1637
|
function UserSidebar({
|
|
1629
1638
|
user,
|
|
1630
1639
|
roleLabel,
|
|
@@ -1637,6 +1646,10 @@ function UserSidebar({
|
|
|
1637
1646
|
onProfile
|
|
1638
1647
|
}) {
|
|
1639
1648
|
const isDark = useDarkMode();
|
|
1649
|
+
const [imgError, setImgError] = react.useState(false);
|
|
1650
|
+
react.useEffect(() => {
|
|
1651
|
+
setImgError(false);
|
|
1652
|
+
}, [user?.pictureUrl]);
|
|
1640
1653
|
react.useEffect(() => {
|
|
1641
1654
|
if (isOpen) {
|
|
1642
1655
|
document.body.style.overflow = "hidden";
|
|
@@ -1652,10 +1665,6 @@ function UserSidebar({
|
|
|
1652
1665
|
if (user.firstName && user.lastName) return `${user.firstName} ${user.lastName}`;
|
|
1653
1666
|
return user.firstName || user.lastName || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
|
|
1654
1667
|
};
|
|
1655
|
-
const getInitial = () => {
|
|
1656
|
-
if (!user) return "?";
|
|
1657
|
-
return user.firstName?.charAt(0) || user.lastName?.charAt(0) || "?";
|
|
1658
|
-
};
|
|
1659
1668
|
const handleMenuClick = (path) => {
|
|
1660
1669
|
onNavigate(path);
|
|
1661
1670
|
onClose();
|
|
@@ -1715,38 +1724,22 @@ function UserSidebar({
|
|
|
1715
1724
|
padding: "8px"
|
|
1716
1725
|
},
|
|
1717
1726
|
children: [
|
|
1718
|
-
user.pictureUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1727
|
+
user.pictureUrl && !imgError ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1719
1728
|
"img",
|
|
1720
1729
|
{
|
|
1721
1730
|
src: user.pictureUrl,
|
|
1722
1731
|
alt: getFullName(),
|
|
1732
|
+
onError: () => setImgError(true),
|
|
1723
1733
|
style: {
|
|
1724
1734
|
width: "56px",
|
|
1725
1735
|
height: "56px",
|
|
1726
1736
|
borderRadius: "50%",
|
|
1727
1737
|
objectFit: "cover",
|
|
1738
|
+
flexShrink: 0,
|
|
1728
1739
|
boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
|
|
1729
1740
|
}
|
|
1730
1741
|
}
|
|
1731
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1732
|
-
"div",
|
|
1733
|
-
{
|
|
1734
|
-
style: {
|
|
1735
|
-
width: "56px",
|
|
1736
|
-
height: "56px",
|
|
1737
|
-
borderRadius: "50%",
|
|
1738
|
-
background: "linear-gradient(135deg, var(--color-alias-color-brand-secondary, #80d897), var(--color-alias-color-brand-primary, #1e7d55))",
|
|
1739
|
-
display: "flex",
|
|
1740
|
-
alignItems: "center",
|
|
1741
|
-
justifyContent: "center",
|
|
1742
|
-
color: "#fff",
|
|
1743
|
-
fontWeight: 700,
|
|
1744
|
-
fontSize: "20px",
|
|
1745
|
-
boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
|
|
1746
|
-
},
|
|
1747
|
-
children: getInitial()
|
|
1748
|
-
}
|
|
1749
|
-
),
|
|
1742
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(AvatarPlaceholder3, { size: 56 }),
|
|
1750
1743
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1751
1744
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1752
1745
|
"p",
|