@codebit-programando-solucoes/codebit-web-antd 1.1.45 → 1.1.47

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.
@@ -4,6 +4,8 @@ import * as React from 'react';
4
4
  export interface LoggedMainContainerProps {
5
5
  /** Content to render in the main area */
6
6
  children: React.ReactNode;
7
+ /** Viewport width (px) below which the layout switches to the mobile drawer/header. Defaults to `768`. */
8
+ mobileBreakpoint?: number;
7
9
  }
8
10
 
9
11
  /**
@@ -17,7 +19,7 @@ export interface LoggedMainContainerProps {
17
19
  * - Role‑based menu filtering
18
20
  * - User logout functionality
19
21
  * - Application version display
20
- * - Header user-profile avatar/dropdown (see `UserMenu`), built from the `userMenuItems` config function
22
+ * - A `headerExtra` slot occupying the header's entire right-hand side — the host app composes its own theme toggle, user menu, etc. there (see `ThemeToggle`, `UserMenu`)
21
23
  *
22
24
  * This component must be used within a `CodebitConfigProvider` and `CodebitThemeContext` context to access configuration such as menu items, user data, and theme settings.
23
25
  *
@@ -62,21 +62,20 @@ export interface CodebitConfigContextType {
62
62
  /** Function that returns menu items configuration for items displayed above the logout button in the bottom menu. */
63
63
  bottomMenuItems?: (user?: LoggedUser) => MenuItem[];
64
64
  /**
65
- * Function that returns menu items configuration for the header user-menu dropdown (opened by clicking the user avatar next to the theme toggle). Takes an optional
66
- * `LoggedUser` object as parameter and returns an array of `MenuItem` objects. Clicks on these items invoke `onMenuClick` with the item's key, but — unlike
67
- * `menuItems`/`bottomMenuItems` — never trigger the built-in navigation/logout behavior; the host application is fully responsible for reacting to the click (e.g. opening a
68
- * modal).
65
+ * Renders the entire right-hand side of the header (where the theme toggle and user menu used to be hardcoded). Receives the current `LoggedUser` and returns whatever the host
66
+ * application wants there — typically `<ThemeToggle />`, a `<UserMenu />` built from its own items/click handling, and any app-specific controls, composed together. The
67
+ * library no longer assembles this area itself; `ThemeToggle` and `UserMenu` remain exported so the host app can reuse them.
69
68
  */
70
- userMenuItems?: (user?: LoggedUser) => MenuItem[];
69
+ headerExtra?: (user?: LoggedUser) => React.ReactNode;
71
70
  /**
72
- * Function invoked when a menu item is clicked. Receives the item's key.
73
- *
74
- * For clicks originating from `menuItems`/`bottomMenuItems` (sidebar navigation), the return value controls the built-in behavior:
71
+ * Function invoked when a menu item is clicked. Receives the item's key. Only covers `menuItems`/`bottomMenuItems` (sidebar navigation) clicks — the return value controls the
72
+ * built-in behavior:
75
73
  *
76
74
  * - Returning **`false`** cancels the internal action (navigation or logout).
77
75
  * - Returning **`true`** (or any other truthy value) lets the internal processing continue as usual.
78
76
  *
79
- * For clicks originating from `userMenuItems` (header user-menu dropdown), there is no built-in action to cancel — the return value is ignored for these clicks.
77
+ * Clicks inside `headerExtra`'s content (e.g. a `UserMenu` composed there) are entirely the host application's responsibility — they don't go through this callback unless the
78
+ * host app chooses to wire it up that way itself.
80
79
  */
81
80
  onMenuClick?: (key: string) => boolean;
82
81
  }
@@ -97,24 +96,19 @@ export interface CodebitConfigProviderProps {
97
96
  secondarySidebarWidth?: number;
98
97
  /** Function that returns bottom‑menu items. */
99
98
  bottomMenuItems?: (user?: LoggedUser) => MenuItem[];
100
- /**
101
- * Function that returns items for the header user-menu dropdown (e.g. a "Minhas preferências" entry). Clicks on these items invoke `onMenuClick` but never trigger the
102
- * built-in navigation/logout behavior — the host application is fully responsible for reacting to the click (e.g. opening a modal).
103
- */
104
- userMenuItems?: (user?: LoggedUser) => MenuItem[];
99
+ /** Renders the entire right-hand side of the header. See {@link CodebitConfigContextType.headerExtra} — same contract, this is just the prop the host app passes in. */
100
+ headerExtra?: (user?: LoggedUser) => React.ReactNode;
105
101
  /** Function to handle user logout. */
106
102
  doLogout: () => Promise<void>;
107
103
  /** Function to check login status and return user data. */
108
104
  checkLogin: () => Promise<any | null>;
109
105
  /**
110
- * Callback executed when a menu item is clicked. Receives the item's key.
111
- *
112
- * For `menuItems`/`bottomMenuItems` clicks (sidebar navigation):
106
+ * Callback executed when a menu item is clicked. Receives the item's key. Only covers `menuItems`/`bottomMenuItems` (sidebar navigation) clicks:
113
107
  *
114
108
  * - Return **`false`** to **prevent** the default internal handling (navigation, logout, etc.).
115
109
  * - Return **`true`** (or any truthy value) to allow the default processing to proceed.
116
110
  *
117
- * For `userMenuItems` clicks (header user-menu dropdown), the return value is ignored — there is no default action to prevent.
111
+ * Clicks inside `headerExtra`'s content are not routed through this callback automatically — wire that up yourself if you want to reuse the same handler.
118
112
  */
119
113
  onMenuClick?: (key: string) => boolean;
120
114
  }
