adminator-admin-dashboard 2.7.1 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +40 -12
- package/dist/main.js +1771 -2565
- package/dist/main.js.map +1 -1
- package/package.json +22 -34
- package/src/assets/scripts/app.js +3 -3
- package/src/assets/scripts/utils/theme.js +4 -2
- package/src/assets/scripts/vectorMaps/index.js +5 -5
- package/dist/55b07f26c86c8e3d3754.svg +0 -1
- package/dist/9fad440d8ee7a949a9a9.svg +0 -1
- package/dist/test.html +0 -91
- package/src/assets/scripts/app.ts +0 -757
- package/src/assets/scripts/components/Chart.ts +0 -1350
- package/src/assets/scripts/components/Sidebar.ts +0 -388
- package/src/assets/scripts/datatable/index.ts +0 -707
- package/src/assets/scripts/datepicker/index.ts +0 -699
- package/src/assets/scripts/ui/index.ts +0 -740
- package/src/assets/scripts/utils/date.ts +0 -363
- package/src/assets/scripts/utils/dom.ts +0 -513
- package/src/assets/scripts/utils/theme.ts +0 -313
- package/src/assets/scripts/vectorMaps/index.ts +0 -542
- package/src/test.html +0 -96
- package/src/types/index.ts +0 -236
- /package/dist/assets/{c1e38fd9e0e74ba58f7a2b77ef29fdd3.svg → fontawesome-webfont.svg} +0 -0
- /package/dist/assets/{f0fc8c798eac5636249c4ea287832422.svg → themify.svg} +0 -0
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Modern Sidebar Component with TypeScript
|
|
3
|
-
* Replaces jQuery-based sidebar functionality with vanilla JavaScript
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { ComponentInterface, SidebarOptions, SidebarState, AnimationOptions } from '../../../types';
|
|
7
|
-
|
|
8
|
-
export interface SidebarEventDetail {
|
|
9
|
-
collapsed: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface SidebarToggleEvent extends CustomEvent {
|
|
13
|
-
detail: SidebarEventDetail;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
declare global {
|
|
17
|
-
interface Window {
|
|
18
|
-
EVENT?: Event;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class Sidebar implements ComponentInterface {
|
|
23
|
-
public name: string = 'Sidebar';
|
|
24
|
-
public element: HTMLElement;
|
|
25
|
-
public options: SidebarOptions;
|
|
26
|
-
public isInitialized: boolean = false;
|
|
27
|
-
|
|
28
|
-
private sidebar: HTMLElement | null;
|
|
29
|
-
private sidebarMenu: HTMLElement | null;
|
|
30
|
-
private sidebarToggleLinks: NodeListOf<HTMLAnchorElement>;
|
|
31
|
-
private sidebarToggleById: HTMLElement | null;
|
|
32
|
-
private app: HTMLElement | null;
|
|
33
|
-
private state: SidebarState;
|
|
34
|
-
|
|
35
|
-
constructor(element?: HTMLElement, options: SidebarOptions = {}) {
|
|
36
|
-
this.element = element || document.body;
|
|
37
|
-
this.options = {
|
|
38
|
-
breakpoint: 768,
|
|
39
|
-
collapsible: true,
|
|
40
|
-
autoHide: true,
|
|
41
|
-
animation: true,
|
|
42
|
-
animationDuration: 200,
|
|
43
|
-
...options,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
this.sidebar = document.querySelector('.sidebar');
|
|
47
|
-
this.sidebarMenu = document.querySelector('.sidebar .sidebar-menu');
|
|
48
|
-
this.sidebarToggleLinks = document.querySelectorAll('.sidebar-toggle a');
|
|
49
|
-
this.sidebarToggleById = document.querySelector('#sidebar-toggle');
|
|
50
|
-
this.app = document.querySelector('.app');
|
|
51
|
-
|
|
52
|
-
this.state = {
|
|
53
|
-
isCollapsed: false,
|
|
54
|
-
isMobile: false,
|
|
55
|
-
activeMenu: null,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
this.init();
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Initialize the sidebar component
|
|
63
|
-
*/
|
|
64
|
-
public init(): void {
|
|
65
|
-
if (!this.sidebar || !this.sidebarMenu) {
|
|
66
|
-
console.warn('Sidebar: Required elements not found');
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
this.setupMenuToggle();
|
|
71
|
-
this.setupSidebarToggle();
|
|
72
|
-
this.setActiveLink();
|
|
73
|
-
this.handleResize();
|
|
74
|
-
this.setupEventListeners();
|
|
75
|
-
|
|
76
|
-
this.isInitialized = true;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Destroy the sidebar component
|
|
81
|
-
*/
|
|
82
|
-
public destroy(): void {
|
|
83
|
-
this.removeEventListeners();
|
|
84
|
-
this.isInitialized = false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Setup dropdown menu functionality
|
|
89
|
-
*/
|
|
90
|
-
private setupMenuToggle(): void {
|
|
91
|
-
if (!this.sidebarMenu) return;
|
|
92
|
-
|
|
93
|
-
const menuLinks = this.sidebarMenu.querySelectorAll('li a');
|
|
94
|
-
|
|
95
|
-
menuLinks.forEach(link => {
|
|
96
|
-
link.addEventListener('click', this.handleMenuClick.bind(this));
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Handle menu item click
|
|
102
|
-
*/
|
|
103
|
-
private handleMenuClick(e: Event): void {
|
|
104
|
-
const link = e.target as HTMLAnchorElement;
|
|
105
|
-
const listItem = link.parentElement as HTMLLIElement;
|
|
106
|
-
const dropdownMenu = listItem?.querySelector('.dropdown-menu') as HTMLElement;
|
|
107
|
-
|
|
108
|
-
// If this is a regular navigation link (not dropdown), allow normal navigation
|
|
109
|
-
if (!dropdownMenu) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Only prevent default for dropdown toggles
|
|
114
|
-
e.preventDefault();
|
|
115
|
-
|
|
116
|
-
if (listItem.classList.contains('open')) {
|
|
117
|
-
this.closeDropdown(listItem, dropdownMenu);
|
|
118
|
-
} else {
|
|
119
|
-
this.closeAllDropdowns();
|
|
120
|
-
this.openDropdown(listItem, dropdownMenu);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Open dropdown with smooth animation
|
|
126
|
-
*/
|
|
127
|
-
private openDropdown(listItem: HTMLLIElement, dropdownMenu: HTMLElement): void {
|
|
128
|
-
listItem.classList.add('open');
|
|
129
|
-
dropdownMenu.style.display = 'block';
|
|
130
|
-
dropdownMenu.style.height = '0px';
|
|
131
|
-
dropdownMenu.style.overflow = 'hidden';
|
|
132
|
-
|
|
133
|
-
// Get the natural height
|
|
134
|
-
const height = dropdownMenu.scrollHeight;
|
|
135
|
-
|
|
136
|
-
// Animate to full height
|
|
137
|
-
const animation = dropdownMenu.animate([
|
|
138
|
-
{ height: '0px' },
|
|
139
|
-
{ height: `${height}px` },
|
|
140
|
-
], {
|
|
141
|
-
duration: this.options.animationDuration,
|
|
142
|
-
easing: 'ease-out',
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
animation.onfinish = (): void => {
|
|
146
|
-
dropdownMenu.style.height = 'auto';
|
|
147
|
-
dropdownMenu.style.overflow = 'visible';
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Close dropdown with smooth animation
|
|
153
|
-
*/
|
|
154
|
-
private closeDropdown(listItem: HTMLLIElement, dropdownMenu: HTMLElement): void {
|
|
155
|
-
const height = dropdownMenu.scrollHeight;
|
|
156
|
-
|
|
157
|
-
dropdownMenu.style.height = `${height}px`;
|
|
158
|
-
dropdownMenu.style.overflow = 'hidden';
|
|
159
|
-
|
|
160
|
-
const animation = dropdownMenu.animate([
|
|
161
|
-
{ height: `${height}px` },
|
|
162
|
-
{ height: '0px' },
|
|
163
|
-
], {
|
|
164
|
-
duration: this.options.animationDuration,
|
|
165
|
-
easing: 'ease-in',
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
animation.onfinish = (): void => {
|
|
169
|
-
listItem.classList.remove('open');
|
|
170
|
-
dropdownMenu.style.display = 'none';
|
|
171
|
-
dropdownMenu.style.height = '';
|
|
172
|
-
dropdownMenu.style.overflow = '';
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Close all open dropdowns
|
|
178
|
-
*/
|
|
179
|
-
private closeAllDropdowns(): void {
|
|
180
|
-
if (!this.sidebarMenu) return;
|
|
181
|
-
|
|
182
|
-
const openItems = this.sidebarMenu.querySelectorAll('li.open');
|
|
183
|
-
|
|
184
|
-
openItems.forEach(item => {
|
|
185
|
-
const dropdownMenu = item.querySelector('.dropdown-menu') as HTMLElement;
|
|
186
|
-
if (dropdownMenu) {
|
|
187
|
-
this.closeDropdown(item as HTMLLIElement, dropdownMenu);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Also remove the has-active-child class
|
|
191
|
-
item.classList.remove('has-active-child');
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Setup sidebar toggle functionality
|
|
197
|
-
*/
|
|
198
|
-
private setupSidebarToggle(): void {
|
|
199
|
-
// Handle mobile sidebar toggle links (inside .sidebar-toggle divs)
|
|
200
|
-
this.sidebarToggleLinks.forEach(link => {
|
|
201
|
-
if (link && this.app) {
|
|
202
|
-
link.addEventListener('click', this.handleSidebarToggle.bind(this));
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
// Handle the main topbar sidebar toggle
|
|
207
|
-
if (this.sidebarToggleById && this.app) {
|
|
208
|
-
this.sidebarToggleById.addEventListener('click', this.handleSidebarToggle.bind(this));
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Handle sidebar toggle click
|
|
214
|
-
*/
|
|
215
|
-
private handleSidebarToggle(e: Event): void {
|
|
216
|
-
e.preventDefault();
|
|
217
|
-
this.toggleSidebar();
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Toggle sidebar and handle resize events properly
|
|
222
|
-
*/
|
|
223
|
-
private toggleSidebar(): void {
|
|
224
|
-
if (!this.app) return;
|
|
225
|
-
|
|
226
|
-
const wasCollapsed = this.state.isCollapsed;
|
|
227
|
-
this.state.isCollapsed = !wasCollapsed;
|
|
228
|
-
|
|
229
|
-
this.app.classList.toggle('is-collapsed');
|
|
230
|
-
|
|
231
|
-
// Dispatch custom event with proper typing
|
|
232
|
-
setTimeout(() => {
|
|
233
|
-
const event: SidebarToggleEvent = new CustomEvent('sidebar:toggle', {
|
|
234
|
-
detail: { collapsed: this.state.isCollapsed },
|
|
235
|
-
}) as SidebarToggleEvent;
|
|
236
|
-
|
|
237
|
-
window.dispatchEvent(event);
|
|
238
|
-
|
|
239
|
-
// Still trigger resize for masonry but with a specific check
|
|
240
|
-
if (window.EVENT) {
|
|
241
|
-
window.dispatchEvent(window.EVENT);
|
|
242
|
-
}
|
|
243
|
-
}, this.options.animationDuration || 300);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Set active link based on current URL
|
|
248
|
-
*/
|
|
249
|
-
private setActiveLink(): void {
|
|
250
|
-
if (!this.sidebar) return;
|
|
251
|
-
|
|
252
|
-
// Remove active class from all nav items (including dropdown items)
|
|
253
|
-
const allNavItems = this.sidebar.querySelectorAll('.nav-item');
|
|
254
|
-
allNavItems.forEach(item => {
|
|
255
|
-
item.classList.remove('actived');
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// Close all dropdowns first
|
|
259
|
-
this.closeAllDropdowns();
|
|
260
|
-
|
|
261
|
-
// Get current page filename
|
|
262
|
-
const currentPath = window.location.pathname;
|
|
263
|
-
const currentPage = currentPath.split('/').pop() || 'index.html';
|
|
264
|
-
|
|
265
|
-
// Find and activate the correct nav item
|
|
266
|
-
const allLinks = this.sidebar.querySelectorAll('a[href]');
|
|
267
|
-
|
|
268
|
-
allLinks.forEach(link => {
|
|
269
|
-
const href = link.getAttribute('href');
|
|
270
|
-
if (!href || href === 'javascript:void(0);' || href === 'javascript:void(0)') return;
|
|
271
|
-
|
|
272
|
-
// Extract filename from href
|
|
273
|
-
const linkPage = href.split('/').pop();
|
|
274
|
-
|
|
275
|
-
if (linkPage === currentPage) {
|
|
276
|
-
const navItem = link.closest('.nav-item') as HTMLElement;
|
|
277
|
-
if (navItem) {
|
|
278
|
-
navItem.classList.add('actived');
|
|
279
|
-
this.state.activeMenu = linkPage || null;
|
|
280
|
-
|
|
281
|
-
// If this is inside a dropdown, handle parent dropdown specially
|
|
282
|
-
const parentDropdown = navItem.closest('.dropdown-menu') as HTMLElement;
|
|
283
|
-
if (parentDropdown) {
|
|
284
|
-
const parentDropdownItem = parentDropdown.closest('.nav-item.dropdown') as HTMLElement;
|
|
285
|
-
if (parentDropdownItem) {
|
|
286
|
-
// Open the parent dropdown
|
|
287
|
-
parentDropdownItem.classList.add('open');
|
|
288
|
-
parentDropdown.style.display = 'block';
|
|
289
|
-
|
|
290
|
-
// Add special styling to indicate parent has active child
|
|
291
|
-
parentDropdownItem.classList.add('has-active-child');
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Handle window resize
|
|
301
|
-
*/
|
|
302
|
-
private handleResize(): void {
|
|
303
|
-
this.state.isMobile = window.innerWidth <= (this.options.breakpoint || 768);
|
|
304
|
-
|
|
305
|
-
if (this.options.autoHide && this.state.isMobile) {
|
|
306
|
-
// Auto-hide logic for mobile
|
|
307
|
-
this.collapse();
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Setup event listeners
|
|
313
|
-
*/
|
|
314
|
-
private setupEventListeners(): void {
|
|
315
|
-
window.addEventListener('resize', this.handleResize.bind(this));
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Remove event listeners
|
|
320
|
-
*/
|
|
321
|
-
private removeEventListeners(): void {
|
|
322
|
-
window.removeEventListener('resize', this.handleResize.bind(this));
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Public method to refresh active links (useful for SPA navigation)
|
|
327
|
-
*/
|
|
328
|
-
public refreshActiveLink(): void {
|
|
329
|
-
this.setActiveLink();
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Public method to toggle sidebar programmatically
|
|
334
|
-
*/
|
|
335
|
-
public toggle(): void {
|
|
336
|
-
this.toggleSidebar();
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Public method to collapse sidebar
|
|
341
|
-
*/
|
|
342
|
-
public collapse(): void {
|
|
343
|
-
if (!this.app || this.state.isCollapsed) return;
|
|
344
|
-
|
|
345
|
-
this.state.isCollapsed = true;
|
|
346
|
-
this.app.classList.add('is-collapsed');
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Public method to expand sidebar
|
|
351
|
-
*/
|
|
352
|
-
public expand(): void {
|
|
353
|
-
if (!this.app || !this.state.isCollapsed) return;
|
|
354
|
-
|
|
355
|
-
this.state.isCollapsed = false;
|
|
356
|
-
this.app.classList.remove('is-collapsed');
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Public method to check if sidebar is collapsed
|
|
361
|
-
*/
|
|
362
|
-
public isCollapsed(): boolean {
|
|
363
|
-
return this.state.isCollapsed;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Get current sidebar state
|
|
368
|
-
*/
|
|
369
|
-
public getState(): SidebarState {
|
|
370
|
-
return { ...this.state };
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Update sidebar options
|
|
375
|
-
*/
|
|
376
|
-
public updateOptions(newOptions: Partial<SidebarOptions>): void {
|
|
377
|
-
this.options = { ...this.options, ...newOptions };
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Get current options
|
|
382
|
-
*/
|
|
383
|
-
public getOptions(): SidebarOptions {
|
|
384
|
-
return { ...this.options };
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
export default Sidebar;
|