@qwickapps/react-framework 1.5.5 → 1.5.7

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 (125) hide show
  1. package/dist/components/QwickApp.d.ts.map +1 -1
  2. package/dist/components/ResponsiveMenu.d.ts.map +1 -1
  3. package/dist/components/Scaffold.d.ts.map +1 -1
  4. package/dist/components/index.d.ts +1 -0
  5. package/dist/components/index.d.ts.map +1 -1
  6. package/dist/contexts/NavigationContext.d.ts +64 -0
  7. package/dist/contexts/NavigationContext.d.ts.map +1 -0
  8. package/dist/contexts/index.d.ts +2 -0
  9. package/dist/contexts/index.d.ts.map +1 -1
  10. package/dist/hooks/useBaseProps.d.ts +12 -1161
  11. package/dist/hooks/useBaseProps.d.ts.map +1 -1
  12. package/dist/index.esm.js +514 -272
  13. package/dist/index.js +514 -272
  14. package/dist/palettes/manifest.json +19 -19
  15. package/dist/palettes/palette-autumn.1.4.9.css +172 -0
  16. package/dist/palettes/palette-autumn.1.4.9.min.css +1 -0
  17. package/dist/palettes/palette-autumn.1.5.0.css +172 -0
  18. package/dist/palettes/palette-autumn.1.5.0.min.css +1 -0
  19. package/dist/palettes/palette-autumn.1.5.1.css +172 -0
  20. package/dist/palettes/palette-autumn.1.5.1.min.css +1 -0
  21. package/dist/palettes/palette-autumn.1.5.2.css +172 -0
  22. package/dist/palettes/palette-autumn.1.5.2.min.css +1 -0
  23. package/dist/palettes/palette-autumn.1.5.3.css +172 -0
  24. package/dist/palettes/palette-autumn.1.5.3.min.css +1 -0
  25. package/dist/palettes/palette-autumn.1.5.4.css +172 -0
  26. package/dist/palettes/palette-autumn.1.5.4.min.css +1 -0
  27. package/dist/palettes/palette-autumn.1.5.6.css +172 -0
  28. package/dist/palettes/palette-autumn.1.5.6.min.css +1 -0
  29. package/dist/palettes/palette-autumn.1.5.7.css +172 -0
  30. package/dist/palettes/palette-autumn.1.5.7.min.css +1 -0
  31. package/dist/palettes/palette-cosmic.1.4.9.css +172 -0
  32. package/dist/palettes/palette-cosmic.1.4.9.min.css +1 -0
  33. package/dist/palettes/palette-cosmic.1.5.0.css +172 -0
  34. package/dist/palettes/palette-cosmic.1.5.0.min.css +1 -0
  35. package/dist/palettes/palette-cosmic.1.5.1.css +172 -0
  36. package/dist/palettes/palette-cosmic.1.5.1.min.css +1 -0
  37. package/dist/palettes/palette-cosmic.1.5.2.css +172 -0
  38. package/dist/palettes/palette-cosmic.1.5.2.min.css +1 -0
  39. package/dist/palettes/palette-cosmic.1.5.3.css +172 -0
  40. package/dist/palettes/palette-cosmic.1.5.3.min.css +1 -0
  41. package/dist/palettes/palette-cosmic.1.5.4.css +172 -0
  42. package/dist/palettes/palette-cosmic.1.5.4.min.css +1 -0
  43. package/dist/palettes/palette-cosmic.1.5.6.css +172 -0
  44. package/dist/palettes/palette-cosmic.1.5.6.min.css +1 -0
  45. package/dist/palettes/palette-cosmic.1.5.7.css +172 -0
  46. package/dist/palettes/palette-cosmic.1.5.7.min.css +1 -0
  47. package/dist/palettes/palette-default.1.4.9.css +178 -0
  48. package/dist/palettes/palette-default.1.4.9.min.css +1 -0
  49. package/dist/palettes/palette-default.1.5.0.css +178 -0
  50. package/dist/palettes/palette-default.1.5.0.min.css +1 -0
  51. package/dist/palettes/palette-default.1.5.1.css +178 -0
  52. package/dist/palettes/palette-default.1.5.1.min.css +1 -0
  53. package/dist/palettes/palette-default.1.5.2.css +178 -0
  54. package/dist/palettes/palette-default.1.5.2.min.css +1 -0
  55. package/dist/palettes/palette-default.1.5.3.css +178 -0
  56. package/dist/palettes/palette-default.1.5.3.min.css +1 -0
  57. package/dist/palettes/palette-default.1.5.4.css +178 -0
  58. package/dist/palettes/palette-default.1.5.4.min.css +1 -0
  59. package/dist/palettes/palette-default.1.5.6.css +178 -0
  60. package/dist/palettes/palette-default.1.5.6.min.css +1 -0
  61. package/dist/palettes/palette-default.1.5.7.css +178 -0
  62. package/dist/palettes/palette-default.1.5.7.min.css +1 -0
  63. package/dist/palettes/palette-ocean.1.4.9.css +172 -0
  64. package/dist/palettes/palette-ocean.1.4.9.min.css +1 -0
  65. package/dist/palettes/palette-ocean.1.5.0.css +172 -0
  66. package/dist/palettes/palette-ocean.1.5.0.min.css +1 -0
  67. package/dist/palettes/palette-ocean.1.5.1.css +172 -0
  68. package/dist/palettes/palette-ocean.1.5.1.min.css +1 -0
  69. package/dist/palettes/palette-ocean.1.5.2.css +172 -0
  70. package/dist/palettes/palette-ocean.1.5.2.min.css +1 -0
  71. package/dist/palettes/palette-ocean.1.5.3.css +172 -0
  72. package/dist/palettes/palette-ocean.1.5.3.min.css +1 -0
  73. package/dist/palettes/palette-ocean.1.5.4.css +172 -0
  74. package/dist/palettes/palette-ocean.1.5.4.min.css +1 -0
  75. package/dist/palettes/palette-ocean.1.5.6.css +172 -0
  76. package/dist/palettes/palette-ocean.1.5.6.min.css +1 -0
  77. package/dist/palettes/palette-ocean.1.5.7.css +172 -0
  78. package/dist/palettes/palette-ocean.1.5.7.min.css +1 -0
  79. package/dist/palettes/palette-spring.1.4.9.css +160 -0
  80. package/dist/palettes/palette-spring.1.4.9.min.css +1 -0
  81. package/dist/palettes/palette-spring.1.5.0.css +160 -0
  82. package/dist/palettes/palette-spring.1.5.0.min.css +1 -0
  83. package/dist/palettes/palette-spring.1.5.1.css +160 -0
  84. package/dist/palettes/palette-spring.1.5.1.min.css +1 -0
  85. package/dist/palettes/palette-spring.1.5.2.css +160 -0
  86. package/dist/palettes/palette-spring.1.5.2.min.css +1 -0
  87. package/dist/palettes/palette-spring.1.5.3.css +166 -0
  88. package/dist/palettes/palette-spring.1.5.3.min.css +1 -0
  89. package/dist/palettes/palette-spring.1.5.4.css +166 -0
  90. package/dist/palettes/palette-spring.1.5.4.min.css +1 -0
  91. package/dist/palettes/palette-spring.1.5.6.css +166 -0
  92. package/dist/palettes/palette-spring.1.5.6.min.css +1 -0
  93. package/dist/palettes/palette-spring.1.5.7.css +166 -0
  94. package/dist/palettes/palette-spring.1.5.7.min.css +1 -0
  95. package/dist/palettes/palette-winter.1.4.9.css +172 -0
  96. package/dist/palettes/palette-winter.1.4.9.min.css +1 -0
  97. package/dist/palettes/palette-winter.1.5.0.css +172 -0
  98. package/dist/palettes/palette-winter.1.5.0.min.css +1 -0
  99. package/dist/palettes/palette-winter.1.5.1.css +172 -0
  100. package/dist/palettes/palette-winter.1.5.1.min.css +1 -0
  101. package/dist/palettes/palette-winter.1.5.2.css +172 -0
  102. package/dist/palettes/palette-winter.1.5.2.min.css +1 -0
  103. package/dist/palettes/palette-winter.1.5.3.css +172 -0
  104. package/dist/palettes/palette-winter.1.5.3.min.css +1 -0
  105. package/dist/palettes/palette-winter.1.5.4.css +172 -0
  106. package/dist/palettes/palette-winter.1.5.4.min.css +1 -0
  107. package/dist/palettes/palette-winter.1.5.6.css +172 -0
  108. package/dist/palettes/palette-winter.1.5.6.min.css +1 -0
  109. package/dist/palettes/palette-winter.1.5.7.css +172 -0
  110. package/dist/palettes/palette-winter.1.5.7.min.css +1 -0
  111. package/dist/utils/iconMap.d.ts +21 -8
  112. package/dist/utils/iconMap.d.ts.map +1 -1
  113. package/dist/utils/reactUtils.d.ts +0 -23
  114. package/dist/utils/reactUtils.d.ts.map +1 -1
  115. package/package.json +1 -1
  116. package/src/__tests__/utils/iconMap.test.tsx +197 -0
  117. package/src/components/QwickApp.tsx +24 -15
  118. package/src/components/ResponsiveMenu.tsx +3 -4
  119. package/src/components/Scaffold.tsx +3 -4
  120. package/src/components/index.ts +1 -0
  121. package/src/components/pages/Page.tsx +2 -2
  122. package/src/contexts/NavigationContext.tsx +168 -0
  123. package/src/contexts/index.ts +2 -0
  124. package/src/utils/iconMap.tsx +209 -151
  125. package/src/utils/reactUtils.tsx +2 -47
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Navigation Context - Smart navigation that auto-detects React Router
3
+ *
4
+ * Provides navigation functions that work with React Router when available,
5
+ * falling back to window.location for non-router apps or SSR.
6
+ *
7
+ * Usage:
8
+ * - Wrap your app with NavigationProvider (done automatically by QwickApp)
9
+ * - Use useNavigation() hook to get navigate function and location
10
+ *
11
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
12
+ */
13
+
14
+ import { createContext, useContext, type ReactNode } from 'react';
15
+ import {
16
+ useNavigate,
17
+ useLocation,
18
+ useInRouterContext,
19
+ } from 'react-router-dom';
20
+
21
+ /**
22
+ * Location type matching React Router's location shape
23
+ */
24
+ export interface NavigationLocation {
25
+ pathname: string;
26
+ search: string;
27
+ hash: string;
28
+ }
29
+
30
+ /**
31
+ * Navigate function type
32
+ */
33
+ export type NavigateFunction = (to: string | number) => void;
34
+
35
+ /**
36
+ * Navigation context value
37
+ */
38
+ export interface NavigationContextValue {
39
+ navigate: NavigateFunction;
40
+ location: NavigationLocation | undefined;
41
+ }
42
+
43
+ const NavigationContext = createContext<NavigationContextValue | null>(null);
44
+
45
+ /**
46
+ * Internal provider that uses React Router hooks
47
+ * Only rendered when we're inside a Router context
48
+ */
49
+ function ReactRouterNavigationProvider({ children }: { children: ReactNode }) {
50
+ const reactRouterNavigate = useNavigate();
51
+ const reactRouterLocation = useLocation();
52
+
53
+ const navigate: NavigateFunction = (to) => {
54
+ if (typeof to === 'string') {
55
+ reactRouterNavigate(to);
56
+ } else if (typeof to === 'number') {
57
+ reactRouterNavigate(to);
58
+ }
59
+ };
60
+
61
+ // Defensive check for location - fall back to window.location if React Router's location is undefined
62
+ const location: NavigationLocation | undefined = reactRouterLocation
63
+ ? {
64
+ pathname: reactRouterLocation.pathname,
65
+ search: reactRouterLocation.search,
66
+ hash: reactRouterLocation.hash,
67
+ }
68
+ : typeof window !== 'undefined'
69
+ ? {
70
+ pathname: window.location.pathname,
71
+ search: window.location.search,
72
+ hash: window.location.hash,
73
+ }
74
+ : undefined;
75
+
76
+ return (
77
+ <NavigationContext.Provider value={{ navigate, location }}>
78
+ {children}
79
+ </NavigationContext.Provider>
80
+ );
81
+ }
82
+
83
+ /**
84
+ * Internal provider that uses window.location fallback
85
+ * Used when not inside a React Router context
86
+ */
87
+ function FallbackNavigationProvider({ children }: { children: ReactNode }) {
88
+ const navigate: NavigateFunction = (to) => {
89
+ if (typeof window === 'undefined') return;
90
+
91
+ if (typeof to === 'string') {
92
+ window.location.href = to;
93
+ } else if (typeof to === 'number') {
94
+ window.history.go(to);
95
+ }
96
+ };
97
+
98
+ const location: NavigationLocation | undefined =
99
+ typeof window !== 'undefined'
100
+ ? {
101
+ pathname: window.location.pathname,
102
+ search: window.location.search,
103
+ hash: window.location.hash,
104
+ }
105
+ : undefined;
106
+
107
+ return (
108
+ <NavigationContext.Provider value={{ navigate, location }}>
109
+ {children}
110
+ </NavigationContext.Provider>
111
+ );
112
+ }
113
+
114
+ /**
115
+ * Smart Navigation Provider
116
+ *
117
+ * Automatically detects if the app is inside a React Router context:
118
+ * - If inside Router: uses React Router's useNavigate/useLocation (respects basename)
119
+ * - If outside Router: falls back to window.location
120
+ *
121
+ * This is included automatically by QwickApp - you don't need to add it manually.
122
+ */
123
+ export function NavigationProvider({ children }: { children: ReactNode }) {
124
+ // Check if we're inside a React Router using the official hook
125
+ // This is more reliable than checking internal UNSAFE contexts
126
+ const isInRouter = useInRouterContext();
127
+
128
+ if (isInRouter) {
129
+ // We're inside a Router, use React Router's navigation
130
+ return (
131
+ <ReactRouterNavigationProvider>{children}</ReactRouterNavigationProvider>
132
+ );
133
+ }
134
+
135
+ // Not inside a Router, use window.location fallback
136
+ return <FallbackNavigationProvider>{children}</FallbackNavigationProvider>;
137
+ }
138
+
139
+ /**
140
+ * Hook to access navigation functions
141
+ *
142
+ * @returns Object containing navigate function and current location
143
+ *
144
+ * @example
145
+ * ```tsx
146
+ * function MyComponent() {
147
+ * const { navigate, location } = useNavigation();
148
+ *
149
+ * const handleClick = () => {
150
+ * navigate('/dashboard');
151
+ * };
152
+ *
153
+ * return <button onClick={handleClick}>Go to Dashboard</button>;
154
+ * }
155
+ * ```
156
+ */
157
+ export function useNavigation(): NavigationContextValue {
158
+ const context = useContext(NavigationContext);
159
+
160
+ if (!context) {
161
+ throw new Error(
162
+ 'useNavigation must be used within a NavigationProvider. ' +
163
+ 'Make sure your component is wrapped in QwickApp or NavigationProvider.'
164
+ );
165
+ }
166
+
167
+ return context;
168
+ }
@@ -3,6 +3,8 @@ export { DataProvider, t, T, useData, useDataContext, useDataProvider, useResolv
3
3
  export type { DataProviderProps } from './DataContext';
4
4
  export { DimensionsProvider, useDimensions } from './DimensionsContext';
5
5
  export type { DimensionsContextValue, DimensionTokens } from './DimensionsContext';
6
+ export { NavigationProvider, useNavigation } from './NavigationContext';
7
+ export type { NavigateFunction, NavigationContextValue, NavigationLocation } from './NavigationContext';
6
8
  export { PaletteProvider, usePalette } from './PaletteContext';
7
9
  export type { PaletteConfig, PaletteContextValue } from './PaletteContext';
8
10
  export { ThemeProvider, useTheme } from './ThemeContext';
@@ -1,80 +1,101 @@
1
1
  /**
2
2
  * Icon Mapping Utility
3
- *
3
+ *
4
4
  * Provides centralized icon mapping for both Material-UI components and emoji representations.
5
5
  * Used across the framework for consistent icon rendering in buttons, navigation, admin UI, etc.
6
- *
6
+ *
7
+ * Features:
8
+ * - Static map for commonly used icons with emoji support
9
+ * - Fallback to HelpOutline icon for unmapped icons (with console warning)
10
+ * - Runtime icon registration via registerIcon() for app-specific icons
11
+ *
7
12
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
13
  */
9
14
 
10
15
  import React from 'react';
16
+
17
+ // Material UI Icons - sorted alphabetically
11
18
  import {
19
+ AccountCircle,
20
+ Add,
21
+ Architecture,
22
+ ArrowBack,
23
+ ArrowForward,
12
24
  Article,
13
- Home,
25
+ AttachMoney,
26
+ Autorenew,
27
+ Block,
14
28
  Book,
15
- Download,
29
+ Business,
30
+ Check,
31
+ CheckCircle,
32
+ Close,
33
+ Cloud,
16
34
  CloudDownload,
17
35
  CloudUpload,
36
+ Code,
18
37
  Computer,
19
- Settings,
38
+ Construction,
20
39
  Dashboard,
40
+ Delete,
41
+ Download,
42
+ Edit,
43
+ Email,
44
+ Explore,
45
+ Favorite,
46
+ Group,
47
+ Help,
48
+ HelpOutline,
49
+ Home,
21
50
  Info,
51
+ InsertPhoto,
52
+ IntegrationInstructions,
22
53
  Inventory,
23
54
  Inventory2,
24
- Help,
25
- Add,
26
- Edit,
27
- Delete,
28
- Check,
29
- Close,
30
- ArrowForward,
31
- ArrowBack,
55
+ Key,
56
+ Layers,
57
+ LibraryBooks,
58
+ LocalOffer,
59
+ Lock,
60
+ LockOpen,
61
+ Login,
62
+ Logout,
63
+ ManageAccounts,
64
+ Memory,
32
65
  Menu,
33
- Search,
34
- Favorite,
35
- Star,
36
- Share,
66
+ Notifications,
67
+ People,
68
+ Person,
69
+ PersonSearch,
70
+ Phone,
71
+ PhotoLibrary,
72
+ PlayArrow,
73
+ Psychology,
74
+ Refresh,
75
+ Rocket,
76
+ RotateRight,
77
+ Route,
37
78
  Save,
79
+ Search,
80
+ Security,
38
81
  Send,
39
- Email,
40
- Phone,
41
- Person,
42
- Group,
43
- Business,
82
+ Settings,
83
+ Share,
84
+ Shield,
44
85
  ShoppingCart,
45
86
  Speed,
87
+ Star,
88
+ Storage,
46
89
  SupportAgent,
90
+ Sync,
91
+ TrendingUp,
47
92
  Tune,
48
- AttachMoney,
49
- Lock,
50
- LockOpen,
93
+ VerifiedUser,
51
94
  Visibility,
52
95
  VisibilityOff,
53
- // New icons for seed content
54
- Psychology,
55
- Autorenew,
56
- Code,
57
- IntegrationInstructions,
58
- Construction,
59
- Work,
60
- Layers,
61
- TrendingUp,
62
- Route,
63
- Sync,
64
- Architecture,
65
- Security,
66
- VerifiedUser,
67
- // Additional icons for control panels and admin UIs
68
96
  VpnKey,
69
- Key,
70
- PersonSearch,
71
- ManageAccounts,
72
- Storage,
73
- Refresh,
74
- Block,
75
- CheckCircle,
76
- RotateRight,
77
- Memory,
97
+ Work,
98
+ WorkspacePremium,
78
99
  } from '@mui/icons-material';
79
100
 
80
101
  /**
@@ -86,139 +107,175 @@ export interface IconMapping {
86
107
  }
87
108
 
88
109
  /**
89
- * Centralized icon registry mapping icon names to their representations
90
- * Supports both Material-UI components and emoji for different contexts
110
+ * Centralized icon registry mapping icon names to their representations.
111
+ * Sorted alphabetically by category, then by key within each category.
112
+ *
113
+ * For icons not in this map, getIconComponent() will return a HelpOutline fallback
114
+ * and log a warning. Use registerIcon() to add app-specific icons at runtime.
91
115
  */
92
116
  export const iconMap: Record<string, IconMapping> = {
93
- // Navigation & Layout
94
- home: { emoji: '🏠', component: Home },
95
- menu: { emoji: '☰', component: Menu },
96
- dashboard: { emoji: '📊', component: Dashboard },
97
-
98
- // Information & Help
99
- info: { emoji: 'ℹ️', component: Info },
100
- about: { emoji: 'ℹ️', component: Info },
101
- help: { emoji: '❓', component: Help },
102
- book: { emoji: '📖', component: Book },
103
-
104
- // Communication
105
- email: { emoji: '📧', component: Email },
106
- contact: { emoji: '📧', component: Email },
107
- phone: { emoji: '📱', component: Phone },
108
- send: { emoji: '📤', component: Send },
109
-
110
- // Actions
117
+ // === Actions ===
111
118
  add: { emoji: '➕', component: Add },
112
- edit: { emoji: '✏️', component: Edit },
113
- delete: { emoji: '🗑️', component: Delete },
114
- save: { emoji: '💾', component: Save },
115
119
  check: { emoji: '✓', component: Check },
120
+ check_circle: { emoji: '✅', component: CheckCircle },
116
121
  close: { emoji: '✕', component: Close },
117
-
118
- // Navigation
119
- arrowforward: { emoji: '', component: ArrowForward },
120
- arrowback: { emoji: '', component: ArrowBack },
121
-
122
- // Content
122
+ delete: { emoji: '🗑️', component: Delete },
123
+ edit: { emoji: '✏️', component: Edit },
124
+ refresh: { emoji: '🔄', component: Refresh },
125
+ rotate_right: { emoji: '🔄', component: RotateRight },
126
+ save: { emoji: '💾', component: Save },
123
127
  search: { emoji: '🔍', component: Search },
128
+ send: { emoji: '📤', component: Send },
124
129
  share: { emoji: '🔗', component: Share },
125
- download: { emoji: '⬇️', component: Download },
126
- clouddownload: { emoji: '☁️⬇️', component: CloudDownload },
127
- cloudupload: { emoji: '☁️⬆️', component: CloudUpload },
128
-
129
- // User & Social
130
- person: { emoji: '👤', component: Person },
131
- user: { emoji: '👤', component: Person },
132
- group: { emoji: '👥', component: Group },
133
- favorite: { emoji: '❤️', component: Favorite },
134
- star: { emoji: '⭐', component: Star },
135
- verified_user: { emoji: '✅', component: VerifiedUser },
136
-
137
- // Business
138
- business: { emoji: '🏢', component: Business },
139
- shoppingcart: { emoji: '🛒', component: ShoppingCart },
140
- cart: { emoji: '🛒', component: ShoppingCart },
141
- attachmoney: { emoji: '💰', component: AttachMoney },
142
-
143
- // Security
130
+ sync: { emoji: '🔄', component: Sync },
131
+
132
+ // === Authentication & Security ===
133
+ block: { emoji: '🚫', component: Block },
134
+ key: { emoji: '🔑', component: Key },
144
135
  lock: { emoji: '🔒', component: Lock },
145
- lockopen: { emoji: '🔓', component: LockOpen },
136
+ lock_open: { emoji: '🔓', component: LockOpen },
137
+ lockopen: { emoji: '🔓', component: LockOpen }, // alias
138
+ login: { emoji: '🔑', component: Login },
139
+ logout: { emoji: '🚪', component: Logout },
140
+ security: { emoji: '🔐', component: Security },
141
+ shield: { emoji: '🛡️', component: Shield },
142
+ verified_user: { emoji: '✅', component: VerifiedUser },
146
143
  visibility: { emoji: '👁️', component: Visibility },
147
- visibilityoff: { emoji: '🙈', component: VisibilityOff },
148
-
149
- // System
150
- settings: { emoji: '⚙️', component: Settings },
151
- computer: { emoji: '💻', component: Computer },
152
-
153
- // Content Types
154
- article: { emoji: '📰', component: Article },
155
- blog: { emoji: '📝', component: Book },
156
- news: { emoji: '📰', component: Book },
157
- products: { emoji: '🛍️', component: ShoppingCart },
158
- services: { emoji: '⚙️', component: Settings },
159
- portfolio: { emoji: '💼', component: Business },
160
- gallery: { emoji: '🖼️', component: Business },
161
- inventory: { emoji: '📦', component: Inventory },
162
- inventory_2: { emoji: '📦', component: Inventory2 },
163
- speed: { emoji: '', component: Speed },
144
+ visibility_off: { emoji: '🙈', component: VisibilityOff },
145
+ visibilityoff: { emoji: '🙈', component: VisibilityOff }, // alias
146
+ vpn_key: { emoji: '🔐', component: VpnKey },
147
+
148
+ // === Business & Commerce ===
149
+ attach_money: { emoji: '💰', component: AttachMoney },
150
+ attachmoney: { emoji: '💰', component: AttachMoney }, // alias
151
+ business: { emoji: '🏢', component: Business },
152
+ cart: { emoji: '🛒', component: ShoppingCart }, // alias
153
+ shopping_cart: { emoji: '🛒', component: ShoppingCart },
154
+ shoppingcart: { emoji: '🛒', component: ShoppingCart }, // alias
155
+ work: { emoji: '💼', component: Work },
156
+ workspace_premium: { emoji: '', component: WorkspacePremium },
157
+
158
+ // === Communication ===
159
+ contact: { emoji: '📧', component: Email }, // alias
160
+ email: { emoji: '📧', component: Email },
161
+ mail: { emoji: '📧', component: Email }, // alias
162
+ notifications: { emoji: '🔔', component: Notifications },
163
+ phone: { emoji: '📱', component: Phone },
164
164
  support_agent: { emoji: '🛎️', component: SupportAgent },
165
- tune: { emoji: '🎛️', component: Tune },
166
165
 
167
- // Development & Technology
168
- code: { emoji: '💻', component: Code },
169
- psychology: { emoji: '🧠', component: Psychology },
166
+ // === Content & Media ===
167
+ article: { emoji: '📰', component: Article },
168
+ blog: { emoji: '📝', component: Book }, // alias
169
+ book: { emoji: '📖', component: Book },
170
+ gallery: { emoji: '🖼️', component: InsertPhoto }, // alias
171
+ image: { emoji: '🖼️', component: InsertPhoto },
172
+ insert_photo: { emoji: '🖼️', component: InsertPhoto },
173
+ library_books: { emoji: '📚', component: LibraryBooks },
174
+ news: { emoji: '📰', component: Article }, // alias
175
+ photo_library: { emoji: '📸', component: PhotoLibrary },
176
+ play: { emoji: '▶️', component: PlayArrow }, // alias
177
+ play_arrow: { emoji: '▶️', component: PlayArrow },
178
+ portfolio: { emoji: '💼', component: Business }, // alias
179
+
180
+ // === Development & Technology ===
181
+ architecture: { emoji: '🏛️', component: Architecture },
170
182
  autorenew: { emoji: '🔄', component: Autorenew },
171
- integration_instructions: { emoji: '🔌', component: IntegrationInstructions },
183
+ cloud: { emoji: '☁️', component: Cloud },
184
+ cloud_download: { emoji: '☁️⬇️', component: CloudDownload },
185
+ cloud_upload: { emoji: '☁️⬆️', component: CloudUpload },
186
+ clouddownload: { emoji: '☁️⬇️', component: CloudDownload }, // alias
187
+ cloudupload: { emoji: '☁️⬆️', component: CloudUpload }, // alias
188
+ code: { emoji: '💻', component: Code },
189
+ computer: { emoji: '💻', component: Computer },
172
190
  construction: { emoji: '🚧', component: Construction },
173
- work: { emoji: '💼', component: Work },
191
+ integration_instructions: { emoji: '🔌', component: IntegrationInstructions },
192
+ memory: { emoji: '🧠', component: Memory },
193
+ psychology: { emoji: '🧠', component: Psychology },
194
+ rocket: { emoji: '🚀', component: Rocket },
195
+ storage: { emoji: '💾', component: Storage },
196
+
197
+ // === Navigation & Layout ===
198
+ arrow_back: { emoji: '←', component: ArrowBack },
199
+ arrow_forward: { emoji: '→', component: ArrowForward },
200
+ arrowback: { emoji: '←', component: ArrowBack }, // alias
201
+ arrowforward: { emoji: '→', component: ArrowForward }, // alias
202
+ dashboard: { emoji: '📊', component: Dashboard },
203
+ download: { emoji: '⬇️', component: Download },
204
+ explore: { emoji: '🧭', component: Explore },
205
+ home: { emoji: '🏠', component: Home },
174
206
  layers: { emoji: '📚', component: Layers },
175
- trending_up: { emoji: '📈', component: TrendingUp },
207
+ menu: { emoji: '', component: Menu },
176
208
  route: { emoji: '🗺️', component: Route },
177
- sync: { emoji: '🔄', component: Sync },
178
- architecture: { emoji: '🏛️', component: Architecture },
179
- security: { emoji: '🔐', component: Security },
209
+ settings: { emoji: '⚙️', component: Settings },
210
+ trending_up: { emoji: '📈', component: TrendingUp },
211
+ tune: { emoji: '🎛️', component: Tune },
180
212
 
181
- // Control Panel & Admin UI Icons
182
- key: { emoji: '🔑', component: Key },
183
- vpn_key: { emoji: '🔐', component: VpnKey },
213
+ // === Products & Inventory ===
214
+ inventory: { emoji: '📦', component: Inventory },
215
+ inventory_2: { emoji: '📦', component: Inventory2 },
216
+ local_offer: { emoji: '🏷️', component: LocalOffer },
217
+ products: { emoji: '🛍️', component: ShoppingCart }, // alias
218
+ services: { emoji: '⚙️', component: Settings }, // alias
219
+ speed: { emoji: '⚡', component: Speed },
220
+
221
+ // === Status & Feedback ===
222
+ about: { emoji: 'ℹ️', component: Info }, // alias
223
+ favorite: { emoji: '❤️', component: Favorite },
224
+ heart: { emoji: '❤️', component: Favorite }, // alias
225
+ help: { emoji: '❓', component: Help },
226
+ info: { emoji: 'ℹ️', component: Info },
227
+ star: { emoji: '⭐', component: Star },
228
+
229
+ // === Users & People ===
230
+ account_circle: { emoji: '👤', component: AccountCircle },
231
+ group: { emoji: '👥', component: Group },
232
+ manage_accounts: { emoji: '👤', component: ManageAccounts },
233
+ people: { emoji: '👥', component: People },
234
+ person: { emoji: '👤', component: Person },
184
235
  person_search: { emoji: '🔍', component: PersonSearch },
185
- manage_accounts: { emoji: '👥', component: ManageAccounts },
186
- storage: { emoji: '💾', component: Storage },
187
- refresh: { emoji: '🔄', component: Refresh },
188
- block: { emoji: '🚫', component: Block },
189
- check_circle: { emoji: '✅', component: CheckCircle },
190
- rotate_right: { emoji: '🔄', component: RotateRight },
191
- memory: { emoji: '🧠', component: Memory },
236
+ user: { emoji: '👤', component: Person }, // alias
237
+ users: { emoji: '👥', component: People }, // alias
192
238
  };
193
239
 
194
240
  /**
195
241
  * Get emoji representation of an icon
196
- * @param iconName - Icon name (case-insensitive)
242
+ * @param iconName - Icon name (case-insensitive, supports snake_case)
197
243
  * @param fallback - Fallback emoji if icon not found (default: 🔗)
198
244
  * @returns Emoji string
199
245
  */
200
246
  export function getIconEmoji(iconName: string | undefined, fallback: string = '🔗'): string {
201
247
  if (!iconName) return fallback;
202
- const mapping = iconMap[iconName.toLowerCase()];
203
- return mapping?.emoji || iconName;
248
+ const normalized = iconName.toLowerCase();
249
+ const mapping = iconMap[normalized];
250
+ return mapping?.emoji || fallback;
204
251
  }
205
252
 
206
253
  /**
207
- * Get Material-UI component representation of an icon
208
- * @param iconName - Icon name (case-insensitive)
209
- * @returns React element or null if not found
254
+ * Get Material-UI component representation of an icon.
255
+ *
256
+ * Uses the static iconMap for known icons. For unmapped icons,
257
+ * returns a HelpOutline fallback and logs a warning.
258
+ *
259
+ * @param iconName - Icon name (case-insensitive, supports snake_case)
260
+ * @returns React element (mapped icon or HelpOutline fallback), or null if no name provided
210
261
  */
211
262
  export function getIconComponent(iconName: string | undefined): React.ReactElement | null {
212
263
  if (!iconName) return null;
213
-
214
- const mapping = iconMap[iconName.toLowerCase()];
215
- if (!mapping?.component) {
216
- console.warn(`[IconMap] Icon "${iconName}" not found in registry`);
217
- return null;
264
+
265
+ const normalized = iconName.toLowerCase();
266
+ const mapping = iconMap[normalized];
267
+
268
+ if (mapping?.component) {
269
+ const IconComponent = mapping.component;
270
+ return <IconComponent />;
271
+ }
272
+
273
+ // Fallback: Return HelpOutline icon and warn about unmapped icon
274
+ // Use registerIcon() to add app-specific icons at runtime
275
+ if (process.env.NODE_ENV !== 'production') {
276
+ console.warn(`[IconMap] Icon "${iconName}" not found. Add it to iconMap or use registerIcon().`);
218
277
  }
219
-
220
- const IconComponent = mapping.component;
221
- return <IconComponent />;
278
+ return <HelpOutline />;
222
279
  }
223
280
 
224
281
  /**
@@ -230,14 +287,15 @@ export function registerIcon(name: string, mapping: IconMapping): void {
230
287
  }
231
288
 
232
289
  /**
233
- * Check if an icon is registered
290
+ * Check if an icon is registered in the static map
291
+ * If false, getIconComponent will return HelpOutline fallback
234
292
  */
235
293
  export function hasIcon(iconName: string): boolean {
236
294
  return iconName.toLowerCase() in iconMap;
237
295
  }
238
296
 
239
297
  /**
240
- * Get all registered icon names
298
+ * Get all registered icon names from the static map
241
299
  */
242
300
  export function getRegisteredIcons(): string[] {
243
301
  return Object.keys(iconMap);
@@ -7,55 +7,10 @@
7
7
 
8
8
  import { ReactNode } from 'react';
9
9
 
10
- /** Location type for routing */
11
- type LocationType = { pathname: string, search: string, hash: string };
12
-
13
- /**
14
- * Get the current location from browser or undefined in SSR
15
- * Works without relying on routing libraries
16
- * @returns {object | undefined} - The location object if in browser, otherwise undefined
17
- */
18
- export const useSafeLocation = (): LocationType | undefined => {
19
- // Use browser location if available (works in any React app)
20
- if (typeof window !== 'undefined') {
21
- return {
22
- pathname: window.location.pathname,
23
- search: window.location.search,
24
- hash: window.location.hash
25
- };
26
- }
27
- return undefined;
28
- };
29
-
30
- /**
31
- * Navigate function type
32
- */
33
- export type NavigateFunction = (to: string | number, options?: unknown) => void;
34
-
35
- /**
36
- * Get a navigation function with fallback to window.location
37
- * Works without relying on routing libraries
38
- * @returns {NavigateFunction} - The navigate function
39
- */
40
- export const useSafeNavigate = (): NavigateFunction => {
41
- // Return function that uses window.location
42
- return (to: string | number) => {
43
- if (typeof to === 'string') {
44
- if (typeof window !== 'undefined') {
45
- window.location.href = to;
46
- }
47
- } else if (typeof to === 'number') {
48
- if (typeof window !== 'undefined' && window.history) {
49
- window.history.go(to);
50
- }
51
- }
52
- };
53
- };
54
-
55
10
  /**
56
11
  * Extract text content from ReactNode for code processing
57
12
  * Handles natural React usage like <Code>const x = 1;</Code>
58
- *
13
+ *
59
14
  * @param node - The ReactNode to extract text from
60
15
  * @returns String representation of the node's text content
61
16
  */
@@ -73,7 +28,7 @@ export function extractTextFromReactNode(node: ReactNode): string {
73
28
  }
74
29
 
75
30
  if (Array.isArray(node)) {
76
- return node.map(child => extractTextFromReactNode(child)).join('');
31
+ return node.map((child) => extractTextFromReactNode(child)).join('');
77
32
  }
78
33
 
79
34
  // For React elements, try to extract text content