@admin-layout/tailwind-design-pro 12.2.4-alpha.1 → 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.
Files changed (157) hide show
  1. package/README.md +80 -0
  2. package/lib/components/LanguageMenu/LanguageMenu.d.ts.map +1 -1
  3. package/lib/components/LanguageMenu/LanguageMenu.js +6 -2
  4. package/lib/components/LanguageMenu/LanguageMenu.js.map +1 -1
  5. package/lib/components/Layout/BasicLayout/index.d.ts +19 -0
  6. package/lib/components/Layout/BasicLayout/index.d.ts.map +1 -1
  7. package/lib/components/Layout/BasicLayout/index.js +63 -14
  8. package/lib/components/Layout/BasicLayout/index.js.map +1 -1
  9. package/lib/components/Layout/BasicLayout/utils.js +1 -1
  10. package/lib/components/Layout/BasicLayout/utils.js.map +1 -1
  11. package/lib/components/Layout/GlobalFooter/BottomMenuDropdown.js +1 -1
  12. package/lib/components/Layout/GlobalFooter/BottomMenuDropdown.js.map +1 -1
  13. package/lib/components/Layout/GlobalHeader/Header.d.ts.map +1 -1
  14. package/lib/components/Layout/GlobalHeader/Header.js +12 -4
  15. package/lib/components/Layout/GlobalHeader/Header.js.map +1 -1
  16. package/lib/components/Layout/GlobalHeader/MainHeader.d.ts.map +1 -1
  17. package/lib/components/Layout/GlobalHeader/MainHeader.js +2 -1
  18. package/lib/components/Layout/GlobalHeader/MainHeader.js.map +1 -1
  19. package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.d.ts +12 -0
  20. package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.d.ts.map +1 -0
  21. package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.js +36 -0
  22. package/lib/components/Layout/GlobalHeader/NavbarSlotStrip.js.map +1 -0
  23. package/lib/components/Layout/GlobalHeader/RightContent.d.ts +1 -2
  24. package/lib/components/Layout/GlobalHeader/RightContent.d.ts.map +1 -1
  25. package/lib/components/Layout/GlobalHeader/RightContent.js +10 -72
  26. package/lib/components/Layout/GlobalHeader/RightContent.js.map +1 -1
  27. package/lib/components/Layout/GlobalHeader/RightMenu.d.ts.map +1 -1
  28. package/lib/components/Layout/GlobalHeader/RightMenu.js +16 -80
  29. package/lib/components/Layout/GlobalHeader/RightMenu.js.map +1 -1
  30. package/lib/components/Layout/GlobalHeader/SearchBar.d.ts +43 -0
  31. package/lib/components/Layout/GlobalHeader/SearchBar.d.ts.map +1 -1
  32. package/lib/components/Layout/GlobalHeader/SearchBar.js +380 -43
  33. package/lib/components/Layout/GlobalHeader/SearchBar.js.map +1 -1
  34. package/lib/components/Layout/GlobalHeader/index.d.ts +1 -0
  35. package/lib/components/Layout/GlobalHeader/index.d.ts.map +1 -1
  36. package/lib/components/Layout/ProTailwindLayout.d.ts +20 -8
  37. package/lib/components/Layout/ProTailwindLayout.d.ts.map +1 -1
  38. package/lib/components/Layout/ProTailwindLayout.js +255 -88
  39. package/lib/components/Layout/ProTailwindLayout.js.map +1 -1
  40. package/lib/components/Layout/Sidebar/BottomMenu.d.ts.map +1 -1
  41. package/lib/components/Layout/Sidebar/BottomMenu.js +55 -82
  42. package/lib/components/Layout/Sidebar/BottomMenu.js.map +1 -1
  43. package/lib/components/Layout/Sidebar/DynamicIcon.d.ts.map +1 -1
  44. package/lib/components/Layout/Sidebar/DynamicIcon.js +80 -19
  45. package/lib/components/Layout/Sidebar/DynamicIcon.js.map +1 -1
  46. package/lib/components/Layout/Sidebar/MainSidebar.d.ts.map +1 -1
  47. package/lib/components/Layout/Sidebar/MainSidebar.js +29 -24
  48. package/lib/components/Layout/Sidebar/MainSidebar.js.map +1 -1
  49. package/lib/components/Layout/Sidebar/MainSidebarMenu.d.ts.map +1 -1
  50. package/lib/components/Layout/Sidebar/MainSidebarMenu.js +213 -36
  51. package/lib/components/Layout/Sidebar/MainSidebarMenu.js.map +1 -1
  52. package/lib/components/Layout/Sidebar/MenuDynamicDialog.d.ts +12 -0
  53. package/lib/components/Layout/Sidebar/MenuDynamicDialog.d.ts.map +1 -0
  54. package/lib/components/Layout/Sidebar/MenuDynamicDialog.js +79 -0
  55. package/lib/components/Layout/Sidebar/MenuDynamicDialog.js.map +1 -0
  56. package/lib/components/Layout/Sidebar/PerplexSidebar.d.ts.map +1 -1
  57. package/lib/components/Layout/Sidebar/PerplexSidebar.js +42 -33
  58. package/lib/components/Layout/Sidebar/PerplexSidebar.js.map +1 -1
  59. package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.d.ts +25 -0
  60. package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.d.ts.map +1 -0
  61. package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.js +287 -0
  62. package/lib/components/Layout/Sidebar/PerplexSidebarFlyoutContext.js.map +1 -0
  63. package/lib/components/Layout/Sidebar/PerplexSidebarMenu.d.ts.map +1 -1
  64. package/lib/components/Layout/Sidebar/PerplexSidebarMenu.js +321 -43
  65. package/lib/components/Layout/Sidebar/PerplexSidebarMenu.js.map +1 -1
  66. package/lib/components/Layout/Sidebar/SidebarRailFX.d.ts +23 -0
  67. package/lib/components/Layout/Sidebar/SidebarRailFX.d.ts.map +1 -0
  68. package/lib/components/Layout/Sidebar/SidebarRailFX.js +229 -0
  69. package/lib/components/Layout/Sidebar/SidebarRailFX.js.map +1 -0
  70. package/lib/components/Layout/SidebarControlsContext.d.ts +17 -0
  71. package/lib/components/Layout/SidebarControlsContext.d.ts.map +1 -0
  72. package/lib/components/Layout/SidebarControlsContext.js +21 -0
  73. package/lib/components/Layout/SidebarControlsContext.js.map +1 -0
  74. package/lib/components/Layout/TailwindLayout.d.ts.map +1 -1
  75. package/lib/components/Layout/TailwindLayout.js +22 -3
  76. package/lib/components/Layout/TailwindLayout.js.map +1 -1
  77. package/lib/components/Layout/defaultPermissions.d.ts +134 -0
  78. package/lib/components/Layout/defaultPermissions.d.ts.map +1 -0
  79. package/lib/components/Layout/defaultPermissions.js +134 -0
  80. package/lib/components/Layout/defaultPermissions.js.map +1 -0
  81. package/lib/components/Layout/getPageTitle.js +2 -2
  82. package/lib/components/Layout/getPageTitle.js.map +1 -1
  83. package/lib/components/Layout/slot-fill/RightContent.d.ts +3 -1
  84. package/lib/components/Layout/slot-fill/RightContent.d.ts.map +1 -1
  85. package/lib/components/Layout/slot-fill/RightContent.js +4 -6
  86. package/lib/components/Layout/slot-fill/RightContent.js.map +1 -1
  87. package/lib/components/SettingDrawer/SettingDrawer.d.ts.map +1 -1
  88. package/lib/components/SettingDrawer/SettingDrawer.js +21 -18
  89. package/lib/components/SettingDrawer/SettingDrawer.js.map +1 -1
  90. package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.d.ts.map +1 -1
  91. package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.js +8 -14
  92. package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.js.map +1 -1
  93. package/lib/components/SettingDrawer/components/CheckBoxTheme.js +2 -2
  94. package/lib/components/SettingDrawer/components/CheckBoxTheme.js.map +1 -1
  95. package/lib/components/SettingDrawer/components/DeviceTabs.js +2 -2
  96. package/lib/components/SettingDrawer/components/DeviceTabs.js.map +1 -1
  97. package/lib/components/SettingDrawer/components/InvitationSettings.d.ts.map +1 -1
  98. package/lib/components/SettingDrawer/components/InvitationSettings.js +7 -3
  99. package/lib/components/SettingDrawer/components/InvitationSettings.js.map +1 -1
  100. package/lib/components/SettingDrawer/components/LayoutChange.d.ts.map +1 -1
  101. package/lib/components/SettingDrawer/components/LayoutChange.js +8 -11
  102. package/lib/components/SettingDrawer/components/LayoutChange.js.map +1 -1
  103. package/lib/components/SettingDrawer/components/MenuVisibilitySettings.js +5 -5
  104. package/lib/components/SettingDrawer/components/MenuVisibilitySettings.js.map +1 -1
  105. package/lib/components/SettingDrawer/components/NavigationsModes.js +3 -3
  106. package/lib/components/SettingDrawer/components/NavigationsModes.js.map +1 -1
  107. package/lib/components/SettingDrawer/components/RegionalSettings.d.ts.map +1 -1
  108. package/lib/components/SettingDrawer/components/RegionalSettings.js +40 -97
  109. package/lib/components/SettingDrawer/components/RegionalSettings.js.map +1 -1
  110. package/lib/components/SettingDrawer/components/SettingsActions.d.ts.map +1 -1
  111. package/lib/components/SettingDrawer/components/SettingsActions.js +27 -25
  112. package/lib/components/SettingDrawer/components/SettingsActions.js.map +1 -1
  113. package/lib/components/SettingDrawer/components/SettingsDrawerHeader.d.ts.map +1 -1
  114. package/lib/components/SettingDrawer/components/SettingsDrawerHeader.js +4 -3
  115. package/lib/components/SettingDrawer/components/SettingsDrawerHeader.js.map +1 -1
  116. package/lib/components/SettingDrawer/components/Switch.js +2 -2
  117. package/lib/components/SettingDrawer/components/ThemeColor.js +1 -1
  118. package/lib/components/SettingDrawer/components/ThemeColor.js.map +1 -1
  119. package/lib/components/SettingDrawer/components/ThemeSelector.js +1 -1
  120. package/lib/components/SettingDrawer/components/WebFontsSelector.js +1 -1
  121. package/lib/components/SettingDrawer/hooks/useSettingsOperations.d.ts.map +1 -1
  122. package/lib/components/SettingDrawer/hooks/useSettingsOperations.js +13 -9
  123. package/lib/components/SettingDrawer/hooks/useSettingsOperations.js.map +1 -1
  124. package/lib/components/SettingDrawer/utils/constants.d.ts.map +1 -1
  125. package/lib/components/SettingDrawer/utils/constants.js +3 -0
  126. package/lib/components/SettingDrawer/utils/constants.js.map +1 -1
  127. package/lib/components/SettingDrawer/utils/helper.js +1 -1
  128. package/lib/components/SettingDrawer/utils/transformers.d.ts +16 -0
  129. package/lib/components/SettingDrawer/utils/transformers.d.ts.map +1 -1
  130. package/lib/components/SettingDrawer/utils/transformers.js +39 -2
  131. package/lib/components/SettingDrawer/utils/transformers.js.map +1 -1
  132. package/lib/components/SettingsThemeApplier/SettingsThemeApplier.d.ts +10 -0
  133. package/lib/components/SettingsThemeApplier/SettingsThemeApplier.d.ts.map +1 -0
  134. package/lib/components/SettingsThemeApplier/SettingsThemeApplier.js +23 -0
  135. package/lib/components/SettingsThemeApplier/SettingsThemeApplier.js.map +1 -0
  136. package/lib/components/SettingsThemeApplier/index.d.ts +2 -0
  137. package/lib/components/SettingsThemeApplier/index.d.ts.map +1 -0
  138. package/lib/components/index.js +1 -1
  139. package/lib/components/typings.d.ts +29 -0
  140. package/lib/components/typings.d.ts.map +1 -1
  141. package/lib/compute.js +2 -1
  142. package/lib/compute.js.map +1 -1
  143. package/lib/helpers/DynamicIcon.js +7 -1
  144. package/lib/helpers/DynamicIcon.js.map +1 -1
  145. package/lib/hooks/index.d.ts +1 -0
  146. package/lib/hooks/index.d.ts.map +1 -1
  147. package/lib/index.d.ts +3 -0
  148. package/lib/index.d.ts.map +1 -1
  149. package/lib/index.js +1 -1
  150. package/lib/index.js.map +1 -1
  151. package/lib/routes.json +6 -1
  152. package/lib/styles/index.css +321 -0
  153. package/lib/utils/settingsTheme.d.ts +40 -0
  154. package/lib/utils/settingsTheme.d.ts.map +1 -0
  155. package/lib/utils/settingsTheme.js +106 -0
  156. package/lib/utils/settingsTheme.js.map +1 -0
  157. 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
