@hortonstudio/main 1.2.0 → 1.2.2
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/index.js +148 -42
- package/package.json +1 -1
package/index.js
CHANGED
@@ -1,48 +1,77 @@
|
|
1
|
-
// ver 1.
|
1
|
+
// ver 1.2.2
|
2
2
|
|
3
3
|
const API_NAME = 'hsmain';
|
4
4
|
|
5
5
|
window[API_NAME] = window[API_NAME] || {};
|
6
6
|
window[API_NAME].loaded = false
|
7
7
|
|
8
|
+
// Dynamic module loader function (like Finsweet's approach)
|
9
|
+
const loadModule = async (moduleName) => {
|
10
|
+
const baseURL = new URL('./', import.meta.url).href;
|
11
|
+
|
12
|
+
switch (moduleName) {
|
13
|
+
case "data-hs-anim-text":
|
14
|
+
return import(new URL('./animations/text.js', import.meta.url).href);
|
15
|
+
case "data-hs-anim-hero":
|
16
|
+
return import(new URL('./animations/hero.js', import.meta.url).href);
|
17
|
+
case "data-hs-anim-transition":
|
18
|
+
return import(new URL('./animations/transition.js', import.meta.url).href);
|
19
|
+
case "data-hs-util-toc":
|
20
|
+
return import(new URL('./utils/toc.js', import.meta.url).href);
|
21
|
+
case "data-hs-util-progress":
|
22
|
+
return import(new URL('./utils/scroll-progress.js', import.meta.url).href);
|
23
|
+
case "data-hs-util-navbar":
|
24
|
+
return import(new URL('./utils/navbar.js', import.meta.url).href);
|
25
|
+
case "smooth-scroll":
|
26
|
+
return import(new URL('./autoInit/smooth-scroll.js', import.meta.url).href);
|
27
|
+
default:
|
28
|
+
throw new Error(`HortonStudio module "${moduleName}" is not supported.`);
|
29
|
+
}
|
30
|
+
|
31
|
+
// Refresh Webflow after processing
|
32
|
+
setTimeout(() => {
|
33
|
+
if (window.Webflow && window.Webflow.ready) {
|
34
|
+
window.Webflow.ready();
|
35
|
+
}
|
36
|
+
|
37
|
+
// Run all registered post-Webflow callbacks (even without Webflow)
|
38
|
+
setTimeout(() => {
|
39
|
+
postWebflowCallbacks.forEach(callback => {
|
40
|
+
try {
|
41
|
+
callback();
|
42
|
+
} catch (error) {
|
43
|
+
console.error('Callback error:', error);
|
44
|
+
}
|
45
|
+
});
|
46
|
+
window[API_NAME].loaded = true;
|
47
|
+
}, 100);
|
48
|
+
}, 100);
|
49
|
+
};
|
50
|
+
|
8
51
|
const animationModules = {
|
9
|
-
"data-hs-anim-text":
|
10
|
-
"data-hs-anim-hero":
|
11
|
-
"data-hs-anim-transition":
|
52
|
+
"data-hs-anim-text": true,
|
53
|
+
"data-hs-anim-hero": true,
|
54
|
+
"data-hs-anim-transition": true
|
12
55
|
};
|
13
56
|
|
14
57
|
const utilityModules = {
|
15
|
-
"data-hs-util-toc":
|
16
|
-
"data-hs-util-progress":
|
17
|
-
"data-hs-util-navbar":
|
58
|
+
"data-hs-util-toc": true,
|
59
|
+
"data-hs-util-progress": true,
|
60
|
+
"data-hs-util-navbar": true
|
18
61
|
};
|
19
62
|
|
20
63
|
// Modules that auto-initialize
|
21
64
|
const autoInitModules = {
|
22
|
-
"smooth-scroll":
|
65
|
+
"smooth-scroll": true
|
23
66
|
};
|
24
67
|
|
25
68
|
// Store callbacks to run after Webflow.ready()
|
26
69
|
const postWebflowCallbacks = [];
|
27
70
|
|
28
|
-
const loadModule = (moduleName) => {
|
29
|
-
// Check manual modules first
|
30
|
-
let modulePath = animationModules[moduleName] || utilityModules[moduleName];
|
31
|
-
|
32
|
-
// Then check auto-init modules
|
33
|
-
if (!modulePath) {
|
34
|
-
modulePath = autoInitModules[moduleName];
|
35
|
-
}
|
36
|
-
|
37
|
-
if (!modulePath) {
|
38
|
-
throw new Error(`HortonStudio module "${moduleName}" is not supported.`);
|
39
|
-
}
|
40
|
-
return import(modulePath);
|
41
|
-
};
|
42
|
-
|
43
71
|
const findCurrentScriptTag = () => {
|
44
|
-
|
45
|
-
|
72
|
+
// Use import.meta.url like Finsweet does
|
73
|
+
const scripts = [...document.querySelectorAll(`script[data-hs-main][src="${import.meta.url}"]`)];
|
74
|
+
return scripts[0] || document.querySelector('script[data-hs-main]');
|
46
75
|
};
|
47
76
|
|
48
77
|
const processModules = async (scriptTag) => {
|
@@ -76,7 +105,6 @@ const processModules = async (scriptTag) => {
|
|
76
105
|
};
|
77
106
|
|
78
107
|
const refreshWebflow = () => {
|
79
|
-
|
80
108
|
setTimeout(() => {
|
81
109
|
if (window.Webflow && window.Webflow.ready) {
|
82
110
|
window.Webflow.ready();
|
@@ -115,12 +143,19 @@ const loadHsModule = async (moduleName) => {
|
|
115
143
|
try {
|
116
144
|
const { init, version } = await loadModule(moduleName);
|
117
145
|
const initResult = await init();
|
118
|
-
const { result } = initResult || {};
|
146
|
+
const { result, destroy } = initResult || {};
|
119
147
|
|
120
148
|
moduleObj.version = version;
|
121
|
-
|
149
|
+
|
150
|
+
// Finsweet-style destroy and restart methods
|
151
|
+
moduleObj.destroy = () => {
|
152
|
+
destroy?.();
|
122
153
|
apiInstance.process.delete(moduleName);
|
123
|
-
|
154
|
+
};
|
155
|
+
|
156
|
+
moduleObj.restart = () => {
|
157
|
+
moduleObj.destroy?.();
|
158
|
+
return apiInstance.load(moduleName);
|
124
159
|
};
|
125
160
|
|
126
161
|
moduleObj.resolve?.(result);
|
@@ -137,10 +172,18 @@ const loadHsModule = async (moduleName) => {
|
|
137
172
|
};
|
138
173
|
|
139
174
|
const initializeAPI = () => {
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
175
|
+
// Handle early API calls (like Finsweet)
|
176
|
+
const existingAPI = window[API_NAME];
|
177
|
+
if (existingAPI && !Array.isArray(existingAPI)) {
|
178
|
+
processAPI();
|
179
|
+
return;
|
180
|
+
}
|
181
|
+
|
182
|
+
const existingRequests = Array.isArray(existingAPI) ? existingAPI : [];
|
183
|
+
const scripts = [...document.querySelectorAll(`script[data-hs-main][src="${import.meta.url}"]`)];
|
184
|
+
const scriptTag = scripts[0] || document.querySelector('script[data-hs-main]');
|
185
|
+
|
186
|
+
// Handle rich text blocks
|
144
187
|
const richTextBlocks = document.querySelectorAll('.w-richtext');
|
145
188
|
richTextBlocks.forEach(block => {
|
146
189
|
const images = block.querySelectorAll('img');
|
@@ -150,17 +193,33 @@ const initializeAPI = () => {
|
|
150
193
|
});
|
151
194
|
|
152
195
|
window[API_NAME] = {
|
153
|
-
|
196
|
+
scripts,
|
154
197
|
modules: {},
|
155
198
|
process: new Set(),
|
156
|
-
|
157
199
|
load: loadHsModule,
|
200
|
+
|
201
|
+
// Push method for queuing (like Finsweet)
|
202
|
+
push(...requests) {
|
203
|
+
for (let [moduleName, callback] of requests) {
|
204
|
+
if (typeof callback === 'function') {
|
205
|
+
this.modules[moduleName]?.loading?.then(callback);
|
206
|
+
} else {
|
207
|
+
this.load(moduleName);
|
208
|
+
}
|
209
|
+
}
|
210
|
+
},
|
211
|
+
|
212
|
+
// Destroy all modules
|
213
|
+
destroy() {
|
214
|
+
for (let moduleName in this.modules) {
|
215
|
+
this.modules[moduleName]?.destroy?.();
|
216
|
+
}
|
217
|
+
},
|
158
218
|
|
159
219
|
// API function for scripts to register post-initialization callbacks
|
160
220
|
afterReady: (callback) => {
|
161
221
|
if (typeof callback === 'function') {
|
162
222
|
postWebflowCallbacks.push(callback);
|
163
|
-
} else {
|
164
223
|
}
|
165
224
|
},
|
166
225
|
|
@@ -168,7 +227,6 @@ const initializeAPI = () => {
|
|
168
227
|
afterWebflowReady: (callback) => {
|
169
228
|
if (typeof callback === 'function') {
|
170
229
|
postWebflowCallbacks.push(callback);
|
171
|
-
} else {
|
172
230
|
}
|
173
231
|
},
|
174
232
|
|
@@ -189,13 +247,61 @@ const initializeAPI = () => {
|
|
189
247
|
}
|
190
248
|
};
|
191
249
|
|
192
|
-
|
250
|
+
processAPI();
|
251
|
+
|
252
|
+
// Process any queued requests
|
253
|
+
window[API_NAME].push(...existingRequests);
|
254
|
+
};
|
193
255
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
256
|
+
const processAPI = () => {
|
257
|
+
// Check for auto mode
|
258
|
+
let autoMode = false;
|
259
|
+
for (let script of window[API_NAME].scripts || []) {
|
260
|
+
autoMode ||= script.getAttribute('data-hs-auto') === 'true';
|
261
|
+
|
262
|
+
// Load modules based on script attributes
|
263
|
+
for (const moduleName of Object.keys({ ...animationModules, ...utilityModules })) {
|
264
|
+
if (script.hasAttribute(moduleName)) {
|
265
|
+
loadHsModule(moduleName);
|
198
266
|
}
|
267
|
+
}
|
268
|
+
}
|
269
|
+
|
270
|
+
// Auto-discovery mode (scan DOM for attributes)
|
271
|
+
if (autoMode) {
|
272
|
+
document.fonts.ready.then(() => {
|
273
|
+
const foundModules = new Set();
|
274
|
+
const allElements = document.querySelectorAll('*');
|
275
|
+
|
276
|
+
for (let element of allElements) {
|
277
|
+
for (let attrName of element.getAttributeNames()) {
|
278
|
+
// Look for data-hs-[something] attributes
|
279
|
+
const match = attrName.match(/^data-hs-([^-=]+)/)?.[1];
|
280
|
+
if (match && attributeToModule[match]) {
|
281
|
+
foundModules.add(attributeToModule[match]);
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
for (let moduleName of foundModules) {
|
287
|
+
loadHsModule(moduleName);
|
288
|
+
}
|
289
|
+
});
|
290
|
+
}
|
291
|
+
|
292
|
+
// Always load auto-init modules
|
293
|
+
for (const moduleName of Object.keys(autoInitModules)) {
|
294
|
+
loadHsModule(moduleName);
|
295
|
+
}
|
296
|
+
|
297
|
+
// Hide .transition elements if transition module is not loaded
|
298
|
+
const hasTransition = window[API_NAME].scripts?.some(script =>
|
299
|
+
script.hasAttribute('data-hs-anim-transition')
|
300
|
+
);
|
301
|
+
if (!hasTransition) {
|
302
|
+
const transitionElements = document.querySelectorAll('.transition');
|
303
|
+
transitionElements.forEach(element => {
|
304
|
+
element.style.display = 'none';
|
199
305
|
});
|
200
306
|
}
|
201
307
|
};
|