package/dist/index.cjs CHANGED
@@ -620,7 +620,7 @@ var __webpack_exports__ = {};
620
620
  const codebit_web_namespaceObject = require("@codebit-programando-solucoes/codebit-web");
621
621
  const logger = new codebit_web_namespaceObject.Logger('CodebitConfigContext');
622
622
  const CodebitConfigContext = /*#__PURE__*/ (0, external_react_.createContext)(null);
623
- function CodebitConfigProvider({ children, menuItems, version = '1.0', showVersion = ()=>true, secondarySidebar, secondarySidebarWidth = 280, bottomMenuItems, userMenuItems, doLogout, checkLogin, onMenuClick }) {
623
+ function CodebitConfigProvider({ children, menuItems, version = '1.0', showVersion = ()=>true, secondarySidebar, secondarySidebarWidth = 280, bottomMenuItems, headerExtra, doLogout, checkLogin, onMenuClick }) {
624
624
  const [isLogged, setIsLogged] = (0, external_react_.useState)(null);
625
625
  const [user, setUser] = (0, external_react_.useState)(null);
626
626
  const logout = async ()=>{
@@ -665,7 +665,7 @@ var __webpack_exports__ = {};
665
665
  secondarySidebar,
666
666
  secondarySidebarWidth,
667
667
  bottomMenuItems,
668
- userMenuItems,
668
+ headerExtra,
669
669
  onMenuClick
670
670
  }), [
671
671
  menuItems,
@@ -676,7 +676,7 @@ var __webpack_exports__ = {};
676
676
  secondarySidebar,
677
677
  secondarySidebarWidth,
678
678
  bottomMenuItems,
679
- userMenuItems,
679
+ headerExtra,
680
680
  onMenuClick
681
681
  ]);
682
682
  return /*#__PURE__*/ (0, jsx_runtime.jsx)(CodebitConfigContext.Provider, {
@@ -692,7 +692,7 @@ var __webpack_exports__ = {};
692
692
  secondarySidebar: external_prop_types_default().func,
693
693
  secondarySidebarWidth: external_prop_types_default().number,
694
694
  bottomMenuItems: external_prop_types_default().func,
695
- userMenuItems: external_prop_types_default().func,
695
+ headerExtra: external_prop_types_default().func,
696
696
  doLogout: external_prop_types_default().func.isRequired,
697
697
  checkLogin: external_prop_types_default().func.isRequired,
698
698
  onMenuClick: external_prop_types_default().func
@@ -878,21 +878,26 @@ var __webpack_exports__ = {};
878
878
  }),
879
879
  fontFamily: external_prop_types_default().string
880
880
  };
881
- const ThemeToggle = ()=>{
882
- const config = (0, external_react_.useContext)(CodebitThemeContext);
883
- if (!config) throw new Error('ThemeToggle must be used within CodebitThemeContext');
884
- (0, external_react_.useEffect)(()=>{
885
- document.documentElement.style.colorScheme = config.isDarkMode ? 'dark' : 'light';
886
- }, [
887
- config.isDarkMode
888
- ]);
889
- return /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Switch, {
890
- theme: config.isDarkMode ? 'dark' : 'light',
891
- checked: config.isDarkMode,
892
- onChange: (value)=>config.setIsDarkMode(value),
893
- checkedChildren: /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MoonOutlined, {}),
894
- unCheckedChildren: /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.SunOutlined, {})
895
- });
881
+ const LoggedMainContainer_module = {
882
+ layout: "layout-mL5o6I",
883
+ drawer: "drawer-oj0mJX",
884
+ drawerBody: "drawerBody-YtAN37",
885
+ drawerFlex: "drawerFlex-AGTAax",
886
+ sider: "sider-BDy1Bs",
887
+ siderLayout: "siderLayout-C8H0uI",
888
+ secondarySidebar: "secondarySidebar-P6J_Xn",
889
+ menu: "menu-KMvPt7",
890
+ menuContainer: "menuContainer-ahnhBu",
891
+ menuLabel: "menuLabel-csBJTc",
892
+ menuDescription: "menuDescription-d6BFBO",
893
+ menuSpacer: "menuSpacer-RIB3II",
894
+ versionMenu: "versionMenu-NM4uyG",
895
+ bottomMenu: "bottomMenu-VtOktS",
896
+ header: "header-vgc67L",
897
+ mobile: "mobile-mKGxb5",
898
+ secondarySidebarTrigger: "secondarySidebarTrigger-dD6WGB",
899
+ headerSpace: "headerSpace-Fd_iha",
900
+ content: "content-OZHp2h"
896
901
  };
