@hortonstudio/main 1.2.1 → 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.
Files changed (2) hide show
  1. package/index.js +114 -17
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // ver 1.2.1
1
+ // ver 1.2.2
2
2
 
3
3
  const API_NAME = 'hsmain';
4
4
 
@@ -27,6 +27,25 @@ const loadModule = async (moduleName) => {
27
27
  default:
28
28
  throw new Error(`HortonStudio module "${moduleName}" is not supported.`);
29
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);
30
49
  };
31
50
 
32
51
  const animationModules = {
@@ -124,12 +143,19 @@ const loadHsModule = async (moduleName) => {
124
143
  try {
125
144
  const { init, version } = await loadModule(moduleName);
126
145
  const initResult = await init();
127
- const { result } = initResult || {};
146
+ const { result, destroy } = initResult || {};
128
147
 
129
148
  moduleObj.version = version;
130
- moduleObj.restart = () => {
149
+
150
+ // Finsweet-style destroy and restart methods
151
+ moduleObj.destroy = () => {
152
+ destroy?.();
131
153
  apiInstance.process.delete(moduleName);
132
- return loadHsModule(moduleName);
154
+ };
155
+
156
+ moduleObj.restart = () => {
157
+ moduleObj.destroy?.();
158
+ return apiInstance.load(moduleName);
133
159
  };
134
160
 
135
161
  moduleObj.resolve?.(result);
@@ -146,10 +172,18 @@ const loadHsModule = async (moduleName) => {
146
172
  };
147
173
 
148
174
  const initializeAPI = () => {
149
- const apiInstance = window[API_NAME];
150
-
151
- const existingRequests = Array.isArray(apiInstance) ? apiInstance : [];
152
- const scriptTag = findCurrentScriptTag();
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
153
187
  const richTextBlocks = document.querySelectorAll('.w-richtext');
154
188
  richTextBlocks.forEach(block => {
155
189
  const images = block.querySelectorAll('img');
@@ -159,17 +193,33 @@ const initializeAPI = () => {
159
193
  });
160
194
 
161
195
  window[API_NAME] = {
162
- scriptTag,
196
+ scripts,
163
197
  modules: {},
164
198
  process: new Set(),
165
-
166
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
+ },
167
218
 
168
219
  // API function for scripts to register post-initialization callbacks
169
220
  afterReady: (callback) => {
170
221
  if (typeof callback === 'function') {
171
222
  postWebflowCallbacks.push(callback);
172
- } else {
173
223
  }
174
224
  },
175
225
 
@@ -177,7 +227,6 @@ const initializeAPI = () => {
177
227
  afterWebflowReady: (callback) => {
178
228
  if (typeof callback === 'function') {
179
229
  postWebflowCallbacks.push(callback);
180
- } else {
181
230
  }
182
231
  },
183
232
 
@@ -198,13 +247,61 @@ const initializeAPI = () => {
198
247
  }
199
248
  };
200
249
 
201
- processModules(scriptTag);
250
+ processAPI();
251
+
252
+ // Process any queued requests
253
+ window[API_NAME].push(...existingRequests);
254
+ };
202
255
 
203
- if (existingRequests.length > 0) {
204
- existingRequests.forEach(request => {
205
- if (typeof request === 'string') {
206
- window[API_NAME].load(request);
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);
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
+ }
207
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';
208
305
  });
209
306
  }
210
307
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hortonstudio/main",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {