@hortonstudio/main 1.8.1 → 1.9.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/autoInit/accessibility.js +157 -101
- package/autoInit/counter.js +17 -1
- package/autoInit/form.js +58 -13
- package/autoInit/navbar.js +136 -77
- package/autoInit/smooth-scroll.js +33 -10
- package/autoInit/transition.js +88 -62
- package/index.js +18 -9
- package/package.json +1 -1
- package/utils/slider.js +58 -19
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
export function init() {
|
|
2
|
-
|
|
2
|
+
// Centralized cleanup tracking
|
|
3
|
+
const cleanup = {
|
|
4
|
+
observers: [],
|
|
5
|
+
handlers: [],
|
|
6
|
+
scrollTimeout: null
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const addObserver = (observer) => cleanup.observers.push(observer);
|
|
10
|
+
const addHandler = (element, event, handler, options) => {
|
|
11
|
+
element.addEventListener(event, handler, options);
|
|
12
|
+
cleanup.handlers.push({ element, event, handler, options });
|
|
13
|
+
};
|
|
3
14
|
|
|
4
15
|
function setupGeneralAccessibility() {
|
|
5
16
|
setupListAccessibility();
|
|
6
17
|
setupRemoveListAccessibility();
|
|
7
|
-
setupFAQAccessibility();
|
|
18
|
+
setupFAQAccessibility(addHandler);
|
|
8
19
|
setupConvertToSpan();
|
|
9
20
|
setupYearReplacement();
|
|
10
|
-
setupPreventDefault();
|
|
11
|
-
setupRichTextAccessibility();
|
|
12
|
-
setupSummaryAccessibility();
|
|
21
|
+
setupPreventDefault(addHandler);
|
|
22
|
+
setupRichTextAccessibility(addObserver, addHandler, cleanup);
|
|
23
|
+
setupSummaryAccessibility(addHandler);
|
|
13
24
|
setupCustomValuesReplacement();
|
|
14
|
-
setupClickForwarding();
|
|
15
|
-
setupTextSynchronization();
|
|
25
|
+
setupClickForwarding(addHandler);
|
|
26
|
+
setupTextSynchronization(addObserver);
|
|
16
27
|
}
|
|
17
28
|
|
|
18
29
|
function setupListAccessibility() {
|
|
@@ -88,36 +99,35 @@ export function init() {
|
|
|
88
99
|
});
|
|
89
100
|
}
|
|
90
101
|
|
|
91
|
-
function setupFAQAccessibility() {
|
|
102
|
+
function setupFAQAccessibility(addHandler) {
|
|
92
103
|
const faqContainers = document.querySelectorAll('[data-hs-a11y="faq-wrap"]');
|
|
93
104
|
|
|
94
105
|
faqContainers.forEach((container, index) => {
|
|
95
106
|
const button = container.querySelector('[data-hs-a11y="faq-btn"]');
|
|
96
107
|
const contentWrapper = container.querySelector('[data-hs-a11y="faq-content"]');
|
|
97
|
-
|
|
108
|
+
|
|
98
109
|
if (!button || !contentWrapper) return;
|
|
99
|
-
|
|
110
|
+
|
|
100
111
|
const buttonId = `faq-button-${index}`;
|
|
101
112
|
const contentId = `faq-content-${index}`;
|
|
102
|
-
|
|
113
|
+
|
|
103
114
|
button.setAttribute('id', buttonId);
|
|
104
115
|
button.setAttribute('aria-expanded', 'false');
|
|
105
116
|
button.setAttribute('aria-controls', contentId);
|
|
106
|
-
|
|
117
|
+
|
|
107
118
|
contentWrapper.setAttribute('id', contentId);
|
|
108
119
|
contentWrapper.setAttribute('aria-hidden', 'true');
|
|
109
120
|
contentWrapper.setAttribute('role', 'region');
|
|
110
121
|
contentWrapper.setAttribute('aria-labelledby', buttonId);
|
|
111
|
-
|
|
122
|
+
|
|
112
123
|
function toggleFAQ() {
|
|
113
124
|
const isOpen = button.getAttribute('aria-expanded') === 'true';
|
|
114
|
-
|
|
125
|
+
|
|
115
126
|
button.setAttribute('aria-expanded', !isOpen);
|
|
116
127
|
contentWrapper.setAttribute('aria-hidden', isOpen);
|
|
117
128
|
}
|
|
118
|
-
|
|
119
|
-
button
|
|
120
|
-
|
|
129
|
+
|
|
130
|
+
addHandler(button, 'click', toggleFAQ);
|
|
121
131
|
});
|
|
122
132
|
}
|
|
123
133
|
|
|
@@ -216,26 +226,28 @@ export function init() {
|
|
|
216
226
|
});
|
|
217
227
|
}
|
|
218
228
|
|
|
219
|
-
function setupPreventDefault() {
|
|
229
|
+
function setupPreventDefault(addHandler) {
|
|
220
230
|
const elements = document.querySelectorAll('[data-hs-a11y="prevent-default"]');
|
|
221
|
-
|
|
231
|
+
|
|
222
232
|
elements.forEach(element => {
|
|
223
233
|
// Prevent click
|
|
224
|
-
|
|
234
|
+
const clickHandler = (e) => {
|
|
225
235
|
e.preventDefault();
|
|
226
236
|
e.stopPropagation();
|
|
227
237
|
return false;
|
|
228
|
-
}
|
|
229
|
-
|
|
238
|
+
};
|
|
239
|
+
addHandler(element, 'click', clickHandler);
|
|
240
|
+
|
|
230
241
|
// Prevent keyboard activation
|
|
231
|
-
|
|
242
|
+
const keydownHandler = (e) => {
|
|
232
243
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
233
244
|
e.preventDefault();
|
|
234
245
|
e.stopPropagation();
|
|
235
246
|
return false;
|
|
236
247
|
}
|
|
237
|
-
}
|
|
238
|
-
|
|
248
|
+
};
|
|
249
|
+
addHandler(element, 'keydown', keydownHandler);
|
|
250
|
+
|
|
239
251
|
// Additional prevention for anchor links
|
|
240
252
|
if (element.tagName.toLowerCase() === 'a') {
|
|
241
253
|
// Remove or modify href to prevent scroll
|
|
@@ -247,27 +259,23 @@ export function init() {
|
|
|
247
259
|
element.setAttribute('tabindex', '0');
|
|
248
260
|
}
|
|
249
261
|
}
|
|
250
|
-
|
|
251
262
|
});
|
|
252
263
|
}
|
|
253
264
|
|
|
254
|
-
function setupSummaryAccessibility() {
|
|
265
|
+
function setupSummaryAccessibility(addHandler) {
|
|
255
266
|
const summaryContainers = document.querySelectorAll('[data-hs-a11y="summary-wrap"]');
|
|
256
267
|
|
|
257
|
-
|
|
258
268
|
summaryContainers.forEach((container, index) => {
|
|
259
|
-
|
|
260
269
|
const button = container.querySelector('[data-hs-a11y="summary-btn"]');
|
|
261
270
|
const contentWrapper = container.querySelector('[data-hs-a11y="summary-content"]');
|
|
262
|
-
|
|
271
|
+
|
|
263
272
|
if (!button || !contentWrapper) {
|
|
264
273
|
return;
|
|
265
274
|
}
|
|
266
|
-
|
|
267
|
-
|
|
275
|
+
|
|
268
276
|
const buttonId = `summary-button-${index}`;
|
|
269
277
|
const contentId = `summary-content-${index}`;
|
|
270
|
-
|
|
278
|
+
|
|
271
279
|
// Get original button text from first text node only
|
|
272
280
|
const walker = document.createTreeWalker(
|
|
273
281
|
button,
|
|
@@ -275,14 +283,14 @@ export function init() {
|
|
|
275
283
|
null,
|
|
276
284
|
false
|
|
277
285
|
);
|
|
278
|
-
|
|
286
|
+
|
|
279
287
|
let firstTextNode = walker.nextNode();
|
|
280
288
|
while (firstTextNode && !firstTextNode.textContent.trim()) {
|
|
281
289
|
firstTextNode = walker.nextNode();
|
|
282
290
|
}
|
|
283
|
-
|
|
291
|
+
|
|
284
292
|
const originalButtonText = firstTextNode ? firstTextNode.textContent.trim() : button.textContent.trim();
|
|
285
|
-
|
|
293
|
+
|
|
286
294
|
// Function to update all text nodes in button
|
|
287
295
|
function updateButtonText(newText) {
|
|
288
296
|
// Find all text nodes and update them
|
|
@@ -292,7 +300,7 @@ export function init() {
|
|
|
292
300
|
null,
|
|
293
301
|
false
|
|
294
302
|
);
|
|
295
|
-
|
|
303
|
+
|
|
296
304
|
const textNodes = [];
|
|
297
305
|
let node;
|
|
298
306
|
while (node = walker.nextNode()) {
|
|
@@ -300,27 +308,27 @@ export function init() {
|
|
|
300
308
|
textNodes.push(node);
|
|
301
309
|
}
|
|
302
310
|
}
|
|
303
|
-
|
|
311
|
+
|
|
304
312
|
textNodes.forEach(textNode => {
|
|
305
313
|
textNode.textContent = newText;
|
|
306
314
|
});
|
|
307
315
|
}
|
|
308
|
-
|
|
316
|
+
|
|
309
317
|
button.setAttribute('id', buttonId);
|
|
310
318
|
button.setAttribute('aria-expanded', 'false');
|
|
311
319
|
button.setAttribute('aria-controls', contentId);
|
|
312
320
|
button.setAttribute('aria-label', 'View Summary');
|
|
313
|
-
|
|
321
|
+
|
|
314
322
|
contentWrapper.setAttribute('id', contentId);
|
|
315
323
|
contentWrapper.setAttribute('aria-hidden', 'true');
|
|
316
324
|
contentWrapper.setAttribute('role', 'region');
|
|
317
325
|
contentWrapper.setAttribute('aria-labelledby', buttonId);
|
|
318
|
-
|
|
326
|
+
|
|
319
327
|
// Summary is closed by default - no need to check initial state
|
|
320
|
-
|
|
328
|
+
|
|
321
329
|
function toggleSummary() {
|
|
322
330
|
const isOpen = button.getAttribute('aria-expanded') === 'true';
|
|
323
|
-
|
|
331
|
+
|
|
324
332
|
if (isOpen) {
|
|
325
333
|
// Closing
|
|
326
334
|
button.setAttribute('aria-expanded', 'false');
|
|
@@ -334,11 +342,9 @@ export function init() {
|
|
|
334
342
|
updateButtonText('Close');
|
|
335
343
|
contentWrapper.setAttribute('aria-hidden', 'false');
|
|
336
344
|
}
|
|
337
|
-
|
|
338
345
|
}
|
|
339
|
-
|
|
340
|
-
button
|
|
341
|
-
|
|
346
|
+
|
|
347
|
+
addHandler(button, 'click', toggleSummary);
|
|
342
348
|
});
|
|
343
349
|
}
|
|
344
350
|
|
|
@@ -434,54 +440,56 @@ export function init() {
|
|
|
434
440
|
});
|
|
435
441
|
}
|
|
436
442
|
|
|
437
|
-
function setupClickForwarding() {
|
|
443
|
+
function setupClickForwarding(addHandler) {
|
|
438
444
|
// Find all clickable elements (custom styled elements users click)
|
|
439
445
|
const clickableElements = document.querySelectorAll('[data-hs-a11y*="clickable"]');
|
|
440
|
-
|
|
446
|
+
|
|
441
447
|
clickableElements.forEach(clickableElement => {
|
|
442
448
|
const attribute = clickableElement.getAttribute('data-hs-a11y');
|
|
443
|
-
|
|
449
|
+
|
|
444
450
|
// Parse the attribute: "click-trigger-[identifier], clickable"
|
|
445
451
|
const parts = attribute.split(',').map(part => part.trim());
|
|
446
|
-
|
|
452
|
+
|
|
447
453
|
// Find the part with click-trigger and the part with clickable
|
|
448
454
|
const triggerPart = parts.find(part => part.startsWith('click-trigger-'));
|
|
449
455
|
const rolePart = parts.find(part => part === 'clickable');
|
|
450
|
-
|
|
456
|
+
|
|
451
457
|
if (!triggerPart || !rolePart) {
|
|
452
458
|
return;
|
|
453
459
|
}
|
|
454
|
-
|
|
460
|
+
|
|
455
461
|
// Extract identifier from "click-trigger-[identifier]"
|
|
456
462
|
const identifier = triggerPart.replace('click-trigger-', '').trim();
|
|
457
|
-
|
|
463
|
+
|
|
458
464
|
// Find the corresponding trigger element
|
|
459
465
|
const triggerSelector = `[data-hs-a11y*="click-trigger-${identifier}"][data-hs-a11y*="trigger"]`;
|
|
460
466
|
const triggerElement = document.querySelector(triggerSelector);
|
|
461
|
-
|
|
467
|
+
|
|
462
468
|
if (!triggerElement) {
|
|
463
469
|
return;
|
|
464
470
|
}
|
|
465
|
-
|
|
471
|
+
|
|
466
472
|
// Add click event listener to forward clicks
|
|
467
|
-
|
|
473
|
+
const clickHandler = (event) => {
|
|
468
474
|
// Prevent default behavior on the clickable element
|
|
469
475
|
event.preventDefault();
|
|
470
476
|
event.stopPropagation();
|
|
471
|
-
|
|
477
|
+
|
|
472
478
|
// Trigger click on the target element
|
|
473
479
|
triggerElement.click();
|
|
474
|
-
}
|
|
475
|
-
|
|
480
|
+
};
|
|
481
|
+
addHandler(clickableElement, 'click', clickHandler);
|
|
482
|
+
|
|
476
483
|
// Also handle keyboard events for accessibility
|
|
477
|
-
|
|
484
|
+
const keydownHandler = (event) => {
|
|
478
485
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
479
486
|
event.preventDefault();
|
|
480
487
|
event.stopPropagation();
|
|
481
488
|
triggerElement.click();
|
|
482
489
|
}
|
|
483
|
-
}
|
|
484
|
-
|
|
490
|
+
};
|
|
491
|
+
addHandler(clickableElement, 'keydown', keydownHandler);
|
|
492
|
+
|
|
485
493
|
// Ensure clickable element is keyboard accessible
|
|
486
494
|
if (!clickableElement.hasAttribute('tabindex')) {
|
|
487
495
|
clickableElement.setAttribute('tabindex', '0');
|
|
@@ -492,44 +500,44 @@ export function init() {
|
|
|
492
500
|
});
|
|
493
501
|
}
|
|
494
502
|
|
|
495
|
-
function setupTextSynchronization() {
|
|
503
|
+
function setupTextSynchronization(addObserver) {
|
|
496
504
|
// Find all original elements (source of truth)
|
|
497
505
|
const originalElements = document.querySelectorAll('[data-hs-a11y*="original"]');
|
|
498
|
-
|
|
506
|
+
|
|
499
507
|
originalElements.forEach(originalElement => {
|
|
500
508
|
const attribute = originalElement.getAttribute('data-hs-a11y');
|
|
501
|
-
|
|
509
|
+
|
|
502
510
|
// Parse the attribute: "match-text-[identifier], original"
|
|
503
511
|
const parts = attribute.split(',').map(part => part.trim());
|
|
504
|
-
|
|
512
|
+
|
|
505
513
|
// Find the part with match-text and the part with original
|
|
506
514
|
const textPart = parts.find(part => part.startsWith('match-text-'));
|
|
507
515
|
const rolePart = parts.find(part => part === 'original');
|
|
508
|
-
|
|
516
|
+
|
|
509
517
|
if (!textPart || !rolePart) {
|
|
510
518
|
return;
|
|
511
519
|
}
|
|
512
|
-
|
|
520
|
+
|
|
513
521
|
// Extract identifier from "match-text-[identifier]"
|
|
514
522
|
const identifier = textPart.replace('match-text-', '').trim();
|
|
515
|
-
|
|
523
|
+
|
|
516
524
|
// Find all corresponding match elements
|
|
517
525
|
const matchSelector = `[data-hs-a11y*="match-text-${identifier}"][data-hs-a11y*="match"]`;
|
|
518
526
|
const matchElements = document.querySelectorAll(matchSelector);
|
|
519
|
-
|
|
527
|
+
|
|
520
528
|
if (matchElements.length === 0) {
|
|
521
529
|
return;
|
|
522
530
|
}
|
|
523
|
-
|
|
531
|
+
|
|
524
532
|
// Function to synchronize text and aria-label
|
|
525
533
|
function synchronizeContent() {
|
|
526
534
|
const originalText = originalElement.textContent;
|
|
527
535
|
const originalAriaLabel = originalElement.getAttribute('aria-label');
|
|
528
|
-
|
|
536
|
+
|
|
529
537
|
matchElements.forEach(matchElement => {
|
|
530
538
|
// Copy text content
|
|
531
539
|
matchElement.textContent = originalText;
|
|
532
|
-
|
|
540
|
+
|
|
533
541
|
// Synchronize aria-label
|
|
534
542
|
if (originalAriaLabel) {
|
|
535
543
|
// If original has aria-label, copy it to match
|
|
@@ -542,27 +550,27 @@ export function init() {
|
|
|
542
550
|
}
|
|
543
551
|
});
|
|
544
552
|
}
|
|
545
|
-
|
|
553
|
+
|
|
546
554
|
// Initial synchronization
|
|
547
555
|
synchronizeContent();
|
|
548
|
-
|
|
556
|
+
|
|
549
557
|
// Set up MutationObserver to watch for changes
|
|
550
558
|
const observer = new MutationObserver((mutations) => {
|
|
551
559
|
let shouldSync = false;
|
|
552
|
-
|
|
560
|
+
|
|
553
561
|
mutations.forEach((mutation) => {
|
|
554
|
-
if (mutation.type === 'childList' ||
|
|
555
|
-
mutation.type === 'characterData' ||
|
|
562
|
+
if (mutation.type === 'childList' ||
|
|
563
|
+
mutation.type === 'characterData' ||
|
|
556
564
|
(mutation.type === 'attributes' && mutation.attributeName === 'aria-label')) {
|
|
557
565
|
shouldSync = true;
|
|
558
566
|
}
|
|
559
567
|
});
|
|
560
|
-
|
|
568
|
+
|
|
561
569
|
if (shouldSync) {
|
|
562
570
|
synchronizeContent();
|
|
563
571
|
}
|
|
564
572
|
});
|
|
565
|
-
|
|
573
|
+
|
|
566
574
|
// Observe text changes and attribute changes
|
|
567
575
|
observer.observe(originalElement, {
|
|
568
576
|
childList: true,
|
|
@@ -571,16 +579,16 @@ export function init() {
|
|
|
571
579
|
attributes: true,
|
|
572
580
|
attributeFilter: ['aria-label']
|
|
573
581
|
});
|
|
582
|
+
|
|
583
|
+
addObserver(observer);
|
|
574
584
|
});
|
|
575
585
|
}
|
|
576
586
|
|
|
577
|
-
function setupRichTextAccessibility() {
|
|
587
|
+
function setupRichTextAccessibility(addObserver, addHandler, cleanup) {
|
|
578
588
|
const contentAreas = document.querySelectorAll('[data-hs-a11y="rich-content"]');
|
|
579
589
|
const tocLists = document.querySelectorAll('[data-hs-a11y="rich-toc"]');
|
|
580
590
|
|
|
581
|
-
|
|
582
591
|
contentAreas.forEach((contentArea) => {
|
|
583
|
-
|
|
584
592
|
// Since there's only 1 content area and 1 TOC list per page, use the first TOC list
|
|
585
593
|
const tocList = tocLists[0];
|
|
586
594
|
|
|
@@ -592,7 +600,6 @@ export function init() {
|
|
|
592
600
|
return;
|
|
593
601
|
}
|
|
594
602
|
|
|
595
|
-
|
|
596
603
|
const template = tocList.children[0].cloneNode(true);
|
|
597
604
|
// Remove is-active class from template if it exists
|
|
598
605
|
const templateLink = template.querySelector("a");
|
|
@@ -643,7 +650,7 @@ export function init() {
|
|
|
643
650
|
link.appendChild(document.createTextNode(heading.textContent));
|
|
644
651
|
|
|
645
652
|
// Add click handler for smooth scrolling
|
|
646
|
-
|
|
653
|
+
const clickHandler = (e) => {
|
|
647
654
|
e.preventDefault();
|
|
648
655
|
|
|
649
656
|
const targetSection = document.getElementById(sectionId);
|
|
@@ -654,7 +661,8 @@ export function init() {
|
|
|
654
661
|
targetSection.focus();
|
|
655
662
|
}, 100);
|
|
656
663
|
}
|
|
657
|
-
}
|
|
664
|
+
};
|
|
665
|
+
addHandler(link, "click", clickHandler);
|
|
658
666
|
|
|
659
667
|
// Ensure sections are focusable for keyboard users but use CSS to control focus visibility
|
|
660
668
|
const targetSection = document.getElementById(sectionId);
|
|
@@ -672,37 +680,85 @@ export function init() {
|
|
|
672
680
|
// Set up IntersectionObserver for active state (Webflow-style)
|
|
673
681
|
const sections = Array.from(h2Headings).map(heading => heading.parentElement);
|
|
674
682
|
const tocLinks = tocList.querySelectorAll('a');
|
|
683
|
+
let currentActive = null;
|
|
675
684
|
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
685
|
+
const updateActiveLink = () => {
|
|
686
|
+
const windowHeight = window.innerHeight;
|
|
687
|
+
const trigger = windowHeight * 0.75; // 25% from bottom
|
|
688
|
+
|
|
689
|
+
let newActive = null;
|
|
680
690
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
691
|
+
// Find the last section whose top is above the trigger point
|
|
692
|
+
for (let i = sections.length - 1; i >= 0; i--) {
|
|
693
|
+
const rect = sections[i].getBoundingClientRect();
|
|
694
|
+
if (rect.top <= trigger) {
|
|
695
|
+
newActive = sections[i].id;
|
|
696
|
+
break;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
685
699
|
|
|
686
|
-
|
|
687
|
-
|
|
700
|
+
// Only update if active section changed
|
|
701
|
+
if (newActive !== currentActive) {
|
|
702
|
+
currentActive = newActive;
|
|
688
703
|
|
|
689
|
-
|
|
704
|
+
// Remove all is-active
|
|
705
|
+
tocLinks.forEach(link => link.classList.remove('is-active'));
|
|
706
|
+
|
|
707
|
+
// Add to current
|
|
708
|
+
if (currentActive) {
|
|
690
709
|
const activeLink = Array.from(tocLinks).find(link =>
|
|
691
|
-
link.getAttribute('href') === `#${
|
|
710
|
+
link.getAttribute('href') === `#${currentActive}`
|
|
692
711
|
);
|
|
693
712
|
if (activeLink) {
|
|
694
713
|
activeLink.classList.add('is-active');
|
|
695
714
|
}
|
|
696
715
|
}
|
|
697
|
-
}
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
const observerOptions = {
|
|
720
|
+
rootMargin: '0px 0px -75% 0px',
|
|
721
|
+
threshold: 0
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
const observer = new IntersectionObserver(() => {
|
|
725
|
+
updateActiveLink();
|
|
698
726
|
}, observerOptions);
|
|
699
727
|
|
|
700
728
|
// Observe all sections
|
|
701
729
|
sections.forEach(section => observer.observe(section));
|
|
730
|
+
addObserver(observer);
|
|
731
|
+
|
|
732
|
+
// Also update on scroll for smoother tracking
|
|
733
|
+
const scrollHandler = () => {
|
|
734
|
+
if (cleanup.scrollTimeout) clearTimeout(cleanup.scrollTimeout);
|
|
735
|
+
cleanup.scrollTimeout = setTimeout(updateActiveLink, 50);
|
|
736
|
+
};
|
|
737
|
+
addHandler(window, 'scroll', scrollHandler);
|
|
702
738
|
|
|
703
739
|
});
|
|
704
740
|
}
|
|
705
741
|
|
|
706
742
|
setupGeneralAccessibility();
|
|
707
|
-
|
|
743
|
+
|
|
744
|
+
return {
|
|
745
|
+
result: "accessibility initialized",
|
|
746
|
+
destroy: () => {
|
|
747
|
+
// Disconnect all observers
|
|
748
|
+
cleanup.observers.forEach(obs => obs.disconnect());
|
|
749
|
+
cleanup.observers.length = 0;
|
|
750
|
+
|
|
751
|
+
// Remove all event listeners
|
|
752
|
+
cleanup.handlers.forEach(({ element, event, handler, options }) => {
|
|
753
|
+
element.removeEventListener(event, handler, options);
|
|
754
|
+
});
|
|
755
|
+
cleanup.handlers.length = 0;
|
|
756
|
+
|
|
757
|
+
// Clear scroll timeout
|
|
758
|
+
if (cleanup.scrollTimeout) {
|
|
759
|
+
clearTimeout(cleanup.scrollTimeout);
|
|
760
|
+
cleanup.scrollTimeout = null;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
};
|
|
708
764
|
}
|
package/autoInit/counter.js
CHANGED
|
@@ -150,5 +150,21 @@ export function init() {
|
|
|
150
150
|
counters,
|
|
151
151
|
};
|
|
152
152
|
|
|
153
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
result: "counter initialized",
|
|
155
|
+
destroy: () => {
|
|
156
|
+
// Disconnect observer
|
|
157
|
+
if (observer) {
|
|
158
|
+
observer.disconnect();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Clear counters array
|
|
162
|
+
counters.length = 0;
|
|
163
|
+
|
|
164
|
+
// Remove window API
|
|
165
|
+
if (window.hsmain && window.hsmain.counter) {
|
|
166
|
+
delete window.hsmain.counter;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
154
170
|
}
|