@hortonstudio/main 1.9.6 → 1.9.7

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.
Files changed (40) hide show
  1. package/autoInit/accessibility/README.md +126 -0
  2. package/autoInit/accessibility/accessibility.js +56 -0
  3. package/autoInit/accessibility/functions/blog-remover/README.md +61 -0
  4. package/autoInit/accessibility/functions/blog-remover/blog-remover.js +31 -0
  5. package/autoInit/accessibility/functions/click-forwarding/README.md +60 -0
  6. package/autoInit/accessibility/functions/click-forwarding/click-forwarding.js +82 -0
  7. package/autoInit/accessibility/functions/convert-to-span/README.md +59 -0
  8. package/autoInit/accessibility/functions/convert-to-span/convert-to-span.js +70 -0
  9. package/autoInit/accessibility/functions/custom-values-replacement/README.md +71 -0
  10. package/autoInit/accessibility/functions/custom-values-replacement/custom-values-replacement.js +102 -0
  11. package/autoInit/accessibility/functions/dropdown/README.md +212 -0
  12. package/autoInit/accessibility/functions/dropdown/dropdown.js +167 -0
  13. package/autoInit/accessibility/functions/list-accessibility/README.md +56 -0
  14. package/autoInit/accessibility/functions/list-accessibility/list-accessibility.js +23 -0
  15. package/autoInit/accessibility/functions/prevent-default/README.md +58 -0
  16. package/autoInit/accessibility/functions/prevent-default/prevent-default.js +58 -0
  17. package/autoInit/accessibility/functions/remove-list-accessibility/README.md +57 -0
  18. package/autoInit/accessibility/functions/remove-list-accessibility/remove-list-accessibility.js +68 -0
  19. package/autoInit/accessibility/functions/text-synchronization/README.md +62 -0
  20. package/autoInit/accessibility/functions/text-synchronization/text-synchronization.js +101 -0
  21. package/autoInit/accessibility/functions/toc/README.md +79 -0
  22. package/autoInit/accessibility/functions/toc/toc.js +191 -0
  23. package/autoInit/accessibility/functions/year-replacement/README.md +54 -0
  24. package/autoInit/accessibility/functions/year-replacement/year-replacement.js +43 -0
  25. package/autoInit/button/README.md +122 -0
  26. package/autoInit/counter/README.md +274 -0
  27. package/autoInit/{counter.js → counter/counter.js} +20 -5
  28. package/autoInit/form/README.md +338 -0
  29. package/autoInit/{form.js → form/form.js} +44 -29
  30. package/autoInit/navbar/README.md +366 -0
  31. package/autoInit/site-settings/README.md +218 -0
  32. package/autoInit/smooth-scroll/README.md +386 -0
  33. package/autoInit/transition/README.md +301 -0
  34. package/autoInit/{transition.js → transition/transition.js} +13 -2
  35. package/index.js +7 -7
  36. package/package.json +1 -1
  37. package/autoInit/accessibility.js +0 -786
  38. /package/autoInit/{button.js → button/button.js} +0 -0
  39. /package/autoInit/{site-settings.js → site-settings/site-settings.js} +0 -0
  40. /package/autoInit/{smooth-scroll.js → smooth-scroll/smooth-scroll.js} +0 -0
