@dodlhuat/basix 1.2.8 → 1.2.9

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/js/scroll.ts DELETED
@@ -1,47 +0,0 @@
1
- interface ScrollOptions {
2
- behavior?: ScrollBehavior;
3
- offset?: number;
4
- block?: ScrollLogicalPosition;
5
- }
6
-
7
- class Scroll {
8
- public static to(target: string | Element, options: ScrollOptions = {}): void {
9
- const fixed_header = document.querySelector('.main-header') as HTMLElement | null;
10
- const offset = fixed_header ? fixed_header.offsetHeight : 0;
11
-
12
- const settings: Required<ScrollOptions> = {
13
- behavior: "smooth",
14
- offset: offset,
15
- block: "start",
16
- ...options
17
- };
18
-
19
- let el: Element | null = target instanceof Element ? target : null;
20
-
21
- if (typeof target === "string") {
22
- el = document.querySelector(target);
23
- }
24
-
25
- if (!el) return;
26
-
27
- const rect = el.getBoundingClientRect();
28
- const scrollTop = window.scrollY;
29
- const offsetTop = rect.top + scrollTop - settings.offset;
30
-
31
- window.scrollTo({
32
- top: offsetTop,
33
- behavior: settings.behavior
34
- });
35
- }
36
- }
37
-
38
- declare global {
39
- interface Window {
40
- Scroll: typeof Scroll;
41
- }
42
- }
43
-
44
- window.Scroll = Scroll;
45
-
46
- export { Scroll };
47
- export type { ScrollOptions };
package/js/scrollbar.ts DELETED
@@ -1,335 +0,0 @@
1
- interface ScrollbarElements {
2
- viewport: HTMLElement;
3
- content: HTMLElement;
4
- track: HTMLElement;
5
- thumb: HTMLElement;
6
- }
7
-
8
- class Scrollbar {
9
- private static readonly instances = new WeakMap<HTMLElement, Scrollbar>();
10
- private static activeInstance: Scrollbar | null = null;
11
- private static globalListenersInstalled = false;
12
- private static instanceCount = 0;
13
- private static globalListenerAbortController: AbortController | null = null;
14
-
15
- private readonly container!: HTMLElement;
16
- private readonly viewport!: HTMLElement;
17
- private readonly content!: HTMLElement;
18
- private readonly track!: HTMLElement;
19
- private readonly thumb!: HTMLElement;
20
- private readonly MIN_THUMB_HEIGHT!: number;
21
- private readonly ro!: ResizeObserver;
22
-
23
- private dragging = false;
24
- private activePointerId: number | null = null;
25
- private startPointerY = 0;
26
- private startThumbTop = 0;
27
-
28
- // Bound methods for event handling
29
- private readonly boundPointerMove!: (e: PointerEvent) => void;
30
- private readonly boundPointerUp!: (e: PointerEvent) => void;
31
- private readonly boundThumbPointerDown!: (e: PointerEvent) => void;
32
- private readonly boundTrackClick!: (e: MouseEvent) => void;
33
- private readonly boundViewportScroll!: () => void;
34
- private readonly boundUpdateThumb!: () => void;
35
- private readonly boundContainerWheel!: (e: WheelEvent) => void;
36
-
37
- private constructor(container: HTMLElement) {
38
- this.container = container;
39
-
40
- // Query and validate required elements
41
- const elements = this.getRequiredElements(container);
42
- this.viewport = elements.viewport;
43
- this.content = elements.content;
44
- this.track = elements.track;
45
- this.thumb = elements.thumb;
46
-
47
- // Get minimum thumb height from CSS variable or use default
48
- this.MIN_THUMB_HEIGHT = this.getMinThumbHeight();
49
-
50
- // Bind all event handlers once
51
- this.boundPointerMove = this.handlePointerMove.bind(this);
52
- this.boundPointerUp = this.handlePointerUp.bind(this);
53
- this.boundThumbPointerDown = this.handleThumbPointerDown.bind(this);
54
- this.boundTrackClick = this.handleTrackClick.bind(this);
55
- this.boundViewportScroll = this.updateThumb.bind(this);
56
- this.boundUpdateThumb = this.updateThumb.bind(this);
57
- this.boundContainerWheel = this.handleContainerWheel.bind(this);
58
-
59
- // Setup ResizeObserver
60
- this.ro = new ResizeObserver(this.boundUpdateThumb);
61
-
62
- // Initialize
63
- this.attachEventListeners();
64
- Scrollbar.instances.set(container, this);
65
-
66
- // Track instances and install global listeners once for all
67
- Scrollbar.instanceCount++;
68
- if (!Scrollbar.globalListenersInstalled) {
69
- Scrollbar.installGlobalListeners();
70
- }
71
-
72
- // Initial thumb update
73
- requestAnimationFrame(this.boundUpdateThumb);
74
- }
75
-
76
- private getRequiredElements(container: HTMLElement): ScrollbarElements {
77
- const viewport = container.querySelector<HTMLElement>('.viewport');
78
- const content = container.querySelector<HTMLElement>('.content');
79
- const track = container.querySelector<HTMLElement>('.track');
80
- const thumb = container.querySelector<HTMLElement>('.thumb');
81
-
82
- if (!viewport || !content || !track || !thumb) {
83
- throw new Error(
84
- 'Required scrollbar elements not found. Expected: .viewport, .content, .track, .thumb'
85
- );
86
- }
87
-
88
- return { viewport, content, track, thumb };
89
- }
90
-
91
- private getMinThumbHeight(): number {
92
- const cssValue = getComputedStyle(document.documentElement)
93
- .getPropertyValue('--thumb-min')
94
- .trim();
95
-
96
- const parsed = parseInt(cssValue, 10);
97
- const defaultMin = 28;
98
- const absoluteMin = 16;
99
-
100
- return Math.max(absoluteMin, parsed || defaultMin);
101
- }
102
-
103
- private static installGlobalListeners(): void {
104
- const ac = new AbortController();
105
- Scrollbar.globalListenerAbortController = ac;
106
-
107
- document.addEventListener('pointermove', (e: PointerEvent) => {
108
- Scrollbar.activeInstance?.boundPointerMove(e);
109
- }, { passive: false, signal: ac.signal });
110
-
111
- document.addEventListener('pointerup', (e: PointerEvent) => {
112
- Scrollbar.activeInstance?.boundPointerUp(e);
113
- }, { signal: ac.signal });
114
-
115
- document.addEventListener('pointercancel', (e: PointerEvent) => {
116
- Scrollbar.activeInstance?.boundPointerUp(e);
117
- }, { signal: ac.signal });
118
-
119
- Scrollbar.globalListenersInstalled = true;
120
- }
121
-
122
- private attachEventListeners(): void {
123
- // Instance-specific events
124
- this.viewport.addEventListener('scroll', this.boundViewportScroll, { passive: true });
125
- this.thumb.addEventListener('pointerdown', this.boundThumbPointerDown);
126
- this.track.addEventListener('click', this.boundTrackClick);
127
- this.container.addEventListener('wheel', this.boundContainerWheel, { passive: false });
128
-
129
- // Observe size changes
130
- this.ro.observe(this.viewport);
131
- this.ro.observe(this.content);
132
- window.addEventListener('resize', this.boundUpdateThumb);
133
- }
134
-
135
- private updateThumb(): void {
136
- const viewportHeight = this.viewport.clientHeight;
137
- const contentHeight = this.content.scrollHeight;
138
- const trackHeight = this.track.clientHeight;
139
-
140
- // Hide thumb if content fits in viewport
141
- if (contentHeight <= viewportHeight + 1) {
142
- this.thumb.style.display = 'none';
143
- return;
144
- }
145
-
146
- this.thumb.style.display = '';
147
-
148
- // Calculate thumb size
149
- const ratio = viewportHeight / contentHeight;
150
- const thumbHeight = Math.max(
151
- Math.floor(ratio * trackHeight),
152
- this.MIN_THUMB_HEIGHT
153
- );
154
- this.thumb.style.height = `${thumbHeight}px`;
155
-
156
- // Calculate thumb position
157
- const maxScroll = contentHeight - viewportHeight;
158
- const maxThumbTop = trackHeight - thumbHeight;
159
- const scrollRatio = this.viewport.scrollTop / (maxScroll || 1);
160
- const thumbTop = scrollRatio * (maxThumbTop || 0);
161
-
162
- this.thumb.style.top = `${thumbTop}px`;
163
- }
164
-
165
- private handleThumbPointerDown(e: PointerEvent): void {
166
- e.preventDefault();
167
-
168
- this.dragging = true;
169
- this.activePointerId = e.pointerId;
170
- Scrollbar.activeInstance = this;
171
-
172
- // Capture pointer for reliable tracking
173
- try {
174
- this.thumb.setPointerCapture(e.pointerId);
175
- } catch (err) {
176
- console.warn('Failed to capture pointer:', err);
177
- }
178
-
179
- this.startPointerY = e.clientY;
180
-
181
- const thumbRect = this.thumb.getBoundingClientRect();
182
- const trackRect = this.track.getBoundingClientRect();
183
- this.startThumbTop = thumbRect.top - trackRect.top;
184
-
185
- // Prevent text selection during drag
186
- document.body.style.userSelect = 'none';
187
- }
188
-
189
- private handlePointerMove(e: PointerEvent): void {
190
- // Only handle events for the active pointer
191
- if (!this.dragging || this.activePointerId !== e.pointerId) {
192
- return;
193
- }
194
-
195
- e.preventDefault();
196
-
197
- const pointerDelta = e.clientY - this.startPointerY;
198
- const trackHeight = this.track.clientHeight;
199
- const thumbHeight = this.thumb.clientHeight;
200
- const maxThumbTop = trackHeight - thumbHeight;
201
-
202
- // Calculate new thumb position
203
- const newThumbTop = Math.max(
204
- 0,
205
- Math.min(maxThumbTop, this.startThumbTop + pointerDelta)
206
- );
207
- this.thumb.style.top = `${newThumbTop}px`;
208
-
209
- // Update viewport scroll position
210
- const contentHeight = this.content.scrollHeight;
211
- const viewportHeight = this.viewport.clientHeight;
212
- const maxScroll = contentHeight - viewportHeight;
213
- const scrollRatio = newThumbTop / (maxThumbTop || 1);
214
-
215
- this.viewport.scrollTop = scrollRatio * (maxScroll || 0);
216
- }
217
-
218
- private handlePointerUp(e: PointerEvent): void {
219
- if (!this.dragging || this.activePointerId !== e.pointerId) {
220
- return;
221
- }
222
-
223
- this.dragging = false;
224
-
225
- // Release pointer capture
226
- try {
227
- this.thumb.releasePointerCapture(e.pointerId);
228
- } catch (err) {
229
- console.warn('Failed to release pointer:', err);
230
- }
231
-
232
- this.activePointerId = null;
233
- Scrollbar.activeInstance = null;
234
- document.body.style.userSelect = '';
235
- }
236
-
237
- private handleTrackClick(e: MouseEvent): void {
238
- // Ignore clicks directly on the thumb
239
- if (e.target === this.thumb) {
240
- return;
241
- }
242
-
243
- const trackRect = this.track.getBoundingClientRect();
244
- const clickY = e.clientY - trackRect.top;
245
- const thumbHeight = this.thumb.clientHeight;
246
- const trackHeight = this.track.clientHeight;
247
-
248
- // Center thumb on click position
249
- const targetThumbTop = clickY - thumbHeight / 2;
250
- const maxThumbTop = trackHeight - thumbHeight;
251
- const clampedThumbTop = Math.max(0, Math.min(maxThumbTop, targetThumbTop));
252
-
253
- // Calculate corresponding scroll position
254
- const contentHeight = this.content.scrollHeight;
255
- const viewportHeight = this.viewport.clientHeight;
256
- const maxScroll = contentHeight - viewportHeight;
257
- const scrollRatio = clampedThumbTop / (maxThumbTop || 1);
258
- const scrollTop = scrollRatio * (maxScroll || 0);
259
-
260
- this.viewport.scrollTo({ top: scrollTop, behavior: 'smooth' });
261
- }
262
-
263
- private handleContainerWheel(e: WheelEvent): void {
264
- const { scrollTop, scrollHeight, clientHeight } = this.viewport;
265
- const scrollable = scrollHeight > clientHeight;
266
- const atTop = scrollTop === 0 && e.deltaY < 0;
267
- const atBottom = scrollTop + clientHeight >= scrollHeight - 1 && e.deltaY > 0;
268
-
269
- if (scrollable && !atTop && !atBottom) {
270
- e.preventDefault();
271
- }
272
-
273
- this.viewport.scrollTop += e.deltaY;
274
- }
275
-
276
- public destroy(): void {
277
- // Remove event listeners
278
- this.viewport.removeEventListener('scroll', this.boundViewportScroll);
279
- this.thumb.removeEventListener('pointerdown', this.boundThumbPointerDown);
280
- this.track.removeEventListener('click', this.boundTrackClick);
281
- this.container.removeEventListener('wheel', this.boundContainerWheel);
282
- window.removeEventListener('resize', this.boundUpdateThumb);
283
-
284
- // Disconnect observer
285
- this.ro.disconnect();
286
-
287
- // Clear from instances map
288
- Scrollbar.instances.delete(this.container);
289
-
290
- // Clear active instance if this was it
291
- if (Scrollbar.activeInstance === this) {
292
- Scrollbar.activeInstance = null;
293
- }
294
-
295
- // Uninstall global listeners when last instance is destroyed
296
- Scrollbar.instanceCount--;
297
- if (Scrollbar.instanceCount === 0) {
298
- Scrollbar.globalListenerAbortController?.abort();
299
- Scrollbar.globalListenerAbortController = null;
300
- Scrollbar.globalListenersInstalled = false;
301
- }
302
- }
303
-
304
- // Static factory methods
305
- public static create(elementOrSelector: string | HTMLElement): Scrollbar {
306
- const container = typeof elementOrSelector === 'string'
307
- ? document.querySelector<HTMLElement>(elementOrSelector)
308
- : elementOrSelector;
309
-
310
- if (!container) {
311
- throw new Error(`Scrollbar: Element not found for selector "${elementOrSelector}"`);
312
- }
313
-
314
- const existing = Scrollbar.instances.get(container);
315
- if (existing) return existing;
316
-
317
- return new Scrollbar(container);
318
- }
319
-
320
- public static initAll(selector: string): Scrollbar[] {
321
- const containers = document.querySelectorAll<HTMLElement>(selector);
322
- return Array.from(containers).map(container => Scrollbar.create(container));
323
- }
324
-
325
- public static initOne(elementOrSelector: string | HTMLElement): Scrollbar {
326
- return Scrollbar.create(elementOrSelector);
327
- }
328
-
329
- public static getInstance(container: HTMLElement): Scrollbar | undefined {
330
- return Scrollbar.instances.get(container);
331
- }
332
-
333
- }
334
-
335
- export { Scrollbar, ScrollbarElements };
package/js/select.ts DELETED
@@ -1,235 +0,0 @@
1
- class Select {
2
- private readonly element: HTMLSelectElement;
3
- private readonly isMultiselect: boolean;
4
- private readonly dropdown: HTMLElement | null;
5
- private readonly documentClickHandler: (e: Event) => void;
6
-
7
- constructor(elementOrSelector: string | HTMLSelectElement) {
8
- const element = typeof elementOrSelector === 'string'
9
- ? document.querySelector<HTMLSelectElement>(elementOrSelector)
10
- : elementOrSelector;
11
-
12
- if (!element) {
13
- throw new Error(`Select: Element not found for selector "${elementOrSelector}"`);
14
- }
15
-
16
- this.element = element;
17
- const result = Select.initElement(element);
18
-
19
- if (result === null) {
20
- throw new Error(`Select: Failed to initialize select for "${elementOrSelector}"`);
21
- }
22
-
23
- this.isMultiselect = result.isMulti;
24
- this.dropdown = result.dropdown;
25
-
26
- this.documentClickHandler = (e: Event) => {
27
- if (this.dropdown && !this.dropdown.contains(e.target as Node)) {
28
- this.dropdown.classList.remove('open');
29
- }
30
- };
31
- document.addEventListener('click', this.documentClickHandler);
32
- }
33
-
34
- public destroy(): void {
35
- document.removeEventListener('click', this.documentClickHandler);
36
- this.dropdown?.classList.remove('open');
37
- }
38
-
39
- public value(): string | string[] | undefined {
40
- if (!this.element) {
41
- return undefined;
42
- }
43
-
44
- const selectedValues = Array.from(this.element.options)
45
- .filter(option => option.selected)
46
- .map(option => option.value);
47
-
48
- return this.isMultiselect ? selectedValues : selectedValues[0];
49
- }
50
-
51
- public static init(elementOrSelector: string | HTMLSelectElement): boolean | null {
52
- const element = typeof elementOrSelector === 'string'
53
- ? document.querySelector<HTMLSelectElement>(elementOrSelector)
54
- : elementOrSelector;
55
-
56
- if (!element) {
57
- return null;
58
- }
59
-
60
- const result = Select.initElement(element);
61
- if (!result) return null;
62
-
63
- // Static init path: add document listener without lifecycle management
64
- document.addEventListener('click', (e: Event) => {
65
- if (!result.dropdown.contains(e.target as Node)) {
66
- result.dropdown.classList.remove('open');
67
- }
68
- });
69
-
70
- return result.isMulti;
71
- }
72
-
73
- private static initElement(element: HTMLSelectElement): { isMulti: boolean; dropdown: HTMLElement } | null {
74
- if (!Select.transformSelect(element)) {
75
- return null;
76
- }
77
-
78
- const selectGroup = element.closest('.select-group');
79
- if (!selectGroup) {
80
- throw new Error(`Select: Parent .select-group not found for "${element}"`);
81
- }
82
-
83
- const dropdown = selectGroup.querySelector('.dropdown') as HTMLElement | null;
84
- if (!dropdown) {
85
- throw new Error(`Select: Dropdown element not found for "${element}"`);
86
- }
87
-
88
- const selected = dropdown.querySelector('.dropdown-selected') as HTMLElement | null;
89
- const options = dropdown.querySelector('.dropdown-options') as HTMLElement | null;
90
-
91
- if (!selected || !options) {
92
- throw new Error(`Select: Required dropdown elements not found for "${element}"`);
93
- }
94
-
95
- const isMulti = dropdown.dataset.multi === 'true';
96
-
97
- // Toggle dropdown on selected element click
98
- selected.addEventListener('click', () => {
99
- Select.closeAllDropdowns(dropdown);
100
- dropdown.classList.toggle('open');
101
- });
102
-
103
- // Handle option selection
104
- options.addEventListener('click', (e: Event) => {
105
- const target = e.target as HTMLElement;
106
-
107
- if (!target.classList.contains('dropdown-option')) {
108
- return;
109
- }
110
-
111
- if (isMulti) {
112
- Select.handleMultiSelect(target, options, selected, element);
113
- } else {
114
- Select.handleSingleSelect(target, options, selected, dropdown, element);
115
- }
116
- });
117
-
118
- // Close dropdown when clicking the close icon
119
- const closeIcon = options.querySelector('.dropdown-options-icon') as HTMLElement | null;
120
- if (closeIcon) {
121
- closeIcon.addEventListener('click', () => {
122
- dropdown.classList.remove('open');
123
- });
124
- }
125
-
126
- return { isMulti, dropdown };
127
- }
128
-
129
- private static closeAllDropdowns(exceptDropdown?: HTMLElement): void {
130
- document.querySelectorAll('.dropdown').forEach(dropdown => {
131
- if (dropdown !== exceptDropdown) {
132
- dropdown.classList.remove('open');
133
- }
134
- });
135
- }
136
-
137
- private static handleMultiSelect(
138
- option: HTMLElement,
139
- optionsContainer: HTMLElement,
140
- selected: HTMLElement,
141
- selectElement: HTMLSelectElement
142
- ): void {
143
- option.classList.toggle('selected');
144
-
145
- const selectedOptions = Array.from(
146
- optionsContainer.querySelectorAll('.dropdown-option.selected')
147
- ) as HTMLElement[];
148
-
149
- const values = selectedOptions.map(opt => opt.textContent?.trim() || '');
150
- selected.textContent = values.length ? values.join(', ') : 'Select options';
151
-
152
- const selectedValues = selectedOptions.map(opt => opt.dataset.value || '');
153
- Array.from(selectElement.options).forEach(opt => {
154
- opt.selected = selectedValues.includes(opt.value);
155
- });
156
- }
157
-
158
- private static handleSingleSelect(
159
- option: HTMLElement,
160
- optionsContainer: HTMLElement,
161
- selected: HTMLElement,
162
- dropdown: HTMLElement,
163
- selectElement: HTMLSelectElement
164
- ): void {
165
- optionsContainer.querySelectorAll('.dropdown-option').forEach(opt => {
166
- opt.classList.remove('selected');
167
- });
168
-
169
- option.classList.add('selected');
170
- selected.textContent = option.textContent?.trim() || '';
171
- dropdown.classList.remove('open');
172
- selectElement.value = option.dataset.value || '';
173
- }
174
-
175
- private static transformSelect(select: HTMLSelectElement): boolean {
176
- const parent = select.closest('.select-group') as HTMLElement | null;
177
-
178
- if (!parent) {
179
- return false;
180
- }
181
-
182
- const label = parent.querySelector('label');
183
- const isMulti = select.hasAttribute('multiple');
184
- const labelText = label?.textContent?.trim() || 'Select';
185
-
186
- // Create hidden wrapper for original select
187
- const hiddenWrapper = document.createElement('div');
188
- hiddenWrapper.classList.add('hidden');
189
-
190
- if (label) {
191
- hiddenWrapper.appendChild(label);
192
- }
193
- hiddenWrapper.appendChild(select);
194
-
195
- // Create dropdown structure
196
- const dropdown = document.createElement('div');
197
- dropdown.className = 'dropdown';
198
- dropdown.dataset.multi = String(isMulti);
199
-
200
- const dropdownSelected = document.createElement('div');
201
- dropdownSelected.className = 'dropdown-selected';
202
- dropdownSelected.textContent = labelText;
203
-
204
- const dropdownOptions = document.createElement('div');
205
- dropdownOptions.className = 'dropdown-options';
206
-
207
- // Add mobile menu
208
- const optionsMenu = document.createElement('div');
209
- optionsMenu.className = 'dropdown-options-menu hidden';
210
- optionsMenu.innerHTML = 'Select options<span class="dropdown-options-icon icon icon-close"></span>';
211
- dropdownOptions.appendChild(optionsMenu);
212
-
213
- // Create option elements
214
- Array.from(select.options).forEach(opt => {
215
- const optDiv = document.createElement('div');
216
- optDiv.className = 'dropdown-option';
217
- optDiv.dataset.value = opt.value;
218
- optDiv.textContent = opt.textContent;
219
- dropdownOptions.appendChild(optDiv);
220
- });
221
-
222
- // Assemble dropdown
223
- dropdown.appendChild(dropdownSelected);
224
- dropdown.appendChild(dropdownOptions);
225
-
226
- // Replace original content
227
- parent.innerHTML = '';
228
- parent.appendChild(hiddenWrapper);
229
- parent.appendChild(dropdown);
230
-
231
- return true;
232
- }
233
- }
234
-
235
- export { Select };
package/js/sidebar-nav.ts DELETED
@@ -1,66 +0,0 @@
1
- interface SidebarNavOptions {
2
- /** Selector for the toggle button. Default: '.sidebar-toggle' */
3
- toggleSelector?: string;
4
- /** Breakpoint (px) above which the sidebar is always visible. Default: 768 */
5
- breakpoint?: number;
6
- }
7
-
8
- class SidebarNav {
9
- private nav: HTMLElement | null;
10
- private backdrop: HTMLElement | null;
11
- private toggleBtn: HTMLElement | null;
12
- private opts: Required<SidebarNavOptions>;
13
- private _onToggle: () => void;
14
- private _onBackdrop: () => void;
15
- private _onResize: () => void;
16
-
17
- constructor(containerOrSelector: string | HTMLElement, options: SidebarNavOptions = {}) {
18
- const container: HTMLElement | null =
19
- typeof containerOrSelector === 'string'
20
- ? (document.querySelector(containerOrSelector) as HTMLElement | null)
21
- : containerOrSelector;
22
-
23
- this.opts = {
24
- toggleSelector: options.toggleSelector ?? '.sidebar-toggle',
25
- breakpoint: options.breakpoint ?? 768,
26
- };
27
-
28
- this.nav = container?.querySelector('.sidebar-nav') ?? null;
29
- this.backdrop = container?.querySelector('.sidebar-backdrop') ?? null;
30
- this.toggleBtn = document.querySelector(this.opts.toggleSelector);
31
-
32
- this._onToggle = () => this.toggle();
33
- this._onBackdrop = () => this.close();
34
- this._onResize = () => { if (window.innerWidth > this.opts.breakpoint) this.close(); };
35
-
36
- this.toggleBtn?.addEventListener('click', this._onToggle);
37
- this.backdrop?.addEventListener('click', this._onBackdrop);
38
- window.addEventListener('resize', this._onResize);
39
- }
40
-
41
- open(): void {
42
- this.nav?.classList.add('is-open');
43
- this.backdrop?.classList.add('is-visible');
44
- }
45
-
46
- close(): void {
47
- this.nav?.classList.remove('is-open');
48
- this.backdrop?.classList.remove('is-visible');
49
- }
50
-
51
- toggle(): void {
52
- this.nav?.classList.contains('is-open') ? this.close() : this.open();
53
- }
54
-
55
- isOpen(): boolean {
56
- return this.nav?.classList.contains('is-open') ?? false;
57
- }
58
-
59
- destroy(): void {
60
- this.toggleBtn?.removeEventListener('click', this._onToggle);
61
- this.backdrop?.removeEventListener('click', this._onBackdrop);
62
- window.removeEventListener('resize', this._onResize);
63
- }
64
- }
65
-
66
- export { SidebarNav, SidebarNavOptions };