@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/archive/modal.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
function initModal() {
|
|
2
|
-
const config = {
|
|
3
|
-
transitionDuration: 0.3,
|
|
4
|
-
blurOpacity: 0.5,
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
function openModal(element) {
|
|
9
|
-
document.body.classList.add("u-overflow-clip");
|
|
10
|
-
|
|
11
|
-
// Add blur to all other modals
|
|
12
|
-
document.querySelectorAll("[data-hs-modal]").forEach((modal) => {
|
|
13
|
-
if (modal !== element) {
|
|
14
|
-
modal.style.display = "block";
|
|
15
|
-
modal.style.opacity = config.blurOpacity;
|
|
16
|
-
modal.style.transition = `opacity ${config.transitionDuration}s ease`;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function closeModal(element) {
|
|
22
|
-
document.body.classList.remove("u-overflow-clip");
|
|
23
|
-
|
|
24
|
-
// Remove blur from all other modals
|
|
25
|
-
document.querySelectorAll("[data-hs-modal]").forEach((modal) => {
|
|
26
|
-
if (modal !== element) {
|
|
27
|
-
modal.style.display = "none";
|
|
28
|
-
modal.style.opacity = "0";
|
|
29
|
-
modal.style.transition = `opacity ${config.transitionDuration}s ease`;
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
function toggleModal(element) {
|
|
36
|
-
element.x = ((element.x || 0) + 1) % 2;
|
|
37
|
-
|
|
38
|
-
if (element.x) {
|
|
39
|
-
openModal(element);
|
|
40
|
-
} else {
|
|
41
|
-
closeModal(element);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Initialize openclose functionality
|
|
46
|
-
document
|
|
47
|
-
.querySelectorAll('[data-hs-modal="openclose"]')
|
|
48
|
-
.forEach((trigger) => {
|
|
49
|
-
trigger.addEventListener("click", function () {
|
|
50
|
-
toggleModal(this);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Initialize open functionality
|
|
55
|
-
document.querySelectorAll('[data-hs-modal="open"]').forEach((trigger) => {
|
|
56
|
-
trigger.addEventListener("click", function () {
|
|
57
|
-
openModal(this);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Initialize close functionality
|
|
62
|
-
document.querySelectorAll('[data-hs-modal="close"]').forEach((trigger) => {
|
|
63
|
-
trigger.addEventListener("click", function () {
|
|
64
|
-
closeModal(this);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return { result: "modal initialized" };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function init() {
|
|
73
|
-
if (document.readyState === "loading") {
|
|
74
|
-
document.addEventListener("DOMContentLoaded", initModal);
|
|
75
|
-
} else {
|
|
76
|
-
initModal();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return { result: "modal initialized" };
|
|
80
|
-
}
|
package/archive/text.js
DELETED
|
@@ -1,628 +0,0 @@
|
|
|
1
|
-
const API_NAME = "hsmain";
|
|
2
|
-
|
|
3
|
-
// Module-scoped variables for resize handling
|
|
4
|
-
let resizeHandler;
|
|
5
|
-
|
|
6
|
-
// Check for reduced motion preference
|
|
7
|
-
const prefersReducedMotion = () => {
|
|
8
|
-
return (
|
|
9
|
-
window.matchMedia &&
|
|
10
|
-
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
11
|
-
);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const config = {
|
|
15
|
-
global: {
|
|
16
|
-
animationDelay: 0,
|
|
17
|
-
},
|
|
18
|
-
wordSplit: {
|
|
19
|
-
duration: 1.5,
|
|
20
|
-
stagger: 0.05,
|
|
21
|
-
yPercent: 110,
|
|
22
|
-
ease: "power4.out",
|
|
23
|
-
start: "top 97%",
|
|
24
|
-
},
|
|
25
|
-
lineSplit: {
|
|
26
|
-
duration: 1.5,
|
|
27
|
-
stagger: 0.1,
|
|
28
|
-
yPercent: 110,
|
|
29
|
-
ease: "power4.out",
|
|
30
|
-
start: "top 97%",
|
|
31
|
-
},
|
|
32
|
-
charSplit: {
|
|
33
|
-
duration: 1.2,
|
|
34
|
-
stagger: 0.015,
|
|
35
|
-
yPercent: 110,
|
|
36
|
-
ease: "power4.out",
|
|
37
|
-
start: "top 97%",
|
|
38
|
-
},
|
|
39
|
-
appear: {
|
|
40
|
-
y: 50,
|
|
41
|
-
duration: 1.5,
|
|
42
|
-
ease: "power3.out",
|
|
43
|
-
start: "top 97%",
|
|
44
|
-
},
|
|
45
|
-
reveal: {
|
|
46
|
-
y: 50,
|
|
47
|
-
duration: 1.5,
|
|
48
|
-
ease: "power3.out",
|
|
49
|
-
start: "top 97%",
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
function updateConfig(newConfig) {
|
|
54
|
-
function deepMerge(target, source) {
|
|
55
|
-
for (const key in source) {
|
|
56
|
-
if (
|
|
57
|
-
source[key] &&
|
|
58
|
-
typeof source[key] === "object" &&
|
|
59
|
-
!Array.isArray(source[key])
|
|
60
|
-
) {
|
|
61
|
-
target[key] = target[key] || {};
|
|
62
|
-
deepMerge(target[key], source[key]);
|
|
63
|
-
} else {
|
|
64
|
-
target[key] = source[key];
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return target;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
deepMerge(config, newConfig);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function killTextAnimations() {
|
|
74
|
-
activeAnimations.forEach(({ timeline, element }) => {
|
|
75
|
-
if (timeline) {
|
|
76
|
-
timeline.kill();
|
|
77
|
-
}
|
|
78
|
-
if (element?.splitTextInstance) {
|
|
79
|
-
element.splitTextInstance.revert();
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
activeAnimations.length = 0;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function startTextAnimations() {
|
|
86
|
-
if (prefersReducedMotion()) {
|
|
87
|
-
// For reduced motion, just show elements without animation
|
|
88
|
-
showElementsWithoutAnimation();
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
setInitialStates().then(() => {
|
|
93
|
-
initAnimations();
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let activeAnimations = [];
|
|
98
|
-
|
|
99
|
-
async function waitForFonts() {
|
|
100
|
-
try {
|
|
101
|
-
return await document.fonts.ready;
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.warn("Font loading error:", error);
|
|
104
|
-
return Promise.resolve();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function findTextElement(container) {
|
|
109
|
-
// Simple direct approach: if container has direct text content, use it
|
|
110
|
-
// Otherwise use first child with text content
|
|
111
|
-
const firstChild = container.firstElementChild;
|
|
112
|
-
return firstChild && firstChild.textContent.trim() ? firstChild : container;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function showElementsWithoutAnimation() {
|
|
116
|
-
// Safari-optimized: Use single query with comma-separated selectors
|
|
117
|
-
// This is significantly faster than multiple querySelectorAll calls
|
|
118
|
-
const allTextElements = document.querySelectorAll(
|
|
119
|
-
'[data-hs-anim="char"], [data-hs-anim="word"], [data-hs-anim="line"], [data-hs-anim="appear"], [data-hs-anim="reveal"], [data-hs-anim="group"]'
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// Batch DOM operations for better Safari performance
|
|
123
|
-
const elementsArray = Array.from(allTextElements);
|
|
124
|
-
elementsArray.forEach((element) => {
|
|
125
|
-
try {
|
|
126
|
-
gsap.set(element, {
|
|
127
|
-
autoAlpha: 1,
|
|
128
|
-
y: 0,
|
|
129
|
-
yPercent: 0,
|
|
130
|
-
opacity: 1,
|
|
131
|
-
});
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.warn("Error setting element visibility:", error);
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const CharSplitAnimations = {
|
|
139
|
-
async initial() {
|
|
140
|
-
await waitForFonts();
|
|
141
|
-
|
|
142
|
-
if (prefersReducedMotion()) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const elements = document.querySelectorAll('[data-hs-anim="char"]');
|
|
147
|
-
|
|
148
|
-
elements.forEach((container) => {
|
|
149
|
-
const textElement = findTextElement(container);
|
|
150
|
-
|
|
151
|
-
const split = SplitText.create(textElement, {
|
|
152
|
-
type: "words,chars",
|
|
153
|
-
mask: "chars",
|
|
154
|
-
charsClass: "char",
|
|
155
|
-
});
|
|
156
|
-
container.splitTextInstance = split;
|
|
157
|
-
|
|
158
|
-
gsap.set(split.chars, {
|
|
159
|
-
yPercent: config.charSplit.yPercent,
|
|
160
|
-
});
|
|
161
|
-
gsap.set(textElement, { autoAlpha: 1 });
|
|
162
|
-
});
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
async animate() {
|
|
166
|
-
await waitForFonts();
|
|
167
|
-
|
|
168
|
-
if (prefersReducedMotion()) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const elements = document.querySelectorAll('[data-hs-anim="char"]');
|
|
173
|
-
|
|
174
|
-
elements.forEach((container) => {
|
|
175
|
-
const chars = container.querySelectorAll(".char");
|
|
176
|
-
|
|
177
|
-
const tl = gsap.timeline({
|
|
178
|
-
scrollTrigger: {
|
|
179
|
-
trigger: container,
|
|
180
|
-
start: config.charSplit.start,
|
|
181
|
-
invalidateOnRefresh: true,
|
|
182
|
-
toggleActions: "play none none none",
|
|
183
|
-
once: true,
|
|
184
|
-
},
|
|
185
|
-
onComplete: () => {
|
|
186
|
-
if (container.splitTextInstance) {
|
|
187
|
-
container.splitTextInstance.revert();
|
|
188
|
-
delete container.splitTextInstance;
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
tl.to(chars, {
|
|
194
|
-
yPercent: 0,
|
|
195
|
-
duration: config.charSplit.duration,
|
|
196
|
-
stagger: config.charSplit.stagger,
|
|
197
|
-
ease: config.charSplit.ease,
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
activeAnimations.push({ timeline: tl, element: container });
|
|
201
|
-
});
|
|
202
|
-
},
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const WordSplitAnimations = {
|
|
206
|
-
async initial() {
|
|
207
|
-
await waitForFonts();
|
|
208
|
-
|
|
209
|
-
if (prefersReducedMotion()) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const elements = document.querySelectorAll('[data-hs-anim="word"]');
|
|
214
|
-
|
|
215
|
-
elements.forEach((container) => {
|
|
216
|
-
const textElement = findTextElement(container);
|
|
217
|
-
|
|
218
|
-
const split = SplitText.create(textElement, {
|
|
219
|
-
type: "words",
|
|
220
|
-
mask: "words",
|
|
221
|
-
wordsClass: "word",
|
|
222
|
-
});
|
|
223
|
-
container.splitTextInstance = split;
|
|
224
|
-
|
|
225
|
-
gsap.set(split.words, {
|
|
226
|
-
yPercent: config.wordSplit.yPercent,
|
|
227
|
-
});
|
|
228
|
-
gsap.set(textElement, { autoAlpha: 1 });
|
|
229
|
-
});
|
|
230
|
-
},
|
|
231
|
-
|
|
232
|
-
async animate() {
|
|
233
|
-
await waitForFonts();
|
|
234
|
-
|
|
235
|
-
if (prefersReducedMotion()) {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const elements = document.querySelectorAll('[data-hs-anim="word"]');
|
|
240
|
-
|
|
241
|
-
elements.forEach((container) => {
|
|
242
|
-
const words = container.querySelectorAll(".word");
|
|
243
|
-
|
|
244
|
-
const tl = gsap.timeline({
|
|
245
|
-
scrollTrigger: {
|
|
246
|
-
trigger: container,
|
|
247
|
-
start: config.wordSplit.start,
|
|
248
|
-
invalidateOnRefresh: true,
|
|
249
|
-
toggleActions: "play none none none",
|
|
250
|
-
once: true,
|
|
251
|
-
},
|
|
252
|
-
onComplete: () => {
|
|
253
|
-
if (container.splitTextInstance) {
|
|
254
|
-
container.splitTextInstance.revert();
|
|
255
|
-
delete container.splitTextInstance;
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
tl.to(words, {
|
|
261
|
-
yPercent: 0,
|
|
262
|
-
duration: config.wordSplit.duration,
|
|
263
|
-
stagger: config.wordSplit.stagger,
|
|
264
|
-
ease: config.wordSplit.ease,
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
activeAnimations.push({ timeline: tl, element: container });
|
|
268
|
-
});
|
|
269
|
-
},
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const LineSplitAnimations = {
|
|
273
|
-
async initial() {
|
|
274
|
-
await waitForFonts();
|
|
275
|
-
|
|
276
|
-
if (prefersReducedMotion()) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const elements = document.querySelectorAll('[data-hs-anim="line"]');
|
|
281
|
-
|
|
282
|
-
elements.forEach((container) => {
|
|
283
|
-
const textElement = findTextElement(container);
|
|
284
|
-
|
|
285
|
-
const split = SplitText.create(textElement, {
|
|
286
|
-
type: "lines",
|
|
287
|
-
mask: "lines",
|
|
288
|
-
linesClass: "line",
|
|
289
|
-
});
|
|
290
|
-
container.splitTextInstance = split;
|
|
291
|
-
|
|
292
|
-
gsap.set(split.lines, {
|
|
293
|
-
yPercent: config.lineSplit.yPercent,
|
|
294
|
-
});
|
|
295
|
-
gsap.set(textElement, { autoAlpha: 1 });
|
|
296
|
-
});
|
|
297
|
-
},
|
|
298
|
-
|
|
299
|
-
async animate() {
|
|
300
|
-
await waitForFonts();
|
|
301
|
-
|
|
302
|
-
if (prefersReducedMotion()) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const elements = document.querySelectorAll('[data-hs-anim="line"]');
|
|
307
|
-
|
|
308
|
-
elements.forEach((container) => {
|
|
309
|
-
const lines = container.querySelectorAll(".line");
|
|
310
|
-
|
|
311
|
-
const tl = gsap.timeline({
|
|
312
|
-
scrollTrigger: {
|
|
313
|
-
trigger: container,
|
|
314
|
-
start: config.lineSplit.start,
|
|
315
|
-
invalidateOnRefresh: true,
|
|
316
|
-
toggleActions: "play none none none",
|
|
317
|
-
once: true,
|
|
318
|
-
},
|
|
319
|
-
onComplete: () => {
|
|
320
|
-
if (container.splitTextInstance) {
|
|
321
|
-
container.splitTextInstance.revert();
|
|
322
|
-
delete container.splitTextInstance;
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
tl.to(lines, {
|
|
328
|
-
yPercent: 0,
|
|
329
|
-
duration: config.lineSplit.duration,
|
|
330
|
-
stagger: config.lineSplit.stagger,
|
|
331
|
-
ease: config.lineSplit.ease,
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
activeAnimations.push({ timeline: tl, element: container });
|
|
335
|
-
});
|
|
336
|
-
},
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
const AppearAnimations = {
|
|
340
|
-
async initial() {
|
|
341
|
-
await waitForFonts();
|
|
342
|
-
|
|
343
|
-
if (prefersReducedMotion()) {
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
const elements = document.querySelectorAll('[data-hs-anim="appear"]');
|
|
348
|
-
elements.forEach((element) => {
|
|
349
|
-
gsap.set(element, {
|
|
350
|
-
y: config.appear.y,
|
|
351
|
-
opacity: 0,
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
},
|
|
355
|
-
|
|
356
|
-
async animate() {
|
|
357
|
-
await waitForFonts();
|
|
358
|
-
|
|
359
|
-
if (prefersReducedMotion()) {
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const elements = document.querySelectorAll('[data-hs-anim="appear"]');
|
|
364
|
-
|
|
365
|
-
elements.forEach((element) => {
|
|
366
|
-
const tl = gsap.timeline({
|
|
367
|
-
scrollTrigger: {
|
|
368
|
-
trigger: element,
|
|
369
|
-
start: config.appear.start,
|
|
370
|
-
invalidateOnRefresh: true,
|
|
371
|
-
toggleActions: "play none none none",
|
|
372
|
-
once: true,
|
|
373
|
-
},
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
tl.to(element, {
|
|
377
|
-
y: 0,
|
|
378
|
-
opacity: 1,
|
|
379
|
-
duration: config.appear.duration,
|
|
380
|
-
ease: config.appear.ease,
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
activeAnimations.push({ timeline: tl, element: element });
|
|
384
|
-
});
|
|
385
|
-
},
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
const RevealAnimations = {
|
|
389
|
-
async initial() {
|
|
390
|
-
await waitForFonts();
|
|
391
|
-
|
|
392
|
-
if (prefersReducedMotion()) {
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const elements = document.querySelectorAll('[data-hs-anim="reveal"]');
|
|
397
|
-
elements.forEach((element) => {
|
|
398
|
-
gsap.set(element, {
|
|
399
|
-
y: config.reveal.y,
|
|
400
|
-
opacity: 0,
|
|
401
|
-
});
|
|
402
|
-
});
|
|
403
|
-
},
|
|
404
|
-
|
|
405
|
-
async animate() {
|
|
406
|
-
await waitForFonts();
|
|
407
|
-
|
|
408
|
-
if (prefersReducedMotion()) {
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const elements = document.querySelectorAll('[data-hs-anim="reveal"]');
|
|
413
|
-
|
|
414
|
-
elements.forEach((element) => {
|
|
415
|
-
const tl = gsap.timeline({
|
|
416
|
-
scrollTrigger: {
|
|
417
|
-
trigger: element,
|
|
418
|
-
start: config.reveal.start,
|
|
419
|
-
invalidateOnRefresh: true,
|
|
420
|
-
toggleActions: "play none none none",
|
|
421
|
-
once: true,
|
|
422
|
-
},
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
tl.to(element, {
|
|
426
|
-
y: 0,
|
|
427
|
-
opacity: 1,
|
|
428
|
-
duration: config.reveal.duration,
|
|
429
|
-
ease: config.reveal.ease,
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
activeAnimations.push({ timeline: tl, element: element });
|
|
433
|
-
});
|
|
434
|
-
},
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
const GroupAnimations = {
|
|
438
|
-
async initial() {
|
|
439
|
-
await waitForFonts();
|
|
440
|
-
|
|
441
|
-
if (prefersReducedMotion()) {
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
const elements = document.querySelectorAll('[data-hs-anim="group"]');
|
|
446
|
-
elements.forEach((element) => {
|
|
447
|
-
const children = Array.from(element.children);
|
|
448
|
-
gsap.set(children, {
|
|
449
|
-
y: config.appear.y,
|
|
450
|
-
opacity: 0,
|
|
451
|
-
});
|
|
452
|
-
});
|
|
453
|
-
},
|
|
454
|
-
|
|
455
|
-
async animate() {
|
|
456
|
-
await waitForFonts();
|
|
457
|
-
|
|
458
|
-
if (prefersReducedMotion()) {
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
const elements = document.querySelectorAll('[data-hs-anim="group"]');
|
|
463
|
-
|
|
464
|
-
elements.forEach((element) => {
|
|
465
|
-
const children = Array.from(element.children);
|
|
466
|
-
const tl = gsap.timeline({
|
|
467
|
-
scrollTrigger: {
|
|
468
|
-
trigger: element,
|
|
469
|
-
start: config.appear.start,
|
|
470
|
-
invalidateOnRefresh: true,
|
|
471
|
-
toggleActions: "play none none none",
|
|
472
|
-
once: true,
|
|
473
|
-
},
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
tl.to(children, {
|
|
477
|
-
y: 0,
|
|
478
|
-
opacity: 1,
|
|
479
|
-
duration: config.appear.duration,
|
|
480
|
-
ease: config.appear.ease,
|
|
481
|
-
stagger: 0.1,
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
activeAnimations.push({ timeline: tl, element: element });
|
|
485
|
-
});
|
|
486
|
-
},
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
async function setInitialStates() {
|
|
490
|
-
await Promise.all([
|
|
491
|
-
CharSplitAnimations.initial(),
|
|
492
|
-
WordSplitAnimations.initial(),
|
|
493
|
-
LineSplitAnimations.initial(),
|
|
494
|
-
AppearAnimations.initial(),
|
|
495
|
-
RevealAnimations.initial(),
|
|
496
|
-
GroupAnimations.initial(),
|
|
497
|
-
]);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
async function initAnimations() {
|
|
501
|
-
if (config.global.animationDelay > 0) {
|
|
502
|
-
await new Promise((resolve) =>
|
|
503
|
-
setTimeout(resolve, config.global.animationDelay * 1000),
|
|
504
|
-
);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
await Promise.all([
|
|
508
|
-
CharSplitAnimations.animate(),
|
|
509
|
-
WordSplitAnimations.animate(),
|
|
510
|
-
LineSplitAnimations.animate(),
|
|
511
|
-
AppearAnimations.animate(),
|
|
512
|
-
RevealAnimations.animate(),
|
|
513
|
-
GroupAnimations.animate(),
|
|
514
|
-
]);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
export async function init() {
|
|
518
|
-
// Prevent duplicate initialization
|
|
519
|
-
const elements = document.querySelectorAll(
|
|
520
|
-
"[data-hs-anim-text]:not([data-initialized])",
|
|
521
|
-
);
|
|
522
|
-
if (
|
|
523
|
-
elements.length === 0 &&
|
|
524
|
-
document.querySelectorAll(
|
|
525
|
-
'[data-hs-anim="char"]:not([data-initialized]), [data-hs-anim="word"]:not([data-initialized]), [data-hs-anim="line"]:not([data-initialized]), [data-hs-anim="appear"]:not([data-initialized]), [data-hs-anim="reveal"]:not([data-initialized]), [data-hs-anim="group"]:not([data-initialized])',
|
|
526
|
-
).length === 0
|
|
527
|
-
) {
|
|
528
|
-
return { result: "anim-text already initialized", destroy: () => {} };
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// Mark elements as initialized
|
|
532
|
-
elements.forEach((el) => el.setAttribute("data-initialized", "true"));
|
|
533
|
-
document
|
|
534
|
-
.querySelectorAll(
|
|
535
|
-
'[data-hs-anim="char"], [data-hs-anim="word"], [data-hs-anim="line"], [data-hs-anim="appear"], [data-hs-anim="reveal"], [data-hs-anim="group"]',
|
|
536
|
-
)
|
|
537
|
-
.forEach((el) => {
|
|
538
|
-
el.setAttribute("data-initialized", "true");
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
if (prefersReducedMotion()) {
|
|
542
|
-
// For reduced motion, just show elements without animation
|
|
543
|
-
showElementsWithoutAnimation();
|
|
544
|
-
} else {
|
|
545
|
-
await setInitialStates();
|
|
546
|
-
initAnimations();
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Safari optimization: Throttled resize handler using requestAnimationFrame
|
|
550
|
-
let resizeScheduled = false;
|
|
551
|
-
let lastWidth = window.innerWidth;
|
|
552
|
-
|
|
553
|
-
resizeHandler = () => {
|
|
554
|
-
const currentWidth = window.innerWidth;
|
|
555
|
-
if (currentWidth !== lastWidth && !resizeScheduled) {
|
|
556
|
-
lastWidth = currentWidth;
|
|
557
|
-
resizeScheduled = true;
|
|
558
|
-
|
|
559
|
-
// Use requestAnimationFrame instead of setTimeout for better Safari performance
|
|
560
|
-
requestAnimationFrame(() => {
|
|
561
|
-
try {
|
|
562
|
-
ScrollTrigger.refresh();
|
|
563
|
-
} catch (error) {
|
|
564
|
-
console.warn("Error refreshing ScrollTrigger:", error);
|
|
565
|
-
} finally {
|
|
566
|
-
resizeScheduled = false;
|
|
567
|
-
}
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
};
|
|
571
|
-
window.addEventListener("resize", resizeHandler, { passive: true });
|
|
572
|
-
|
|
573
|
-
// Safari optimization: Simplified page load handling
|
|
574
|
-
// Complex event handlers and multiple timeouts cause Safari lag
|
|
575
|
-
if (document.readyState === 'complete') {
|
|
576
|
-
requestAnimationFrame(() => {
|
|
577
|
-
try {
|
|
578
|
-
ScrollTrigger.refresh();
|
|
579
|
-
} catch (error) {
|
|
580
|
-
console.warn("Error refreshing ScrollTrigger:", error);
|
|
581
|
-
}
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
// Initialize API with proper checks
|
|
586
|
-
if (!window[API_NAME]) {
|
|
587
|
-
window[API_NAME] = {};
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
const api = window[API_NAME];
|
|
591
|
-
api.textAnimations = {
|
|
592
|
-
config: config,
|
|
593
|
-
updateConfig: updateConfig,
|
|
594
|
-
start: startTextAnimations,
|
|
595
|
-
kill: killTextAnimations,
|
|
596
|
-
restart: () => {
|
|
597
|
-
killTextAnimations();
|
|
598
|
-
startTextAnimations();
|
|
599
|
-
},
|
|
600
|
-
cleanup: () => {
|
|
601
|
-
killTextAnimations();
|
|
602
|
-
window.removeEventListener("resize", resizeHandler);
|
|
603
|
-
},
|
|
604
|
-
};
|
|
605
|
-
|
|
606
|
-
// Return destroy function
|
|
607
|
-
const destroy = () => {
|
|
608
|
-
// Kill all animations
|
|
609
|
-
killTextAnimations();
|
|
610
|
-
|
|
611
|
-
// Remove resize handler
|
|
612
|
-
if (resizeHandler) {
|
|
613
|
-
window.removeEventListener("resize", resizeHandler);
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
// Remove initialized markers
|
|
617
|
-
document.querySelectorAll("[data-initialized]").forEach((el) => {
|
|
618
|
-
el.removeAttribute("data-initialized");
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
// Clean up API
|
|
622
|
-
if (api.textAnimations) {
|
|
623
|
-
delete api.textAnimations;
|
|
624
|
-
}
|
|
625
|
-
};
|
|
626
|
-
|
|
627
|
-
return { result: "anim-text initialized", destroy };
|
|
628
|
-
}
|