@hortonstudio/main 1.9.11 → 1.9.20
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/.prettierrc +8 -0
- package/README.md +146 -0
- package/eslint.config.js +32 -0
- package/index.ts +275 -0
- package/package.json +19 -2
- package/public/bootstrap.js +16 -0
- package/src/animations/animations.ts +93 -0
- package/src/animations/functions/counter/counter.ts +137 -0
- package/src/config.json +570 -0
- package/src/config.ts +105 -0
- package/src/modules/default/README.md +167 -0
- package/src/modules/default/default.ts +71 -0
- package/{autoInit → src/modules/default/functions}/accessibility/README.md +44 -12
- package/src/modules/default/functions/accessibility/accessibility.ts +54 -0
- package/src/modules/default/functions/accordion/README.md +451 -0
- package/src/modules/default/functions/accordion/accordion.ts +189 -0
- package/src/modules/default/functions/comparison/comparison.ts +424 -0
- package/src/modules/default/functions/marquee/marquee.ts +206 -0
- package/src/modules/default/functions/navbar/README.md +393 -0
- package/src/modules/default/functions/navbar/functions/arrow-navigation/arrow-navigation.ts +183 -0
- package/src/modules/default/functions/navbar/functions/dropdown/dropdown.ts +313 -0
- package/src/modules/default/functions/navbar/functions/menu/menu.ts +315 -0
- package/src/modules/default/functions/navbar/navbar.ts +51 -0
- package/{autoInit → src/modules/default/functions}/smooth-scroll/README.md +45 -14
- package/{autoInit/smooth-scroll/smooth-scroll.js → src/modules/default/functions/smooth-scroll/smooth-scroll.ts} +33 -38
- package/{autoInit → src/modules/default/functions}/transition/README.md +59 -32
- package/src/modules/default/functions/transition/transition.ts +290 -0
- package/src/modules/normalize/README.md +172 -0
- package/src/modules/normalize/functions/clickable/README.md +84 -0
- package/src/modules/normalize/functions/clickable/clickable.ts +43 -0
- package/src/modules/normalize/functions/clickable/functions/normalize/README.md +213 -0
- package/src/modules/normalize/functions/clickable/functions/normalize/normalize.ts +68 -0
- package/src/modules/normalize/functions/dupe/README.md +405 -0
- package/src/modules/normalize/functions/dupe/dupe.ts +197 -0
- package/src/modules/normalize/functions/sync/sync.ts +378 -0
- package/src/modules/normalize/normalize.ts +58 -0
- package/src/modules/structure/README.md +190 -0
- package/src/modules/structure/functions/form/README.md +94 -0
- package/src/modules/structure/functions/form/form.ts +54 -0
- package/src/modules/structure/functions/form/functions/honeypot/README.md +77 -0
- package/src/modules/structure/functions/form/functions/honeypot/honeypot.ts +37 -0
- package/src/modules/structure/functions/form/functions/range/README.md +410 -0
- package/src/modules/structure/functions/form/functions/range/range.ts +92 -0
- package/src/modules/structure/functions/form/functions/select/README.md +393 -0
- package/src/modules/structure/functions/form/functions/select/functions/custom-select/custom-select.ts +637 -0
- package/src/modules/structure/functions/form/functions/select/functions/states/states.ts +118 -0
- package/src/modules/structure/functions/form/functions/select/select.ts +48 -0
- package/src/modules/structure/functions/form/functions/test/test.ts +132 -0
- package/{autoInit/accessibility → src/modules/structure}/functions/pagination/README.md +147 -72
- package/{autoInit/accessibility/functions/pagination/pagination.js → src/modules/structure/functions/pagination/pagination.ts} +98 -50
- package/{autoInit → src/modules/structure/functions}/site-settings/README.md +57 -27
- package/{autoInit/site-settings/site-settings.js → src/modules/structure/functions/site-settings/site-settings.ts} +36 -32
- package/{autoInit/accessibility → src/modules/structure}/functions/toc/README.md +18 -15
- package/{autoInit/accessibility/functions/toc/toc.js → src/modules/structure/functions/toc/functions/heading-links/heading-links.ts} +43 -63
- package/src/modules/structure/functions/toc/functions/progress-bar/progress-bar.ts +101 -0
- package/src/modules/structure/functions/toc/toc.ts +35 -0
- package/{autoInit/accessibility → src/modules/structure}/functions/year-replacement/README.md +7 -6
- package/src/modules/structure/functions/year-replacement/year-replacement.ts +59 -0
- package/src/modules/structure/structure.ts +59 -0
- package/src/utils/attributeSelector.ts +78 -0
- package/src/utils/cssVariables.ts +24 -0
- package/src/utils/gsap.ts +198 -0
- package/src/utils/heightAnimator.ts +130 -0
- package/src/utils/modalManager.ts +150 -0
- package/src/utils.ts +54 -0
- package/tsconfig.json +24 -0
- package/vite.config.js +45 -0
- package/.claude/settings.local.json +0 -70
- package/archive/hero.js +0 -794
- package/archive/modal.js +0 -80
- package/archive/text.js +0 -628
- package/autoInit/accessibility/accessibility.js +0 -53
- package/autoInit/accessibility/functions/blog-remover/README.md +0 -61
- package/autoInit/accessibility/functions/blog-remover/blog-remover.js +0 -31
- package/autoInit/accessibility/functions/click-forwarding/README.md +0 -60
- package/autoInit/accessibility/functions/click-forwarding/click-forwarding.js +0 -82
- package/autoInit/accessibility/functions/dropdown/README.md +0 -212
- package/autoInit/accessibility/functions/dropdown/dropdown.js +0 -167
- package/autoInit/accessibility/functions/list-accessibility/README.md +0 -56
- package/autoInit/accessibility/functions/list-accessibility/list-accessibility.js +0 -23
- package/autoInit/accessibility/functions/text-synchronization/README.md +0 -62
- package/autoInit/accessibility/functions/text-synchronization/text-synchronization.js +0 -101
- package/autoInit/accessibility/functions/year-replacement/year-replacement.js +0 -43
- package/autoInit/button/README.md +0 -122
- package/autoInit/button/button.js +0 -51
- package/autoInit/counter/README.md +0 -274
- package/autoInit/counter/counter.js +0 -185
- package/autoInit/form/README.md +0 -338
- package/autoInit/form/form.js +0 -374
- package/autoInit/navbar/README.md +0 -366
- package/autoInit/navbar/navbar.js +0 -786
- package/autoInit/transition/transition.js +0 -116
- package/index.js +0 -305
- package/utils/before-after/README.md +0 -520
- package/utils/before-after/before-after.js +0 -653
- package/utils/css-animations/buttons/main/bgbasic/btn-main-bgbasic.html +0 -10
- package/utils/css-animations/buttons/main/bgfill/btn-main-bgfill.html +0 -29
- package/utils/css-animations/buttons/navbar/bgbasic/navbar-main-bgbasic.html +0 -17
- package/utils/css-animations/buttons/navbar/bgbasic/navbar-menu-bgbasic.html +0 -16
- package/utils/css-animations/buttons/navbar/bgfill/navbar-main-bgfill.html +0 -46
- package/utils/css-animations/buttons/navbar/bgfill/navbar-menu-bgfill.html +0 -39
- package/utils/css-animations/buttons/navbar/color/navbar-announce-color.html +0 -5
- package/utils/css-animations/buttons/navbar/color/navbar-main-color.html +0 -7
- package/utils/css-animations/buttons/navbar/color/navbar-menu-color.html +0 -7
- package/utils/css-animations/buttons/navbar/double-slide/navbar-announce-double-slide.html +0 -40
- package/utils/css-animations/buttons/navbar/double-slide/navbar-main-double-slide.html +0 -77
- package/utils/css-animations/buttons/navbar/scale/navbar-announce-scale.html +0 -6
- package/utils/css-animations/buttons/navbar/scale/navbar-main-scale.html +0 -9
- package/utils/css-animations/buttons/navbar/scale/navbar-menu-scale.html +0 -8
- package/utils/css-animations/buttons/navbar/underline/navbar-announce-underline.html +0 -32
- package/utils/css-animations/buttons/navbar/underline/navbar-main-underline.html +0 -56
- package/utils/css-animations/buttons/text/color/text-footer-color.html +0 -5
- package/utils/css-animations/buttons/text/color/text-main-color.html +0 -5
- package/utils/css-animations/buttons/text/double-slide/text-main-double-slide.html +0 -56
- package/utils/css-animations/buttons/text/scale/text-footer-scale.html +0 -6
- package/utils/css-animations/buttons/text/scale/text-main-scale.html +0 -6
- package/utils/css-animations/buttons/text/underline/text-footer-underline.html +0 -45
- package/utils/css-animations/buttons/text/underline/text-main-underline.html +0 -58
- package/utils/css-animations/cards/card-clickable.html +0 -11
- package/utils/css-animations/defaults.html +0 -69
package/src/config.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Master configuration with TypeScript type safety
|
|
3
|
+
* Single source of truth for all module configs
|
|
4
|
+
*
|
|
5
|
+
* @version 2.0.0
|
|
6
|
+
*/
|
|
7
|
+
import configData from './config.json';
|
|
8
|
+
|
|
9
|
+
// TypeScript interfaces for autocomplete and type safety
|
|
10
|
+
|
|
11
|
+
export interface AttributeConfig {
|
|
12
|
+
primary: string;
|
|
13
|
+
aliases: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ModuleConfig {
|
|
17
|
+
module: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
attributes?: {
|
|
20
|
+
elements?: Record<string, AttributeConfig>;
|
|
21
|
+
properties?: Record<string, string>;
|
|
22
|
+
placeholders?: Record<string, string>;
|
|
23
|
+
note?: string;
|
|
24
|
+
};
|
|
25
|
+
modes?: Record<string, string>;
|
|
26
|
+
modifiers?: Record<string, string>;
|
|
27
|
+
limits?: Record<string, number>;
|
|
28
|
+
types?: Record<string, string>;
|
|
29
|
+
defaults?: Record<string, string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface GlobalConfig {
|
|
33
|
+
version: string;
|
|
34
|
+
apiName: string;
|
|
35
|
+
attributes: {
|
|
36
|
+
height: string;
|
|
37
|
+
heightValue: string;
|
|
38
|
+
heightDuration: string;
|
|
39
|
+
heightEase: string;
|
|
40
|
+
moduleType: string;
|
|
41
|
+
module: string;
|
|
42
|
+
};
|
|
43
|
+
classes: {
|
|
44
|
+
modalOpen: string;
|
|
45
|
+
overflowHidden: string;
|
|
46
|
+
initialized: string;
|
|
47
|
+
displayContents: string;
|
|
48
|
+
active: string;
|
|
49
|
+
gsap: string;
|
|
50
|
+
};
|
|
51
|
+
cssVars: {
|
|
52
|
+
prefix: string;
|
|
53
|
+
state: {
|
|
54
|
+
name: string;
|
|
55
|
+
values: {
|
|
56
|
+
active: string;
|
|
57
|
+
inactive: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
clickable: ModuleConfig;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface Config {
|
|
65
|
+
_global: GlobalConfig;
|
|
66
|
+
normalize: {
|
|
67
|
+
sync: ModuleConfig;
|
|
68
|
+
clickable: ModuleConfig & {
|
|
69
|
+
normalize: ModuleConfig;
|
|
70
|
+
};
|
|
71
|
+
dupe: ModuleConfig;
|
|
72
|
+
};
|
|
73
|
+
structure: {
|
|
74
|
+
'year-replacement': ModuleConfig;
|
|
75
|
+
toc: ModuleConfig;
|
|
76
|
+
pagination: ModuleConfig;
|
|
77
|
+
'site-settings': ModuleConfig;
|
|
78
|
+
form: {
|
|
79
|
+
honeypot: ModuleConfig;
|
|
80
|
+
range: ModuleConfig;
|
|
81
|
+
test: ModuleConfig;
|
|
82
|
+
select: ModuleConfig & {
|
|
83
|
+
states: ModuleConfig;
|
|
84
|
+
'custom-select': ModuleConfig;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
transition: ModuleConfig;
|
|
89
|
+
default: {
|
|
90
|
+
'smooth-scroll': ModuleConfig;
|
|
91
|
+
accordion: ModuleConfig;
|
|
92
|
+
counter: ModuleConfig;
|
|
93
|
+
comparison: ModuleConfig;
|
|
94
|
+
marquee: ModuleConfig;
|
|
95
|
+
navbar: ModuleConfig & {
|
|
96
|
+
dropdown: ModuleConfig;
|
|
97
|
+
menu: ModuleConfig;
|
|
98
|
+
'arrow-navigation': ModuleConfig;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Export typed config
|
|
104
|
+
export const config = configData as Config;
|
|
105
|
+
export default config;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# **Default Module Documentation**
|
|
2
|
+
|
|
3
|
+
## **Overview**
|
|
4
|
+
|
|
5
|
+
The default module loads all interactive and user-facing modules in Phase 4 of the initialization system. These modules enhance user experience but are not critical for initial page render.
|
|
6
|
+
|
|
7
|
+
**Purpose**: Load interactive features in the background after the page has revealed (after transition).
|
|
8
|
+
|
|
9
|
+
**Phase**: Phase 4 (Default) - runs after transition reveals page
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## **Functions**
|
|
14
|
+
|
|
15
|
+
### **1. Smooth Scroll**
|
|
16
|
+
|
|
17
|
+
Smooth scrolling behavior for anchor links and navigation.
|
|
18
|
+
|
|
19
|
+
**Use case:** Smooth page scrolling, anchor navigation
|
|
20
|
+
|
|
21
|
+
### **2. Navbar**
|
|
22
|
+
|
|
23
|
+
Desktop dropdowns and mobile menu functionality.
|
|
24
|
+
|
|
25
|
+
**Use case:** Navigation menus with hover/click dropdowns, responsive mobile menu
|
|
26
|
+
|
|
27
|
+
### **3. Accessibility**
|
|
28
|
+
|
|
29
|
+
Accessibility enhancements (accordion).
|
|
30
|
+
|
|
31
|
+
**Use case:** WCAG compliance, keyboard navigation, screen reader support
|
|
32
|
+
|
|
33
|
+
### **4. Counter**
|
|
34
|
+
|
|
35
|
+
Animated number counters with scroll triggers.
|
|
36
|
+
|
|
37
|
+
**Use case:** Statistics, metrics, animated numbers
|
|
38
|
+
|
|
39
|
+
### **5. Before-After**
|
|
40
|
+
|
|
41
|
+
Image comparison slider.
|
|
42
|
+
|
|
43
|
+
**Use case:** Before/after comparisons, image sliders
|
|
44
|
+
|
|
45
|
+
### **6. Marquee**
|
|
46
|
+
|
|
47
|
+
Infinite scrolling marquee with content duplication.
|
|
48
|
+
|
|
49
|
+
**Use case:** Logo walls, testimonials, ticker tape effects
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## **Documentation**
|
|
54
|
+
|
|
55
|
+
Each function has detailed documentation in its respective folder:
|
|
56
|
+
|
|
57
|
+
- `functions/smooth-scroll/README.md`
|
|
58
|
+
- `functions/navbar/README.md`
|
|
59
|
+
- `functions/accessibility/README.md`
|
|
60
|
+
- `functions/counter/README.md`
|
|
61
|
+
- `functions/before-after/README.md`
|
|
62
|
+
- `functions/marquee/README.md`
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## **How It Works**
|
|
67
|
+
|
|
68
|
+
The default module uses a dynamic loader pattern:
|
|
69
|
+
|
|
70
|
+
1. Main `default.js` imports all function modules
|
|
71
|
+
2. Each function is loaded in parallel via `Promise.allSettled()`
|
|
72
|
+
3. All destroy functions are collected for cleanup
|
|
73
|
+
4. On destroy, all functions are cleaned up properly
|
|
74
|
+
|
|
75
|
+
**Initialization Flow**:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
Page Load
|
|
79
|
+
↓
|
|
80
|
+
Phase 1: Normalize (clickable, dupe)
|
|
81
|
+
↓
|
|
82
|
+
Phase 2: Visual-DOM (structure, form)
|
|
83
|
+
↓
|
|
84
|
+
Phase 3: Transition reveals page
|
|
85
|
+
↓
|
|
86
|
+
Phase 4: Default modules (interactive features) ← WE ARE HERE
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## **Phased Initialization**
|
|
92
|
+
|
|
93
|
+
### **Why Phase 4?**
|
|
94
|
+
|
|
95
|
+
These modules enhance interactivity but aren't needed for initial render:
|
|
96
|
+
|
|
97
|
+
- Smooth scroll works on interaction
|
|
98
|
+
- Navbar can initialize after page visible
|
|
99
|
+
- Counters animate on scroll
|
|
100
|
+
- Before-after requires user interaction
|
|
101
|
+
|
|
102
|
+
**Without phasing**: All modules compete for resources during initial load → slower perceived performance
|
|
103
|
+
|
|
104
|
+
**With phasing**: Page reveals quickly → interactive features load in background → smooth UX
|
|
105
|
+
|
|
106
|
+
### **Phase Characteristics**
|
|
107
|
+
|
|
108
|
+
- **Timing**: Runs after transition reveals page (Phase 3)
|
|
109
|
+
- **Parallelization**: All functions load in parallel within Phase 4
|
|
110
|
+
- **Resilience**: Uses `Promise.allSettled` - individual failures don't block phase
|
|
111
|
+
- **Non-blocking**: Loads in background, doesn't delay page reveal
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## **Performance**
|
|
116
|
+
|
|
117
|
+
**Expected load time**: ~50-100ms for all functions in parallel
|
|
118
|
+
|
|
119
|
+
Individual timing varies by function:
|
|
120
|
+
|
|
121
|
+
- Smooth scroll: ~5-10ms (event listeners)
|
|
122
|
+
- Navbar: ~20-40ms (dropdowns, menu, keyboard nav)
|
|
123
|
+
- Accessibility: ~10-15ms (accordion)
|
|
124
|
+
- Counter: ~10-20ms (IntersectionObserver, GSAP)
|
|
125
|
+
- Before-after: ~10-20ms (drag handlers, GSAP)
|
|
126
|
+
- Marquee: ~5-15ms (DOM duplication)
|
|
127
|
+
|
|
128
|
+
**Total Phase 4 timing**: Typically completes in 80-120ms (in background)
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## **Barba.js / SPA Compatibility**
|
|
133
|
+
|
|
134
|
+
The default module is fully compatible with Barba.js and other SPA frameworks:
|
|
135
|
+
|
|
136
|
+
### **v2.0.0 Improvements:**
|
|
137
|
+
|
|
138
|
+
- **Resilient loading with Promise.allSettled** - Individual function failures won't break other functions
|
|
139
|
+
- **Graceful error handling** - Failed functions are logged but don't prevent successful ones from working
|
|
140
|
+
- **Complete cleanup on destroy** - All functions properly cleaned up for page transitions
|
|
141
|
+
- **Phased initialization** - Same clean flow on page load and SPA transitions
|
|
142
|
+
|
|
143
|
+
### **On Destroy:**
|
|
144
|
+
|
|
145
|
+
1. Calls destroy() on all successfully loaded functions
|
|
146
|
+
2. Errors during cleanup are caught and logged
|
|
147
|
+
3. Cleanup tracking arrays are reset
|
|
148
|
+
4. Safe for Barba.js page transitions
|
|
149
|
+
|
|
150
|
+
### **On Reinitialize:**
|
|
151
|
+
|
|
152
|
+
1. Attempts to load all functions again
|
|
153
|
+
2. Works like fresh page load on new DOM
|
|
154
|
+
3. Independent function loading ensures maximum resilience
|
|
155
|
+
4. Runs in same Phase 4 timing for consistent UX
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## **Notes**
|
|
160
|
+
|
|
161
|
+
- All functions auto-initialize on page load
|
|
162
|
+
- Each function operates independently
|
|
163
|
+
- Barba.js compatible with proper cleanup
|
|
164
|
+
- No configuration required at default level - each function uses its own config
|
|
165
|
+
- Runs in Phase 4 (after transition) of initialization system
|
|
166
|
+
- Uses Promise.allSettled for maximum reliability
|
|
167
|
+
- Part of v2.0.0 phased initialization architecture
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Orchestrator
|
|
3
|
+
* Manages default interactive modules in parallel (Phase 3)
|
|
4
|
+
*
|
|
5
|
+
* Uses static imports and passes config down to functions
|
|
6
|
+
* Transition module included with 50ms delay for initialization order
|
|
7
|
+
* @version 2.0.0
|
|
8
|
+
*/
|
|
9
|
+
import config from '@config';
|
|
10
|
+
import { init as smoothScrollInit } from './functions/smooth-scroll/smooth-scroll.ts';
|
|
11
|
+
import { init as navbarInit } from './functions/navbar/navbar.ts';
|
|
12
|
+
import { init as accessibilityInit } from './functions/accessibility/accessibility.ts';
|
|
13
|
+
import { init as accordionInit } from './functions/accordion/accordion.ts';
|
|
14
|
+
import { init as comparisonInit } from './functions/comparison/comparison.ts';
|
|
15
|
+
import { init as marqueeInit } from './functions/marquee/marquee.ts';
|
|
16
|
+
import { init as transitionInit } from './functions/transition/transition.ts';
|
|
17
|
+
|
|
18
|
+
const CONFIG_ROOT = 'default';
|
|
19
|
+
|
|
20
|
+
export async function init() {
|
|
21
|
+
const cleanup = { destroyFunctions: [] };
|
|
22
|
+
const moduleConfig = config[CONFIG_ROOT];
|
|
23
|
+
|
|
24
|
+
// Start all functions in parallel
|
|
25
|
+
const modulePromises = [
|
|
26
|
+
smoothScrollInit(moduleConfig['smooth-scroll']),
|
|
27
|
+
navbarInit(moduleConfig.navbar),
|
|
28
|
+
accessibilityInit(), // No config needed for accessibility
|
|
29
|
+
accordionInit(moduleConfig.accordion),
|
|
30
|
+
comparisonInit(moduleConfig.comparison),
|
|
31
|
+
marqueeInit(moduleConfig.marquee),
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// Add transition with 50ms delay to let other modules initialize first
|
|
35
|
+
const transitionPromise = (async () => {
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
37
|
+
return transitionInit(moduleConfig.transition);
|
|
38
|
+
})();
|
|
39
|
+
|
|
40
|
+
const results = await Promise.allSettled([...modulePromises, transitionPromise]);
|
|
41
|
+
|
|
42
|
+
// Collect destroy functions from successful inits
|
|
43
|
+
results.forEach((result) => {
|
|
44
|
+
if (result.status === 'fulfilled' && result.value?.destroy) {
|
|
45
|
+
cleanup.destroyFunctions.push(result.value.destroy);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Log summary
|
|
50
|
+
const succeeded = results.filter((r) => r.status === 'fulfilled').length;
|
|
51
|
+
const failed = results.length - succeeded;
|
|
52
|
+
if (failed > 0) {
|
|
53
|
+
console.warn(
|
|
54
|
+
`[default] ${succeeded}/${results.length} functions loaded successfully. ${failed} failed but won't affect other functions.`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
result: 'default initialized',
|
|
60
|
+
destroy: () => {
|
|
61
|
+
cleanup.destroyFunctions.forEach((destroyFn) => {
|
|
62
|
+
try {
|
|
63
|
+
destroyFn();
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('[default] Error during cleanup:', error);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
cleanup.destroyFunctions.length = 0;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -11,6 +11,7 @@ The accessibility system provides 8 modular functions to enhance website accessi
|
|
|
11
11
|
## **Functions**
|
|
12
12
|
|
|
13
13
|
### **1. Blog Remover**
|
|
14
|
+
|
|
14
15
|
Automatically removes blog wrapper elements that have no blog list content.
|
|
15
16
|
|
|
16
17
|
**Use case:** Clean up empty blog sections when using Webflow CMS conditional visibility.
|
|
@@ -18,6 +19,7 @@ Automatically removes blog wrapper elements that have no blog list content.
|
|
|
18
19
|
---
|
|
19
20
|
|
|
20
21
|
### **2. List Accessibility**
|
|
22
|
+
|
|
21
23
|
Adds proper ARIA `role="list"` and `role="listitem"` to custom-styled lists.
|
|
22
24
|
|
|
23
25
|
**Use case:** Making non-semantic list layouts accessible to screen readers.
|
|
@@ -25,6 +27,7 @@ Adds proper ARIA `role="list"` and `role="listitem"` to custom-styled lists.
|
|
|
25
27
|
---
|
|
26
28
|
|
|
27
29
|
### **3. Year Replacement**
|
|
30
|
+
|
|
28
31
|
Replaces `{{year}}` and `{{month}}` placeholders with current year and month.
|
|
29
32
|
|
|
30
33
|
**Use case:** Auto-updating copyright years and date-based content.
|
|
@@ -32,6 +35,7 @@ Replaces `{{year}}` and `{{month}}` placeholders with current year and month.
|
|
|
32
35
|
---
|
|
33
36
|
|
|
34
37
|
### **4. Click Forwarding**
|
|
38
|
+
|
|
35
39
|
Forwards clicks from decorative wrapper elements to actual interactive trigger elements.
|
|
36
40
|
|
|
37
41
|
**Use case:** Making entire card areas clickable while maintaining semantic structure.
|
|
@@ -39,6 +43,7 @@ Forwards clicks from decorative wrapper elements to actual interactive trigger e
|
|
|
39
43
|
---
|
|
40
44
|
|
|
41
45
|
### **5. Text Synchronization**
|
|
46
|
+
|
|
42
47
|
Synchronizes text content and aria-labels from original element to multiple match elements in real-time.
|
|
43
48
|
|
|
44
49
|
**Use case:** Keeping duplicate content in sync across multiple locations.
|
|
@@ -46,22 +51,25 @@ Synchronizes text content and aria-labels from original element to multiple matc
|
|
|
46
51
|
---
|
|
47
52
|
|
|
48
53
|
### **6. Table of Contents (TOC)**
|
|
54
|
+
|
|
49
55
|
Automatically generates a table of contents from H2 headings with smooth scrolling, focus management, and active state tracking.
|
|
50
56
|
|
|
51
57
|
**Use case:** Auto-generated TOC navigation for blog posts and documentation pages.
|
|
52
58
|
|
|
53
59
|
---
|
|
54
60
|
|
|
55
|
-
### **7.
|
|
56
|
-
|
|
61
|
+
### **7. Accordion**
|
|
62
|
+
|
|
63
|
+
Universal accordion system for FAQ, summary/read-more, and general toggle components. Syncs ARIA with Webflow interactions and optionally updates text content.
|
|
57
64
|
|
|
58
|
-
**Use case:** All
|
|
65
|
+
**Use case:** All accordion/toggle patterns with unified ARIA management and optional text swapping.
|
|
59
66
|
|
|
60
67
|
**Note:** This function replaces the legacy `faq-accessibility` and `summary` functions with a single unified system.
|
|
61
68
|
|
|
62
69
|
---
|
|
63
70
|
|
|
64
71
|
### **8. Pagination**
|
|
72
|
+
|
|
65
73
|
Complete pagination system for paginated lists with controls, counters, dot navigation, and infinite looping. Supports responsive layouts and accessibility features.
|
|
66
74
|
|
|
67
75
|
**Use case:** Multi-item paginated lists (product grids, blog lists, search results) and carousels (with `show-1` config).
|
|
@@ -72,14 +80,7 @@ Complete pagination system for paginated lists with controls, counters, dot navi
|
|
|
72
80
|
|
|
73
81
|
Each function has detailed documentation in its respective folder:
|
|
74
82
|
|
|
75
|
-
- `functions/
|
|
76
|
-
- `functions/list-accessibility/README.md`
|
|
77
|
-
- `functions/year-replacement/README.md`
|
|
78
|
-
- `functions/click-forwarding/README.md`
|
|
79
|
-
- `functions/text-synchronization/README.md`
|
|
80
|
-
- `functions/toc/README.md`
|
|
81
|
-
- `functions/dropdown/README.md`
|
|
82
|
-
- `functions/pagination/README.md`
|
|
83
|
+
- `functions/accordion/README.md`
|
|
83
84
|
|
|
84
85
|
---
|
|
85
86
|
|
|
@@ -88,12 +89,43 @@ Each function has detailed documentation in its respective folder:
|
|
|
88
89
|
The accessibility system uses a dynamic loader pattern:
|
|
89
90
|
|
|
90
91
|
1. Main `accessibility.js` imports all function modules
|
|
91
|
-
2. Each function is loaded in parallel via `Promise.
|
|
92
|
+
2. Each function is loaded in parallel via `Promise.allSettled()`
|
|
92
93
|
3. All destroy functions are collected for cleanup
|
|
93
94
|
4. On destroy, all functions are cleaned up properly
|
|
94
95
|
|
|
95
96
|
---
|
|
96
97
|
|
|
98
|
+
## **Barba.js / SPA Compatibility**
|
|
99
|
+
|
|
100
|
+
The accessibility system is fully compatible with Barba.js and other SPA frameworks:
|
|
101
|
+
|
|
102
|
+
### **v2.0.0 Improvements:**
|
|
103
|
+
|
|
104
|
+
- **Resilient loading with Promise.allSettled** - Individual function failures won't break other functions
|
|
105
|
+
- **Graceful error handling** - Failed functions are logged but don't prevent successful ones from working
|
|
106
|
+
- **Complete cleanup on destroy** - All functions properly cleaned up for page transitions
|
|
107
|
+
|
|
108
|
+
### **Resilient Loading:**
|
|
109
|
+
|
|
110
|
+
- If one accessibility function fails (missing element, error, etc.), others continue working
|
|
111
|
+
- Logs helpful warnings showing which functions succeeded/failed
|
|
112
|
+
- System remains functional even with partial failures
|
|
113
|
+
|
|
114
|
+
### **On Destroy:**
|
|
115
|
+
|
|
116
|
+
1. Calls destroy() on all successfully loaded functions
|
|
117
|
+
2. Errors during cleanup are caught and logged
|
|
118
|
+
3. Cleanup tracking arrays are reset
|
|
119
|
+
4. Safe for Barba.js page transitions
|
|
120
|
+
|
|
121
|
+
### **On Reinitialize:**
|
|
122
|
+
|
|
123
|
+
1. Attempts to load all 8 functions again
|
|
124
|
+
2. Works like fresh page load on new DOM
|
|
125
|
+
3. Independent function loading ensures maximum resilience
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
97
129
|
## **Notes**
|
|
98
130
|
|
|
99
131
|
- All functions auto-initialize on page load
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export async function init() {
|
|
2
|
+
// Centralized cleanup tracking
|
|
3
|
+
const cleanup = {
|
|
4
|
+
modules: {},
|
|
5
|
+
destroyFunctions: [],
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// Empty function map - reserved for future accessibility functions
|
|
9
|
+
const functionMap = {};
|
|
10
|
+
|
|
11
|
+
const loadFunction = async (functionName) => {
|
|
12
|
+
try {
|
|
13
|
+
const { init } = await functionMap[functionName]();
|
|
14
|
+
const result = await init();
|
|
15
|
+
cleanup.modules[functionName] = result;
|
|
16
|
+
if (result && result.destroy) {
|
|
17
|
+
cleanup.destroyFunctions.push(result.destroy);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error(`[accessibility] Failed to load function: ${functionName}`, error);
|
|
22
|
+
return null; // Return null instead of throwing - allows other functions to continue
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Load all functions - use allSettled for resilient loading
|
|
27
|
+
const functionPromises = Object.keys(functionMap).map((name) => loadFunction(name));
|
|
28
|
+
const results = await Promise.allSettled(functionPromises);
|
|
29
|
+
|
|
30
|
+
// Log summary of loaded functions
|
|
31
|
+
const succeeded = results.filter((r) => r.status === 'fulfilled' && r.value).length;
|
|
32
|
+
const failed = results.length - succeeded;
|
|
33
|
+
if (failed > 0) {
|
|
34
|
+
console.warn(
|
|
35
|
+
`[accessibility] ${succeeded}/${results.length} functions loaded successfully. ${failed} failed but won't affect other functions.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
result: 'accessibility initialized (no functions loaded)',
|
|
41
|
+
destroy: () => {
|
|
42
|
+
// Call all destroy functions
|
|
43
|
+
cleanup.destroyFunctions.forEach((destroyFn) => {
|
|
44
|
+
try {
|
|
45
|
+
destroyFn();
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('Error during accessibility cleanup:', error);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
cleanup.destroyFunctions.length = 0;
|
|
51
|
+
cleanup.modules = {};
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|