- const selectOrgName = state => state.platform.orgName;
13
- const selectSettings = state => state.settings;
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
- * Filter menu items based on user visibility settings using filteredRoutes utilities
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
- const ProTailwindLayout = props => {
71
- const {
72
- loaderData: {
73
- permissions,
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
- const routeWithLocale = filterRoutesWithLocale(parentRoute['routes']);
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"],"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]
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
- // During client-side navigations, we hit our exposed API endpoints directly
161
- // do not restore apollo state in cache memory as it can rewrite newer data
162
- const loaderData = await serverLoader();
163
- const {
164
- apolloState
165
- } = loaderData;
166
- try {
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
- container
169
- } = window.__CLIENT_SERVICE__;
170
- const organizationContext = container.get(ClientContainerService.IOrganizationContextService);
171
- organizationContext.hydrate(apolloState);
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 client hydrate');
174
- console.error(e);
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":["TailwindLayout"],"mappings":"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"}
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,KAAgD,MAAM,OAAO,CAAC;AAOrE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAgBhD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAuUhD,CAAC"}
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 switchDialogs from'@app/dialog/WrappedDialogsSwitch';const DialogComponent = ({
2
- path,
3
- onClose
4
- }) => {
5
- const [dialog, setDialog] = useState(null);
6
- useEffect(() => {
7
- if (!dialog) {
8
- switchDialogs(path).then(component => {
9
- setDialog(component);
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
- return dialog ? React__default.createElement(dialog.default, {
14
- onClose: onClose
15
- }) : React__default.createElement("div", null, "Loading...");
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
- const {
38
- profile = {}
39
- } = useAppSelector(state => state?.user || {});
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
- return key === openedModalKey && React__default.createElement("div", {
170
+ if (key !== openedModalKey) {
171
+ return null;
172
+ }
173
+ return React__default.createElement(MenuDynamicDialog, {
163
174
  key: k,
164
- className: "fixed inset-0 z-50 overflow-y-auto"
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
- }, MenusList?.upperMenus?.map((item, k) => React__default.createElement("div", {
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-gray-700 hover:bg-gray-50 cursor-pointer transition-colors",
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')), logoutMenuItems?.length > 0 && React__default.createElement("hr", {
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