web-mojo 2.1.549 → 2.1.626

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 (66) hide show
  1. package/dist/admin.cjs.js +1 -1
  2. package/dist/admin.cjs.js.map +1 -1
  3. package/dist/admin.es.js +19 -10
  4. package/dist/admin.es.js.map +1 -1
  5. package/dist/auth.cjs.js +1 -1
  6. package/dist/auth.cjs.js.map +1 -1
  7. package/dist/auth.es.js +3 -3
  8. package/dist/auth.es.js.map +1 -1
  9. package/dist/charts.cjs.js +1 -1
  10. package/dist/charts.es.js +3 -3
  11. package/dist/chunks/{ChatView-S7z1axRn.js → ChatView-0e0k3QSK.js} +2 -2
  12. package/dist/chunks/{ChatView-S7z1axRn.js.map → ChatView-0e0k3QSK.js.map} +1 -1
  13. package/dist/chunks/{ChatView-DUmQtrvk.js → ChatView-BxbA5ob6.js} +6 -6
  14. package/dist/chunks/{ChatView-DUmQtrvk.js.map → ChatView-BxbA5ob6.js.map} +1 -1
  15. package/dist/chunks/{ContextMenu-DhbGpVSL.js → ContextMenu-ATInMbaI.js} +3 -3
  16. package/dist/chunks/{ContextMenu-DhbGpVSL.js.map → ContextMenu-ATInMbaI.js.map} +1 -1
  17. package/dist/chunks/{ContextMenu-BXCBFtAP.js → ContextMenu-Ckttp-rD.js} +10 -3
  18. package/dist/chunks/{ContextMenu-BXCBFtAP.js.map → ContextMenu-Ckttp-rD.js.map} +1 -1
  19. package/dist/chunks/{DataView-Ek4BYTEr.js → DataView-BQOKPprj.js} +2 -2
  20. package/dist/chunks/{DataView-Ek4BYTEr.js.map → DataView-BQOKPprj.js.map} +1 -1
  21. package/dist/chunks/{DataView-CbcfRwkD.js → DataView-BsWK0Ul7.js} +2 -2
  22. package/dist/chunks/{DataView-CbcfRwkD.js.map → DataView-BsWK0Ul7.js.map} +1 -1
  23. package/dist/chunks/{Dialog-B4CbgRxK.js → Dialog-aTTrQ6uW.js} +5 -5
  24. package/dist/chunks/{Dialog-B4CbgRxK.js.map → Dialog-aTTrQ6uW.js.map} +1 -1
  25. package/dist/chunks/{Dialog-sS4tcneL.js → Dialog-t4J3qOjC.js} +2 -2
  26. package/dist/chunks/{Dialog-sS4tcneL.js.map → Dialog-t4J3qOjC.js.map} +1 -1
  27. package/dist/chunks/{FormView-Nh9T4RYF.js → FormView-DjypPrEw.js} +2 -2
  28. package/dist/chunks/{FormView-Nh9T4RYF.js.map → FormView-DjypPrEw.js.map} +1 -1
  29. package/dist/chunks/{FormView-BochVM_E.js → FormView-DvKBq99H.js} +2 -2
  30. package/dist/chunks/{FormView-BochVM_E.js.map → FormView-DvKBq99H.js.map} +1 -1
  31. package/dist/chunks/{MetricsChart-BnAXZSYf.js → MetricsChart-BHB2dubV.js} +2 -2
  32. package/dist/chunks/{MetricsChart-BnAXZSYf.js.map → MetricsChart-BHB2dubV.js.map} +1 -1
  33. package/dist/chunks/{MetricsChart-DMAFQpiZ.js → MetricsChart-DJ_AMjGg.js} +3 -3
  34. package/dist/chunks/{MetricsChart-DMAFQpiZ.js.map → MetricsChart-DJ_AMjGg.js.map} +1 -1
  35. package/dist/chunks/{PDFViewer-UG4HgNRl.js → PDFViewer-DXoC6y5o.js} +2 -2
  36. package/dist/chunks/{PDFViewer-UG4HgNRl.js.map → PDFViewer-DXoC6y5o.js.map} +1 -1
  37. package/dist/chunks/{PDFViewer-DFGU5qEx.js → PDFViewer-kDd18mqo.js} +3 -3
  38. package/dist/chunks/{PDFViewer-DFGU5qEx.js.map → PDFViewer-kDd18mqo.js.map} +1 -1
  39. package/dist/chunks/{Page-3EI2SKd6.js → Page-BrWp1FsC.js} +2 -2
  40. package/dist/chunks/{Page-3EI2SKd6.js.map → Page-BrWp1FsC.js.map} +1 -1
  41. package/dist/chunks/{Page-x-paxTWR.js → Page-DgKaDD9p.js} +2 -2
  42. package/dist/chunks/{Page-x-paxTWR.js.map → Page-DgKaDD9p.js.map} +1 -1
  43. package/dist/chunks/TopNav-DGtRj5F4.js +1039 -0
  44. package/dist/chunks/TopNav-DGtRj5F4.js.map +1 -0
  45. package/dist/chunks/TopNav-DoAl9Rpd.js +2 -0
  46. package/dist/chunks/TopNav-DoAl9Rpd.js.map +1 -0
  47. package/dist/chunks/{WebApp-Co0le5eH.js → WebApp-DWIriU_w.js} +2 -2
  48. package/dist/chunks/{WebApp-Co0le5eH.js.map → WebApp-DWIriU_w.js.map} +1 -1
  49. package/dist/chunks/{WebApp-gPOds7Ie.js → WebApp-ciExPk0c.js} +30 -14
  50. package/dist/chunks/{WebApp-gPOds7Ie.js.map → WebApp-ciExPk0c.js.map} +1 -1
  51. package/dist/css/web-mojo.css +1 -1
  52. package/dist/docit.cjs.js +1 -1
  53. package/dist/docit.es.js +5 -5
  54. package/dist/index.cjs.js +1 -1
  55. package/dist/index.cjs.js.map +1 -1
  56. package/dist/index.es.js +237 -449
  57. package/dist/index.es.js.map +1 -1
  58. package/dist/lightbox.cjs.js +1 -1
  59. package/dist/lightbox.es.js +4 -4
  60. package/dist/portal.css +222 -0
  61. package/dist/table.css +0 -13
  62. package/package.json +1 -1
  63. package/dist/chunks/TopNav-BzW5Us7F.js +0 -2
  64. package/dist/chunks/TopNav-BzW5Us7F.js.map +0 -1
  65. package/dist/chunks/TopNav-cGCRUequ.js +0 -381
  66. package/dist/chunks/TopNav-cGCRUequ.js.map +0 -1
