@hortonstudio/main 1.2.1 → 1.2.3
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 +168 -23
- package/package.json +1 -1
package/index.js
CHANGED
@@ -1,13 +1,19 @@
|
|
1
|
-
// ver 1.2.
|
1
|
+
// ver 1.2.3
|
2
2
|
|
3
3
|
const API_NAME = 'hsmain';
|
4
4
|
|
5
|
+
console.log(`🟢 ${API_NAME} v1.2.3 initializing...`);
|
6
|
+
console.log('🔍 DOM state:', document.readyState);
|
7
|
+
console.log('🔍 Script URL:', import.meta.url);
|
8
|
+
|
5
9
|
window[API_NAME] = window[API_NAME] || {};
|
6
10
|
window[API_NAME].loaded = false
|
7
11
|
|
8
12
|
// Dynamic module loader function (like Finsweet's approach)
|
9
13
|
const loadModule = async (moduleName) => {
|
14
|
+
console.log(`📦 Loading module: ${moduleName}`);
|
10
15
|
const baseURL = new URL('./', import.meta.url).href;
|
16
|
+
console.log(`📂 Base URL: ${baseURL}`);
|
11
17
|
|
12
18
|
switch (moduleName) {
|
13
19
|
case "data-hs-anim-text":
|
@@ -25,8 +31,28 @@ const loadModule = async (moduleName) => {
|
|
25
31
|
case "smooth-scroll":
|
26
32
|
return import(new URL('./autoInit/smooth-scroll.js', import.meta.url).href);
|
27
33
|
default:
|
34
|
+
console.error(`❌ Unsupported module: ${moduleName}`);
|
28
35
|
throw new Error(`HortonStudio module "${moduleName}" is not supported.`);
|
29
36
|
}
|
37
|
+
|
38
|
+
// Refresh Webflow after processing
|
39
|
+
setTimeout(() => {
|
40
|
+
if (window.Webflow && window.Webflow.ready) {
|
41
|
+
window.Webflow.ready();
|
42
|
+
}
|
43
|
+
|
44
|
+
// Run all registered post-Webflow callbacks (even without Webflow)
|
45
|
+
setTimeout(() => {
|
46
|
+
postWebflowCallbacks.forEach(callback => {
|
47
|
+
try {
|
48
|
+
callback();
|
49
|
+
} catch (error) {
|
50
|
+
console.error('Callback error:', error);
|
51
|
+
}
|
52
|
+
});
|
53
|
+
window[API_NAME].loaded = true;
|
54
|
+
}, 100);
|
55
|
+
}, 100);
|
30
56
|
};
|
31
57
|
|
32
58
|
const animationModules = {
|
@@ -52,21 +78,32 @@ const postWebflowCallbacks = [];
|
|
52
78
|
const findCurrentScriptTag = () => {
|
53
79
|
// Use import.meta.url like Finsweet does
|
54
80
|
const scripts = [...document.querySelectorAll(`script[data-hs-main][src="${import.meta.url}"]`)];
|
55
|
-
|
81
|
+
const fallbackScript = document.querySelector('script[data-hs-main]');
|
82
|
+
const found = scripts[0] || fallbackScript;
|
83
|
+
console.log(`🏷️ Script tag found:`, found);
|
84
|
+
console.log(`🏷️ Script attributes:`, found ? [...found.attributes].map(a => `${a.name}="${a.value}"`).join(' ') : 'none');
|
85
|
+
return found;
|
56
86
|
};
|
57
87
|
|
58
88
|
const processModules = async (scriptTag) => {
|
89
|
+
console.log(`⚙️ Processing modules with script tag:`, scriptTag);
|
59
90
|
const modulePromises = [];
|
60
91
|
|
61
92
|
// Load manual modules based on attributes
|
62
|
-
|
93
|
+
const manualModules = Object.keys({ ...animationModules, ...utilityModules });
|
94
|
+
console.log(`🔍 Checking for manual modules:`, manualModules);
|
95
|
+
|
96
|
+
for (const moduleName of manualModules) {
|
63
97
|
if (scriptTag && scriptTag.hasAttribute(moduleName)) {
|
98
|
+
console.log(`✅ Found attribute for: ${moduleName}`);
|
64
99
|
modulePromises.push(loadHsModule(moduleName));
|
65
100
|
}
|
66
101
|
}
|
67
102
|
|
68
103
|
// Load auto-init modules
|
69
|
-
|
104
|
+
const autoModules = Object.keys(autoInitModules);
|
105
|
+
console.log(`🔄 Auto-loading modules:`, autoModules);
|
106
|
+
for (const moduleName of autoModules) {
|
70
107
|
modulePromises.push(loadHsModule(moduleName));
|
71
108
|
}
|
72
109
|
|
@@ -79,38 +116,51 @@ const processModules = async (scriptTag) => {
|
|
79
116
|
}
|
80
117
|
|
81
118
|
// Wait for ALL modules to finish loading
|
119
|
+
console.log(`⏳ Waiting for ${modulePromises.length} modules to load...`);
|
82
120
|
await Promise.all(modulePromises);
|
121
|
+
console.log(`✅ All modules loaded successfully`);
|
83
122
|
|
84
123
|
// Always refresh Webflow after all modules are loaded
|
85
124
|
refreshWebflow();
|
86
125
|
};
|
87
126
|
|
88
127
|
const refreshWebflow = () => {
|
128
|
+
console.log(`🔄 Refreshing Webflow...`);
|
89
129
|
setTimeout(() => {
|
90
130
|
if (window.Webflow && window.Webflow.ready) {
|
131
|
+
console.log(`🌐 Calling Webflow.ready()`);
|
91
132
|
window.Webflow.ready();
|
133
|
+
} else {
|
134
|
+
console.log(`⚠️ Webflow not detected`);
|
92
135
|
}
|
93
136
|
|
94
137
|
// Run all registered post-Webflow callbacks (even without Webflow)
|
95
138
|
setTimeout(() => {
|
96
|
-
|
139
|
+
console.log(`🔄 Running ${postWebflowCallbacks.length} post-Webflow callbacks`);
|
140
|
+
postWebflowCallbacks.forEach((callback, index) => {
|
97
141
|
try {
|
142
|
+
console.log(`📞 Executing callback ${index + 1}/${postWebflowCallbacks.length}`);
|
98
143
|
callback();
|
99
144
|
} catch (error) {
|
145
|
+
console.error(`❌ Callback ${index + 1} failed:`, error);
|
100
146
|
}
|
101
147
|
});
|
102
148
|
window[API_NAME].loaded = true;
|
103
|
-
|
104
|
-
|
149
|
+
console.log(`🎉 ${API_NAME} fully loaded and ready!`);
|
150
|
+
}, 100);
|
151
|
+
}, 100);
|
105
152
|
};
|
106
153
|
|
107
154
|
const loadHsModule = async (moduleName) => {
|
155
|
+
console.log(`🔄 loadHsModule called for: ${moduleName}`);
|
108
156
|
const apiInstance = window[API_NAME];
|
109
157
|
|
110
158
|
if (apiInstance.process.has(moduleName)) {
|
159
|
+
console.log(`⚠️ Module ${moduleName} already processing, returning existing promise`);
|
111
160
|
return apiInstance.modules[moduleName]?.loading;
|
112
161
|
}
|
113
162
|
|
163
|
+
console.log(`➕ Adding ${moduleName} to process set`);
|
114
164
|
apiInstance.process.add(moduleName);
|
115
165
|
|
116
166
|
const moduleObj = apiInstance.modules[moduleName] || {};
|
@@ -122,14 +172,26 @@ const loadHsModule = async (moduleName) => {
|
|
122
172
|
});
|
123
173
|
|
124
174
|
try {
|
175
|
+
console.log(`📦 Importing ${moduleName}...`);
|
125
176
|
const { init, version } = await loadModule(moduleName);
|
177
|
+
console.log(`✅ ${moduleName} imported, version: ${version}`);
|
178
|
+
|
179
|
+
console.log(`🔧 Initializing ${moduleName}...`);
|
126
180
|
const initResult = await init();
|
127
|
-
const { result } = initResult || {};
|
181
|
+
const { result, destroy } = initResult || {};
|
182
|
+
console.log(`✅ ${moduleName} initialized:`, result);
|
128
183
|
|
129
184
|
moduleObj.version = version;
|
130
|
-
|
185
|
+
|
186
|
+
// Finsweet-style destroy and restart methods
|
187
|
+
moduleObj.destroy = () => {
|
188
|
+
destroy?.();
|
131
189
|
apiInstance.process.delete(moduleName);
|
132
|
-
|
190
|
+
};
|
191
|
+
|
192
|
+
moduleObj.restart = () => {
|
193
|
+
moduleObj.destroy?.();
|
194
|
+
return apiInstance.load(moduleName);
|
133
195
|
};
|
134
196
|
|
135
197
|
moduleObj.resolve?.(result);
|
@@ -139,6 +201,7 @@ const loadHsModule = async (moduleName) => {
|
|
139
201
|
return result;
|
140
202
|
|
141
203
|
} catch (error) {
|
204
|
+
console.error(`❌ Failed to load ${moduleName}:`, error);
|
142
205
|
moduleObj.reject?.(error);
|
143
206
|
apiInstance.process.delete(moduleName);
|
144
207
|
throw error;
|
@@ -146,10 +209,27 @@ const loadHsModule = async (moduleName) => {
|
|
146
209
|
};
|
147
210
|
|
148
211
|
const initializeAPI = () => {
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
const
|
212
|
+
console.log(`🚀 Initializing ${API_NAME} API...`);
|
213
|
+
|
214
|
+
// Handle early API calls (like Finsweet)
|
215
|
+
const existingAPI = window[API_NAME];
|
216
|
+
console.log(`🔍 Existing API:`, existingAPI);
|
217
|
+
|
218
|
+
if (existingAPI && !Array.isArray(existingAPI)) {
|
219
|
+
console.log(`⚡ API already initialized, processing...`);
|
220
|
+
processAPI();
|
221
|
+
return;
|
222
|
+
}
|
223
|
+
|
224
|
+
const existingRequests = Array.isArray(existingAPI) ? existingAPI : [];
|
225
|
+
console.log(`📝 Existing queued requests:`, existingRequests);
|
226
|
+
|
227
|
+
const scripts = [...document.querySelectorAll(`script[data-hs-main][src="${import.meta.url}"]`)];
|
228
|
+
const scriptTag = scripts[0] || document.querySelector('script[data-hs-main]');
|
229
|
+
console.log(`📄 Found ${scripts.length} script tags with exact src match`);
|
230
|
+
console.log(`🏷️ Using script tag:`, scriptTag);
|
231
|
+
|
232
|
+
// Handle rich text blocks
|
153
233
|
const richTextBlocks = document.querySelectorAll('.w-richtext');
|
154
234
|
richTextBlocks.forEach(block => {
|
155
235
|
const images = block.querySelectorAll('img');
|
@@ -159,17 +239,33 @@ const initializeAPI = () => {
|
|
159
239
|
});
|
160
240
|
|
161
241
|
window[API_NAME] = {
|
162
|
-
|
242
|
+
scripts,
|
163
243
|
modules: {},
|
164
244
|
process: new Set(),
|
165
|
-
|
166
245
|
load: loadHsModule,
|
246
|
+
|
247
|
+
// Push method for queuing (like Finsweet)
|
248
|
+
push(...requests) {
|
249
|
+
for (let [moduleName, callback] of requests) {
|
250
|
+
if (typeof callback === 'function') {
|
251
|
+
this.modules[moduleName]?.loading?.then(callback);
|
252
|
+
} else {
|
253
|
+
this.load(moduleName);
|
254
|
+
}
|
255
|
+
}
|
256
|
+
},
|
257
|
+
|
258
|
+
// Destroy all modules
|
259
|
+
destroy() {
|
260
|
+
for (let moduleName in this.modules) {
|
261
|
+
this.modules[moduleName]?.destroy?.();
|
262
|
+
}
|
263
|
+
},
|
167
264
|
|
168
265
|
// API function for scripts to register post-initialization callbacks
|
169
266
|
afterReady: (callback) => {
|
170
267
|
if (typeof callback === 'function') {
|
171
268
|
postWebflowCallbacks.push(callback);
|
172
|
-
} else {
|
173
269
|
}
|
174
270
|
},
|
175
271
|
|
@@ -177,7 +273,6 @@ const initializeAPI = () => {
|
|
177
273
|
afterWebflowReady: (callback) => {
|
178
274
|
if (typeof callback === 'function') {
|
179
275
|
postWebflowCallbacks.push(callback);
|
180
|
-
} else {
|
181
276
|
}
|
182
277
|
},
|
183
278
|
|
@@ -198,19 +293,69 @@ const initializeAPI = () => {
|
|
198
293
|
}
|
199
294
|
};
|
200
295
|
|
201
|
-
|
296
|
+
processAPI();
|
297
|
+
|
298
|
+
// Process any queued requests
|
299
|
+
window[API_NAME].push(...existingRequests);
|
300
|
+
};
|
202
301
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
302
|
+
const processAPI = () => {
|
303
|
+
// Check for auto mode
|
304
|
+
let autoMode = false;
|
305
|
+
for (let script of window[API_NAME].scripts || []) {
|
306
|
+
autoMode ||= script.getAttribute('data-hs-auto') === 'true';
|
307
|
+
|
308
|
+
// Load modules based on script attributes
|
309
|
+
for (const moduleName of Object.keys({ ...animationModules, ...utilityModules })) {
|
310
|
+
if (script.hasAttribute(moduleName)) {
|
311
|
+
loadHsModule(moduleName);
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
// Auto-discovery mode (scan DOM for attributes)
|
317
|
+
if (autoMode) {
|
318
|
+
document.fonts.ready.then(() => {
|
319
|
+
const foundModules = new Set();
|
320
|
+
const allElements = document.querySelectorAll('*');
|
321
|
+
|
322
|
+
for (let element of allElements) {
|
323
|
+
for (let attrName of element.getAttributeNames()) {
|
324
|
+
// Look for data-hs-[something] attributes
|
325
|
+
const match = attrName.match(/^data-hs-([^-=]+)/)?.[1];
|
326
|
+
if (match && attributeToModule[match]) {
|
327
|
+
foundModules.add(attributeToModule[match]);
|
328
|
+
}
|
329
|
+
}
|
207
330
|
}
|
331
|
+
|
332
|
+
for (let moduleName of foundModules) {
|
333
|
+
loadHsModule(moduleName);
|
334
|
+
}
|
335
|
+
});
|
336
|
+
}
|
337
|
+
|
338
|
+
// Always load auto-init modules
|
339
|
+
for (const moduleName of Object.keys(autoInitModules)) {
|
340
|
+
loadHsModule(moduleName);
|
341
|
+
}
|
342
|
+
|
343
|
+
// Hide .transition elements if transition module is not loaded
|
344
|
+
const hasTransition = window[API_NAME].scripts?.some(script =>
|
345
|
+
script.hasAttribute('data-hs-anim-transition')
|
346
|
+
);
|
347
|
+
if (!hasTransition) {
|
348
|
+
const transitionElements = document.querySelectorAll('.transition');
|
349
|
+
transitionElements.forEach(element => {
|
350
|
+
element.style.display = 'none';
|
208
351
|
});
|
209
352
|
}
|
210
353
|
};
|
211
354
|
|
212
355
|
if (document.readyState === 'loading') {
|
356
|
+
console.log(`⏳ DOM still loading, waiting for DOMContentLoaded...`);
|
213
357
|
document.addEventListener('DOMContentLoaded', initializeAPI);
|
214
358
|
} else {
|
359
|
+
console.log(`✅ DOM ready, initializing immediately`);
|
215
360
|
initializeAPI();
|
216
361
|
}
|