@admin-layout/tailwind-design-pro 12.2.4-alpha.0 → 12.2.4-alpha.100
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 +80 -0
- package/lib/components/LanguageMenu/LanguageMenu.d.ts.map +1 -1
- package/lib/components/LanguageMenu/LanguageMenu.js +6 -2
- package/lib/components/LanguageMenu/LanguageMenu.js.map +1 -1
- package/lib/components/Layout/BasicLayout/index.d.ts +20 -1
- package/lib/components/Layout/BasicLayout/index.d.ts.map +1 -1
- package/lib/components/Layout/BasicLayout/index.js +64 -15
- package/lib/components/Layout/BasicLayout/index.js.map +1 -1
- package/lib/components/Layout/BasicLayout/utils.js +1 -1
- package/lib/components/Layout/BasicLayout/utils.js.map +1 -1
- package/lib/components/Layout/GlobalFooter/BottomMenuDropdown.js +1 -1
- package/lib/components/Layout/GlobalFooter/BottomMenuDropdown.js.map +1 -1
- package/lib/components/Layout/GlobalHeader/Header.d.ts.map +1 -1
- package/lib/components/Layout/GlobalHeader/Header.js +12 -4
- package/lib/components/Layout/GlobalHeader/Header.js.map +1 -1
- package/lib/components/Layout/GlobalHeader/MainHeader.d.ts.map +1 -1
- package/lib/components/Layout/GlobalHeader/MainHeader.js +2 -1
- package/lib/components/Layout/GlobalHeader/MainHeader.js.map +1 -1
- package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.d.ts +12 -0
- package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.d.ts.map +1 -0
- package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.js +36 -0
- package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.js.map +1 -0
- package/lib/components/Layout/GlobalHeader/RightContent.d.ts +1 -2
- package/lib/components/Layout/GlobalHeader/RightContent.d.ts.map +1 -1
- package/lib/components/Layout/GlobalHeader/RightContent.js +10 -72
- package/lib/components/Layout/GlobalHeader/RightContent.js.map +1 -1
- package/lib/components/Layout/GlobalHeader/RightMenu.d.ts.map +1 -1
- package/lib/components/Layout/GlobalHeader/RightMenu.js +16 -80
- package/lib/components/Layout/GlobalHeader/RightMenu.js.map +1 -1
- package/lib/components/Layout/GlobalHeader/SearchBar.d.ts +43 -0
- package/lib/components/Layout/GlobalHeader/SearchBar.d.ts.map +1 -1
- package/lib/components/Layout/GlobalHeader/SearchBar.js +380 -43
- package/lib/components/Layout/GlobalHeader/SearchBar.js.map +1 -1
- package/lib/components/Layout/GlobalHeader/index.d.ts +1 -0
- package/lib/components/Layout/GlobalHeader/index.d.ts.map +1 -1
- package/lib/components/Layout/ProTailwindLayout.d.ts +19 -8
- package/lib/components/Layout/ProTailwindLayout.d.ts.map +1 -1
- package/lib/components/Layout/ProTailwindLayout.js +255 -88
- package/lib/components/Layout/ProTailwindLayout.js.map +1 -1
- package/lib/components/Layout/Sidebar/BottomMenu.d.ts.map +1 -1
- package/lib/components/Layout/Sidebar/BottomMenu.js +55 -82
- package/lib/components/Layout/Sidebar/BottomMenu.js.map +1 -1
- package/lib/components/Layout/Sidebar/DynamicIcon.d.ts.map +1 -1
- package/lib/components/Layout/Sidebar/DynamicIcon.js +80 -19
- package/lib/components/Layout/Sidebar/DynamicIcon.js.map +1 -1
- package/lib/components/Layout/Sidebar/MainSidebar.d.ts.map +1 -1
- package/lib/components/Layout/Sidebar/MainSidebar.js +29 -24
- package/lib/components/Layout/Sidebar/MainSidebar.js.map +1 -1
- package/lib/components/Layout/Sidebar/MainSidebarMenu.d.ts.map +1 -1
- package/lib/components/Layout/Sidebar/MainSidebarMenu.js +213 -36
- package/lib/components/Layout/Sidebar/MainSidebarMenu.js.map +1 -1
- package/lib/components/Layout/Sidebar/MenuDynamicDialog.d.ts +12 -0
- package/lib/components/Layout/Sidebar/MenuDynamicDialog.d.ts.map +1 -0
- package/lib/components/Layout/Sidebar/MenuDynamicDialog.js +79 -0
- package/lib/components/Layout/Sidebar/MenuDynamicDialog.js.map +1 -0
- package/lib/components/Layout/Sidebar/PerplexSidebar.d.ts.map +1 -1
- package/lib/components/Layout/Sidebar/PerplexSidebar.js +42 -33
- package/lib/components/Layout/Sidebar/PerplexSidebar.js.map +1 -1
- package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.d.ts +25 -0
- package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.d.ts.map +1 -0
- package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.js +287 -0
- package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.js.map +1 -0
- package/lib/components/Layout/Sidebar/PerplexSidebarMenu.d.ts.map +1 -1
- package/lib/components/Layout/Sidebar/PerplexSidebarMenu.js +321 -43
- package/lib/components/Layout/Sidebar/PerplexSidebarMenu.js.map +1 -1
- package/lib/components/Layout/Sidebar/SidebarRailFX.d.ts +23 -0
- package/lib/components/Layout/Sidebar/SidebarRailFX.d.ts.map +1 -0
- package/lib/components/Layout/Sidebar/SidebarRailFX.js +229 -0
- package/lib/components/Layout/Sidebar/SidebarRailFX.js.map +1 -0
- package/lib/components/Layout/SidebarControlsContext.d.ts +17 -0
- package/lib/components/Layout/SidebarControlsContext.d.ts.map +1 -0
- package/lib/components/Layout/SidebarControlsContext.js +21 -0
- package/lib/components/Layout/SidebarControlsContext.js.map +1 -0
- package/lib/components/Layout/TailwindLayout.d.ts +1 -1
- package/lib/components/Layout/TailwindLayout.d.ts.map +1 -1
- package/lib/components/Layout/TailwindLayout.js +22 -3
- package/lib/components/Layout/TailwindLayout.js.map +1 -1
- package/lib/components/Layout/defaultPermissions.d.ts +134 -0
- package/lib/components/Layout/defaultPermissions.d.ts.map +1 -0
- package/lib/components/Layout/defaultPermissions.js +134 -0
- package/lib/components/Layout/defaultPermissions.js.map +1 -0
- package/lib/components/Layout/getPageTitle.js +2 -2
- package/lib/components/Layout/getPageTitle.js.map +1 -1
- package/lib/components/Layout/slot-fill/RightContent.d.ts +3 -1
- package/lib/components/Layout/slot-fill/RightContent.d.ts.map +1 -1
- package/lib/components/Layout/slot-fill/RightContent.js +4 -6
- package/lib/components/Layout/slot-fill/RightContent.js.map +1 -1
- package/lib/components/SettingDrawer/SettingDrawer.d.ts.map +1 -1
- package/lib/components/SettingDrawer/SettingDrawer.js +22 -19
- package/lib/components/SettingDrawer/SettingDrawer.js.map +1 -1
- package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.d.ts.map +1 -1
- package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.js +8 -14
- package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.js.map +1 -1
- package/lib/components/SettingDrawer/components/CheckBoxTheme.js +2 -2
- package/lib/components/SettingDrawer/components/CheckBoxTheme.js.map +1 -1
- package/lib/components/SettingDrawer/components/DeviceTabs.js +2 -2
- package/lib/components/SettingDrawer/components/DeviceTabs.js.map +1 -1
- package/lib/components/SettingDrawer/components/InvitationSettings.d.ts.map +1 -1
- package/lib/components/SettingDrawer/components/InvitationSettings.js +7 -3
- package/lib/components/SettingDrawer/components/InvitationSettings.js.map +1 -1
- package/lib/components/SettingDrawer/components/LayoutChange.d.ts.map +1 -1
- package/lib/components/SettingDrawer/components/LayoutChange.js +8 -11
- package/lib/components/SettingDrawer/components/LayoutChange.js.map +1 -1
- package/lib/components/SettingDrawer/components/MenuVisibilitySettings.js +5 -5
- package/lib/components/SettingDrawer/components/MenuVisibilitySettings.js.map +1 -1
- package/lib/components/SettingDrawer/components/NavigationsModes.js +3 -3
- package/lib/components/SettingDrawer/components/NavigationsModes.js.map +1 -1
- package/lib/components/SettingDrawer/components/RegionalSettings.d.ts.map +1 -1
- package/lib/components/SettingDrawer/components/RegionalSettings.js +40 -97
- package/lib/components/SettingDrawer/components/RegionalSettings.js.map +1 -1
- package/lib/components/SettingDrawer/components/SettingsActions.d.ts.map +1 -1
- package/lib/components/SettingDrawer/components/SettingsActions.js +27 -25
- package/lib/components/SettingDrawer/components/SettingsActions.js.map +1 -1
- package/lib/components/SettingDrawer/components/SettingsDrawerHeader.d.ts.map +1 -1
- package/lib/components/SettingDrawer/components/SettingsDrawerHeader.js +4 -3
- package/lib/components/SettingDrawer/components/SettingsDrawerHeader.js.map +1 -1
- package/lib/components/SettingDrawer/components/Switch.js +2 -2
- package/lib/components/SettingDrawer/components/ThemeColor.js +1 -1
- package/lib/components/SettingDrawer/components/ThemeColor.js.map +1 -1
- package/lib/components/SettingDrawer/components/ThemeSelector.js +1 -1
- package/lib/components/SettingDrawer/components/WebFontsSelector.js +1 -1
- package/lib/components/SettingDrawer/hooks/useSettingsOperations.d.ts.map +1 -1
- package/lib/components/SettingDrawer/hooks/useSettingsOperations.js +13 -9
- package/lib/components/SettingDrawer/hooks/useSettingsOperations.js.map +1 -1
- package/lib/components/SettingDrawer/utils/constants.d.ts.map +1 -1
- package/lib/components/SettingDrawer/utils/constants.js +3 -0
- package/lib/components/SettingDrawer/utils/constants.js.map +1 -1
- package/lib/components/SettingDrawer/utils/helper.js +1 -1
- package/lib/components/SettingDrawer/utils/transformers.d.ts +16 -0
- package/lib/components/SettingDrawer/utils/transformers.d.ts.map +1 -1
- package/lib/components/SettingDrawer/utils/transformers.js +39 -2
- package/lib/components/SettingDrawer/utils/transformers.js.map +1 -1
- package/lib/components/SettingsThemeApplier/SettingsThemeApplier.d.ts +10 -0
- package/lib/components/SettingsThemeApplier/SettingsThemeApplier.d.ts.map +1 -0
- package/lib/components/SettingsThemeApplier/SettingsThemeApplier.js +23 -0
- package/lib/components/SettingsThemeApplier/SettingsThemeApplier.js.map +1 -0
- package/lib/components/SettingsThemeApplier/index.d.ts +2 -0
- package/lib/components/SettingsThemeApplier/index.d.ts.map +1 -0
- package/lib/components/index.js +1 -1
- package/lib/components/typings.d.ts +29 -0
- package/lib/components/typings.d.ts.map +1 -1
- package/lib/compute.js +2 -1
- package/lib/compute.js.map +1 -1
- package/lib/helpers/DynamicIcon.js +7 -1
- package/lib/helpers/DynamicIcon.js.map +1 -1
- package/lib/hooks/index.d.ts +1 -0
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/useScrollThreshold.d.ts +1 -2
- package/lib/hooks/useScrollThreshold.d.ts.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/routes.json +5 -1
- package/lib/styles/index.css +321 -0
- package/lib/utils/settingsTheme.d.ts +40 -0
- package/lib/utils/settingsTheme.d.ts.map +1 -0
- package/lib/utils/settingsTheme.js +106 -0
- package/lib/utils/settingsTheme.js.map +1 -0
- package/package.json +9 -7
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
import { filterRoutesWithLocale, transformData, addProLayoutParentKeys, removeUnnecessaryProperties, menuDataRender } from '@admin-layout/client';
|
|
2
2
|
import { matchParentRoute } from '@admin-layout/client/lib/utils/parentRoute.js';
|
|
3
3
|
import { getAvailableCategories, getMenusByAdvancedFilter } from '@common-stack/client-react/lib/utils/filteredRoutes.js';
|
|
4
|
-
import { useMatches } from '@remix-run/react';
|
|
4
|
+
import { useLoaderData, useMatches } from '@remix-run/react';
|
|
5
5
|
import { ClientContainerService } from 'common';
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
import { useSelector } from 'react-redux';
|
|
8
8
|
import { createSelector } from 'reselect';
|
|
9
|
+
import { defaultPermissions } from './defaultPermissions.js';
|
|
9
10
|
import { config } from '../../config/env-config.js';
|
|
10
11
|
import BasicLayoutEnhanced from './TailwindLayout.js';
|
|
11
|
-
import stylesheet from '../../styles/index.css?url';
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
import stylesheet from '../../styles/index.css?url'; // Cache for SPA mode menu data to avoid re-fetching on every route change
|
|
13
|
+
let cachedSpaMenuData = null;
|
|
14
|
+
// Safe selectors that handle undefined state slices in SPA mode
|
|
15
|
+
const selectOrgName = state => state?.platform?.orgName ?? '';
|
|
16
|
+
const selectSettings = state => state?.settings ?? {};
|
|
14
17
|
const selector = createSelector([selectOrgName, selectSettings], (orgName, settings) => ({
|
|
15
18
|
orgName,
|
|
16
19
|
settings
|
|
17
20
|
}));
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const handle = {
|
|
22
|
+
i18n: 'menu'
|
|
23
|
+
};
|
|
24
|
+
const links = () => [{
|
|
25
|
+
rel: 'stylesheet',
|
|
26
|
+
href: stylesheet
|
|
27
|
+
}];
|
|
28
|
+
//helper func
|
|
21
29
|
function filterMenuItemsByVisibility(menuData, settings) {
|
|
22
30
|
if (!menuData || !Array.isArray(menuData)) return [];
|
|
23
31
|
const hiddenMenuCategories = settings?.hiddenMenuCategories || [];
|
|
@@ -67,78 +75,30 @@ function filterMenuItemsByVisibility(menuData, settings) {
|
|
|
67
75
|
};
|
|
68
76
|
return filterItemsRecursively(filteredByCategory);
|
|
69
77
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
newMenuData
|
|
75
|
-
}
|
|
76
|
-
} = props;
|
|
77
|
-
const matches = useMatches();
|
|
78
|
-
const current = matches[matches.length - 1];
|
|
79
|
-
const {
|
|
80
|
-
orgName,
|
|
81
|
-
settings
|
|
82
|
-
} = useSelector(state => selector(state));
|
|
83
|
-
// Check if current route has projectId param (pattern: projects/:id)
|
|
84
|
-
const hasProjectId = current?.params?.id && current?.id?.includes('projects/:id');
|
|
85
|
-
// Get project-specific menus or all menus
|
|
86
|
-
const menuDataToUse = React.useMemo(() => {
|
|
87
|
-
if (!hasProjectId) {
|
|
88
|
-
// When NOT in project detail, filter out project-specific routes (hideInMenu: true)
|
|
89
|
-
const nonProjectMenus = newMenuData.filter(item => {
|
|
90
|
-
const isProjectRoute = item.path?.includes('/projects/:id');
|
|
91
|
-
return !isProjectRoute;
|
|
92
|
-
});
|
|
93
|
-
console.log('Not in project - showing non-project menus');
|
|
94
|
-
return nonProjectMenus;
|
|
95
|
-
}
|
|
96
|
-
// When in project detail, show only project-specific routes
|
|
97
|
-
const projectMenus = newMenuData.filter(item => {
|
|
98
|
-
const isProject = item.path?.includes('/projects/:id');
|
|
99
|
-
return isProject;
|
|
100
|
-
});
|
|
101
|
-
console.log('In project - showing project menus');
|
|
102
|
-
return projectMenus;
|
|
103
|
-
}, [hasProjectId, newMenuData]);
|
|
104
|
-
const filteredMenuData = React.useMemo(() => {
|
|
105
|
-
return filterMenuItemsByVisibility(menuDataToUse, settings);
|
|
106
|
-
}, [menuDataToUse, settings?.hiddenMenuCategories, settings?.hiddenMenuKeys]);
|
|
107
|
-
const params = {
|
|
108
|
-
orgName: orgName,
|
|
109
|
-
...(current?.params?.id && {
|
|
110
|
-
id: current.params.id
|
|
111
|
-
})
|
|
112
|
-
};
|
|
113
|
-
return React.createElement(BasicLayoutEnhanced, {
|
|
114
|
-
routeParams: params,
|
|
115
|
-
permissions: permissions,
|
|
116
|
-
menuData: filteredMenuData,
|
|
117
|
-
fullMenuData: newMenuData
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
const handle = {
|
|
121
|
-
i18n: 'menu'
|
|
122
|
-
};
|
|
123
|
-
const links = () => [{
|
|
124
|
-
rel: 'stylesheet',
|
|
125
|
-
href: stylesheet
|
|
126
|
-
}];
|
|
127
|
-
const loader = async params => {
|
|
78
|
+
// NOTE: No HydrateFallback exported - we use SSR so the server-rendered content displays immediately.
|
|
79
|
+
// HydrateFallback should only be used for client-only routes that can't render until clientLoader runs.
|
|
80
|
+
// loader or action
|
|
81
|
+
async function loader(params) {
|
|
128
82
|
const {
|
|
129
83
|
routeConfig
|
|
130
84
|
} = params.context;
|
|
131
|
-
let parentRoute =
|
|
85
|
+
let parentRoute = null;
|
|
132
86
|
try {
|
|
133
87
|
parentRoute = matchParentRoute(routeConfig, config.LAYOUT_ROOT);
|
|
134
88
|
} catch (e) {
|
|
135
|
-
console.log(e);
|
|
89
|
+
console.log('[ProTailwindLayout loader] Error matching parent route:', e);
|
|
136
90
|
}
|
|
137
|
-
|
|
91
|
+
// Handle case when parentRoute is null or doesn't have routes
|
|
92
|
+
const routes = parentRoute?.routes || [];
|
|
93
|
+
if (routes.length === 0) {
|
|
94
|
+
console.warn('[ProTailwindLayout loader] No routes found for LAYOUT_ROOT:', config.LAYOUT_ROOT);
|
|
95
|
+
}
|
|
96
|
+
const routeWithLocale = filterRoutesWithLocale(routes);
|
|
138
97
|
const routeWithChildren = transformData(routeWithLocale);
|
|
139
98
|
const menuDataWithParentKeys = addProLayoutParentKeys(routeWithChildren);
|
|
140
99
|
menuDataWithParentKeys.forEach(item => removeUnnecessaryProperties(item));
|
|
141
100
|
let permissions = params?._dataContext?.permissions;
|
|
101
|
+
const policies = params?._dataContext?.policies;
|
|
142
102
|
let apolloState = params?._dataContext?.apolloState;
|
|
143
103
|
if (!permissions) {
|
|
144
104
|
throw new Error('Permissions not found');
|
|
@@ -146,39 +106,246 @@ const loader = async params => {
|
|
|
146
106
|
if (!apolloState) {
|
|
147
107
|
throw new Error('ApolloState not found');
|
|
148
108
|
}
|
|
149
|
-
const newMenuData = menuDataRender(routeWithLocale, permissions);
|
|
150
|
-
// returnInfo: {"keys":["newMenuData","apolloState","permissions"],"hasOptions":false}
|
|
109
|
+
const newMenuData = menuDataRender(routeWithLocale, permissions, policies);
|
|
110
|
+
// returnInfo: {"keys":["newMenuData","apolloState","permissions","policies"],"hasOptions":false}
|
|
151
111
|
return {
|
|
152
|
-
data: [newMenuData, apolloState, permissions]
|
|
112
|
+
data: [newMenuData, apolloState, permissions, policies]
|
|
153
113
|
};
|
|
154
|
-
}
|
|
114
|
+
}
|
|
155
115
|
async function clientLoader({
|
|
156
|
-
request,
|
|
157
|
-
params,
|
|
158
116
|
serverLoader
|
|
159
117
|
}) {
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
118
|
+
// In SPA mode (ssr: false), serverLoader throws an error when called
|
|
119
|
+
// We check the Remix context to determine if we're in SPA mode
|
|
120
|
+
const remixContext = typeof window !== 'undefined' ? window.__remixContext : null;
|
|
121
|
+
// In SPA mode, isSpaMode is true. In SSR mode, it's false or undefined.
|
|
122
|
+
const isSPAMode = remixContext?.isSpaMode === true;
|
|
123
|
+
console.log('[ProTailwindLayout clientLoader] Starting...', {
|
|
124
|
+
isSPAMode,
|
|
125
|
+
hasRemixContext: !!remixContext,
|
|
126
|
+
remixContextKeys: remixContext ? Object.keys(remixContext) : []
|
|
127
|
+
});
|
|
128
|
+
let loaderData = null;
|
|
129
|
+
let hasValidServerData = false;
|
|
130
|
+
// Only attempt to call serverLoader in SSR mode
|
|
131
|
+
// In SPA mode, serverLoader() will throw "You cannot call serverLoader() in SPA Mode"
|
|
132
|
+
if (!isSPAMode) {
|
|
133
|
+
try {
|
|
134
|
+
console.log('[ProTailwindLayout clientLoader] Calling serverLoader (SSR mode)...');
|
|
135
|
+
loaderData = await serverLoader();
|
|
136
|
+
hasValidServerData = loaderData && loaderData.newMenuData && loaderData.newMenuData.length > 0;
|
|
137
|
+
console.log('[ProTailwindLayout clientLoader] serverLoader result:', {
|
|
138
|
+
hasLoaderData: !!loaderData,
|
|
139
|
+
hasNewMenuData: !!loaderData?.newMenuData,
|
|
140
|
+
menuDataLength: loaderData?.newMenuData?.length || 0,
|
|
141
|
+
hasValidServerData
|
|
142
|
+
});
|
|
143
|
+
} catch (e) {
|
|
144
|
+
// If serverLoader fails, we'll fall back to SPA mode data generation
|
|
145
|
+
// This can happen if the server doesn't return expected data
|
|
146
|
+
console.warn('[ProTailwindLayout clientLoader] serverLoader failed:', e);
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
console.log('[ProTailwindLayout clientLoader] Skipping serverLoader (SPA mode detected)');
|
|
150
|
+
}
|
|
151
|
+
if (hasValidServerData) {
|
|
152
|
+
// SSR mode - hydrate apollo cache and organization context
|
|
167
153
|
const {
|
|
168
|
-
|
|
169
|
-
} =
|
|
170
|
-
|
|
171
|
-
|
|
154
|
+
apolloState
|
|
155
|
+
} = loaderData;
|
|
156
|
+
try {
|
|
157
|
+
const {
|
|
158
|
+
container
|
|
159
|
+
} = window.__CLIENT_SERVICE__;
|
|
160
|
+
// const apolloCache = container.get(ClientTypes.InMemoryCache);
|
|
161
|
+
// apolloCache.restore(apolloState);
|
|
162
|
+
const organizationContext = container.get(ClientContainerService.IOrganizationContextService);
|
|
163
|
+
organizationContext.hydrate(apolloState);
|
|
164
|
+
} catch (e) {
|
|
165
|
+
console.error('[ProTailwindLayout clientLoader] Error in client hydrate:', e);
|
|
166
|
+
}
|
|
167
|
+
console.log('[ProTailwindLayout clientLoader] Returning SSR data with', loaderData.newMenuData.length, 'menu items');
|
|
168
|
+
return loaderData;
|
|
169
|
+
}
|
|
170
|
+
// SPA mode - get route config from window.__ROUTES_CONFIG__ or fetch from routes-config.json
|
|
171
|
+
console.log('[ProTailwindLayout clientLoader] Entering SPA mode route generation...');
|
|
172
|
+
// Return cached data if available to avoid unnecessary fetches on route changes
|
|
173
|
+
if (cachedSpaMenuData && cachedSpaMenuData.newMenuData.length > 0) {
|
|
174
|
+
console.log('[ProTailwindLayout clientLoader] Returning cached SPA menu data');
|
|
175
|
+
return cachedSpaMenuData;
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
// First try to get routes config from window global variable
|
|
179
|
+
// If not available, fall back to fetching from routes-config.json
|
|
180
|
+
let routeConfig = [];
|
|
181
|
+
if (typeof window !== 'undefined' && window.__ROUTES_CONFIG__) {
|
|
182
|
+
console.log('[ProTailwindLayout clientLoader] Using window.__ROUTES_CONFIG__');
|
|
183
|
+
// Handle both array format and object format { routes: [...] }
|
|
184
|
+
const windowConfig = window.__ROUTES_CONFIG__;
|
|
185
|
+
routeConfig = Array.isArray(windowConfig) ? windowConfig : windowConfig?.routes || [];
|
|
186
|
+
}
|
|
187
|
+
if (!routeConfig.length) {
|
|
188
|
+
// Fetch routes-config.json as fallback
|
|
189
|
+
// Try multiple paths since Vite serves files differently in dev vs prod
|
|
190
|
+
console.log('[ProTailwindLayout clientLoader] Fetching routes-config.json...');
|
|
191
|
+
const pathsToTry = ['/app/routes-config.json', '/routes-config.json', './routes-config.json'];
|
|
192
|
+
for (const path of pathsToTry) {
|
|
193
|
+
try {
|
|
194
|
+
const response = await fetch(path);
|
|
195
|
+
if (response.ok) {
|
|
196
|
+
const jsonData = await response.json();
|
|
197
|
+
// Handle both array format and object format { routes: [...] }
|
|
198
|
+
routeConfig = Array.isArray(jsonData) ? jsonData : jsonData?.routes || [];
|
|
199
|
+
console.log('[ProTailwindLayout clientLoader] Fetched routes-config.json from', path);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
} catch (fetchError) {
|
|
203
|
+
console.warn('[ProTailwindLayout clientLoader] Failed to fetch from', path);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (!routeConfig.length) {
|
|
207
|
+
console.warn('[ProTailwindLayout clientLoader] Could not fetch routes-config.json from any path');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
console.log('[ProTailwindLayout clientLoader] routeConfig:', {
|
|
211
|
+
isArray: Array.isArray(routeConfig),
|
|
212
|
+
length: routeConfig?.length || 0,
|
|
213
|
+
topLevelKeys: routeConfig?.map?.(r => r.key) || []
|
|
214
|
+
});
|
|
215
|
+
// Transform routes to menu format - the config already has hierarchical structure with nested routes
|
|
216
|
+
// Mirror the SSR pipeline: filter hidden/resource routes, sort by priority, recurse.
|
|
217
|
+
const transformToMenuData = routes => {
|
|
218
|
+
return routes.filter(r => !r.hideInMenu && !r.isResourceRoute && !r.path?.includes('/resources/')).slice().sort((a, b) => (parseInt(a?.priority, 10) || 0) - (parseInt(b?.priority, 10) || 0)).map(route => {
|
|
219
|
+
const menuItem = {
|
|
220
|
+
key: route.key,
|
|
221
|
+
name: route.name,
|
|
222
|
+
path: route.path,
|
|
223
|
+
icon: route.icon,
|
|
224
|
+
position: route.position,
|
|
225
|
+
priority: route.priority,
|
|
226
|
+
exact: route.exact,
|
|
227
|
+
requiredFeatures: route.requiredFeatures
|
|
228
|
+
};
|
|
229
|
+
// Recursively transform child routes
|
|
230
|
+
if (route.routes && route.routes.length > 0) {
|
|
231
|
+
menuItem.children = transformToMenuData(route.routes);
|
|
232
|
+
}
|
|
233
|
+
return menuItem;
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
// Use ONLY the `/` root-layout entry for the sidebar menu.
|
|
237
|
+
// The route generator emits multiple `root-layout` entries (e.g. `/` and `/o/:orgName`),
|
|
238
|
+
// but org-scoped routes (`/o/:orgName/*`) should not appear in the global SPA sidebar.
|
|
239
|
+
const rootLayouts = (routeConfig || []).filter?.(r => r.key === 'root-layout' && r.path === config.LAYOUT_ROOT && Array.isArray(r.routes) && r.routes.length > 0) || [];
|
|
240
|
+
// Deduplicate by route key so duplicates from multiple layout entries don't render twice
|
|
241
|
+
const seenKeys = new Set();
|
|
242
|
+
const menuRoutes = rootLayouts.length ? rootLayouts.flatMap(rl => rl.routes).filter(r => {
|
|
243
|
+
if (!r?.key || seenKeys.has(r.key)) return false;
|
|
244
|
+
seenKeys.add(r.key);
|
|
245
|
+
return true;
|
|
246
|
+
}) : routeConfig;
|
|
247
|
+
console.log('[ProTailwindLayout clientLoader] Root layouts found:', rootLayouts.length, rootLayouts.map(r => r.path));
|
|
248
|
+
console.log('[ProTailwindLayout clientLoader] Menu routes count:', menuRoutes?.length || 0);
|
|
249
|
+
const menuData = transformToMenuData(menuRoutes || []);
|
|
250
|
+
console.log('[ProTailwindLayout clientLoader] Final menuData:', {
|
|
251
|
+
length: menuData.length,
|
|
252
|
+
items: menuData.map(m => ({
|
|
253
|
+
key: m.key,
|
|
254
|
+
name: m.name,
|
|
255
|
+
path: m.path,
|
|
256
|
+
icon: m.icon,
|
|
257
|
+
childrenCount: m.children?.length || 0
|
|
258
|
+
}))
|
|
259
|
+
});
|
|
260
|
+
// Cache the result for subsequent route changes
|
|
261
|
+
cachedSpaMenuData = {
|
|
262
|
+
newMenuData: menuData,
|
|
263
|
+
permissions: defaultPermissions,
|
|
264
|
+
apolloState: {}
|
|
265
|
+
};
|
|
266
|
+
return cachedSpaMenuData;
|
|
172
267
|
} catch (e) {
|
|
173
|
-
console.error('Error in
|
|
174
|
-
console.error(
|
|
268
|
+
console.error('[ProTailwindLayout clientLoader] Error generating menu data in SPA mode:', e);
|
|
269
|
+
console.error('[ProTailwindLayout clientLoader] Error details:', {
|
|
270
|
+
name: e.name,
|
|
271
|
+
message: e.message,
|
|
272
|
+
stack: e.stack
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
newMenuData: [],
|
|
276
|
+
permissions: {},
|
|
277
|
+
apolloState: {}
|
|
278
|
+
};
|
|
175
279
|
}
|
|
176
|
-
return loaderData;
|
|
177
280
|
}
|
|
281
|
+
// NOTE: We intentionally do NOT set clientLoader.hydrate = true
|
|
282
|
+
// This means:
|
|
283
|
+
// - Initial page load: Uses server loader data directly (instant SSR)
|
|
284
|
+
// - Client navigation: clientLoader runs to fetch/transform data
|
|
285
|
+
// - No HydrateFallback needed since SSR content renders immediately
|
|
178
286
|
const shouldRevalidate = ({
|
|
179
287
|
currentParams,
|
|
180
288
|
nextParams
|
|
181
289
|
}) => {
|
|
182
290
|
return currentParams.orgName !== nextParams.orgName;
|
|
183
291
|
};
|
|
292
|
+
function ProTailwindLayout(props) {
|
|
293
|
+
// Use Remix's useLoaderData to get data from clientLoader/loader
|
|
294
|
+
const loaderData = useLoaderData() || {
|
|
295
|
+
permissions: null,
|
|
296
|
+
newMenuData: []
|
|
297
|
+
};
|
|
298
|
+
const {
|
|
299
|
+
permissions = defaultPermissions,
|
|
300
|
+
newMenuData = []
|
|
301
|
+
} = loaderData || {};
|
|
302
|
+
const matches = useMatches();
|
|
303
|
+
const current = matches[matches.length - 1];
|
|
304
|
+
const {
|
|
305
|
+
orgName,
|
|
306
|
+
settings
|
|
307
|
+
} = useSelector(state => selector(state));
|
|
308
|
+
// Check if current route has projectId param (pattern: projects/:id)
|
|
309
|
+
const hasProjectId = current?.params?.id && current?.id?.includes('projects/:id');
|
|
310
|
+
// Get project-specific menus or all menus
|
|
311
|
+
const menuDataToUse = React.useMemo(() => {
|
|
312
|
+
if (!hasProjectId) {
|
|
313
|
+
// When NOT in project detail, filter out project-specific routes (hideInMenu: true)
|
|
314
|
+
return newMenuData.filter(item => !item.path?.includes('/projects/:id'));
|
|
315
|
+
}
|
|
316
|
+
// When in project detail, show only project-specific routes
|
|
317
|
+
return newMenuData.filter(item => item.path?.includes('/projects/:id'));
|
|
318
|
+
}, [hasProjectId, newMenuData]);
|
|
319
|
+
const filteredMenuData = React.useMemo(() => {
|
|
320
|
+
return filterMenuItemsByVisibility(menuDataToUse, settings);
|
|
321
|
+
}, [menuDataToUse, settings?.hiddenMenuCategories, settings?.hiddenMenuKeys]);
|
|
322
|
+
// Keep the last non-empty menu so a transient empty loaderData — e.g. during a
|
|
323
|
+
// clientLoader revalidation or the SSR→client hydration handoff, where
|
|
324
|
+
// `useLoaderData()` momentarily yields the `{ newMenuData: [] }` default — does NOT
|
|
325
|
+
// collapse the sidebar to nothing and then re-expand it. That collapse/re-expand was
|
|
326
|
+
// a visible "blink" of the whole menu. Once we have rendered items we never fall back
|
|
327
|
+
// to an empty menu; real menu changes (which produce a non-empty list) still apply.
|
|
328
|
+
const lastNonEmptyMenu = React.useRef(filteredMenuData);
|
|
329
|
+
if (filteredMenuData.length > 0) {
|
|
330
|
+
lastNonEmptyMenu.current = filteredMenuData;
|
|
331
|
+
}
|
|
332
|
+
const stableMenuData = filteredMenuData.length > 0 ? filteredMenuData : lastNonEmptyMenu.current;
|
|
333
|
+
const lastNonEmptyFullMenu = React.useRef(newMenuData);
|
|
334
|
+
if (newMenuData.length > 0) {
|
|
335
|
+
lastNonEmptyFullMenu.current = newMenuData;
|
|
336
|
+
}
|
|
337
|
+
const stableFullMenuData = newMenuData.length > 0 ? newMenuData : lastNonEmptyFullMenu.current;
|
|
338
|
+
const params = {
|
|
339
|
+
orgName: orgName,
|
|
340
|
+
...(current?.params?.id && {
|
|
341
|
+
id: current.params.id
|
|
342
|
+
})
|
|
343
|
+
};
|
|
344
|
+
return React.createElement(BasicLayoutEnhanced, {
|
|
345
|
+
routeParams: params,
|
|
346
|
+
permissions: permissions,
|
|
347
|
+
menuData: stableMenuData,
|
|
348
|
+
fullMenuData: stableFullMenuData
|
|
349
|
+
});
|
|
350
|
+
}
|
|
184
351
|
export { clientLoader, ProTailwindLayout as default, handle, links, loader, shouldRevalidate }; //# sourceMappingURL=ProTailwindLayout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProTailwindLayout.js","sources":["../../../src/components/Layout/ProTailwindLayout.tsx"],"sourcesContent":[null],"names":[
|
|
1
|
+
{"version":3,"file":"ProTailwindLayout.js","sources":["../../../src/components/Layout/ProTailwindLayout.tsx"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomMenu.d.ts","sourceRoot":"","sources":["../../../../src/components/Layout/Sidebar/BottomMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"BottomMenu.d.ts","sourceRoot":"","sources":["../../../../src/components/Layout/Sidebar/BottomMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAM3D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AA2BhD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAwRhD,CAAC"}
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import React__default,{useState,useRef,useEffect}from'react';import {Link}from'@remix-run/react';import {useAppSelector}from'@admin-layout/client';import {generateMenuPath}from'../util.js';import {renderDynamicIcon}from'../../../helpers/DynamicIcon.js';import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import React__default,{useState,useRef,useEffect}from'react';import {Link}from'@remix-run/react';import {useAppSelector}from'@admin-layout/client';import {generateMenuPath}from'../util.js';import {renderDynamicIcon}from'../../../helpers/DynamicIcon.js';import {MenuDynamicDialog}from'./MenuDynamicDialog.js';// Smooth entrance for the account/user dropdown — matches the rail's motion language.
|
|
2
|
+
// transform/opacity/filter only; honors prefers-reduced-motion.
|
|
3
|
+
const BOTTOM_MENU_MOTION_CSS = `
|
|
4
|
+
@keyframes qlBottomDropdownIn {
|
|
5
|
+
from { opacity: 0; transform: translateY(8px) scale(0.96); filter: blur(4px); }
|
|
6
|
+
to { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
|
|
7
|
+
}
|
|
8
|
+
.ql-bottom-dropdown {
|
|
9
|
+
animation: qlBottomDropdownIn 0.2s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
10
|
+
will-change: transform, opacity;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
@keyframes qlBmItemIn {
|
|
13
|
+
from { opacity: 0; transform: translateX(-6px); }
|
|
14
|
+
to { opacity: 1; transform: translateX(0); }
|
|
15
|
+
}
|
|
16
|
+
.ql-bm-item {
|
|
17
|
+
animation: qlBmItemIn 0.26s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
18
|
+
animation-delay: calc(40ms + var(--i, 0) * 26ms);
|
|
19
|
+
}
|
|
20
|
+
@media (prefers-reduced-motion: reduce) {
|
|
21
|
+
.ql-bottom-dropdown { animation-duration: 0.01ms; filter: none; }
|
|
22
|
+
.ql-bm-item { animation: none; opacity: 1; }
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
17
25
|
const BottomMenu = ({
|
|
18
26
|
menuData,
|
|
19
27
|
routeParams,
|
|
@@ -34,13 +42,13 @@ const BottomMenu = ({
|
|
|
34
42
|
t: key => key
|
|
35
43
|
}; // Mock translation function
|
|
36
44
|
// const cancelRef = React.useRef();
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
// Memoized selector to avoid returning new references
|
|
46
|
+
const userState = useAppSelector(state => state?.user);
|
|
47
|
+
const profile = userState?.profile || {};
|
|
40
48
|
const {
|
|
41
49
|
nickname,
|
|
42
50
|
picture: profilePicture
|
|
43
|
-
} = profile
|
|
51
|
+
} = profile;
|
|
44
52
|
const onOpen = () => setIsOpen(true);
|
|
45
53
|
const onClose = () => setIsOpen(false);
|
|
46
54
|
const toggleMenu = () => setIsOpen(!isOpen);
|
|
@@ -159,62 +167,17 @@ const BottomMenu = ({
|
|
|
159
167
|
key,
|
|
160
168
|
name
|
|
161
169
|
} = item;
|
|
162
|
-
|
|
170
|
+
if (key !== openedModalKey) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
return React__default.createElement(MenuDynamicDialog, {
|
|
163
174
|
key: k,
|
|
164
|
-
|
|
165
|
-
}, React__default.createElement("div", {
|
|
166
|
-
className: "flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
|
167
|
-
}, React__default.createElement("div", {
|
|
168
|
-
className: "fixed inset-0 transition-opacity",
|
|
169
|
-
"aria-hidden": "true"
|
|
170
|
-
}, React__default.createElement("div", {
|
|
171
|
-
className: "absolute inset-0 bg-black bg-opacity-50",
|
|
172
|
-
onClick: () => {
|
|
173
|
-
onClose();
|
|
174
|
-
setOpenedModalKey(null);
|
|
175
|
-
}
|
|
176
|
-
})), React__default.createElement("span", {
|
|
177
|
-
className: "hidden sm:inline-block sm:align-middle sm:h-screen",
|
|
178
|
-
"aria-hidden": "true"
|
|
179
|
-
}, "\u200B"), React__default.createElement("div", {
|
|
180
|
-
className: "inline-block align-bottom rounded-themed-lg text-left overflow-hidden shadow-themed-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full themed-modal",
|
|
181
|
-
role: "dialog",
|
|
182
|
-
"aria-modal": "true",
|
|
183
|
-
"aria-labelledby": "modal-headline"
|
|
184
|
-
}, React__default.createElement("div", {
|
|
185
|
-
className: "px-4 pt-5 pb-4 sm:p-6 sm:pb-4"
|
|
186
|
-
}, React__default.createElement("div", {
|
|
187
|
-
className: "flex justify-end"
|
|
188
|
-
}, React__default.createElement("button", {
|
|
189
|
-
type: "button",
|
|
190
|
-
className: "rounded-themed text-muted-foreground hover:text-foreground focus-themed",
|
|
191
|
-
onClick: () => {
|
|
192
|
-
onClose();
|
|
193
|
-
setOpenedModalKey(null);
|
|
194
|
-
}
|
|
195
|
-
}, React__default.createElement("span", {
|
|
196
|
-
className: "sr-only"
|
|
197
|
-
}, "Close"), React__default.createElement("svg", {
|
|
198
|
-
className: "h-6 w-6",
|
|
199
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
200
|
-
fill: "none",
|
|
201
|
-
viewBox: "0 0 24 24",
|
|
202
|
-
stroke: "currentColor",
|
|
203
|
-
"aria-hidden": "true"
|
|
204
|
-
}, React__default.createElement("path", {
|
|
205
|
-
strokeLinecap: "round",
|
|
206
|
-
strokeLinejoin: "round",
|
|
207
|
-
strokeWidth: "2",
|
|
208
|
-
d: "M6 18L18 6M6 6l12 12"
|
|
209
|
-
})))), React__default.createElement("div", {
|
|
210
|
-
className: "mt-2"
|
|
211
|
-
}, React__default.createElement(DialogComponent, {
|
|
212
|
-
path: dialogPath,
|
|
175
|
+
dialogPath: dialogPath,
|
|
213
176
|
onClose: () => {
|
|
214
177
|
onClose();
|
|
215
178
|
setOpenedModalKey(null);
|
|
216
179
|
}
|
|
217
|
-
})
|
|
180
|
+
});
|
|
218
181
|
});
|
|
219
182
|
};
|
|
220
183
|
return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
|
|
@@ -247,11 +210,18 @@ const BottomMenu = ({
|
|
|
247
210
|
}))), isMobile && React__default.createElement("span", {
|
|
248
211
|
className: "text-lg font-medium"
|
|
249
212
|
}, t(nickname))), isOpen && React__default.createElement("div", {
|
|
250
|
-
className: "bg-background absolute bottom-full mb-2 w-72 rounded-themed shadow-themed-lg py-1 themed-dropdown ring-1 ring-border focus:outline-none z-40",
|
|
213
|
+
className: "ql-bottom-dropdown bg-background absolute bottom-full mb-2 w-72 rounded-themed shadow-themed-lg py-1 themed-dropdown ring-1 ring-border focus:outline-none z-40",
|
|
251
214
|
role: "menu",
|
|
252
215
|
"aria-orientation": "vertical",
|
|
253
|
-
"aria-labelledby": "user-menu"
|
|
254
|
-
|
|
216
|
+
"aria-labelledby": "user-menu",
|
|
217
|
+
style: {
|
|
218
|
+
transformOrigin: 'bottom left'
|
|
219
|
+
}
|
|
220
|
+
}, React__default.createElement("style", {
|
|
221
|
+
dangerouslySetInnerHTML: {
|
|
222
|
+
__html: BOTTOM_MENU_MOTION_CSS
|
|
223
|
+
}
|
|
224
|
+
}), MenusList?.upperMenus?.map((item, k) => React__default.createElement("div", {
|
|
255
225
|
key: k,
|
|
256
226
|
className: "px-1 py-1"
|
|
257
227
|
}, item.modal ? getMenuItemModal(item) : getMenuItemPath(item))), MenusList?.upperMenus?.length > 0 && MenusList?.middleMenus?.length > 0 && React__default.createElement("hr", {
|
|
@@ -261,9 +231,12 @@ const BottomMenu = ({
|
|
|
261
231
|
className: "px-1 py-1"
|
|
262
232
|
}, item.modal ? getMenuItemModal(item) : getMenuItemPath(item))), profile && accountMenuItems?.children && React__default.createElement("div", {
|
|
263
233
|
className: "py-2"
|
|
264
|
-
}, accountMenuItems.children.map(item => React__default.createElement(Link, {
|
|
234
|
+
}, accountMenuItems.children.map((item, idx) => React__default.createElement(Link, {
|
|
265
235
|
key: item.key,
|
|
266
|
-
className: "flex items-center justify-between px-4 py-2 text-sm text-
|
|
236
|
+
className: "ql-bm-item flex items-center justify-between px-4 py-2 text-sm text-foreground hover:bg-muted cursor-pointer transition-colors",
|
|
237
|
+
style: {
|
|
238
|
+
['--i']: idx
|
|
239
|
+
},
|
|
267
240
|
to: generateMenuPath(item.path, routeParams)
|
|
268
241
|
}, React__default.createElement("div", {
|
|
269
242
|
className: "flex items-center"
|
|
@@ -271,7 +244,12 @@ const BottomMenu = ({
|
|
|
271
244
|
className: "mr-3 text-base"
|
|
272
245
|
}, item.icon), React__default.createElement("span", null, item.name)), item.hasNotification && React__default.createElement("div", {
|
|
273
246
|
className: "w-2 h-2 bg-blue-500 rounded-full"
|
|
274
|
-
})))), profile && React__default.createElement("hr", {
|
|
247
|
+
})))), profile && accountMenuItems?.children && React__default.createElement("hr", {
|
|
248
|
+
className: "border-border my-1"
|
|
249
|
+
}), logoutMenuItems?.map((item, k) => React__default.createElement("div", {
|
|
250
|
+
key: k,
|
|
251
|
+
className: "px-1 py-1"
|
|
252
|
+
}, item.modal ? getMenuItemModal(item) : getMenuItemPath(item))), profile && logoutMenuItems?.length > 0 && React__default.createElement("hr", {
|
|
275
253
|
className: "border-border my-1"
|
|
276
254
|
}), profile && React__default.createElement("div", {
|
|
277
255
|
className: "flex items-center px-4 py-2"
|
|
@@ -285,10 +263,5 @@ const BottomMenu = ({
|
|
|
285
263
|
className: "text-white text-sm font-medium"
|
|
286
264
|
}, (nickname || 'Guest').charAt(0).toUpperCase())), React__default.createElement("span", {
|
|
287
265
|
className: "text-sm font-medium"
|
|
288
|
-
}, nickname || 'Guest')),
|
|
289
|
-
className: "border-border my-1"
|
|
290
|
-
}), logoutMenuItems?.map((item, k) => React__default.createElement("div", {
|
|
291
|
-
key: k,
|
|
292
|
-
className: "px-1 py-1"
|
|
293
|
-
}, item.modal ? getMenuItemModal(item) : getMenuItemPath(item))))), getMenuModals());
|
|
266
|
+
}, nickname || 'Guest')))), getMenuModals());
|
|
294
267
|
};export{BottomMenu};//# sourceMappingURL=BottomMenu.js.map
|