@@ -1,381 +0,0 @@
1
- import { V as View } from "./WebApp-gPOds7Ie.js";
2
- class TopNav extends View {
3
- constructor(options = {}) {
4
- const themes = {
5
- light: "navbar navbar-expand-lg navbar-light topnav-light",
6
- dark: "navbar navbar-expand-lg navbar-dark topnav-dark",
7
- clean: "navbar navbar-expand-lg navbar-light topnav-clean",
8
- gradient: "navbar navbar-expand-lg navbar-dark topnav-gradient"
9
- };
10
- const themeName = options.theme || "light";
11
- let navbarClass = themes[themeName] || themes.light;
12
- if (options.shadow) {
13
- navbarClass += ` topnav-shadow-${options.shadow}`;
14
- }
15
- super({
16
- tagName: "nav",
17
- className: navbarClass,
18
- style: "position: relative; z-index: 1030;",
19
- ...options
20
- });
21
- this.displayMode = options.displayMode || "both";
22
- this.showPageIcon = options.showPageIcon !== false;
23
- this.showPageDescription = options.showPageDescription || false;
24
- this.showBreadcrumbs = options.showBreadcrumbs || false;
25
- this.currentPage = null;
26
- this.previousPage = null;
27
- this.config = {
28
- brand: options.brand || "MOJO App",
29
- brandIcon: options.brandIcon || "bi bi-play-circle",
30
- brandRoute: options.brandRoute || "/",
31
- navItems: options.navItems || [],
32
- rightItems: options.rightItems || [],
33
- showSidebarToggle: options.showSidebarToggle || false,
34
- sidebarToggleAction: options.sidebarToggleAction || "toggle-sidebar",
35
- ...options
36
- };
37
- this.userMenu = options.userMenu || this.findMenuItem("user");
38
- if (this.userMenu) this.userMenu.id = "user";
39
- this.loginMenu = options.loginMenu || this.findMenuItem("login");
40
- this.setupPageListeners();
41
- }
42
- findMenuItem(id) {
43
- let item = this.config.navItems.find((item2) => item2.id === id);
44
- if (!item) {
45
- item = this.config.rightItems.find((item2) => item2.id === id);
46
- }
47
- return item || null;
48
- }
49
- replaceMenuItem(id, new_menu) {
50
- const navIndex = this.config.navItems.findIndex((item) => item.id === id);
51
- if (navIndex !== -1) {
52
- this.config.navItems[navIndex] = new_menu;
53
- return true;
54
- }
55
- const rightIndex = this.config.rightItems.findIndex((item) => item.id === id);
56
- if (rightIndex !== -1) {
57
- this.config.rightItems[rightIndex] = new_menu;
58
- return true;
59
- }
60
- return false;
61
- }
62
- setBrand(brand, icon = null) {
63
- this.config.brand = brand;
64
- this.config.brandIcon = icon || this.config.brandIcon;
65
- this.render();
66
- }
67
- setUser(user) {
68
- if (!user) {
69
- this.replaceMenuItem("user", this.loginMenu);
70
- } else {
71
- this.userMenu.label = user.get("display_name");
72
- this.replaceMenuItem("login", this.userMenu);
73
- }
74
- this.setModel(user);
75
- }
76
- _onModelChange() {
77
- if (this.model) {
78
- this.userMenu.label = this.model.get("display_name");
79
- }
80
- if (this.isMounted()) {
81
- this.render();
82
- }
83
- }
84
- /**
85
- * Get template based on display mode
86
- */
87
- async getTemplate() {
88
- return `
89
- <div class="container-fluid">
90
- {{#data.showSidebarToggle}}
91
- <button class="topnav-sidebar-toggle me-2" data-action="{{data.sidebarToggleAction}}" aria-label="Toggle Sidebar">
92
- <i class="bi bi-chevron-right toggle-chevron"></i>
93
- </button>
94
- {{/data.showSidebarToggle}}
95
-
96
- {{#data.showPageInfo}}
97
- <div class="navbar-brand d-flex align-items-center">
98
- {{#data.currentPageIcon}}<i class="{{data.currentPageIcon}} me-2"></i>{{/data.currentPageIcon}}
99
- <div>
100
- <span>{{data.currentPageName}}</span>
101
- {{#data.currentPageDescription}}
102
- <small class="d-block" style="font-size: 0.75rem; line-height: 1;">{{data.currentPageDescription}}</small>
103
- {{/data.currentPageDescription}}
104
- </div>
105
- </div>
106
- {{/data.showPageInfo}}
107
-
108
- {{^data.showPageInfo}}
109
- <a class="navbar-brand" href="{{data.brandRoute}}">
110
- {{#data.brandIcon}}<i class="{{data.brandIcon}} me-2"></i>{{/data.brandIcon}}
111
- {{data.brand}}
112
- </a>
113
- {{/data.showPageInfo}}
114
-
115
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#{{data.navbarId}}">
116
- <span class="navbar-toggler-icon"></span>
117
- </button>
118
-
119
- <div class="collapse navbar-collapse" id="{{data.navbarId}}">
120
- {{#data.showNavItems}}
121
- <ul class="navbar-nav me-auto mb-2 mb-lg-0">
122
- {{#data.navItems}}
123
- <li class="nav-item">
124
- <a class="nav-link {{#active}}active{{/active}}" href="{{route}}">
125
- {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}
126
- {{text}}
127
- </a>
128
- </li>
129
- {{/data.navItems}}
130
- </ul>
131
- {{/data.showNavItems}}
132
-
133
- {{#data.hasRightItems}}
134
- <div class="navbar-nav ms-auto">
135
- {{#data.rightItems}}
136
- {{#isDropdown}}
137
- <div class="nav-item dropdown">
138
- <a class="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">
139
- {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}
140
- {{label}}
141
- </a>
142
- <ul class="dropdown-menu dropdown-menu-end">
143
- {{#items}}
144
- {{#divider}}
145
- <li><hr class="dropdown-divider"></li>
146
- {{/divider}}
147
- {{^divider}}
148
- <li>
149
- <a class="dropdown-item" role="button" {{#action}}data-action="{{action}}"{{/action}}>
150
- {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}
151
- {{label}}
152
- </a>
153
- </li>
154
- {{/divider}}
155
- {{/items}}
156
- </ul>
157
- </div>
158
- {{/isDropdown}}
159
- {{^isDropdown}}
160
- {{#isButton}}
161
- <button class="{{buttonClass}}" data-action="{{action}}" data-id="{{id}}">
162
- {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}
163
- {{label}}
164
- </button>
165
- {{/isButton}}
166
- {{^isButton}}
167
- <a class="nav-link" href="{{href}}" {{#action}}data-action="{{action}}"{{/action}}>
168
- {{#icon}}<i class="{{icon}} me-1"></i>{{/icon}}
169
- {{label}}
170
- </a>
171
- {{/isButton}}
172
- {{/isDropdown}}
173
- {{/data.rightItems}}
174
- </div>
175
- {{/data.hasRightItems}}
176
- </div>
177
- </div>
178
- `;
179
- }
180
- /**
181
- * Process and normalize data before rendering (like Sidebar)
182
- */
183
- async onBeforeRender() {
184
- await super.onBeforeRender();
185
- const showPageInfo = this.displayMode === "page" || this.displayMode === "both";
186
- const showNavItems = this.displayMode === "menu" || this.displayMode === "both";
187
- const navItems = this.filterItemsByPermissions(this.config.navItems || []);
188
- const rightItems = this.processRightItems(this.config.rightItems || []);
189
- this.data = {
190
- // Brand information
191
- brand: this.config.brand,
192
- brandIcon: this.config.brandIcon,
193
- brandRoute: this.config.brandRoute,
194
- // Navbar configuration
195
- navbarId: `navbar-${this.id}`,
196
- // Navigation items
197
- navItems,
198
- showNavItems,
199
- // Right items
200
- rightItems,
201
- hasRightItems: rightItems.length > 0,
202
- // Page display
203
- showPageInfo,
204
- currentPageName: this.currentPage?.title || this.currentPage?.name || "",
205
- currentPageIcon: this.currentPage?.icon || this.currentPage?.pageIcon || "",
206
- currentPageDescription: this.showPageDescription ? this.currentPage?.description : "",
207
- // Sidebar toggle
208
- showSidebarToggle: this.config.showSidebarToggle,
209
- sidebarToggleAction: this.config.sidebarToggleAction,
210
- // Display mode
211
- displayMode: this.displayMode
212
- };
213
- }
214
- /**
215
- * Process right items configuration
216
- */
217
- processRightItems(rightItems) {
218
- return this.filterItemsByPermissions(rightItems).map((item) => {
219
- const processedItem = { ...item };
220
- if (item.items) {
221
- processedItem.items = this.filterItemsByPermissions(item.items);
222
- }
223
- if (processedItem.items && processedItem.items.length > 0) {
224
- processedItem.isDropdown = true;
225
- processedItem.isButton = false;
226
- } else if (item.buttonClass) {
227
- processedItem.isButton = true;
228
- processedItem.isDropdown = false;
229
- } else {
230
- processedItem.isButton = false;
231
- processedItem.isDropdown = false;
232
- }
233
- if (item.handler) {
234
- this.rightItemHandlers = this.rightItemHandlers || /* @__PURE__ */ new Map();
235
- this.rightItemHandlers.set(item.id, item.handler);
236
- }
237
- return processedItem;
238
- });
239
- }
240
- /**
241
- * Setup listeners for page change events
242
- */
243
- setupPageListeners() {
244
- this.getApp().events.on(["page:show", "page:hide", "page:denied"], (data) => {
245
- this.onPageChanged(data);
246
- });
247
- }
248
- /**
249
- * Handle page before change event
250
- * @param {object} data - Event data
251
- */
252
- onPageBeforeChange(data) {
253
- if (this.displayMode === "page" || this.displayMode === "both") ;
254
- }
255
- /**
256
- * Handle page changed event
257
- * @param {object} data - Event data with previousPage and currentPage
258
- */
259
- onPageChanged(data) {
260
- this.previousPage = this.currentPage;
261
- this.currentPage = data.page;
262
- if (this.displayMode === "page" || this.displayMode === "both") {
263
- this.updatePageDisplay();
264
- }
265
- if (this.displayMode === "menu" || this.displayMode === "both") {
266
- if (this.currentPage && this.currentPage.route) {
267
- this.updateActiveItem(this.currentPage.route);
268
- }
269
- }
270
- }
271
- /**
272
- * Update the display to show current page info
273
- */
274
- updatePageDisplay() {
275
- if (!this.currentPage) return;
276
- if (this.mounted) {
277
- this.render();
278
- }
279
- }
280
- updateActiveItem(currentRoute) {
281
- const normalizeRoute = (route) => {
282
- if (!route) return "/";
283
- return route.startsWith("/") ? route : `/${route}`;
284
- };
285
- const normalizedCurrentRoute = normalizeRoute(currentRoute);
286
- const navItems = this.data.navItems.map((item) => {
287
- const normalizedItemRoute = normalizeRoute(item.route);
288
- let isActive = false;
289
- if (normalizedItemRoute === "/" && normalizedCurrentRoute === "/") {
290
- isActive = true;
291
- } else if (normalizedItemRoute !== "/" && normalizedCurrentRoute !== "/") {
292
- isActive = normalizedCurrentRoute.startsWith(normalizedItemRoute) || normalizedCurrentRoute === normalizedItemRoute;
293
- }
294
- return {
295
- ...item,
296
- active: isActive
297
- };
298
- });
299
- this.updateData({ navItems }, true);
300
- }
301
- onPassThruActionProfile() {
302
- this.getApp().events.emit("portal:action", { action: "profile" });
303
- }
304
- onActionSettings() {
305
- this.getApp().events.emit("portal:action", { action: "settings" });
306
- }
307
- onActionLogout() {
308
- this.getApp().events.emit("auth:logout", { action: "logout" });
309
- }
310
- /**
311
- * Handle dynamic action dispatch for right items
312
- */
313
- async handleAction(actionName, event, element) {
314
- const itemId = element.getAttribute("data-id");
315
- if (itemId && this.rightItemHandlers && this.rightItemHandlers.has(itemId)) {
316
- const handler = this.rightItemHandlers.get(itemId);
317
- if (typeof handler === "function") {
318
- return await handler.call(this, actionName, event, element);
319
- }
320
- }
321
- const methodName = `onAction${actionName.charAt(0).toUpperCase() + actionName.slice(1).replace(/-([a-z])/g, (g) => g[1].toUpperCase())}`;
322
- if (typeof this[methodName] === "function") {
323
- return await this[methodName](event, element);
324
- }
325
- this.emit("action", {
326
- action: actionName,
327
- event,
328
- element,
329
- topnav: this
330
- });
331
- }
332
- /**
333
- * Handle default actions by searching through rightItems and navItems
334
- */
335
- async onActionDefault(action, event, el) {
336
- if (this.config.navItems) {
337
- for (const item of this.config.navItems) {
338
- if (item.action === action && item.handler) {
339
- await item.handler.call(this, action, event, el);
340
- return true;
341
- }
342
- }
343
- }
344
- if (this.config.rightItems) {
345
- for (const item of this.config.rightItems) {
346
- if (item.action === action && item.handler) {
347
- await item.handler.call(this, action, event, el);
348
- return true;
349
- }
350
- if (item.items) {
351
- for (const subItem of item.items) {
352
- if (subItem.action === action && subItem.handler) {
353
- await subItem.handler.call(this, action, event, el);
354
- return true;
355
- }
356
- }
357
- }
358
- }
359
- }
360
- this.getApp().events.emit("portal:action", { action, event, el });
361
- return false;
362
- }
363
- /**
364
- * Filter items by user permissions
365
- */
366
- filterItemsByPermissions(items) {
367
- if (!items) return [];
368
- const app = this.getApp();
369
- const activeUser = app?.activeUser;
370
- return items.filter((item) => {
371
- if (item.permissions && activeUser) {
372
- return activeUser.hasPermission(item.permissions);
373
- }
374
- return true;
375
- });
376
- }
377
- }
378
- export {
379
- TopNav as T
380
- };
381
- //# sourceMappingURL=TopNav-cGCRUequ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TopNav-cGCRUequ.js","sources":["../../src/core/views/navigation/TopNav.js"],"sourcesContent":["/**\n * TopNav - Bootstrap navbar component for MOJO framework\n * Provides clean, responsive top navigation\n */\n\nimport View from '@core/View.js';\n\nclass TopNav extends View {\n constructor(options = {}) {\n // Define theme-to-class mappings\n const themes = {\n light: 'navbar navbar-expand-lg navbar-light topnav-light',\n dark: 'navbar navbar-expand-lg navbar-dark topnav-dark',\n clean: 'navbar navbar-expand-lg navbar-light topnav-clean',\n gradient: 'navbar navbar-expand-lg navbar-dark topnav-gradient',\n };\n\n // Set a default theme and determine the final class string\n const themeName = options.theme || 'light';\n let navbarClass = themes[themeName] || themes.light;\n\n // Add shadow class if specified\n if (options.shadow) {\n navbarClass += ` topnav-shadow-${options.shadow}`;\n }\n\n super({\n tagName: 'nav',\n className: navbarClass,\n style: 'position: relative; z-index: 1030;',\n ...options\n });\n\n // Display mode configuration\n this.displayMode = options.displayMode || 'both'; // 'menu' | 'page' | 'both'\n this.showPageIcon = options.showPageIcon !== false;\n this.showPageDescription = options.showPageDescription || false;\n this.showBreadcrumbs = options.showBreadcrumbs || false;\n\n // Current page tracking\n this.currentPage = null;\n this.previousPage = null;\n\n // Store raw config for processing in onBeforeRender\n this.config = {\n brand: options.brand || 'MOJO App',\n brandIcon: options.brandIcon || 'bi bi-play-circle',\n brandRoute: options.brandRoute || '/',\n navItems: options.navItems || [],\n rightItems: options.rightItems || [],\n showSidebarToggle: options.showSidebarToggle || false,\n sidebarToggleAction: options.sidebarToggleAction || 'toggle-sidebar',\n ...options\n };\n this.userMenu = options.userMenu || this.findMenuItem('user');\n if (this.userMenu) this.userMenu.id = \"user\";\n this.loginMenu = options.loginMenu || this.findMenuItem('login');\n // Setup page event listeners\n this.setupPageListeners();\n }\n\n findMenuItem(id) {\n let item = this.config.navItems.find(item => item.id === id);\n if (!item) {\n item = this.config.rightItems.find(item => item.id === id);\n }\n return item || null;\n }\n\n replaceMenuItem(id, new_menu) {\n // Find and replace in navItems\n const navIndex = this.config.navItems.findIndex(item => item.id === id);\n if (navIndex !== -1) {\n this.config.navItems[navIndex] = new_menu;\n return true;\n }\n\n // Find and replace in rightItems\n const rightIndex = this.config.rightItems.findIndex(item => item.id === id);\n if (rightIndex !== -1) {\n this.config.rightItems[rightIndex] = new_menu;\n return true;\n }\n\n return false;\n }\n\n setBrand(brand, icon=null) {\n this.config.brand = brand;\n this.config.brandIcon = icon || this.config.brandIcon;\n this.render();\n }\n\n setUser(user) {\n if (!user) {\n this.replaceMenuItem('user', this.loginMenu);\n } else {\n this.userMenu.label = user.get(\"display_name\");\n this.replaceMenuItem('login', this.userMenu);\n }\n this.setModel(user);\n }\n\n _onModelChange() {\n if (this.model) {\n this.userMenu.label = this.model.get(\"display_name\");\n }\n if (this.isMounted()) {\n this.render();\n }\n }\n\n /**\n * Get template based on display mode\n */\n async getTemplate() {\n return `\n <div class=\"container-fluid\">\n {{#data.showSidebarToggle}}\n <button class=\"topnav-sidebar-toggle me-2\" data-action=\"{{data.sidebarToggleAction}}\" aria-label=\"Toggle Sidebar\">\n <i class=\"bi bi-chevron-right toggle-chevron\"></i>\n </button>\n {{/data.showSidebarToggle}}\n\n {{#data.showPageInfo}}\n <div class=\"navbar-brand d-flex align-items-center\">\n {{#data.currentPageIcon}}<i class=\"{{data.currentPageIcon}} me-2\"></i>{{/data.currentPageIcon}}\n <div>\n <span>{{data.currentPageName}}</span>\n {{#data.currentPageDescription}}\n <small class=\"d-block\" style=\"font-size: 0.75rem; line-height: 1;\">{{data.currentPageDescription}}</small>\n {{/data.currentPageDescription}}\n </div>\n </div>\n {{/data.showPageInfo}}\n\n {{^data.showPageInfo}}\n <a class=\"navbar-brand\" href=\"{{data.brandRoute}}\">\n {{#data.brandIcon}}<i class=\"{{data.brandIcon}} me-2\"></i>{{/data.brandIcon}}\n {{data.brand}}\n </a>\n {{/data.showPageInfo}}\n\n <button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#{{data.navbarId}}\">\n <span class=\"navbar-toggler-icon\"></span>\n </button>\n\n <div class=\"collapse navbar-collapse\" id=\"{{data.navbarId}}\">\n {{#data.showNavItems}}\n <ul class=\"navbar-nav me-auto mb-2 mb-lg-0\">\n {{#data.navItems}}\n <li class=\"nav-item\">\n <a class=\"nav-link {{#active}}active{{/active}}\" href=\"{{route}}\">\n {{#icon}}<i class=\"{{icon}} me-1\"></i>{{/icon}}\n {{text}}\n </a>\n </li>\n {{/data.navItems}}\n </ul>\n {{/data.showNavItems}}\n\n {{#data.hasRightItems}}\n <div class=\"navbar-nav ms-auto\">\n {{#data.rightItems}}\n {{#isDropdown}}\n <div class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" role=\"button\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\">\n {{#icon}}<i class=\"{{icon}} me-1\"></i>{{/icon}}\n {{label}}\n </a>\n <ul class=\"dropdown-menu dropdown-menu-end\">\n {{#items}}\n {{#divider}}\n <li><hr class=\"dropdown-divider\"></li>\n {{/divider}}\n {{^divider}}\n <li>\n <a class=\"dropdown-item\" role=\"button\" {{#action}}data-action=\"{{action}}\"{{/action}}>\n {{#icon}}<i class=\"{{icon}} me-1\"></i>{{/icon}}\n {{label}}\n </a>\n </li>\n {{/divider}}\n {{/items}}\n </ul>\n </div>\n {{/isDropdown}}\n {{^isDropdown}}\n {{#isButton}}\n <button class=\"{{buttonClass}}\" data-action=\"{{action}}\" data-id=\"{{id}}\">\n {{#icon}}<i class=\"{{icon}} me-1\"></i>{{/icon}}\n {{label}}\n </button>\n {{/isButton}}\n {{^isButton}}\n <a class=\"nav-link\" href=\"{{href}}\" {{#action}}data-action=\"{{action}}\"{{/action}}>\n {{#icon}}<i class=\"{{icon}} me-1\"></i>{{/icon}}\n {{label}}\n </a>\n {{/isButton}}\n {{/isDropdown}}\n {{/data.rightItems}}\n </div>\n {{/data.hasRightItems}}\n </div>\n </div>\n `;\n }\n\n /**\n * Process and normalize data before rendering (like Sidebar)\n */\n async onBeforeRender() {\n await super.onBeforeRender();\n\n const showPageInfo = this.displayMode === 'page' || this.displayMode === 'both';\n const showNavItems = this.displayMode === 'menu' || this.displayMode === 'both';\n\n // Filter navItems based on permissions\n const navItems = this.filterItemsByPermissions(this.config.navItems || []);\n\n // Process right items\n const rightItems = this.processRightItems(this.config.rightItems || []);\n\n this.data = {\n // Brand information\n brand: this.config.brand,\n brandIcon: this.config.brandIcon,\n brandRoute: this.config.brandRoute,\n\n // Navbar configuration\n navbarId: `navbar-${this.id}`,\n\n // Navigation items\n navItems: navItems,\n showNavItems: showNavItems,\n\n // Right items\n rightItems: rightItems,\n hasRightItems: rightItems.length > 0,\n\n // Page display\n showPageInfo: showPageInfo,\n currentPageName: this.currentPage?.title || this.currentPage?.name || '',\n currentPageIcon: this.currentPage?.icon || this.currentPage?.pageIcon || '',\n currentPageDescription: this.showPageDescription ? this.currentPage?.description : '',\n\n // Sidebar toggle\n showSidebarToggle: this.config.showSidebarToggle,\n sidebarToggleAction: this.config.sidebarToggleAction,\n\n // Display mode\n displayMode: this.displayMode\n };\n }\n\n /**\n * Process right items configuration\n */\n processRightItems(rightItems) {\n return this.filterItemsByPermissions(rightItems).map(item => {\n const processedItem = { ...item };\n\n // Filter dropdown items by permissions if they exist\n if (item.items) {\n processedItem.items = this.filterItemsByPermissions(item.items);\n }\n\n // Determine item type\n if (processedItem.items && processedItem.items.length > 0) {\n // Dropdown menu\n processedItem.isDropdown = true;\n processedItem.isButton = false;\n } else if (item.buttonClass) {\n // Button\n processedItem.isButton = true;\n processedItem.isDropdown = false;\n } else {\n // Link\n processedItem.isButton = false;\n processedItem.isDropdown = false;\n }\n\n // Store handler if provided\n if (item.handler) {\n this.rightItemHandlers = this.rightItemHandlers || new Map();\n this.rightItemHandlers.set(item.id, item.handler);\n }\n\n return processedItem;\n });\n }\n\n /**\n * Setup listeners for page change events\n */\n setupPageListeners() {\n // Use global MOJO event bus if available\n this.getApp().events.on([\"page:show\", \"page:hide\", \"page:denied\"], (data) => {\n this.onPageChanged(data);\n });\n }\n\n /**\n * Handle page before change event\n * @param {object} data - Event data\n */\n onPageBeforeChange(data) {\n // Can be used to show loading state\n if (this.displayMode === 'page' || this.displayMode === 'both') {\n // Optionally show loading indicator\n }\n }\n\n /**\n * Handle page changed event\n * @param {object} data - Event data with previousPage and currentPage\n */\n onPageChanged(data) {\n this.previousPage = this.currentPage;\n this.currentPage = data.page;\n\n // Update display based on mode\n if (this.displayMode === 'page' || this.displayMode === 'both') {\n this.updatePageDisplay();\n }\n\n // Update active menu items\n if (this.displayMode === 'menu' || this.displayMode === 'both') {\n if (this.currentPage && this.currentPage.route) {\n this.updateActiveItem(this.currentPage.route);\n }\n }\n }\n\n /**\n * Update the display to show current page info\n */\n updatePageDisplay() {\n if (!this.currentPage) return;\n\n // Just trigger re-render, onBeforeRender will handle the data processing\n if (this.mounted) {\n this.render();\n }\n }\n\n updateActiveItem(currentRoute) {\n // Normalize routes for comparison\n const normalizeRoute = (route) => {\n if (!route) return '/';\n return route.startsWith('/') ? route : `/${route}`;\n };\n\n const normalizedCurrentRoute = normalizeRoute(currentRoute);\n\n // Update active states with improved matching\n const navItems = this.data.navItems.map(item => {\n const normalizedItemRoute = normalizeRoute(item.route);\n\n // Check for active state\n let isActive = false;\n\n if (normalizedItemRoute === '/' && normalizedCurrentRoute === '/') {\n // Exact match for home route\n isActive = true;\n } else if (normalizedItemRoute !== '/' && normalizedCurrentRoute !== '/') {\n // For non-home routes, check if current route starts with nav item route\n // This allows /users to be active when on /users/123\n isActive = normalizedCurrentRoute.startsWith(normalizedItemRoute) ||\n normalizedCurrentRoute === normalizedItemRoute;\n }\n\n return {\n ...item,\n active: isActive\n };\n });\n\n this.updateData({ navItems }, true);\n }\n\n onPassThruActionProfile() {\n // Implement profile functionality here\n this.getApp().events.emit(\"portal:action\", {action: \"profile\"});\n }\n\n onActionSettings() {\n // Implement settings functionality here\n this.getApp().events.emit(\"portal:action\", {action: \"settings\"});\n }\n\n onActionLogout() {\n // Implement logout functionality here\n this.getApp().events.emit(\"auth:logout\", {action: \"logout\"});\n }\n\n /**\n * Handle dynamic action dispatch for right items\n */\n async handleAction(actionName, event, element) {\n // Check for custom handler first\n const itemId = element.getAttribute('data-id');\n if (itemId && this.rightItemHandlers && this.rightItemHandlers.has(itemId)) {\n const handler = this.rightItemHandlers.get(itemId);\n if (typeof handler === 'function') {\n return await handler.call(this, actionName, event, element);\n }\n }\n\n // Fallback to default action methods\n const methodName = `onAction${actionName.charAt(0).toUpperCase() + actionName.slice(1).replace(/-([a-z])/g, (g) => g[1].toUpperCase())}`;\n if (typeof this[methodName] === 'function') {\n return await this[methodName](event, element);\n }\n\n // Emit action event if no handler found\n this.emit('action', {\n action: actionName,\n event: event,\n element: element,\n topnav: this\n });\n }\n\n /**\n * Handle default actions by searching through rightItems and navItems\n */\n async onActionDefault(action, event, el) {\n // Check navItems first\n if (this.config.navItems) {\n for (const item of this.config.navItems) {\n if (item.action === action && item.handler) {\n await item.handler.call(this, action, event, el);\n return true;\n }\n }\n }\n\n // Check rightItems\n if (this.config.rightItems) {\n for (const item of this.config.rightItems) {\n if (item.action === action && item.handler) {\n await item.handler.call(this, action, event, el);\n return true;\n }\n // Also check dropdown items\n if (item.items) {\n for (const subItem of item.items) {\n if (subItem.action === action && subItem.handler) {\n await subItem.handler.call(this, action, event, el);\n return true;\n }\n }\n }\n }\n }\n\n this.getApp().events.emit(\"portal:action\", { action, event, el });\n\n return false;\n }\n\n /**\n * Filter items by user permissions\n */\n filterItemsByPermissions(items) {\n if (!items) return [];\n\n const app = this.getApp();\n const activeUser = app?.activeUser;\n\n return items.filter(item => {\n // If item has permissions and user exists, check permissions\n if (item.permissions && activeUser) {\n return activeUser.hasPermission(item.permissions);\n }\n // If no permissions required or no user, show the item\n return true;\n });\n }\n\n}\n\nexport default TopNav;\n"],"names":["item"],"mappings":"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"}