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/dist/index.mjs CHANGED
@@ -623,6 +623,25 @@ function ProfileIcon() {
623
623
  }
624
624
  );
625
625
  }
626
+ function AvatarPlaceholder({ size = 40 }) {
627
+ return /* @__PURE__ */ jsx(
628
+ "div",
629
+ {
630
+ style: {
631
+ width: `${size}px`,
632
+ height: `${size}px`,
633
+ borderRadius: "50%",
634
+ backgroundColor: "#f1f5f9",
635
+ display: "flex",
636
+ alignItems: "center",
637
+ justifyContent: "center",
638
+ flexShrink: 0,
639
+ boxShadow: "0 2px 8px rgba(0,0,0,0.05)"
640
+ },
641
+ children: /* @__PURE__ */ jsx("svg", { width: size * 0.6, height: size * 0.6, viewBox: "0 0 24 24", fill: "#94a3b8", children: /* @__PURE__ */ 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" }) })
642
+ }
643
+ );
644
+ }
626
645
  function SidebarUserProfile({
627
646
  user,
628
647
  roleLabel,
@@ -631,6 +650,10 @@ function SidebarUserProfile({
631
650
  onProfile
632
651
  }) {
633
652
  const isDark = useDarkMode();
653
+ const [imgError, setImgError] = useState(false);
654
+ useEffect(() => {
655
+ setImgError(false);
656
+ }, [user?.pictureUrl]);
634
657
  if (!user) return null;
635
658
  const getFullName = () => {
636
659
  if (user.firstName && user.lastName) {
@@ -638,9 +661,6 @@ function SidebarUserProfile({
638
661
  }
639
662
  return user.firstName || user.lastName || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
640
663
  };
641
- const getInitial = () => {
642
- return user.firstName?.charAt(0) || user.lastName?.charAt(0) || "?";
643
- };
644
664
  if (collapsed) {
645
665
  return /* @__PURE__ */ jsxs("div", { style: {
646
666
  padding: "12px 8px",
@@ -656,36 +676,21 @@ function SidebarUserProfile({
656
676
  onClick: onProfile,
657
677
  title: onProfile ? "\u0E14\u0E39\u0E42\u0E1B\u0E23\u0E44\u0E1F\u0E25\u0E4C" : getFullName(),
658
678
  style: { cursor: onProfile ? "pointer" : "default" },
659
- children: user.pictureUrl ? /* @__PURE__ */ jsx(
679
+ children: user.pictureUrl && !imgError ? /* @__PURE__ */ jsx(
660
680
  "img",
661
681
  {
662
682
  src: user.pictureUrl,
663
683
  alt: getFullName(),
684
+ onError: () => setImgError(true),
664
685
  style: {
665
686
  width: "36px",
666
687
  height: "36px",
667
688
  borderRadius: "50%",
668
- objectFit: "cover"
689
+ objectFit: "cover",
690
+ flexShrink: 0
669
691
  }
670
692
  }
671
- ) : /* @__PURE__ */ jsx(
672
- "div",
673
- {
674
- style: {
675
- width: "36px",
676
- height: "36px",
677
- borderRadius: "50%",
678
- background: "var(--color-alias-color-brand-primary, #1e7d55)",
679
- display: "flex",
680
- alignItems: "center",
681
- justifyContent: "center",
682
- color: "#fff",
683
- fontWeight: 700,
684
- fontSize: "14px"
685
- },
686
- children: getInitial()
687
- }
688
- )
693
+ ) : /* @__PURE__ */ jsx(AvatarPlaceholder, { size: 36 })
689
694
  }
690
695
  ),
691
696
  onProfile && /* @__PURE__ */ jsx(
@@ -775,11 +780,12 @@ function SidebarUserProfile({
775
780
  transition: "opacity 0.15s ease"
776
781
  },
777
782
  children: [
778
- user.pictureUrl ? /* @__PURE__ */ jsx(
783
+ user.pictureUrl && !imgError ? /* @__PURE__ */ jsx(
779
784
  "img",
780
785
  {
781
786
  src: user.pictureUrl,
782
787
  alt: getFullName(),
788
+ onError: () => setImgError(true),
783
789
  style: {
784
790
  width: "40px",
785
791
  height: "40px",
@@ -788,25 +794,7 @@ function SidebarUserProfile({
788
794
  flexShrink: 0
789
795
  }
790
796
  }
791
- ) : /* @__PURE__ */ jsx(
792
- "div",
793
- {
794
- style: {
795
- width: "40px",
796
- height: "40px",
797
- borderRadius: "50%",
798
- background: "var(--color-alias-color-brand-primary, #1e7d55)",
799
- display: "flex",
800
- alignItems: "center",
801
- justifyContent: "center",
802
- color: "#fff",
803
- fontWeight: 700,
804
- fontSize: "16px",
805
- flexShrink: 0
806
- },
807
- children: getInitial()
808
- }
809
- ),
797
+ ) : /* @__PURE__ */ jsx(AvatarPlaceholder, { size: 40 }),
810
798
  /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
811
799
  /* @__PURE__ */ jsx("p", { style: {
812
800
  fontWeight: 600,
@@ -1098,6 +1086,25 @@ function HamburgerIcon() {
1098
1086
  function MessageOutlinedIcon(props) {
1099
1087
  return /* @__PURE__ */ jsx("svg", { focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", fill: "currentColor", ...props, children: /* @__PURE__ */ 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" }) });
1100
1088
  }
1089
+ function AvatarPlaceholder2({ size = 44 }) {
1090
+ return /* @__PURE__ */ jsx(
1091
+ "div",
1092
+ {
1093
+ style: {
1094
+ width: `${size}px`,
1095
+ height: `${size}px`,
1096
+ borderRadius: "50%",
1097
+ backgroundColor: "#f1f5f9",
1098
+ display: "flex",
1099
+ alignItems: "center",
1100
+ justifyContent: "center",
1101
+ flexShrink: 0,
1102
+ boxShadow: "0 2px 8px rgba(0,0,0,0.05)"
1103
+ },
1104
+ children: /* @__PURE__ */ jsx("svg", { width: size * 0.6, height: size * 0.6, viewBox: "0 0 24 24", fill: "#94a3b8", children: /* @__PURE__ */ 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" }) })
1105
+ }
1106
+ );
1107
+ }
1101
1108
  function getNotifBg(type) {
1102
1109
  const map = {
1103
1110
  success: "#dcfce7",
@@ -1129,11 +1136,14 @@ function UserHeader({
1129
1136
  className
1130
1137
  }) {
1131
1138
  const displayName = `${user?.firstName || ""} ${user?.lastName || ""}`.trim() || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
1132
- const firstChar = user?.firstName?.charAt(0) || "\u0E1C";
1133
1139
  const [isNotifOpen, setIsNotifOpen] = useState(false);
1134
1140
  const [activeFilter, setActiveFilter] = useState("all");
1135
1141
  const notifRef = useRef(null);
1136
1142
  const isDark = useDarkMode();
1143
+ const [imgError, setImgError] = useState(false);
1144
+ useEffect(() => {
1145
+ setImgError(false);
1146
+ }, [user?.pictureUrl]);
1137
1147
  useEffect(() => {
1138
1148
  const handleClickOutside = (e) => {
1139
1149
  if (notifRef.current && !notifRef.current.contains(e.target)) {
@@ -1196,42 +1206,22 @@ function UserHeader({
1196
1206
  overflow: "hidden"
1197
1207
  },
1198
1208
  children: [
1199
- user?.pictureUrl ? /* @__PURE__ */ jsx(
1209
+ user?.pictureUrl && !imgError ? /* @__PURE__ */ jsx(
1200
1210
  "img",
1201
1211
  {
1202
1212
  src: user.pictureUrl,
1203
1213
  alt: displayName,
1214
+ onError: () => setImgError(true),
1204
1215
  style: {
1205
1216
  width: "44px",
1206
1217
  height: "44px",
1207
1218
  borderRadius: "50%",
1208
1219
  objectFit: "cover",
1209
- border: "2px solid rgba(255,255,255,0.7)"
1210
- }
1211
- }
1212
- ) : /* @__PURE__ */ jsx(
1213
- "div",
1214
- {
1215
- style: {
1216
- width: "44px",
1217
- height: "44px",
1218
- borderRadius: "50%",
1219
- background: "rgba(255,255,255,0.2)",
1220
1220
  border: "2px solid rgba(255,255,255,0.7)",
1221
- display: "flex",
1222
- alignItems: "center",
1223
- justifyContent: "center",
1224
- boxShadow: "0 1px 3px rgba(0,0,0,0.1)"
1225
- },
1226
- children: /* @__PURE__ */ jsx(
1227
- "span",
1228
- {
1229
- style: { color: "#fff", fontSize: "18px", fontWeight: 600 },
1230
- children: firstChar
1231
- }
1232
- )
1221
+ flexShrink: 0
1222
+ }
1233
1223
  }
1234
- ),
1224
+ ) : /* @__PURE__ */ jsx(AvatarPlaceholder2, { size: 44 }),
1235
1225
  /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1236
1226
  /* @__PURE__ */ jsxs(
1237
1227
  "p",
@@ -1623,6 +1613,25 @@ function ProfileIcon2() {
1623
1613
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "7", r: "4" })
1624
1614
  ] });
1625
1615
  }
1616
+ function AvatarPlaceholder3({ size = 56 }) {
1617
+ return /* @__PURE__ */ jsx(
1618
+ "div",
1619
+ {
1620
+ style: {
1621
+ width: `${size}px`,
1622
+ height: `${size}px`,
1623
+ borderRadius: "50%",
1624
+ backgroundColor: "#f1f5f9",
1625
+ display: "flex",
1626
+ alignItems: "center",
1627
+ justifyContent: "center",
1628
+ flexShrink: 0,
1629
+ boxShadow: "0 2px 8px rgba(0,0,0,0.05)"
1630
+ },
1631
+ children: /* @__PURE__ */ jsx("svg", { width: size * 0.6, height: size * 0.6, viewBox: "0 0 24 24", fill: "#94a3b8", children: /* @__PURE__ */ 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" }) })
1632
+ }
1633
+ );
1634
+ }
1626
1635
  function UserSidebar({
1627
1636
  user,
1628
1637
  roleLabel,
@@ -1635,6 +1644,10 @@ function UserSidebar({
1635
1644
  onProfile
1636
1645
  }) {
1637
1646
  const isDark = useDarkMode();
1647
+ const [imgError, setImgError] = useState(false);
1648
+ useEffect(() => {
1649
+ setImgError(false);
1650
+ }, [user?.pictureUrl]);
1638
1651
  useEffect(() => {
1639
1652
  if (isOpen) {
1640
1653
  document.body.style.overflow = "hidden";
@@ -1650,10 +1663,6 @@ function UserSidebar({
1650
1663
  if (user.firstName && user.lastName) return `${user.firstName} ${user.lastName}`;
1651
1664
  return user.firstName || user.lastName || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
1652
1665
  };
1653
- const getInitial = () => {
1654
- if (!user) return "?";
1655
- return user.firstName?.charAt(0) || user.lastName?.charAt(0) || "?";
1656
- };
1657
1666
  const handleMenuClick = (path) => {
1658
1667
  onNavigate(path);
1659
1668
  onClose();
@@ -1713,38 +1722,22 @@ function UserSidebar({
1713
1722
  padding: "8px"
1714
1723
  },
1715
1724
  children: [
1716
- user.pictureUrl ? /* @__PURE__ */ jsx(
1725
+ user.pictureUrl && !imgError ? /* @__PURE__ */ jsx(
1717
1726
  "img",
1718
1727
  {
1719
1728
  src: user.pictureUrl,
1720
1729
  alt: getFullName(),
1730
+ onError: () => setImgError(true),
1721
1731
  style: {
1722
1732
  width: "56px",
1723
1733
  height: "56px",
1724
1734
  borderRadius: "50%",
1725
1735
  objectFit: "cover",
1736
+ flexShrink: 0,
1726
1737
  boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
1727
1738
  }
1728
1739
  }
1729
- ) : /* @__PURE__ */ jsx(
1730
- "div",
1731
- {
1732
- style: {
1733
- width: "56px",
1734
- height: "56px",
1735
- borderRadius: "50%",
1736
- background: "linear-gradient(135deg, var(--color-alias-color-brand-secondary, #80d897), var(--color-alias-color-brand-primary, #1e7d55))",
1737
- display: "flex",
1738
- alignItems: "center",
1739
- justifyContent: "center",
1740
- color: "#fff",
1741
- fontWeight: 700,
1742
- fontSize: "20px",
1743
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
1744
- },
1745
- children: getInitial()
1746
- }
1747
- ),
1740
+ ) : /* @__PURE__ */ jsx(AvatarPlaceholder3, { size: 56 }),
1748
1741
  /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1749
1742
  /* @__PURE__ */ jsx(
1750
1743
  "p",