897
902
  const external_react_i18next_namespaceObject = require("react-i18next");
898
903
  const external_i18next_namespaceObject = require("i18next");
@@ -916,157 +921,7 @@ var __webpack_exports__ = {};
916
921
  const useCodebitWebAntdTranslation = ()=>(0, external_react_i18next_namespaceObject.useTranslation)('codebitWebAntd', {
917
922
  i18n: i18n
918
923
  });
919
- const UserMenu_module = {
920
- trigger: "trigger-tlcps4",
921
- avatar: "avatar-Tmnqa_",
922
- caret: "caret-OWS8_0",
923
- panel: "panel-GCcfCo",
924
- userInfo: "userInfo-fDuDn1",
925
- userName: "userName-sIs1iq",
926
- userSubtitle: "userSubtitle-Fflhaw",
927
- divider: "divider-JJjJVy",
928
- menu: "menu-cuORr_"
929
- };
930
- const OPEN_KEYS = new Set([
931
- 'Enter',
932
- ' '
933
- ]);
934
- const { Text } = external_antd_namespaceObject.Typography;
935
- function getInitials(name) {
936
- const parts = name?.trim().split(/\s+/).filter(Boolean) ?? [];
937
- if (0 === parts.length) return '';
938
- const first = [
939
- ...parts[0]
940
- ];
941
- if (1 === parts.length) return first.slice(0, 2).join('').toUpperCase();
942
- const last = [
943
- ...parts.at(-1)
944
- ];
945
- return `${first[0]}${last[0]}`.toUpperCase();
946
- }
947
- function UserMenuPanel({ user, items, onItemClick }) {
948
- return /*#__PURE__*/ (0, jsx_runtime.jsxs)("div", {
949
- className: UserMenu_module.panel,
950
- children: [
951
- /*#__PURE__*/ (0, jsx_runtime.jsxs)("div", {
952
- className: UserMenu_module.userInfo,
953
- children: [
954
- /*#__PURE__*/ (0, jsx_runtime.jsx)(Text, {
955
- className: UserMenu_module.userName,
956
- strong: true,
957
- children: user?.name
958
- }),
959
- user?.subtitle && /*#__PURE__*/ (0, jsx_runtime.jsx)(Text, {
960
- className: UserMenu_module.userSubtitle,
961
- type: 'secondary',
962
- children: user.subtitle
963
- })
964
- ]
965
- }),
966
- /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Divider, {
967
- className: UserMenu_module.divider
968
- }),
969
- /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Menu, {
970
- className: UserMenu_module.menu,
971
- items: items,
972
- onClick: ({ key })=>onItemClick?.(key)
973
- })
974
- ]
975
- });
976
- }
977
- UserMenuPanel.propTypes = {
978
- user: external_prop_types_default().shape({
979
- name: external_prop_types_default().string,
980
- subtitle: external_prop_types_default().string
981
- }),
982
- items: external_prop_types_default().arrayOf(external_prop_types_default().object).isRequired,
983
- onItemClick: external_prop_types_default().func
984
- };
985
- function createPopupRender(user, items, onItemClick) {
986
- return ()=>/*#__PURE__*/ (0, jsx_runtime.jsx)(UserMenuPanel, {
987
- user: user,
988
- items: items,
989
- onItemClick: onItemClick
990
- });
991
- }
992
- function UserMenu({ user, items = [], onItemClick, caretIcon = /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.DownOutlined, {}) }) {
993
- const { t } = useCodebitWebAntdTranslation();
994
- const [open, setOpen] = (0, external_react_.useState)(false);
995
- const initials = getInitials(user?.name);
996
- const handleItemClick = (key)=>{
997
- setOpen(false);
998
- onItemClick?.(key);
999
- };
1000
- const avatar = /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Avatar, {
1001
- className: UserMenu_module.avatar,
1002
- children: initials || /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.UserOutlined, {})
1003
- });
1004
- if (!items.length) return avatar;
1005
- return /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Dropdown, {
1006
- trigger: [
1007
- 'click'
1008
- ],
1009
- open: open,
1010
- onOpenChange: setOpen,
1011
- placement: 'bottomRight',
1012
- popupRender: createPopupRender(user, items, handleItemClick),
1013
- children: /*#__PURE__*/ (0, jsx_runtime.jsxs)(external_antd_namespaceObject.Space, {
1014
- className: UserMenu_module.trigger,
1015
- role: 'button',
1016
- tabIndex: 0,
1017
- "aria-haspopup": 'menu',
1018
- "aria-expanded": open,
1019
- "aria-label": t('UserMenu.openMenu'),
1020
- onKeyDown: (event)=>{
1021
- if (!OPEN_KEYS.has(event.key)) return;
1022
- event.preventDefault();
1023
- setOpen((wasOpen)=>!wasOpen);
1024
- },
1025
- children: [
1026
- avatar,
1027
- /*#__PURE__*/ (0, jsx_runtime.jsx)("span", {
1028
- className: UserMenu_module.caret,
1029
- children: caretIcon
1030
- })
1031
- ]
1032
- })
1033
- });
1034
- }
1035
- UserMenu.propTypes = {
1036
- user: external_prop_types_default().shape({
1037
- name: external_prop_types_default().string,
1038
- email: external_prop_types_default().string,
1039
- id: external_prop_types_default().string,
1040
- roles: external_prop_types_default().arrayOf(external_prop_types_default().string),
1041
- subtitle: external_prop_types_default().string
1042
- }),
1043
- items: external_prop_types_default().arrayOf(external_prop_types_default().object),
1044
- onItemClick: external_prop_types_default().func,
1045
- caretIcon: external_prop_types_default().node
1046
- };
1047
- const LoggedMainContainer_module = {
1048
- layout: "layout-mL5o6I",
1049
- drawer: "drawer-oj0mJX",
1050
- drawerBody: "drawerBody-YtAN37",
1051
- drawerFlex: "drawerFlex-AGTAax",
1052
- sider: "sider-BDy1Bs",
1053
- siderLayout: "siderLayout-C8H0uI",
1054
- secondarySidebar: "secondarySidebar-P6J_Xn",
1055
- menu: "menu-KMvPt7",
1056
- menuContainer: "menuContainer-ahnhBu",
1057
- menuLabel: "menuLabel-csBJTc",
1058
- menuDescription: "menuDescription-d6BFBO",
1059
- menuSpacer: "menuSpacer-RIB3II",
1060
- versionMenu: "versionMenu-NM4uyG",
1061
- bottomMenu: "bottomMenu-VtOktS",
1062
- header: "header-vgc67L",
1063
- mobile: "mobile-mKGxb5",
1064
- headerSpace: "headerSpace-Fd_iha",
1065
- headerDivider: "headerDivider-yfEwNN",
1066
- content: "content-OZHp2h"
1067
- };
1068
924
  const { Header, Sider, Content } = external_antd_namespaceObject.Layout;
1069
- const { Text: LoggedMainContainer_Text } = external_antd_namespaceObject.Typography;
1070
925
  const MENU_KEY_APP_LOGOUT = 'app-logout';
1071
926
  function filterMenuItemsByRole(items, user) {
1072
927
  return items.filter((item)=>{
@@ -1075,7 +930,7 @@ var __webpack_exports__ = {};
1075
930
  return item.roles.some((role)=>user.roles.includes(role));
1076
931
  });
1077
932
  }
1078
- function LoggedMainContainer({ children }) {
933
+ function LoggedMainContainer({ children, mobileBreakpoint = 768 }) {
1079
934
  const [collapsed, setCollapsed] = (0, external_react_.useState)(true);
1080
935
  const [isMobile, setIsMobile] = (0, external_react_.useState)(false);
1081
936
  const [drawerVisible, setDrawerVisible] = (0, external_react_.useState)(false);
@@ -1086,7 +941,7 @@ var __webpack_exports__ = {};
1086
941
  const navigate = (0, external_react_router_namespaceObject.useNavigate)();
1087
942
  const location = (0, external_react_router_namespaceObject.useLocation)();
1088
943
  if (!configCodebit || !configTheme) throw new Error('LoggedContainer must be used within CodebitConfigProvider and CodebitThemeContext');
1089
- const { logout, user, menuItems, version, showVersion, secondarySidebar, secondarySidebarWidth = 280, bottomMenuItems, userMenuItems, onMenuClick } = configCodebit;
944
+ const { logout, user, menuItems, version, showVersion, secondarySidebar, secondarySidebarWidth = 280, bottomMenuItems, headerExtra, onMenuClick } = configCodebit;
1090
945
  const { isDarkMode } = configTheme;
1091
946
  const theme = isDarkMode ? 'dark' : 'light';
1092
947
  const allMenuItems = (0, external_react_.useMemo)(()=>[
@@ -1108,13 +963,6 @@ var __webpack_exports__ = {};
1108
963
  bottomMenuItems,
1109
964
  user
1110
965
  ]);
1111
- const filteredUserMenuItems = (0, external_react_.useMemo)(()=>{
1112
- if (!userMenuItems) return [];
1113
- return filterMenuItemsByRole(userMenuItems(user), user);
1114
- }, [
1115
- userMenuItems,
1116
- user
1117
- ]);
1118
966
  const memoizedBottomMenuItems = (0, external_react_.useMemo)(()=>[
1119
967
  ...filteredBottomMenuItems,
1120
968
  {
@@ -1166,11 +1014,6 @@ var __webpack_exports__ = {};
1166
1014
  isMobile,
1167
1015
  setDrawerVisible
1168
1016
  ]);
1169
- const handleUserMenuItemClick = (0, external_react_.useCallback)((key)=>{
1170
- onMenuClick?.(key);
1171
- }, [
1172
- onMenuClick
1173
- ]);
1174
1017
  const primaryMenu = (0, external_react_.useMemo)(()=>/*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Menu, {
1175
1018
  theme: theme,
1176
1019
  mode: 'inline',
@@ -1187,11 +1030,13 @@ var __webpack_exports__ = {};
1187
1030
  handleMenuClick
1188
1031
  ]);
1189
1032
  (0, external_react_.useEffect)(()=>{
1190
- const checkScreenSize = ()=>setIsMobile(window.innerWidth < 768);
1033
+ const checkScreenSize = ()=>setIsMobile(window.innerWidth < mobileBreakpoint);
1191
1034
  checkScreenSize();
1192
1035
  window.addEventListener('resize', checkScreenSize);
1193
1036
  return ()=>window.removeEventListener('resize', checkScreenSize);
1194
- }, []);
1037
+ }, [
1038
+ mobileBreakpoint
1039
+ ]);
1195
1040
  const menuContent = /*#__PURE__*/ (0, jsx_runtime.jsxs)(jsx_runtime.Fragment, {
1196
1041
  children: [
1197
1042
  primaryMenu,
@@ -1282,40 +1127,29 @@ var __webpack_exports__ = {};
1282
1127
  /*#__PURE__*/ (0, jsx_runtime.jsxs)(Header, {
1283
1128
  className: `${LoggedMainContainer_module.header} ${isMobile ? LoggedMainContainer_module.mobile : ''}`,
1284
1129
  children: [
1285
- /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Space, {
1286
- children: isMobile ? /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Button, {
1287
- type: 'text',
1288
- icon: /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MenuOutlined, {}),
1289
- onClick: ()=>setDrawerVisible(true)
1290
- }) : /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Button, {
1291
- type: 'text',
1292
- icon: collapsed ? /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MenuUnfoldOutlined, {}) : /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MenuFoldOutlined, {}),
1293
- onClick: ()=>setCollapsed(!collapsed)
1294
- })
1295
- }),
1296
1130
  /*#__PURE__*/ (0, jsx_runtime.jsxs)(external_antd_namespaceObject.Space, {
1297
- size: isMobile ? 'small' : 'middle',
1298
- className: `${LoggedMainContainer_module.headerSpace} ${isMobile ? LoggedMainContainer_module.mobile : ''}`,
1299
1131
  children: [
1132
+ isMobile ? /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Button, {
1133
+ type: 'text',
1134
+ icon: /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MenuOutlined, {}),
1135
+ onClick: ()=>setDrawerVisible(true)
1136
+ }) : /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Button, {
1137
+ type: 'text',
1138
+ icon: collapsed ? /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MenuUnfoldOutlined, {}) : /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MenuFoldOutlined, {}),
1139
+ onClick: ()=>setCollapsed(!collapsed)
1140
+ }),
1300
1141
  secondarySidebar && isMobile && /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Button, {
1301
1142
  type: 'text',
1302
1143
  icon: /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.WechatOutlined, {}),
1144
+ className: LoggedMainContainer_module.secondarySidebarTrigger,
1303
1145
  onClick: ()=>setSecondarySidebarDrawerVisible(true)
1304
- }),
1305
- !isMobile && /*#__PURE__*/ (0, jsx_runtime.jsx)(LoggedMainContainer_Text, {
1306
- children: t('LoggedMainContainer.theme')
1307
- }),
1308
- /*#__PURE__*/ (0, jsx_runtime.jsx)(ThemeToggle, {}),
1309
- /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Divider, {
1310
- type: 'vertical',
1311
- className: LoggedMainContainer_module.headerDivider
1312
- }),
1313
- /*#__PURE__*/ (0, jsx_runtime.jsx)(UserMenu, {
1314
- user: user,
1315
- items: filteredUserMenuItems,
1316
- onItemClick: handleUserMenuItemClick
1317
1146
  })
1318
1147
  ]
1148
+ }),
1149
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Space, {
1150
+ size: isMobile ? 'small' : 'middle',
1151
+ className: `${LoggedMainContainer_module.headerSpace} ${isMobile ? LoggedMainContainer_module.mobile : ''}`,
1152
+ children: headerExtra?.(user)
1319
1153
  })
1320
1154
  ]
1321
1155
  }),
@@ -1329,7 +1163,152 @@ var __webpack_exports__ = {};
1329
1163
  });
1330
1164
  }
1331
1165
  LoggedMainContainer.propTypes = {
1332
- children: external_prop_types_default().node.isRequired
1166
+ children: external_prop_types_default().node.isRequired,
1167
+ mobileBreakpoint: external_prop_types_default().number
1168
+ };
1169
+ const ThemeToggle = ()=>{
1170
+ const config = (0, external_react_.useContext)(CodebitThemeContext);
1171
+ if (!config) throw new Error('ThemeToggle must be used within CodebitThemeContext');
1172
+ (0, external_react_.useEffect)(()=>{
1173
+ document.documentElement.style.colorScheme = config.isDarkMode ? 'dark' : 'light';
1174
+ }, [
1175
+ config.isDarkMode
1176
+ ]);
1177
+ return /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Switch, {
1178
+ theme: config.isDarkMode ? 'dark' : 'light',
1179
+ checked: config.isDarkMode,
1180
+ onChange: (value)=>config.setIsDarkMode(value),
1181
+ checkedChildren: /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MoonOutlined, {}),
1182
+ unCheckedChildren: /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.SunOutlined, {})
1183
+ });
1184
+ };
1185
+ const UserMenu_module = {
1186
+ trigger: "trigger-tlcps4",
1187
+ avatar: "avatar-Tmnqa_",
1188
+ caret: "caret-OWS8_0",
1189
+ panel: "panel-GCcfCo",
1190
+ userInfo: "userInfo-fDuDn1",
1191
+ userName: "userName-sIs1iq",
1192
+ userSubtitle: "userSubtitle-Fflhaw",
1193
+ divider: "divider-JJjJVy",
1194
+ menu: "menu-cuORr_"
1195
+ };
1196
+ const OPEN_KEYS = new Set([
1197
+ 'Enter',
1198
+ ' '
1199
+ ]);
1200
+ const { Text } = external_antd_namespaceObject.Typography;
1201
+ function getInitials(name) {
1202
+ const parts = name?.trim().split(/\s+/).filter(Boolean) ?? [];
1203
+ if (0 === parts.length) return '';
1204
+ const first = [
1205
+ ...parts[0]
1206
+ ];
1207
+ if (1 === parts.length) return first.slice(0, 2).join('').toUpperCase();
1208
+ const last = [
1209
+ ...parts.at(-1)
1210
+ ];
1211
+ return `${first[0]}${last[0]}`.toUpperCase();
1212
+ }
1213
+ function UserMenuPanel({ user, items, onItemClick }) {
1214
+ return /*#__PURE__*/ (0, jsx_runtime.jsxs)("div", {
1215
+ className: UserMenu_module.panel,
1216
+ children: [
1217
+ /*#__PURE__*/ (0, jsx_runtime.jsxs)("div", {
1218
+ className: UserMenu_module.userInfo,
1219
+ children: [
1220
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(Text, {
1221
+ className: UserMenu_module.userName,
1222
+ strong: true,
1223
+ children: user?.name
1224
+ }),
1225
+ user?.subtitle && /*#__PURE__*/ (0, jsx_runtime.jsx)(Text, {
1226
+ className: UserMenu_module.userSubtitle,
1227
+ type: 'secondary',
1228
+ children: user.subtitle
1229
+ })
1230
+ ]
1231
+ }),
1232
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Divider, {
1233
+ className: UserMenu_module.divider
1234
+ }),
1235
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Menu, {
1236
+ className: UserMenu_module.menu,
1237
+ items: items,
1238
+ onClick: ({ key })=>onItemClick?.(key)
1239
+ })
1240
+ ]
1241
+ });
1242
+ }
1243
+ UserMenuPanel.propTypes = {
1244
+ user: external_prop_types_default().shape({
1245
+ name: external_prop_types_default().string,
1246
+ subtitle: external_prop_types_default().string
1247
+ }),
1248
+ items: external_prop_types_default().arrayOf(external_prop_types_default().object).isRequired,
1249
+ onItemClick: external_prop_types_default().func
1250
+ };
1251
+ function createPopupRender(user, items, onItemClick) {
1252
+ return ()=>/*#__PURE__*/ (0, jsx_runtime.jsx)(UserMenuPanel, {
1253
+ user: user,
1254
+ items: items,
1255
+ onItemClick: onItemClick
1256
+ });
1257
+ }
1258
+ function UserMenu({ user, items = [], onItemClick, caretIcon = /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.DownOutlined, {}) }) {
1259
+ const { t } = useCodebitWebAntdTranslation();
1260
+ const [open, setOpen] = (0, external_react_.useState)(false);
1261
+ const initials = getInitials(user?.name);
1262
+ const handleItemClick = (key)=>{
1263
+ setOpen(false);
1264
+ onItemClick?.(key);
1265
+ };
1266
+ const avatar = /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Avatar, {
1267
+ className: UserMenu_module.avatar,
1268
+ children: initials || /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.UserOutlined, {})
1269
+ });
1270
+ if (!items.length) return avatar;
1271
+ return /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Dropdown, {
1272
+ trigger: [
1273
+ 'click'
1274
+ ],
1275
+ open: open,
1276
+ onOpenChange: setOpen,
1277
+ placement: 'bottomRight',
1278
+ popupRender: createPopupRender(user, items, handleItemClick),
1279
+ children: /*#__PURE__*/ (0, jsx_runtime.jsxs)(external_antd_namespaceObject.Space, {
1280
+ className: UserMenu_module.trigger,
1281
+ role: 'button',
1282
+ tabIndex: 0,
1283
+ "aria-haspopup": 'menu',
1284
+ "aria-expanded": open,
1285
+ "aria-label": t('UserMenu.openMenu'),
1286
+ onKeyDown: (event)=>{
1287
+ if (!OPEN_KEYS.has(event.key)) return;
1288
+ event.preventDefault();
1289
+ setOpen((wasOpen)=>!wasOpen);
1290
+ },
1291
+ children: [
1292
+ avatar,
1293
+ /*#__PURE__*/ (0, jsx_runtime.jsx)("span", {
1294
+ className: UserMenu_module.caret,
1295
+ children: caretIcon
1296
+ })
1297
+ ]
1298
+ })
1299
+ });
1300
+ }
1301
+ UserMenu.propTypes = {
1302
+ user: external_prop_types_default().shape({
1303
+ name: external_prop_types_default().string,
1304
+ email: external_prop_types_default().string,
1305
+ id: external_prop_types_default().string,
1306
+ roles: external_prop_types_default().arrayOf(external_prop_types_default().string),
1307
+ subtitle: external_prop_types_default().string
1308
+ }),
1309
+ items: external_prop_types_default().arrayOf(external_prop_types_default().object),
1310
+ onItemClick: external_prop_types_default().func,
1311
+ caretIcon: external_prop_types_default().node
1333
1312
  };
1334
1313
  function useErrorMessage() {
1335
1314
  const { t } = useCodebitWebAntdTranslation();
package/dist/index.css CHANGED
@@ -13,61 +13,6 @@ html.dark-theme {
13
13
  height: 100dvh !important;
14
14
  }
15
15
 
16
- .trigger-tlcps4 {
17
- cursor: pointer;
18
- }
19
-
20
- .avatar-Tmnqa_ {
21
- background: var(--antd-color-primary);
22
- flex-shrink: 0;
23
- }
24
-
25
- .caret-OWS8_0 {
26
- color: var(--antd-color-text-secondary);
27
- font-size: var(--antd-font-size-xs);
28
- }
29
-
30
- .panel-GCcfCo {
31
- background: var(--antd-color-bg-elevated);
32
- border: 1px solid var(--antd-color-border-secondary);
33
- border-radius: var(--antd-border-radius-lg);
34
- min-width: 200px;
35
- max-width: 280px;
36
- box-shadow: var(--antd-shadow-lg);
37
- flex-direction: column;
38
- display: flex;
39
- overflow: hidden;
40
- }
41
-
42
- .userInfo-fDuDn1 {
43
- padding: var(--antd-padding-xs) var(--antd-padding-sm);
44
- gap: var(--antd-margin-xxs);
45
- flex-direction: column;
46
- display: flex;
47
- }
48
-
49
- .userName-sIs1iq {
50
- text-overflow: ellipsis;
51
- white-space: nowrap;
52
- overflow: hidden;
53
- }
54
-
55
- .userSubtitle-Fflhaw {
56
- font-size: var(--antd-font-size-sm);
57
- text-overflow: ellipsis;
58
- white-space: nowrap;
59
- overflow: hidden;
60
- }
61
-
62
- .divider-JJjJVy {
63
- margin: 0;
64
- }
65
-
66
- .menu-cuORr_ {
67
- background: none;
68
- border-inline-end: none;
69
- }
70
-
71
16
  .layout-mL5o6I {
72
17
  height: 100vh;
73
18
  position: fixed;
@@ -158,6 +103,7 @@ html.dark-theme {
158
103
  background: none;
159
104
  justify-content: space-between;
160
105
  align-items: center;
106
+ gap: 0;
161
107
  display: flex;
162
108
  }
163
109
 
@@ -166,18 +112,21 @@ html.dark-theme {
166
112
  height: var(--antd-control-height-lg);
167
113
  }
168
114
 
115
+ .secondarySidebarTrigger-dD6WGB {
116
+ margin-right: var(--antd-padding-xs);
117
+ }
118
+
169
119
  .headerSpace-Fd_iha {
170
120
  gap: var(--antd-margin);
121
+ min-width: 0;
171
122
  }
172
123
 
173
- .headerSpace-Fd_iha.mobile-mKGxb5 {
174
- gap: var(--antd-margin-xs);
124
+ .headerSpace-Fd_iha .ant-space-item {
125
+ min-width: 0;
175
126
  }
176
127
 
177
- .headerDivider-yfEwNN {
178
- height: var(--antd-control-height-sm);
179
- border-color: var(--antd-color-split);
180
- margin: 0;
128
+ .headerSpace-Fd_iha.mobile-mKGxb5 {
129
+ gap: var(--antd-margin-xs);
181
130
  }
182
131
 
183
132
  .content-OZHp2h {
@@ -185,6 +134,68 @@ html.dark-theme {
185
134
  position: relative;
186
135
  }
187
136
 
137
+ .trigger-tlcps4 {
138
+ cursor: pointer;
139
+ }
140
+
141
+ .avatar-Tmnqa_ {
142
+ background: var(--antd-color-primary);
143
+ flex-shrink: 0;
144
+ }
145
+
146
+ .caret-OWS8_0 {
147
+ color: var(--antd-color-text-secondary);
148
+ font-size: var(--antd-font-size-xs);
149
+ }
150
+
151
+ .panel-GCcfCo {
152
+ background: var(--antd-color-bg-elevated);
153
+ border: 1px solid var(--antd-color-border-secondary);
154
+ border-radius: var(--antd-border-radius-lg);
155
+ min-width: 200px;
156
+ max-width: 280px;
157
+ box-shadow: var(--antd-shadow-lg);
158
+ flex-direction: column;
159
+ display: flex;
160
+ overflow: hidden;
161
+ }
162
+
163
+ .userInfo-fDuDn1 {
164
+ padding: var(--antd-padding-xs) var(--antd-padding-sm);
165
+ gap: var(--antd-margin-xxs);
166
+ flex-direction: column;
167
+ display: flex;
168
+ }
169
+
170
+ .userName-sIs1iq {
171
+ text-overflow: ellipsis;
172
+ white-space: nowrap;
173
+ overflow: hidden;
174
+ }
175
+
176
+ .userSubtitle-Fflhaw {
177
+ font-size: var(--antd-font-size-sm);
178
+ text-overflow: ellipsis;
179
+ white-space: nowrap;
180
+ overflow: hidden;
181
+ }
182
+
183
+ .divider-JJjJVy {
184
+ margin: 0;
185
+ }
186
+
187
+ .menu-cuORr_ {
188
+ background: none;
189
+ border-inline-end: none;
190
+ }
191
+
192
+ .menu-cuORr_ .ant-dropdown-menu-title-content {
193
+ text-overflow: ellipsis;
194
+ white-space: nowrap;
195
+ min-width: 0;
196
+ overflow: hidden;
197
+ }
198
+
188
199
  .listCard-ISftFd {
189
200
  width: 100%;
190
201
  height: 100%;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebit-programando-solucoes/codebit-web-antd",
3
- "version": "1.1.45",
3
+ "version": "1.1.47",
4
4
  "main": "./dist/index.cjs",
5
5
  "type": "module",
6
6
  "types": "./src/index.d.ts",