@hortonstudio/main 1.1.27 → 1.1.29
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/HS-MAIN-DOCUMENTATION.md +567 -0
- package/animations/transition.js +12 -5
- package/index.js +20 -12
- package/package.json +1 -1
- package/utils/toc.js +29 -0
@@ -0,0 +1,567 @@
|
|
1
|
+
# @hortonstudio/main - Complete Usage Guide
|
2
|
+
|
3
|
+
This is a comprehensive guide for using the `@hortonstudio/main` animation and utility library, designed for modern web applications including Webflow, Next.js, React, and vanilla JavaScript projects.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
1. [Installation & Setup](#installation--setup)
|
7
|
+
2. [Framework Integration](#framework-integration)
|
8
|
+
3. [Hero Animations](#hero-animations)
|
9
|
+
4. [Text Animations](#text-animations)
|
10
|
+
5. [Page Transitions](#page-transitions)
|
11
|
+
6. [Utility Modules](#utility-modules)
|
12
|
+
7. [Auto-Init Modules](#auto-init-modules)
|
13
|
+
8. [Configuration](#configuration)
|
14
|
+
9. [API Reference](#api-reference)
|
15
|
+
|
16
|
+
---
|
17
|
+
|
18
|
+
## Installation & Setup
|
19
|
+
|
20
|
+
### 1. Include the Script
|
21
|
+
Add this script tag to your page (preferably in the `<head>` or before closing `</body>`):
|
22
|
+
|
23
|
+
```html
|
24
|
+
<script src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest/index.js"
|
25
|
+
data-hs-main
|
26
|
+
data-hs-anim-hero
|
27
|
+
data-hs-util-toc></script>
|
28
|
+
```
|
29
|
+
|
30
|
+
### 2. Required Dependencies
|
31
|
+
Ensure GSAP with required plugins is loaded before the main script:
|
32
|
+
|
33
|
+
```html
|
34
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
35
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
|
36
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/SplitText.min.js"></script>
|
37
|
+
```
|
38
|
+
|
39
|
+
### 3. Module Loading
|
40
|
+
Modules are loaded based on data attributes on the script tag:
|
41
|
+
|
42
|
+
- `data-hs-main`: **Required** - Core library identifier
|
43
|
+
- `data-hs-anim-*`: Animation modules
|
44
|
+
- `data-hs-util-*`: Utility modules
|
45
|
+
|
46
|
+
**Example:**
|
47
|
+
```html
|
48
|
+
<script src="index.js"
|
49
|
+
data-hs-main
|
50
|
+
data-hs-anim-hero
|
51
|
+
data-hs-anim-text
|
52
|
+
data-hs-util-navbar
|
53
|
+
data-hs-util-progress></script>
|
54
|
+
```
|
55
|
+
|
56
|
+
---
|
57
|
+
|
58
|
+
## Framework Integration
|
59
|
+
|
60
|
+
### Webflow
|
61
|
+
The library works seamlessly with Webflow with full integration support:
|
62
|
+
|
63
|
+
```html
|
64
|
+
<script src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest/index.js"
|
65
|
+
data-hs-main
|
66
|
+
data-hs-anim-hero
|
67
|
+
data-hs-util-toc></script>
|
68
|
+
```
|
69
|
+
|
70
|
+
### Next.js / React
|
71
|
+
For Next.js applications, install and use as an ES module:
|
72
|
+
|
73
|
+
```bash
|
74
|
+
npm install @hortonstudio/main
|
75
|
+
```
|
76
|
+
|
77
|
+
```javascript
|
78
|
+
// In your component or _app.js
|
79
|
+
import { useEffect } from 'react'
|
80
|
+
|
81
|
+
export default function MyApp({ Component, pageProps }) {
|
82
|
+
useEffect(() => {
|
83
|
+
// Load the library after component mounts
|
84
|
+
import('@hortonstudio/main').then((lib) => {
|
85
|
+
// Library automatically initializes
|
86
|
+
console.log('HS Main loaded:', window.hsmain)
|
87
|
+
})
|
88
|
+
}, [])
|
89
|
+
|
90
|
+
return <Component {...pageProps} />
|
91
|
+
}
|
92
|
+
```
|
93
|
+
|
94
|
+
### Vanilla JavaScript
|
95
|
+
For standard JavaScript projects:
|
96
|
+
|
97
|
+
```javascript
|
98
|
+
// Import as ES module
|
99
|
+
import '@hortonstudio/main'
|
100
|
+
|
101
|
+
// Or use CDN with script tag
|
102
|
+
// <script src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest/index.js" data-hs-main></script>
|
103
|
+
|
104
|
+
// Access via global API
|
105
|
+
console.log(window.hsmain.status())
|
106
|
+
```
|
107
|
+
|
108
|
+
### Vue.js
|
109
|
+
```javascript
|
110
|
+
// In main.js or component
|
111
|
+
import { onMounted } from 'vue'
|
112
|
+
import '@hortonstudio/main'
|
113
|
+
|
114
|
+
export default {
|
115
|
+
setup() {
|
116
|
+
onMounted(() => {
|
117
|
+
// Library ready after DOM mount
|
118
|
+
window.hsmain.afterReady(() => {
|
119
|
+
console.log('Animations ready!')
|
120
|
+
})
|
121
|
+
})
|
122
|
+
}
|
123
|
+
}
|
124
|
+
```
|
125
|
+
|
126
|
+
### Framework-Agnostic Initialization
|
127
|
+
The library detects the environment and initializes appropriately:
|
128
|
+
|
129
|
+
- **With Webflow**: Uses `Webflow.ready()` and `Webflow.push()`
|
130
|
+
- **Without Webflow**: Uses standard DOM events and timeouts
|
131
|
+
- **Universal**: All animations and utilities work in any environment
|
132
|
+
|
133
|
+
---
|
134
|
+
|
135
|
+
## Hero Animations
|
136
|
+
|
137
|
+
Hero animations create orchestrated entrance animations for landing page elements.
|
138
|
+
|
139
|
+
### Basic Setup
|
140
|
+
|
141
|
+
#### 1. Navigation
|
142
|
+
```html
|
143
|
+
<nav data-hs-hero="nav">
|
144
|
+
<!-- Your navigation content -->
|
145
|
+
</nav>
|
146
|
+
```
|
147
|
+
|
148
|
+
#### 2. Advanced Navigation (with staggered animations)
|
149
|
+
```html
|
150
|
+
<nav data-hs-hero="nav" data-hs-heroconfig="advanced">
|
151
|
+
<div data-hs-hero="nav-logo">
|
152
|
+
<!-- Logo content -->
|
153
|
+
</div>
|
154
|
+
<ul data-hs-hero="nav-list">
|
155
|
+
<li><a href="#">Link 1</a></li>
|
156
|
+
<li><a href="#">Link 2</a></li>
|
157
|
+
</ul>
|
158
|
+
<div data-hs-hero="nav-menu">
|
159
|
+
<!-- Menu button -->
|
160
|
+
</div>
|
161
|
+
<div data-hs-hero="nav-button">
|
162
|
+
<!-- CTA button -->
|
163
|
+
</div>
|
164
|
+
</nav>
|
165
|
+
```
|
166
|
+
|
167
|
+
#### 3. Headings with Text Splitting
|
168
|
+
```html
|
169
|
+
<div data-hs-hero="heading" data-hs-heroconfig="word">
|
170
|
+
<h1>Your Main Heading</h1>
|
171
|
+
</div>
|
172
|
+
|
173
|
+
<div data-hs-hero="heading" data-hs-heroconfig="line">
|
174
|
+
<h1>Multi-line Heading That Splits by Lines</h1>
|
175
|
+
</div>
|
176
|
+
|
177
|
+
<div data-hs-hero="heading" data-hs-heroconfig="char">
|
178
|
+
<h1>Character Split Animation</h1>
|
179
|
+
</div>
|
180
|
+
```
|
181
|
+
|
182
|
+
#### 4. Subheadings
|
183
|
+
```html
|
184
|
+
<div data-hs-hero="subheading" data-hs-heroconfig="appear">
|
185
|
+
<h2>Simple fade-in subheading</h2>
|
186
|
+
</div>
|
187
|
+
|
188
|
+
<div data-hs-hero="subheading" data-hs-heroconfig="word">
|
189
|
+
<h2>Word-split subheading</h2>
|
190
|
+
</div>
|
191
|
+
```
|
192
|
+
|
193
|
+
#### 5. Other Hero Elements
|
194
|
+
```html
|
195
|
+
<!-- Announcement banner -->
|
196
|
+
<div data-hs-hero="announce">
|
197
|
+
<p>Special announcement</p>
|
198
|
+
</div>
|
199
|
+
|
200
|
+
<!-- Tag/category -->
|
201
|
+
<div data-hs-hero="tag">
|
202
|
+
<span>Category Tag</span>
|
203
|
+
</div>
|
204
|
+
|
205
|
+
<!-- Buttons (all children animate with stagger) -->
|
206
|
+
<div data-hs-hero="button">
|
207
|
+
<a href="#" class="btn">Primary Button</a>
|
208
|
+
<a href="#" class="btn">Secondary Button</a>
|
209
|
+
</div>
|
210
|
+
|
211
|
+
<!-- Images -->
|
212
|
+
<img data-hs-hero="image" src="hero-image.jpg" alt="Hero Image">
|
213
|
+
|
214
|
+
<!-- General appear elements -->
|
215
|
+
<div data-hs-hero="appear">
|
216
|
+
<p>Any content that should fade in</p>
|
217
|
+
</div>
|
218
|
+
```
|
219
|
+
|
220
|
+
### Hero Configuration Options
|
221
|
+
|
222
|
+
| Attribute Value | Description | Usage |
|
223
|
+
|----------------|-------------|--------|
|
224
|
+
| `word` | Split text by words | `data-hs-heroconfig="word"` |
|
225
|
+
| `line` | Split text by lines | `data-hs-heroconfig="line"` |
|
226
|
+
| `char` | Split text by characters | `data-hs-heroconfig="char"` |
|
227
|
+
| `appear` | Simple fade-in animation | `data-hs-heroconfig="appear"` |
|
228
|
+
| `advanced` | Enable advanced nav animations | `data-hs-heroconfig="advanced"` |
|
229
|
+
|
230
|
+
---
|
231
|
+
|
232
|
+
## Text Animations
|
233
|
+
|
234
|
+
Text animations provide scroll-triggered text splitting animations for content sections.
|
235
|
+
|
236
|
+
### Setup Classes
|
237
|
+
|
238
|
+
Add these classes to parent elements, with the actual text element as the first child:
|
239
|
+
|
240
|
+
#### 1. Word Split Animation
|
241
|
+
```html
|
242
|
+
<div class="a-word-split">
|
243
|
+
<h2>Text that splits by words on scroll</h2>
|
244
|
+
</div>
|
245
|
+
```
|
246
|
+
|
247
|
+
#### 2. Line Split Animation
|
248
|
+
```html
|
249
|
+
<div class="a-line-split">
|
250
|
+
<h2>Multi-line text that splits by lines</h2>
|
251
|
+
</div>
|
252
|
+
```
|
253
|
+
|
254
|
+
#### 3. Character Split Animation
|
255
|
+
```html
|
256
|
+
<div class="a-char-split">
|
257
|
+
<h1>Text split by individual characters</h1>
|
258
|
+
</div>
|
259
|
+
```
|
260
|
+
|
261
|
+
#### 4. Simple Appear Animation
|
262
|
+
```html
|
263
|
+
<div class="a-appear">
|
264
|
+
<p>Content that fades in on scroll</p>
|
265
|
+
</div>
|
266
|
+
```
|
267
|
+
|
268
|
+
### Important Notes
|
269
|
+
- **First child targeting**: The animation targets the **first child element** of the element with the class
|
270
|
+
- **Scroll triggered**: All text animations trigger when the element enters the viewport
|
271
|
+
- **Auto cleanup**: SplitText instances are automatically cleaned up after animation completes
|
272
|
+
|
273
|
+
---
|
274
|
+
|
275
|
+
## Page Transitions
|
276
|
+
|
277
|
+
Page transitions create smooth animations between page loads.
|
278
|
+
|
279
|
+
### Setup
|
280
|
+
|
281
|
+
#### 1. Add Transition Trigger Element
|
282
|
+
```html
|
283
|
+
<!-- This element triggers the transition animation -->
|
284
|
+
<div class="transition-trigger" style="display: none;"></div>
|
285
|
+
```
|
286
|
+
|
287
|
+
#### 2. Add Transition Overlay
|
288
|
+
```html
|
289
|
+
<!-- This element covers the screen during transitions -->
|
290
|
+
<div class="transition">
|
291
|
+
<!-- Your transition content/animation -->
|
292
|
+
</div>
|
293
|
+
```
|
294
|
+
|
295
|
+
#### 3. Exclude Links from Transitions
|
296
|
+
```html
|
297
|
+
<!-- Links that should NOT trigger transitions -->
|
298
|
+
<a href="/page" class="no-transition">Direct Link</a>
|
299
|
+
<a href="/external" target="_blank">External Link</a>
|
300
|
+
<a href="#section">Anchor Link</a>
|
301
|
+
```
|
302
|
+
|
303
|
+
### Configuration
|
304
|
+
- **Intro Duration**: 800ms (time for page load transition)
|
305
|
+
- **Exit Duration**: 400ms (time for page exit transition)
|
306
|
+
- **Excluded**: Links with `no-transition` class, external links, anchor links
|
307
|
+
- **Auto-disable**: Transitions disable on window resize for mobile compatibility
|
308
|
+
|
309
|
+
---
|
310
|
+
|
311
|
+
## Utility Modules
|
312
|
+
|
313
|
+
### Table of Contents (TOC)
|
314
|
+
Auto-generates navigation from page headings.
|
315
|
+
|
316
|
+
```html
|
317
|
+
<!-- Container where TOC will be inserted -->
|
318
|
+
<nav data-hs-toc="container">
|
319
|
+
<!-- TOC items will be auto-generated here -->
|
320
|
+
</nav>
|
321
|
+
|
322
|
+
<!-- Headings that should appear in TOC -->
|
323
|
+
<h2 data-hs-toc="item">Section 1</h2>
|
324
|
+
<h3 data-hs-toc="item">Subsection 1.1</h3>
|
325
|
+
<h2 data-hs-toc="item">Section 2</h2>
|
326
|
+
```
|
327
|
+
|
328
|
+
### Scroll Progress Indicator
|
329
|
+
Shows page scroll progress.
|
330
|
+
|
331
|
+
```html
|
332
|
+
<!-- Progress bar element -->
|
333
|
+
<div data-hs-progress="bar"></div>
|
334
|
+
```
|
335
|
+
|
336
|
+
### Smart Navbar
|
337
|
+
Navbar that hides/shows based on scroll direction.
|
338
|
+
|
339
|
+
```html
|
340
|
+
<nav data-hs-navbar="container">
|
341
|
+
<!-- Your navigation content -->
|
342
|
+
</nav>
|
343
|
+
```
|
344
|
+
|
345
|
+
**Behavior:**
|
346
|
+
- Hides when scrolling down
|
347
|
+
- Shows when scrolling up
|
348
|
+
- Always visible at the top of the page
|
349
|
+
- Smooth transitions with CSS transforms
|
350
|
+
|
351
|
+
---
|
352
|
+
|
353
|
+
## Auto-Init Modules
|
354
|
+
|
355
|
+
These modules load automatically without requiring data attributes.
|
356
|
+
|
357
|
+
### Smooth Scroll
|
358
|
+
- **Automatically enabled** for all anchor links
|
359
|
+
- **Smooth scrolling** to page sections
|
360
|
+
- **Offset support** for fixed headers
|
361
|
+
- **No setup required**
|
362
|
+
|
363
|
+
---
|
364
|
+
|
365
|
+
## Configuration
|
366
|
+
|
367
|
+
### Global API Access
|
368
|
+
All modules expose configuration through the global API:
|
369
|
+
|
370
|
+
```javascript
|
371
|
+
// Access the API (default name: 'hsmain')
|
372
|
+
window.hsmain
|
373
|
+
|
374
|
+
// Check module status
|
375
|
+
window.hsmain.status() // All modules
|
376
|
+
window.hsmain.status('data-hs-anim-hero') // Specific module
|
377
|
+
|
378
|
+
// Restart a module
|
379
|
+
window.hsmain.modules['data-hs-anim-hero'].restart()
|
380
|
+
```
|
381
|
+
|
382
|
+
### Hero Animation Configuration
|
383
|
+
```javascript
|
384
|
+
// Update hero animation settings
|
385
|
+
window.hsmain.heroAnimations.updateConfig({
|
386
|
+
global: {
|
387
|
+
animationDelay: 0.5 // Delay before animations start
|
388
|
+
},
|
389
|
+
headingSplit: {
|
390
|
+
duration: 2.0, // Animation duration
|
391
|
+
stagger: 0.15, // Delay between elements
|
392
|
+
yPercent: 120, // Initial position offset
|
393
|
+
ease: "power3.out" // Easing function
|
394
|
+
}
|
395
|
+
})
|
396
|
+
|
397
|
+
// Restart hero animations with new config
|
398
|
+
window.hsmain.heroAnimations.restart()
|
399
|
+
```
|
400
|
+
|
401
|
+
### Module Animation Configuration
|
402
|
+
```javascript
|
403
|
+
// Update text animation settings
|
404
|
+
window.hsmain.moduleAnimations.config.updateConfig({
|
405
|
+
wordSplit: {
|
406
|
+
duration: 1.8,
|
407
|
+
stagger: 0.1,
|
408
|
+
start: "top 90%" // ScrollTrigger start position
|
409
|
+
}
|
410
|
+
})
|
411
|
+
```
|
412
|
+
|
413
|
+
---
|
414
|
+
|
415
|
+
## API Reference
|
416
|
+
|
417
|
+
### Core API Methods
|
418
|
+
|
419
|
+
```javascript
|
420
|
+
// Load a module manually
|
421
|
+
window.hsmain.load('data-hs-util-navbar')
|
422
|
+
|
423
|
+
// Check if modules are loaded/loading
|
424
|
+
window.hsmain.status()
|
425
|
+
// Returns: { loaded: [...], loading: [...], animations: [...], utilities: [...] }
|
426
|
+
|
427
|
+
// Register callback for after library initialization
|
428
|
+
window.hsmain.afterReady(() => {
|
429
|
+
console.log('Library is ready!')
|
430
|
+
})
|
431
|
+
|
432
|
+
// Legacy Webflow callback (still supported)
|
433
|
+
window.hsmain.afterWebflowReady(() => {
|
434
|
+
console.log('Webflow compatibility mode')
|
435
|
+
})
|
436
|
+
```
|
437
|
+
|
438
|
+
### Hero Animations API
|
439
|
+
|
440
|
+
```javascript
|
441
|
+
// Available methods
|
442
|
+
window.hsmain.heroAnimations.start() // Start animations
|
443
|
+
window.hsmain.heroAnimations.kill() // Stop animations
|
444
|
+
window.hsmain.heroAnimations.restart() // Restart animations
|
445
|
+
window.hsmain.heroAnimations.config // Current configuration
|
446
|
+
window.hsmain.heroAnimations.updateConfig(newConfig) // Update settings
|
447
|
+
```
|
448
|
+
|
449
|
+
### Timing Configuration
|
450
|
+
|
451
|
+
#### Hero Animation Timing (in seconds)
|
452
|
+
```javascript
|
453
|
+
const timing = {
|
454
|
+
announce: 0, // Announcement elements
|
455
|
+
nav: 0.1, // Main navigation
|
456
|
+
navLogo: 0.3, // Navigation logo
|
457
|
+
navList: 0.35, // Navigation links
|
458
|
+
navMenu: 0.35, // Menu button
|
459
|
+
navButton: 0.5, // CTA button
|
460
|
+
tag: 0.1, // Category tags
|
461
|
+
heading: 0.15, // Main headings
|
462
|
+
subheading: 0.25, // Subheadings
|
463
|
+
button: 0.35, // Action buttons
|
464
|
+
image: 0.5, // Images
|
465
|
+
appear: 0.6 // General appear elements
|
466
|
+
}
|
467
|
+
```
|
468
|
+
|
469
|
+
---
|
470
|
+
|
471
|
+
## CSS Utility Classes
|
472
|
+
|
473
|
+
The library includes these utility classes:
|
474
|
+
|
475
|
+
```css
|
476
|
+
/* Transition styles */
|
477
|
+
.transition { display: block; }
|
478
|
+
.w-editor .transition { display: none; }
|
479
|
+
.no-scroll-transition { overflow: hidden; position: relative; }
|
480
|
+
|
481
|
+
/* Split text masks */
|
482
|
+
.line-mask, .word-mask, .char-mask {
|
483
|
+
padding-bottom: .1em;
|
484
|
+
margin-bottom: -.1em;
|
485
|
+
padding-inline: .1em;
|
486
|
+
margin-inline: -.1em;
|
487
|
+
}
|
488
|
+
|
489
|
+
/* Scroll improvements */
|
490
|
+
html, body {
|
491
|
+
overscroll-behavior: none;
|
492
|
+
scrollbar-gutter: stable;
|
493
|
+
}
|
494
|
+
```
|
495
|
+
|
496
|
+
---
|
497
|
+
|
498
|
+
## Best Practices
|
499
|
+
|
500
|
+
### 1. Module Loading
|
501
|
+
- Only load modules you actually use
|
502
|
+
- Include required dependencies before the main script
|
503
|
+
- Use `data-hs-main` on the script tag
|
504
|
+
|
505
|
+
### 2. Hero Animations
|
506
|
+
- Structure your HTML with proper parent/child relationships
|
507
|
+
- Use semantic HTML elements (h1, h2, nav, etc.)
|
508
|
+
- Test animations on different screen sizes
|
509
|
+
|
510
|
+
### 3. Text Animations
|
511
|
+
- Place classes on parent containers, not the text elements directly
|
512
|
+
- Ensure the text element is the first child
|
513
|
+
- Consider animation timing with page scroll speed
|
514
|
+
|
515
|
+
### 4. Performance
|
516
|
+
- Animations wait for fonts to load (`document.fonts.ready`)
|
517
|
+
- SplitText instances are cleaned up automatically
|
518
|
+
- Modules only initialize when needed
|
519
|
+
|
520
|
+
### 5. Framework Integration
|
521
|
+
- **Webflow**: Full integration with Webflow's responsive design and interactions
|
522
|
+
- **React/Next.js**: Works with SSR and client-side rendering
|
523
|
+
- **Vue.js**: Compatible with reactive data and component lifecycle
|
524
|
+
- **Universal**: Framework-agnostic core ensures compatibility
|
525
|
+
|
526
|
+
---
|
527
|
+
|
528
|
+
## Troubleshooting
|
529
|
+
|
530
|
+
### Common Issues
|
531
|
+
|
532
|
+
1. **Animations not starting**
|
533
|
+
- Check that GSAP and plugins are loaded
|
534
|
+
- Verify data attributes are correct
|
535
|
+
- Check browser console for errors
|
536
|
+
|
537
|
+
2. **Text splitting not working**
|
538
|
+
- Ensure SplitText plugin is loaded
|
539
|
+
- Check that target element is the first child
|
540
|
+
- Verify class names are correct
|
541
|
+
|
542
|
+
3. **Module not loading**
|
543
|
+
- Check script tag has `data-hs-main`
|
544
|
+
- Verify module attribute name
|
545
|
+
- Check `window.hsmain.status()` for loading state
|
546
|
+
|
547
|
+
4. **Webflow conflicts**
|
548
|
+
- Ensure script loads after Webflow
|
549
|
+
- Check for conflicting CSS
|
550
|
+
- Test without other custom scripts
|
551
|
+
|
552
|
+
### Debug Commands
|
553
|
+
|
554
|
+
```javascript
|
555
|
+
// Check what's loaded
|
556
|
+
console.log(window.hsmain.status())
|
557
|
+
|
558
|
+
// Check for errors
|
559
|
+
window.hsmain.modules
|
560
|
+
|
561
|
+
// Restart problematic modules
|
562
|
+
window.hsmain.modules['module-name'].restart()
|
563
|
+
```
|
564
|
+
|
565
|
+
---
|
566
|
+
|
567
|
+
*This documentation covers version 1.1.27 of @hortonstudio/main*
|
package/animations/transition.js
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
const API_NAME = 'hsmain';
|
3
3
|
export async function init() {
|
4
4
|
|
5
|
-
// Register the transition logic to run after
|
6
|
-
window[API_NAME].
|
5
|
+
// Register the transition logic to run after library is ready
|
6
|
+
window[API_NAME].afterReady(() => {
|
7
7
|
// Only run if jQuery is available
|
8
8
|
if (typeof $ !== 'undefined') {
|
9
9
|
initTransitions();
|
@@ -21,9 +21,16 @@ function initTransitions() {
|
|
21
21
|
|
22
22
|
// On Page Load
|
23
23
|
if (transitionTrigger.length > 0) {
|
24
|
-
Webflow.push
|
25
|
-
|
26
|
-
|
24
|
+
if (window.Webflow && window.Webflow.push) {
|
25
|
+
Webflow.push(function () {
|
26
|
+
transitionTrigger.click();
|
27
|
+
});
|
28
|
+
} else {
|
29
|
+
// Non-Webflow initialization
|
30
|
+
setTimeout(() => {
|
31
|
+
transitionTrigger.click();
|
32
|
+
}, 100);
|
33
|
+
}
|
27
34
|
$("body").addClass("no-scroll-transition");
|
28
35
|
setTimeout(() => {$("body").removeClass("no-scroll-transition");}, introDurationMS);
|
29
36
|
}
|
package/index.js
CHANGED
@@ -79,18 +79,18 @@ const refreshWebflow = () => {
|
|
79
79
|
setTimeout(() => {
|
80
80
|
if (window.Webflow && window.Webflow.ready) {
|
81
81
|
window.Webflow.ready();
|
82
|
-
|
83
|
-
// Run all registered post-Webflow callbacks
|
84
|
-
setTimeout(() => {
|
85
|
-
postWebflowCallbacks.forEach(callback => {
|
86
|
-
try {
|
87
|
-
callback();
|
88
|
-
} catch (error) {
|
89
|
-
}
|
90
|
-
});
|
91
|
-
window[API_NAME].loaded = true;
|
92
|
-
},);
|
93
82
|
}
|
83
|
+
|
84
|
+
// Run all registered post-Webflow callbacks (even without Webflow)
|
85
|
+
setTimeout(() => {
|
86
|
+
postWebflowCallbacks.forEach(callback => {
|
87
|
+
try {
|
88
|
+
callback();
|
89
|
+
} catch (error) {
|
90
|
+
}
|
91
|
+
});
|
92
|
+
window[API_NAME].loaded = true;
|
93
|
+
},);
|
94
94
|
},);
|
95
95
|
};
|
96
96
|
|
@@ -155,7 +155,15 @@ const initializeAPI = () => {
|
|
155
155
|
|
156
156
|
load: loadHsModule,
|
157
157
|
|
158
|
-
// API function for scripts to register post-
|
158
|
+
// API function for scripts to register post-initialization callbacks
|
159
|
+
afterReady: (callback) => {
|
160
|
+
if (typeof callback === 'function') {
|
161
|
+
postWebflowCallbacks.push(callback);
|
162
|
+
} else {
|
163
|
+
}
|
164
|
+
},
|
165
|
+
|
166
|
+
// Legacy alias for Webflow compatibility
|
159
167
|
afterWebflowReady: (callback) => {
|
160
168
|
if (typeof callback === 'function') {
|
161
169
|
postWebflowCallbacks.push(callback);
|
package/package.json
CHANGED
package/utils/toc.js
CHANGED
@@ -44,6 +44,35 @@ export async function init() {
|
|
44
44
|
link.appendChild(number);
|
45
45
|
link.appendChild(document.createTextNode(heading.textContent));
|
46
46
|
|
47
|
+
// Add click handler to prevent focus on mouse clicks but allow keyboard focus
|
48
|
+
link.addEventListener('click', (e) => {
|
49
|
+
// Prevent default to handle scrolling ourselves
|
50
|
+
e.preventDefault();
|
51
|
+
|
52
|
+
const targetSection = document.getElementById(sectionId);
|
53
|
+
if (targetSection) {
|
54
|
+
// Scroll to the section
|
55
|
+
targetSection.scrollIntoView({ behavior: 'smooth' });
|
56
|
+
|
57
|
+
// Don't focus the target element on mouse clicks (Safari focus issue)
|
58
|
+
// Focus will still work with keyboard navigation (Enter key, etc.)
|
59
|
+
}
|
60
|
+
});
|
61
|
+
|
62
|
+
// Handle keyboard navigation (Enter/Space) to maintain accessibility
|
63
|
+
link.addEventListener('keydown', (e) => {
|
64
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
65
|
+
e.preventDefault();
|
66
|
+
|
67
|
+
const targetSection = document.getElementById(sectionId);
|
68
|
+
if (targetSection) {
|
69
|
+
targetSection.scrollIntoView({ behavior: 'smooth' });
|
70
|
+
// Allow focus for keyboard users
|
71
|
+
targetSection.focus();
|
72
|
+
}
|
73
|
+
}
|
74
|
+
});
|
75
|
+
|
47
76
|
// Add item to the TOC list
|
48
77
|
tocList.appendChild(tocItem);
|
49
78
|
});
|