@dodlhuat/basix 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +266 -6
- package/css/accordion.scss +86 -87
- package/css/alert.scss +137 -137
- package/css/button.scss +48 -0
- package/css/calendar.scss +957 -0
- package/css/card.scss +65 -65
- package/css/chart.scss +270 -157
- package/css/chat-bubbles.scss +134 -68
- package/css/chips.scss +109 -19
- package/css/colors.scss +32 -32
- package/css/datepicker.scss +336 -336
- package/css/defaults.scss +90 -90
- package/css/docs.scss +529 -0
- package/css/editor.scss +36 -0
- package/css/file-uploader.scss +1 -1
- package/css/flyout-menu.scss +361 -361
- package/css/form.scss +0 -15
- package/css/gallery.scss +65 -6
- package/css/grid.scss +41 -40
- package/css/group-picker.scss +345 -0
- package/css/guitar-chords.css +250 -250
- package/css/icons.scss +330 -330
- package/css/parameters.scss +3 -3
- package/css/placeholder.scss +33 -33
- package/css/popover.scss +206 -0
- package/css/progress.scss +76 -32
- package/css/properties.scss +51 -36
- package/css/push-menu.scss +302 -174
- package/css/reset.scss +39 -39
- package/css/scrollbar.scss +62 -5
- package/css/sidebar-nav.scss +92 -0
- package/css/spinner.scss +65 -65
- package/css/stepper.scss +48 -12
- package/css/style.css +3155 -254
- package/css/style.css.map +1 -1
- package/css/style.min.css +1 -1
- package/css/style.scss +51 -45
- package/css/table.scss +199 -199
- package/css/tabs.scss +154 -123
- package/css/timeline.scss +83 -38
- package/css/timepicker.scss +100 -5
- package/css/toast.scss +81 -81
- package/css/virtual-dropdown.scss +35 -29
- package/js/calendar.js +532 -0
- package/js/calendar.ts +706 -0
- package/js/chart.js +573 -257
- package/js/chart.ts +692 -0
- package/js/code-viewer.js +10 -10
- package/js/code-viewer.ts +188 -188
- package/js/datepicker.ts +627 -627
- package/js/docs-nav.js +204 -0
- package/js/dropdown.ts +179 -179
- package/js/editor.js +50 -6
- package/js/editor.ts +483 -444
- package/js/file-uploader.js +1 -0
- package/js/file-uploader.ts +1 -0
- package/js/flyout-menu.js +14 -14
- package/js/flyout-menu.ts +249 -249
- package/js/form-builder.js +106 -106
- package/js/gallery.js +14 -8
- package/js/gallery.ts +245 -236
- package/js/group-picker.js +342 -0
- package/js/group-picker.ts +447 -0
- package/js/guitar-chords.js +268 -268
- package/js/lazy-loader.js +121 -121
- package/js/modal.ts +166 -166
- package/js/popover.js +163 -0
- package/js/popover.ts +219 -0
- package/js/position.js +108 -0
- package/js/position.ts +111 -0
- package/js/push-menu.js +113 -0
- package/js/push-menu.ts +284 -145
- package/js/request.js +50 -50
- package/js/scroll.ts +47 -47
- package/js/scrollbar.js +13 -0
- package/js/scrollbar.ts +324 -307
- package/js/select.ts +216 -216
- package/js/sidebar-nav.js +41 -0
- package/js/sidebar-nav.ts +66 -0
- package/js/table.ts +452 -452
- package/js/tabs.ts +279 -279
- package/js/theme.js +17 -6
- package/js/theme.ts +234 -224
- package/js/toast.ts +137 -137
- package/js/tooltip.js +6 -60
- package/js/tooltip.ts +184 -251
- package/js/tsconfig.json +18 -18
- package/js/utils.ts +83 -83
- package/js/virtual-dropdown.js +25 -25
- package/js/virtual-dropdown.ts +365 -365
- package/package.json +37 -39
- package/js/index.js +0 -816
- package/js/index.ts +0 -987
package/js/push-menu.js
CHANGED
|
@@ -8,10 +8,120 @@ class PushMenu {
|
|
|
8
8
|
if (!this.elements.navigation || !this.elements.content) {
|
|
9
9
|
throw new Error('PushMenu: Required elements not found (.navigation, .push-content)');
|
|
10
10
|
}
|
|
11
|
+
this.buildPanels();
|
|
11
12
|
this.elements.navigation.addEventListener('change', this.handleNavigationChange.bind(this));
|
|
12
13
|
this.elements.backdrop?.addEventListener('click', this.handleBackdropClick);
|
|
13
14
|
this.initialized = true;
|
|
14
15
|
}
|
|
16
|
+
// ─── Panel construction ────────────────────────────────────────────────
|
|
17
|
+
static buildPanels() {
|
|
18
|
+
const menu = this.elements.menu;
|
|
19
|
+
if (!menu)
|
|
20
|
+
return;
|
|
21
|
+
const rootUl = menu.querySelector(':scope > ul');
|
|
22
|
+
if (!rootUl)
|
|
23
|
+
return;
|
|
24
|
+
// Wrap root ul in a panel
|
|
25
|
+
const rootPanel = document.createElement('div');
|
|
26
|
+
rootPanel.classList.add('push-menu-panel', 'is-active');
|
|
27
|
+
rootPanel.dataset.level = '0';
|
|
28
|
+
rootPanel.appendChild(rootUl);
|
|
29
|
+
menu.appendChild(rootPanel);
|
|
30
|
+
// Recursively extract nested uls into sibling panels
|
|
31
|
+
this.extractSubPanels(rootPanel, 1);
|
|
32
|
+
this.panelStack = [rootPanel];
|
|
33
|
+
}
|
|
34
|
+
static extractSubPanels(panel, level) {
|
|
35
|
+
// Collect all uls currently in this panel before any mutations
|
|
36
|
+
const uls = Array.from(panel.querySelectorAll('ul'));
|
|
37
|
+
for (const ul of uls) {
|
|
38
|
+
const listItems = Array.from(ul.children);
|
|
39
|
+
for (const li of listItems) {
|
|
40
|
+
const childUl = li.querySelector(':scope > ul');
|
|
41
|
+
if (!childUl)
|
|
42
|
+
continue;
|
|
43
|
+
// Determine label from the immediate anchor child
|
|
44
|
+
const parentAnchor = li.querySelector(':scope > a');
|
|
45
|
+
const title = parentAnchor?.textContent?.trim() ?? '';
|
|
46
|
+
// ── Build sub-panel ──────────────────────────────────────
|
|
47
|
+
const subPanel = document.createElement('div');
|
|
48
|
+
subPanel.classList.add('push-menu-panel');
|
|
49
|
+
subPanel.dataset.level = String(level);
|
|
50
|
+
// Header: back button + breadcrumb title
|
|
51
|
+
const header = document.createElement('div');
|
|
52
|
+
header.classList.add('push-menu-panel-header');
|
|
53
|
+
const backBtn = document.createElement('button');
|
|
54
|
+
backBtn.classList.add('push-menu-back');
|
|
55
|
+
backBtn.setAttribute('aria-label', 'Back');
|
|
56
|
+
backBtn.innerHTML = `<span class="icon icon-navigate_before" aria-hidden="true"></span>`;
|
|
57
|
+
header.addEventListener('click', () => PushMenu.goBack());
|
|
58
|
+
const titleEl = document.createElement('span');
|
|
59
|
+
titleEl.classList.add('push-menu-panel-title');
|
|
60
|
+
titleEl.textContent = title;
|
|
61
|
+
header.appendChild(backBtn);
|
|
62
|
+
header.appendChild(titleEl);
|
|
63
|
+
subPanel.appendChild(header);
|
|
64
|
+
// Move the child ul into the sub-panel
|
|
65
|
+
subPanel.appendChild(childUl);
|
|
66
|
+
// Append sub-panel as sibling inside the nav
|
|
67
|
+
this.elements.menu?.appendChild(subPanel);
|
|
68
|
+
// ── Replace anchor with a trigger span in the parent li ──
|
|
69
|
+
const trigger = document.createElement('span');
|
|
70
|
+
trigger.classList.add('push-menu-item');
|
|
71
|
+
trigger.textContent = title;
|
|
72
|
+
// Chevron icon
|
|
73
|
+
const chevron = document.createElement('span');
|
|
74
|
+
chevron.classList.add('push-menu-chevron');
|
|
75
|
+
chevron.setAttribute('aria-hidden', 'true');
|
|
76
|
+
chevron.innerHTML = `<span class="icon icon-navigate_next" aria-hidden="true"></span>`;
|
|
77
|
+
trigger.appendChild(chevron);
|
|
78
|
+
if (parentAnchor) {
|
|
79
|
+
parentAnchor.replaceWith(trigger);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
li.prepend(trigger);
|
|
83
|
+
}
|
|
84
|
+
trigger.addEventListener('click', () => PushMenu.openPanel(subPanel));
|
|
85
|
+
// Recurse into the newly created sub-panel
|
|
86
|
+
this.extractSubPanels(subPanel, level + 1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ─── Panel navigation ──────────────────────────────────────────────────
|
|
91
|
+
static openPanel(panel) {
|
|
92
|
+
const currentPanel = this.panelStack[this.panelStack.length - 1];
|
|
93
|
+
currentPanel.classList.remove('is-active');
|
|
94
|
+
currentPanel.classList.add('is-prev');
|
|
95
|
+
panel.classList.add('is-active');
|
|
96
|
+
this.panelStack.push(panel);
|
|
97
|
+
}
|
|
98
|
+
static goBack() {
|
|
99
|
+
if (this.panelStack.length <= 1)
|
|
100
|
+
return;
|
|
101
|
+
const currentPanel = this.panelStack.pop();
|
|
102
|
+
const prevPanel = this.panelStack[this.panelStack.length - 1];
|
|
103
|
+
currentPanel.classList.remove('is-active');
|
|
104
|
+
prevPanel.classList.remove('is-prev');
|
|
105
|
+
prevPanel.classList.add('is-active');
|
|
106
|
+
}
|
|
107
|
+
static resetPanels() {
|
|
108
|
+
const menu = this.elements.menu;
|
|
109
|
+
if (!menu)
|
|
110
|
+
return;
|
|
111
|
+
// Wait for the close animation before snapping panels back
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
const panels = Array.from(menu.querySelectorAll('.push-menu-panel'));
|
|
114
|
+
panels.forEach((panel, index) => {
|
|
115
|
+
panel.classList.remove('is-active', 'is-prev');
|
|
116
|
+
if (index === 0)
|
|
117
|
+
panel.classList.add('is-active');
|
|
118
|
+
});
|
|
119
|
+
if (panels[0]) {
|
|
120
|
+
this.panelStack = [panels[0]];
|
|
121
|
+
}
|
|
122
|
+
}, 300);
|
|
123
|
+
}
|
|
124
|
+
// ─── Open / close ──────────────────────────────────────────────────────
|
|
15
125
|
static handleNavigationChange() {
|
|
16
126
|
const isPushed = this.elements.content?.classList.contains('pushed') ?? false;
|
|
17
127
|
if (!isPushed) {
|
|
@@ -19,6 +129,7 @@ class PushMenu {
|
|
|
19
129
|
}
|
|
20
130
|
else {
|
|
21
131
|
this.elements.content?.removeEventListener('click', this.clickNav);
|
|
132
|
+
this.resetPanels();
|
|
22
133
|
}
|
|
23
134
|
this.pushToggle();
|
|
24
135
|
}
|
|
@@ -80,6 +191,7 @@ class PushMenu {
|
|
|
80
191
|
controlIcon: null,
|
|
81
192
|
backdrop: null
|
|
82
193
|
};
|
|
194
|
+
this.panelStack = [];
|
|
83
195
|
this.initialized = false;
|
|
84
196
|
}
|
|
85
197
|
static refresh() {
|
|
@@ -100,6 +212,7 @@ PushMenu.elements = {
|
|
|
100
212
|
backdrop: null
|
|
101
213
|
};
|
|
102
214
|
PushMenu.initialized = false;
|
|
215
|
+
PushMenu.panelStack = [];
|
|
103
216
|
PushMenu.clickNav = () => {
|
|
104
217
|
const navigation = PushMenu.elements.navigation;
|
|
105
218
|
navigation?.click();
|
package/js/push-menu.ts
CHANGED
|
@@ -1,145 +1,284 @@
|
|
|
1
|
-
interface PushMenuElements {
|
|
2
|
-
navigation: HTMLElement | null;
|
|
3
|
-
content: HTMLElement | null;
|
|
4
|
-
menu: HTMLElement | null;
|
|
5
|
-
header: HTMLElement | null;
|
|
6
|
-
controlIcon: HTMLElement | null;
|
|
7
|
-
backdrop: HTMLElement | null;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
class PushMenu {
|
|
11
|
-
private static elements: PushMenuElements = {
|
|
12
|
-
navigation: null,
|
|
13
|
-
content: null,
|
|
14
|
-
menu: null,
|
|
15
|
-
header: null,
|
|
16
|
-
controlIcon: null,
|
|
17
|
-
backdrop: null
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
private static initialized = false;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this.
|
|
61
|
-
|
|
62
|
-
this.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
1
|
+
interface PushMenuElements {
|
|
2
|
+
navigation: HTMLElement | null;
|
|
3
|
+
content: HTMLElement | null;
|
|
4
|
+
menu: HTMLElement | null;
|
|
5
|
+
header: HTMLElement | null;
|
|
6
|
+
controlIcon: HTMLElement | null;
|
|
7
|
+
backdrop: HTMLElement | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class PushMenu {
|
|
11
|
+
private static elements: PushMenuElements = {
|
|
12
|
+
navigation: null,
|
|
13
|
+
content: null,
|
|
14
|
+
menu: null,
|
|
15
|
+
header: null,
|
|
16
|
+
controlIcon: null,
|
|
17
|
+
backdrop: null
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
private static initialized = false;
|
|
21
|
+
private static panelStack: HTMLElement[] = [];
|
|
22
|
+
|
|
23
|
+
public static init(): void {
|
|
24
|
+
if (this.initialized) {
|
|
25
|
+
console.warn('PushMenu: Already initialized');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.refresh();
|
|
30
|
+
|
|
31
|
+
if (!this.elements.navigation || !this.elements.content) {
|
|
32
|
+
throw new Error('PushMenu: Required elements not found (.navigation, .push-content)');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.buildPanels();
|
|
36
|
+
|
|
37
|
+
this.elements.navigation.addEventListener('change', this.handleNavigationChange.bind(this));
|
|
38
|
+
this.elements.backdrop?.addEventListener('click', this.handleBackdropClick);
|
|
39
|
+
|
|
40
|
+
this.initialized = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ─── Panel construction ────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
private static buildPanels(): void {
|
|
46
|
+
const menu = this.elements.menu;
|
|
47
|
+
if (!menu) return;
|
|
48
|
+
|
|
49
|
+
const rootUl = menu.querySelector(':scope > ul');
|
|
50
|
+
if (!rootUl) return;
|
|
51
|
+
|
|
52
|
+
// Wrap root ul in a panel
|
|
53
|
+
const rootPanel = document.createElement('div');
|
|
54
|
+
rootPanel.classList.add('push-menu-panel', 'is-active');
|
|
55
|
+
rootPanel.dataset.level = '0';
|
|
56
|
+
rootPanel.appendChild(rootUl);
|
|
57
|
+
menu.appendChild(rootPanel);
|
|
58
|
+
|
|
59
|
+
// Recursively extract nested uls into sibling panels
|
|
60
|
+
this.extractSubPanels(rootPanel, 1);
|
|
61
|
+
|
|
62
|
+
this.panelStack = [rootPanel];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private static extractSubPanels(panel: HTMLElement, level: number): void {
|
|
66
|
+
// Collect all uls currently in this panel before any mutations
|
|
67
|
+
const uls = Array.from(panel.querySelectorAll('ul')) as HTMLUListElement[];
|
|
68
|
+
|
|
69
|
+
for (const ul of uls) {
|
|
70
|
+
const listItems = Array.from(ul.children) as HTMLElement[];
|
|
71
|
+
|
|
72
|
+
for (const li of listItems) {
|
|
73
|
+
const childUl = li.querySelector(':scope > ul') as HTMLElement | null;
|
|
74
|
+
if (!childUl) continue;
|
|
75
|
+
|
|
76
|
+
// Determine label from the immediate anchor child
|
|
77
|
+
const parentAnchor = li.querySelector(':scope > a') as HTMLElement | null;
|
|
78
|
+
const title = parentAnchor?.textContent?.trim() ?? '';
|
|
79
|
+
|
|
80
|
+
// ── Build sub-panel ──────────────────────────────────────
|
|
81
|
+
const subPanel = document.createElement('div');
|
|
82
|
+
subPanel.classList.add('push-menu-panel');
|
|
83
|
+
subPanel.dataset.level = String(level);
|
|
84
|
+
|
|
85
|
+
// Header: back button + breadcrumb title
|
|
86
|
+
const header = document.createElement('div');
|
|
87
|
+
header.classList.add('push-menu-panel-header');
|
|
88
|
+
|
|
89
|
+
const backBtn = document.createElement('button');
|
|
90
|
+
backBtn.classList.add('push-menu-back');
|
|
91
|
+
backBtn.setAttribute('aria-label', 'Back');
|
|
92
|
+
backBtn.innerHTML = `<span class="icon icon-navigate_before" aria-hidden="true"></span>`;
|
|
93
|
+
header.addEventListener('click', () => PushMenu.goBack());
|
|
94
|
+
|
|
95
|
+
const titleEl = document.createElement('span');
|
|
96
|
+
titleEl.classList.add('push-menu-panel-title');
|
|
97
|
+
titleEl.textContent = title;
|
|
98
|
+
|
|
99
|
+
header.appendChild(backBtn);
|
|
100
|
+
header.appendChild(titleEl);
|
|
101
|
+
subPanel.appendChild(header);
|
|
102
|
+
|
|
103
|
+
// Move the child ul into the sub-panel
|
|
104
|
+
subPanel.appendChild(childUl);
|
|
105
|
+
|
|
106
|
+
// Append sub-panel as sibling inside the nav
|
|
107
|
+
this.elements.menu?.appendChild(subPanel);
|
|
108
|
+
|
|
109
|
+
// ── Replace anchor with a trigger span in the parent li ──
|
|
110
|
+
const trigger = document.createElement('span');
|
|
111
|
+
trigger.classList.add('push-menu-item');
|
|
112
|
+
trigger.textContent = title;
|
|
113
|
+
|
|
114
|
+
// Chevron icon
|
|
115
|
+
const chevron = document.createElement('span');
|
|
116
|
+
chevron.classList.add('push-menu-chevron');
|
|
117
|
+
chevron.setAttribute('aria-hidden', 'true');
|
|
118
|
+
chevron.innerHTML = `<span class="icon icon-navigate_next" aria-hidden="true"></span>`;
|
|
119
|
+
trigger.appendChild(chevron);
|
|
120
|
+
|
|
121
|
+
if (parentAnchor) {
|
|
122
|
+
parentAnchor.replaceWith(trigger);
|
|
123
|
+
} else {
|
|
124
|
+
li.prepend(trigger);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
trigger.addEventListener('click', () => PushMenu.openPanel(subPanel));
|
|
128
|
+
|
|
129
|
+
// Recurse into the newly created sub-panel
|
|
130
|
+
this.extractSubPanels(subPanel, level + 1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ─── Panel navigation ──────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
public static openPanel(panel: HTMLElement): void {
|
|
138
|
+
const currentPanel = this.panelStack[this.panelStack.length - 1];
|
|
139
|
+
|
|
140
|
+
currentPanel.classList.remove('is-active');
|
|
141
|
+
currentPanel.classList.add('is-prev');
|
|
142
|
+
|
|
143
|
+
panel.classList.add('is-active');
|
|
144
|
+
|
|
145
|
+
this.panelStack.push(panel);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public static goBack(): void {
|
|
149
|
+
if (this.panelStack.length <= 1) return;
|
|
150
|
+
|
|
151
|
+
const currentPanel = this.panelStack.pop()!;
|
|
152
|
+
const prevPanel = this.panelStack[this.panelStack.length - 1];
|
|
153
|
+
|
|
154
|
+
currentPanel.classList.remove('is-active');
|
|
155
|
+
prevPanel.classList.remove('is-prev');
|
|
156
|
+
prevPanel.classList.add('is-active');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private static resetPanels(): void {
|
|
160
|
+
const menu = this.elements.menu;
|
|
161
|
+
if (!menu) return;
|
|
162
|
+
|
|
163
|
+
// Wait for the close animation before snapping panels back
|
|
164
|
+
setTimeout(() => {
|
|
165
|
+
const panels = Array.from(menu.querySelectorAll('.push-menu-panel')) as HTMLElement[];
|
|
166
|
+
panels.forEach((panel, index) => {
|
|
167
|
+
panel.classList.remove('is-active', 'is-prev');
|
|
168
|
+
if (index === 0) panel.classList.add('is-active');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
if (panels[0]) {
|
|
172
|
+
this.panelStack = [panels[0]];
|
|
173
|
+
}
|
|
174
|
+
}, 300);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ─── Open / close ──────────────────────────────────────────────────────
|
|
178
|
+
|
|
179
|
+
private static handleNavigationChange(): void {
|
|
180
|
+
const isPushed = this.elements.content?.classList.contains('pushed') ?? false;
|
|
181
|
+
|
|
182
|
+
if (!isPushed) {
|
|
183
|
+
this.elements.content?.addEventListener('click', this.clickNav);
|
|
184
|
+
} else {
|
|
185
|
+
this.elements.content?.removeEventListener('click', this.clickNav);
|
|
186
|
+
this.resetPanels();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
this.pushToggle();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public static pushToggle(): void {
|
|
193
|
+
if (!this.elements.content || !this.elements.menu) {
|
|
194
|
+
throw new Error('PushMenu: Required elements not found (.push-content, .push-menu)');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const isPushed = this.elements.content.classList.contains('pushed');
|
|
198
|
+
|
|
199
|
+
this.toggleClass(this.elements.content, 'pushed', !isPushed);
|
|
200
|
+
this.toggleClass(this.elements.menu, 'pushed', !isPushed);
|
|
201
|
+
this.toggleClass(this.elements.header, 'pushed', !isPushed);
|
|
202
|
+
this.toggleClass(this.elements.backdrop, 'pushed', !isPushed);
|
|
203
|
+
|
|
204
|
+
if (this.elements.controlIcon) {
|
|
205
|
+
if (isPushed) {
|
|
206
|
+
this.elements.controlIcon.classList.remove('icon-menu_open');
|
|
207
|
+
this.elements.controlIcon.classList.add('icon-menu');
|
|
208
|
+
} else {
|
|
209
|
+
this.elements.controlIcon.classList.add('icon-menu_open');
|
|
210
|
+
this.elements.controlIcon.classList.remove('icon-menu');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private static toggleClass(element: HTMLElement | null, className: string, add: boolean): void {
|
|
216
|
+
if (!element) return;
|
|
217
|
+
if (add) {
|
|
218
|
+
element.classList.add(className);
|
|
219
|
+
} else {
|
|
220
|
+
element.classList.remove(className);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private static clickNav = (): void => {
|
|
225
|
+
const navigation = PushMenu.elements.navigation as HTMLElement;
|
|
226
|
+
navigation?.click();
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
private static handleBackdropClick = (): void => {
|
|
230
|
+
if (PushMenu.isOpen()) {
|
|
231
|
+
const navigation = PushMenu.elements.navigation as HTMLElement;
|
|
232
|
+
navigation?.click();
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
public static open(): void {
|
|
237
|
+
if (!this.elements.content?.classList.contains('pushed')) {
|
|
238
|
+
this.pushToggle();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public static close(): void {
|
|
243
|
+
if (this.elements.content?.classList.contains('pushed')) {
|
|
244
|
+
this.pushToggle();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
public static isOpen(): boolean {
|
|
249
|
+
return this.elements.content?.classList.contains('pushed') ?? false;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
public static destroy(): void {
|
|
253
|
+
if (!this.initialized) return;
|
|
254
|
+
|
|
255
|
+
this.elements.navigation?.removeEventListener('change', this.handleNavigationChange);
|
|
256
|
+
this.elements.content?.removeEventListener('click', this.clickNav);
|
|
257
|
+
this.elements.backdrop?.removeEventListener('click', this.handleBackdropClick);
|
|
258
|
+
|
|
259
|
+
this.close();
|
|
260
|
+
|
|
261
|
+
this.elements = {
|
|
262
|
+
navigation: null,
|
|
263
|
+
content: null,
|
|
264
|
+
menu: null,
|
|
265
|
+
header: null,
|
|
266
|
+
controlIcon: null,
|
|
267
|
+
backdrop: null
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
this.panelStack = [];
|
|
271
|
+
this.initialized = false;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
public static refresh(): void {
|
|
275
|
+
this.elements.navigation = document.querySelector('.navigation');
|
|
276
|
+
this.elements.content = document.querySelector('.push-content');
|
|
277
|
+
this.elements.menu = document.querySelector('.push-menu');
|
|
278
|
+
this.elements.header = document.querySelector('.main-header');
|
|
279
|
+
this.elements.controlIcon = document.querySelector('.navigation-controls .icon');
|
|
280
|
+
this.elements.backdrop = document.querySelector('.push-menu-backdrop');
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export { PushMenu, type PushMenuElements };
|