@hortonstudio/main 1.7.14 → 1.7.16
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/autoInit/form.js +15 -0
- package/autoInit/transition.js +30 -82
- package/index.js +9 -24
- package/package.json +1 -1
package/autoInit/form.js
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
export function init() {
|
|
2
|
+
// Honeypot spam prevention
|
|
3
|
+
document.addEventListener('submit', (e) => {
|
|
4
|
+
const form = e.target;
|
|
5
|
+
if (form.tagName !== 'FORM') return;
|
|
6
|
+
|
|
7
|
+
const honeypot = form.querySelector('[data-hs-form="form-handler"]');
|
|
8
|
+
if (honeypot && honeypot.value) {
|
|
9
|
+
// Honeypot filled - likely a bot
|
|
10
|
+
e.preventDefault();
|
|
11
|
+
e.stopPropagation();
|
|
12
|
+
e.stopImmediatePropagation();
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}, true);
|
|
16
|
+
|
|
2
17
|
// Simple Custom Select Component for Webflow
|
|
3
18
|
(function() {
|
|
4
19
|
'use strict';
|
package/autoInit/transition.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const API_NAME = "hsmain";
|
|
3
3
|
|
|
4
4
|
export async function init() {
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
// Wait for Webflow to be ready before initializing transitions
|
|
7
7
|
window[API_NAME].afterWebflowReady(() => {
|
|
8
8
|
setTimeout(() => {
|
|
@@ -14,104 +14,52 @@ export async function init() {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function initTransitions() {
|
|
17
|
-
const transitionTrigger = document.querySelector("
|
|
18
|
-
const transitionElement = document.querySelector(
|
|
19
|
-
|
|
20
|
-
// Page Load - Trigger entrance animation with optional delay
|
|
21
|
-
if (transitionTrigger) {
|
|
22
|
-
// Check if entrance transition should be skipped
|
|
23
|
-
const skipEntrance = sessionStorage.getItem('skip-entrance-transition');
|
|
24
|
-
if (skipEntrance) {
|
|
25
|
-
sessionStorage.removeItem('skip-entrance-transition');
|
|
26
|
-
// Keep transition element hidden when skipping animation
|
|
27
|
-
if (transitionElement) {
|
|
28
|
-
transitionElement.style.display = "none";
|
|
29
|
-
}
|
|
30
|
-
return; // Skip entrance animation
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Check if this is the first page load of the session
|
|
34
|
-
const isFirstLoad = !sessionStorage.getItem('transition-loaded');
|
|
35
|
-
const delayAttr = transitionElement?.getAttribute('data-hs-delay');
|
|
36
|
-
const delaySeconds = delayAttr ? parseFloat(delayAttr) : 0;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const triggerAnimation = () => {
|
|
40
|
-
Webflow.push(function () {
|
|
41
|
-
transitionTrigger.click();
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
if (isFirstLoad && delaySeconds > 0) {
|
|
46
|
-
setTimeout(triggerAnimation, delaySeconds * 1000);
|
|
47
|
-
sessionStorage.setItem('transition-loaded', 'true');
|
|
48
|
-
} else {
|
|
49
|
-
triggerAnimation();
|
|
50
|
-
if (isFirstLoad) {
|
|
51
|
-
sessionStorage.setItem('transition-loaded', 'true');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
17
|
+
const transitionTrigger = document.querySelector('[data-hs-transition="trigger"]');
|
|
18
|
+
const transitionElement = document.querySelector('[data-hs-transition="element"]');
|
|
55
19
|
|
|
56
|
-
|
|
57
|
-
function waitForTransitionComplete(callback) {
|
|
58
|
-
if (!transitionElement) return;
|
|
59
|
-
|
|
60
|
-
const checkComplete = () => {
|
|
61
|
-
if (transitionElement.classList.contains('transition-done')) {
|
|
62
|
-
callback();
|
|
63
|
-
} else {
|
|
64
|
-
setTimeout(checkComplete, 50);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
checkComplete();
|
|
68
|
-
}
|
|
20
|
+
if (!transitionTrigger || !transitionElement) return;
|
|
69
21
|
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
22
|
+
// Get exit time from data attribute (in seconds)
|
|
23
|
+
const exitTimeAttr = transitionElement.getAttribute('data-hs-exit-time');
|
|
24
|
+
const exitTime = exitTimeAttr ? parseFloat(exitTimeAttr) * 1000 : 0;
|
|
25
|
+
|
|
26
|
+
// Page Load - Trigger entrance animation
|
|
27
|
+
// Check if this is the first page load of the session
|
|
28
|
+
const isFirstLoad = !sessionStorage.getItem('transition-loaded');
|
|
29
|
+
|
|
30
|
+
const triggerAnimation = () => {
|
|
31
|
+
Webflow.push(function () {
|
|
32
|
+
transitionTrigger.click();
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
triggerAnimation();
|
|
37
|
+
if (isFirstLoad) {
|
|
38
|
+
sessionStorage.setItem('transition-loaded', 'true');
|
|
80
39
|
}
|
|
81
40
|
|
|
82
41
|
// On Link Click
|
|
83
42
|
document.addEventListener("click", function (e) {
|
|
84
43
|
const link = e.target.closest("a");
|
|
85
|
-
|
|
44
|
+
|
|
86
45
|
if (
|
|
87
46
|
link &&
|
|
88
47
|
link.hostname === window.location.hostname &&
|
|
89
48
|
link.getAttribute("href") &&
|
|
90
49
|
link.getAttribute("href").indexOf("#") === -1 &&
|
|
91
|
-
link.getAttribute("target") !== "_blank"
|
|
92
|
-
transitionTrigger
|
|
50
|
+
link.getAttribute("target") !== "_blank"
|
|
93
51
|
) {
|
|
94
|
-
// Check if transitions are prevented
|
|
95
|
-
const transitionPrevented = hasTransitionPrevented(link);
|
|
96
|
-
|
|
97
|
-
if (transitionPrevented) {
|
|
98
|
-
// Set flag to prevent entrance animation on next page
|
|
99
|
-
sessionStorage.setItem('skip-entrance-transition', 'true');
|
|
100
|
-
// Navigate normally without exit animation
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
52
|
e.preventDefault();
|
|
105
|
-
|
|
53
|
+
|
|
106
54
|
let transitionURL = link.getAttribute("href");
|
|
107
|
-
|
|
55
|
+
|
|
108
56
|
// Trigger exit animation
|
|
109
57
|
transitionTrigger.click();
|
|
110
|
-
|
|
111
|
-
// Wait for
|
|
112
|
-
|
|
58
|
+
|
|
59
|
+
// Wait for exit time, then navigate
|
|
60
|
+
setTimeout(() => {
|
|
113
61
|
window.location = transitionURL;
|
|
114
|
-
});
|
|
62
|
+
}, exitTime);
|
|
115
63
|
}
|
|
116
64
|
});
|
|
117
65
|
|
|
@@ -128,4 +76,4 @@ function initTransitions() {
|
|
|
128
76
|
transitionElement.style.display = "none";
|
|
129
77
|
}
|
|
130
78
|
});
|
|
131
|
-
}
|
|
79
|
+
}
|
package/index.js
CHANGED
|
@@ -29,12 +29,6 @@ const initializeHsMain = async () => {
|
|
|
29
29
|
|
|
30
30
|
const allDataAttributes = { ...animationModules, ...utilityModules };
|
|
31
31
|
|
|
32
|
-
const waitForWebflow = async () =>
|
|
33
|
-
new Promise((resolve) => {
|
|
34
|
-
if (!window.Webflow) window.Webflow = [];
|
|
35
|
-
window.Webflow.push(resolve);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
32
|
const moduleMap = {
|
|
39
33
|
transition: () => import("./autoInit/transition.js"),
|
|
40
34
|
"data-hs-util-ba": () => import("./utils/before-after.js"),
|
|
@@ -253,42 +247,33 @@ const initializeHsMain = async () => {
|
|
|
253
247
|
});
|
|
254
248
|
});
|
|
255
249
|
|
|
256
|
-
const
|
|
250
|
+
const waitForIx3 = async () => {
|
|
257
251
|
const startTime = Date.now();
|
|
258
252
|
const timeout = 2000; // 2 second timeout
|
|
259
253
|
|
|
260
254
|
return new Promise((resolve) => {
|
|
261
|
-
const
|
|
255
|
+
const checkIx3 = () => {
|
|
262
256
|
const htmlElement = document.documentElement;
|
|
263
|
-
const
|
|
257
|
+
const hasIx3 = htmlElement.classList.contains('w-mod-ix3');
|
|
264
258
|
|
|
265
|
-
if (
|
|
259
|
+
if (hasIx3) {
|
|
266
260
|
resolve(true);
|
|
267
261
|
} else if (Date.now() - startTime >= timeout) {
|
|
268
|
-
console.warn('[hsmain]
|
|
262
|
+
console.warn('[hsmain] IX3 (w-mod-ix3) not detected after 2s timeout. Proceeding anyway, but Webflow interactions may not be fully loaded.');
|
|
269
263
|
resolve(false);
|
|
270
264
|
} else {
|
|
271
|
-
setTimeout(
|
|
265
|
+
setTimeout(checkIx3, 50);
|
|
272
266
|
}
|
|
273
267
|
};
|
|
274
|
-
|
|
268
|
+
checkIx3();
|
|
275
269
|
});
|
|
276
270
|
};
|
|
277
271
|
|
|
278
272
|
const finalize = async () => {
|
|
279
273
|
processModules();
|
|
280
|
-
await waitForWebflow();
|
|
281
|
-
|
|
282
|
-
// Small delay to ensure all scripts are fully initialized
|
|
283
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
284
|
-
|
|
285
|
-
// Force Webflow to reinitialize (not redraw) - rescans DOM and rebinds interactions
|
|
286
|
-
if (window.Webflow && typeof window.Webflow.ready === 'function') {
|
|
287
|
-
window.Webflow.ready();
|
|
288
|
-
}
|
|
289
274
|
|
|
290
|
-
// Wait for
|
|
291
|
-
await
|
|
275
|
+
// Wait for IX3 to be ready before firing callbacks
|
|
276
|
+
await waitForIx3();
|
|
292
277
|
|
|
293
278
|
window[API_NAME].loaded = true;
|
|
294
279
|
readyCallbacks.forEach((callback) => {
|