@@ -0,0 +1,122 @@
1
+ # **Button Icon System Documentation**
2
+
3
+ ## **Overview**
4
+
5
+ The button icon system automatically clones icons from a "main" slot to a "placeholder" slot within button wrappers. This allows for consistent icon duplication for animation or styling purposes.
6
+
7
+ **Note:** This functionality is **already set up** in the Global / Button components. This documentation is for custom button implementations that require this icon cloning behavior.
8
+
9
+ ---
10
+
11
+ ## **Button Icon Cloning**
12
+
13
+ ### **Required Elements**
14
+
15
+ **Button Wrapper** *(main wrapper of the button)*
16
+
17
+ * data-site-button="wrapper"
18
+
19
+ **Icon Wrapper** *(wraps both main and placeholder icons)*
20
+
21
+ * data-site-button-icon="wrapper"
22
+
23
+ **Main Icon** *(the source icon to be cloned)*
24
+
25
+ * data-site-button-icon="main"
26
+ * Contains: `[data-site-icon="slot"]` (the actual icon element)
27
+
28
+ **Placeholder Icon** *(the destination for the cloned icon)*
29
+
30
+ * data-site-button-icon="placeholder"
31
+ * Contains: `[data-site-icon="slot"]` (will be replaced with cloned icon)
32
+
33
+ **Typical element layout:**
34
+
35
+ 1. Button Wrapper (data-site-button="wrapper")
36
+ 1. Button Content
37
+ 1. Icon Wrapper (data-site-button-icon="wrapper")
38
+ 1. Main Icon (data-site-button-icon="main")
39
+ 1. Icon Slot (data-site-icon="slot")
40
+ 1. SVG or Icon Element
41
+ 2. Placeholder Icon (data-site-button-icon="placeholder")
42
+ 1. Icon Slot (data-site-icon="slot")
43
+ 1. Empty (will be replaced)
44
+
45
+ ### **What It Does**
46
+
47
+ 1. **Finds all button wrappers** with `[data-site-button="wrapper"]`
48
+ 2. **Checks for icon wrapper** - If no `[data-site-button-icon="wrapper"]`, skips button
49
+ 3. **Clones main icon** - Gets first `[data-site-icon="slot"]` inside main icon
50
+ 4. **Replaces placeholder** - Swaps placeholder slot with cloned main slot
51
+
52
+ ### **When It Runs**
53
+
54
+ * Runs once on page load
55
+ * Runs again on Barba.js page transitions (via `reinitialize()`)
56
+ * No ongoing monitoring or event listeners
57
+
58
+ ### **Notes**
59
+
60
+ 1. **Global / Button components** already include this setup by default
61
+ * Use this documentation only for custom button implementations
62
+ 2. If any required element is missing, that button is skipped (no errors)
63
+ 3. The system works independently for each button on the page
64
+ 4. No cleanup needed - purely DOM manipulation
65
+
66
+ ---
67
+
68
+ ## **Example Structure**
69
+
70
+ ```html
71
+ <div data-site-button="wrapper">
72
+ <div data-site-button-icon="wrapper">
73
+ <!-- Main icon (source) -->
74
+ <div data-site-button-icon="main">
75
+ <div data-site-icon="slot">
76
+ <svg><!-- Your icon --></svg>
77
+ </div>
78
+ </div>
79
+
80
+ <!-- Placeholder icon (destination) -->
81
+ <div data-site-button-icon="placeholder">
82
+ <div data-site-icon="slot">
83
+ <!-- This entire element gets replaced with cloned main slot -->
84
+ </div>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ ```
89
+
90
+ **Result:** The placeholder slot is replaced with an exact clone of the main slot (including the SVG).
91
+
92
+ ---
93
+
94
+ ## **Key Attributes Summary**
95
+
96
+ | Attribute | Purpose | Required On |
97
+ | ----- | ----- | ----- |
98
+ | `data-site-button="wrapper"` | Button container | Wrapper div |
99
+ | `data-site-button-icon="wrapper"` | Icon container | Icon wrapper div |
100
+ | `data-site-button-icon="main"` | Source icon | Main icon div |
101
+ | `data-site-button-icon="placeholder"` | Clone destination | Placeholder icon div |
102
+ | `data-site-icon="slot"` | Icon slot element | Both main and placeholder |
103
+
104
+ ---
105
+
106
+ ## **Common Issues**
107
+
108
+ **Icons not cloning:**
109
+
110
+ 1. Verify all required attributes are present
111
+ 2. Check that `[data-site-icon="slot"]` is the **first child** of both main and placeholder
112
+ 3. Ensure button wrapper has `[data-site-button="wrapper"]`
113
+
114
+ **Icons not updating after Barba transition:**
115
+
116
+ 1. Ensure `window.hsmain.reinitialize()` is called after transition
117
+ 2. Check that new page content has proper button structure
118
+
119
+ **Multiple buttons on page:**
120
+
121
+ 1. Each button works independently - if one fails, others continue
122
+ 2. Check console for warnings about missing elements
@@ -0,0 +1,274 @@
1
+ # **Counter System Documentation**
2
+
3
+ ## **Overview**
4
+
5
+ The counter system provides animated number counting that triggers when the counter scrolls into view. It supports prefixes, suffixes, decimals, and automatically handles accessibility by combining all text content into an aria-label.
6
+
7
+ ---
8
+
9
+ ## **Counter Setup**
10
+
11
+ ### **Required Elements**
12
+
13
+ **Counter Wrapper** *(main wrapper of the counter)*
14
+
15
+ * data-hs-counter="wrapper"
16
+
17
+ **Counter Number** *(the number element to animate)*
18
+
19
+ * data-hs-anim="counter"
20
+ * Contains the target number with optional prefix/suffix (e.g., "20+", "$1,500", "99.9%")
21
+
22
+ **Typical element layout:**
23
+
24
+ 1. Counter Wrapper (data-hs-counter="wrapper")
25
+ 1. Counter Number (data-hs-anim="counter")
26
+ 1. Text: "20+"
27
+ 2. Description Text (optional)
28
+ 1. Text: "Years of Experience"
29
+
30
+ ### **What It Does**
31
+
32
+ 1. **Parses numbers** - Extracts prefix, number, and suffix from counter text
33
+ 2. **Scroll trigger** - Uses IntersectionObserver to detect when counter enters viewport
34
+ 3. **Animates count** - Counts from 0 to target number with easeOutQuart easing
35
+ 4. **Accessibility** - Combines ALL text within wrapper into aria-label (e.g., "20+ Years of Experience")
36
+ 5. **Respects motion preferences** - Skips animation if user has `prefers-reduced-motion` enabled
37
+
38
+ ### **When It Runs**
39
+
40
+ * Runs once on page load to set up observers
41
+ * Triggers animation when counter scrolls into view (threshold: 0)
42
+ * Each counter only animates once (tracks with `data-animated="true"`)
43
+ * Runs again on Barba.js page transitions (via `reinitialize()`)
44
+
45
+ ---
46
+
47
+ ## **Number Formats**
48
+
49
+ ### **Supported Formats**
50
+
51
+ The counter automatically detects and preserves:
52
+
53
+ **Prefix:**
54
+ ```
55
+ $1000 � Counts from $0 to $1000
56
+ +500 � Counts from +0 to +500
57
+ ```
58
+
59
+ **Suffix:**
60
+ ```
61
+ 100% � Counts from 0% to 100%
62
+ 50+ � Counts from 0+ to 50+
63
+ 1000K � Counts from 0K to 1000K
64
+ ```
65
+
66
+ **Decimals:**
67
+ ```
68
+ 99.9 � Counts from 0.0 to 99.9 (preserves 1 decimal)
69
+ 3.14159 � Counts from 0.00000 to 3.14159 (preserves 5 decimals)
70
+ ```
71
+
72
+ **Combined:**
73
+ ```
74
+ $99.99 � Counts from $0.00 to $99.99
75
+ 50.5% � Counts from 0.0% to 50.5%
76
+ ```
77
+
78
+ ---
79
+
80
+ ## **Accessibility**
81
+
82
+ ### **Automatic ARIA Setup**
83
+
84
+ For each counter wrapper, the system:
85
+
86
+ 1. **Combines all text** - Uses TreeWalker to find all text nodes within wrapper
87
+ 2. **Creates aria-label** - Joins text with spaces (e.g., "20+ Years of Experience")
88
+ 3. **Sets role** - Adds `role="img"` to wrapper
89
+ 4. **Hides children** - Sets `aria-hidden="true"` on all descendant elements
90
+
91
+ ### **Example**
92
+
93
+ ```html
94
+ <!-- Before JS runs -->
95
+ <div data-hs-counter="wrapper">
96
+ <div data-hs-anim="counter">20+</div>
97
+ <div>Years of Experience</div>
98
+ </div>
99
+
100
+ <!-- After JS runs -->
101
+ <div data-hs-counter="wrapper" aria-label="20+ Years of Experience" role="img">
102
+ <div data-hs-anim="counter" aria-hidden="true">20+</div>
103
+ <div aria-hidden="true">Years of Experience</div>
104
+ </div>
105
+ ```
106
+
107
+ Screen readers announce: "20+ Years of Experience"
108
+
109
+ ---
110
+
111
+ ## **Usage Examples**
112
+
113
+ ### **Basic Counter**
114
+
115
+ ```html
116
+ <div data-hs-counter="wrapper">
117
+ <div data-hs-anim="counter">1000</div>
118
+ </div>
119
+ ```
120
+
121
+ **Result:** Counts from 0 to 1000 when scrolled into view
122
+ **aria-label:** "1000"
123
+
124
+ ### **Counter with Description**
125
+
126
+ ```html
127
+ <div data-hs-counter="wrapper">
128
+ <div data-hs-anim="counter">50+</div>
129
+ <p>Projects Completed</p>
130
+ </div>
131
+ ```
132
+
133
+ **Result:** Counts from 0+ to 50+
134
+ **aria-label:** "50+ Projects Completed"
135
+
136
+ ### **Currency Counter**
137
+
138
+ ```html
139
+ <div data-hs-counter="wrapper">
140
+ <div data-hs-anim="counter">$99.99</div>
141
+ <p>Starting Price</p>
142
+ </div>
143
+ ```
144
+
145
+ **Result:** Counts from $0.00 to $99.99
146
+ **aria-label:** "$99.99 Starting Price"
147
+
148
+ ### **Percentage Counter**
149
+
150
+ ```html
151
+ <div data-hs-counter="wrapper">
152
+ <div data-hs-anim="counter">99.9%</div>
153
+ <p>Uptime Guarantee</p>
154
+ </div>
155
+ ```
156
+
157
+ **Result:** Counts from 0.0% to 99.9%
158
+ **aria-label:** "99.9% Uptime Guarantee"
159
+
160
+ ---
161
+
162
+ ## **Configuration**
163
+
164
+ ### **Default Settings**
165
+
166
+ ```javascript
167
+ {
168
+ duration: 3000 // Animation duration in milliseconds
169
+ }
170
+ ```
171
+
172
+ ### **Updating Config**
173
+
174
+ ```javascript
175
+ window.hsmain.counter.updateConfig({
176
+ duration: 2000 // Faster animation
177
+ });
178
+ ```
179
+
180
+ **Note:** Config changes only affect counters that haven't animated yet.
181
+
182
+ ---
183
+
184
+ ## **API Methods**
185
+
186
+ ### **Trigger Animation Manually**
187
+
188
+ ```javascript
189
+ window.hsmain.counter.triggerAnimation('[data-hs-counter="wrapper"]');
190
+ ```
191
+
192
+ Manually triggers animation for a specific counter (bypasses scroll detection).
193
+
194
+ ### **Reset All Counters**
195
+
196
+ ```javascript
197
+ window.hsmain.counter.reset();
198
+ ```
199
+
200
+ Resets all counters to original state and re-enables scroll triggers.
201
+
202
+ ### **Access Counter Elements**
203
+
204
+ ```javascript
205
+ window.hsmain.counter.counters
206
+ ```
207
+
208
+ Returns array of all counter wrapper elements.
209
+
210
+ ---
211
+
212
+ ## **Animation Behavior**
213
+
214
+ ### **Easing Function**
215
+
216
+ Uses **easeOutQuart** for smooth deceleration:
217
+ - Starts fast
218
+ - Slows down as it approaches target
219
+ - Creates natural counting effect
220
+
221
+ ### **Reduced Motion**
222
+
223
+ If user has `prefers-reduced-motion: reduce` enabled:
224
+ - Skips animation entirely
225
+ - Shows final number immediately
226
+ - Respects user accessibility preferences
227
+
228
+ ---
229
+
230
+ ## **Key Attributes Summary**
231
+
232
+ | Attribute | Purpose | Required On |
233
+ | ----- | ----- | ----- |
234
+ | `data-hs-counter="wrapper"` | Counter container | Wrapper div |
235
+ | `data-hs-anim="counter"` | Number to animate | Number element |
236
+
237
+ ---
238
+
239
+ ## **Notes**
240
+
241
+ 1. **One-time animation** - Each counter animates only once when first scrolled into view
242
+ 2. **IntersectionObserver** - Uses `threshold: 0` (triggers as soon as any part is visible)
243
+ 3. **Original text preserved** - Stores original value in `data-hs-original` attribute
244
+ 4. **Barba.js compatible** - Automatically reinitializes on page transitions
245
+ 5. **No visual component** - Works with any styling, just handles number animation and a11y
246
+
247
+ ---
248
+
249
+ ## **Common Issues**
250
+
251
+ **Counter not animating:**
252
+
253
+ 1. Verify `data-hs-counter="wrapper"` is on container element
254
+ 2. Check that `data-hs-anim="counter"` is on number element
255
+ 3. Ensure number element contains parseable number
256
+ 4. Check if `prefers-reduced-motion` is enabled (animation skips)
257
+
258
+ **Wrong number format:**
259
+
260
+ 1. Counter auto-detects prefix/suffix - ensure format is: `[prefix][number][suffix]`
261
+ 2. Decimals are auto-detected from original number
262
+ 3. Use dot (.) for decimal separator, not comma
263
+
264
+ **Aria-label missing text:**
265
+
266
+ 1. Ensure all text is within `[data-hs-counter="wrapper"]`
267
+ 2. Check that text nodes have actual content (not just whitespace)
268
+ 3. Verify elements aren't hidden with `display: none` when script runs
269
+
270
+ **Counter animates multiple times:**
271
+
272
+ 1. This shouldn't happen - check if `reset()` is being called unintentionally
273
+ 2. Verify `data-animated` attribute is being set correctly
274
+ 3. Check for multiple script instances running
@@ -84,12 +84,27 @@ export function init() {
84
84
  const statsElements = document.querySelectorAll('[data-hs-counter="wrapper"]');
85
85
 
86
86
  statsElements.forEach((element) => {
87
- const numberElement = element.querySelector('[data-hs-anim="counter"]');
88
- const originalText = numberElement.getAttribute("data-hs-original");
89
-
90
- element.setAttribute("aria-label", originalText);
87
+ // Collect all text nodes and join with spaces
88
+ const walker = document.createTreeWalker(
89
+ element,
90
+ NodeFilter.SHOW_TEXT,
91
+ null
92
+ );
93
+
94
+ const textParts = [];
95
+ let node;
96
+ while (node = walker.nextNode()) {
97
+ const text = node.textContent.trim();
98
+ if (text) {
99
+ textParts.push(text);
100
+ }
101
+ }
102
+
103
+ const allText = textParts.join(' ');
104
+
105
+ element.setAttribute("aria-label", allText);
91
106
  element.setAttribute("role", "img");
92
-
107
+
93
108
  const allChildren = element.querySelectorAll("*");
94
109
  allChildren.forEach((child) => {
95
110
  child.setAttribute("aria-hidden", "true");