@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.
@@ -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*
@@ -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 Webflow is ready
6
- window[API_NAME].afterWebflowReady(() => {
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(function () {
25
- transitionTrigger.click();
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-Webflow callbacks
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hortonstudio/main",
3
- "version": "1.1.27",
3
+ "version": "1.1.29",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {
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
  });