@hortonstudio/main 1.2.9 → 1.2.12

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.
@@ -1,5 +1,10 @@
1
1
  const API_NAME = 'hsmain';
2
2
 
3
+ // Check for reduced motion preference
4
+ const prefersReducedMotion = () => {
5
+ return window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6
+ };
7
+
3
8
  // Animation timing (in seconds)
4
9
  const timing = {
5
10
  announce: 0,
@@ -119,12 +124,76 @@ function startHeroAnimations() {
119
124
  init();
120
125
  }
121
126
 
127
+ function showHeroElementsWithoutAnimation() {
128
+ // Simply show all hero elements without any animation or split text
129
+ const allHeroElements = [
130
+ ...document.querySelectorAll('[data-hs-hero="announce"]'),
131
+ ...document.querySelectorAll('[data-hs-hero="nav"]'),
132
+ ...document.querySelectorAll('[data-hs-hero="nav-menu"]'),
133
+ ...document.querySelectorAll('[data-hs-hero="nav-logo"]'),
134
+ ...document.querySelectorAll('[data-hs-hero="nav-button"] > *:first-child'),
135
+ ...document.querySelectorAll('[data-hs-hero="nav-list"] > * > *:first-child'),
136
+ ...document.querySelectorAll('[data-hs-hero="heading"] > *:first-child'),
137
+ ...document.querySelectorAll('[data-hs-hero="subheading"] > *:first-child'),
138
+ ...document.querySelectorAll('[data-hs-hero="tag"] > *:first-child'),
139
+ ...document.querySelectorAll('[data-hs-hero="button"] > *'),
140
+ ...document.querySelectorAll('[data-hs-hero="image"]'),
141
+ ...document.querySelectorAll('[data-hs-hero="appear"]')
142
+ ];
143
+
144
+ allHeroElements.forEach(element => {
145
+ if (element) {
146
+ gsap.set(element, {
147
+ autoAlpha: 1,
148
+ opacity: 1,
149
+ y: 0,
150
+ yPercent: 0
151
+ });
152
+ // Remove any pointer-events restrictions
153
+ element.style.pointerEvents = '';
154
+ }
155
+ });
156
+
157
+ // Restore page-wide tabbing
158
+ const allFocusableElements = document.querySelectorAll('[data-original-tabindex]');
159
+ allFocusableElements.forEach(el => {
160
+ el.style.pointerEvents = '';
161
+ const originalTabindex = el.getAttribute('data-original-tabindex');
162
+ if (originalTabindex === '0') {
163
+ el.removeAttribute('tabindex');
164
+ } else {
165
+ el.setAttribute('tabindex', originalTabindex);
166
+ }
167
+ el.removeAttribute('data-original-tabindex');
168
+ });
169
+ }
170
+
122
171
  export async function init() {
123
172
  if (typeof window.gsap === "undefined") {
124
173
  console.error('GSAP not found - hero animations disabled');
125
174
  return;
126
175
  }
127
176
 
177
+ if (prefersReducedMotion()) {
178
+ // For reduced motion, just show elements without animation
179
+ showHeroElementsWithoutAnimation();
180
+
181
+ // Still expose the API for consistency
182
+ window[API_NAME] = window[API_NAME] || {};
183
+ window[API_NAME].heroAnimations = {
184
+ config: config,
185
+ updateConfig: updateConfig,
186
+ start: startHeroAnimations,
187
+ kill: killHeroAnimations,
188
+ restart: () => {
189
+ killHeroAnimations();
190
+ startHeroAnimations();
191
+ }
192
+ };
193
+
194
+ return { result: 'anim-hero initialized (reduced motion)' };
195
+ }
196
+
128
197
  gsap.registerPlugin(ScrollTrigger, SplitText);
129
198
 
130
199
  // Element selection
@@ -1,5 +1,10 @@
1
1
  const API_NAME = 'hsmain';
2
2
 
3
+ // Check for reduced motion preference
4
+ const prefersReducedMotion = () => {
5
+ return window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6
+ };
7
+
3
8
  const config = {
4
9
  global: {
5
10
  animationDelay: 0
@@ -62,6 +67,12 @@ function killTextAnimations() {
62
67
  }
63
68
 
64
69
  function startTextAnimations() {
70
+ if (prefersReducedMotion()) {
71
+ // For reduced motion, just show elements without animation
72
+ showElementsWithoutAnimation();
73
+ return;
74
+ }
75
+
65
76
  setInitialStates().then(() => {
66
77
  initAnimations();
67
78
  });
@@ -73,14 +84,36 @@ function waitForFonts() {
73
84
  return document.fonts.ready;
74
85
  }
75
86
 
87
+ function showElementsWithoutAnimation() {
88
+ // Simply show all text elements without any animation or split text
89
+ const allTextElements = [
90
+ ...document.querySelectorAll(".a-char-split > *:first-child"),
91
+ ...document.querySelectorAll(".a-word-split > *:first-child"),
92
+ ...document.querySelectorAll(".a-line-split > *:first-child"),
93
+ ...document.querySelectorAll('.a-appear')
94
+ ];
95
+
96
+ allTextElements.forEach(element => {
97
+ gsap.set(element, {
98
+ autoAlpha: 1,
99
+ y: 0,
100
+ yPercent: 0,
101
+ opacity: 1
102
+ });
103
+ });
104
+ }
105
+
76
106
  const CharSplitAnimations = {
77
107
  async initial() {
78
108
  await waitForFonts();
79
109
 
110
+ if (prefersReducedMotion()) {
111
+ return;
112
+ }
113
+
80
114
  const elements = document.querySelectorAll(".a-char-split > *:first-child");
81
115
 
82
- elements.forEach((textElement, index) => {
83
-
116
+ elements.forEach((textElement) => {
84
117
  const split = SplitText.create(textElement, {
85
118
  type: "chars",
86
119
  mask: "chars",
@@ -98,6 +131,10 @@ const CharSplitAnimations = {
98
131
  async animate() {
99
132
  await waitForFonts();
100
133
 
134
+ if (prefersReducedMotion()) {
135
+ return;
136
+ }
137
+
101
138
  document.querySelectorAll(".a-char-split > *:first-child").forEach((textElement) => {
102
139
  const chars = textElement.querySelectorAll('.char');
103
140
  const tl = gsap.timeline({
@@ -127,10 +164,13 @@ const WordSplitAnimations = {
127
164
  async initial() {
128
165
  await waitForFonts();
129
166
 
167
+ if (prefersReducedMotion()) {
168
+ return;
169
+ }
170
+
130
171
  const elements = document.querySelectorAll(".a-word-split > *:first-child");
131
172
 
132
- elements.forEach((textElement, index) => {
133
-
173
+ elements.forEach((textElement) => {
134
174
  const split = SplitText.create(textElement, {
135
175
  type: "words",
136
176
  mask: "words",
@@ -148,6 +188,10 @@ const WordSplitAnimations = {
148
188
  async animate() {
149
189
  await waitForFonts();
150
190
 
191
+ if (prefersReducedMotion()) {
192
+ return;
193
+ }
194
+
151
195
  document.querySelectorAll(".a-word-split > *:first-child").forEach((textElement) => {
152
196
  const words = textElement.querySelectorAll('.word');
153
197
  const tl = gsap.timeline({
@@ -177,10 +221,13 @@ const LineSplitAnimations = {
177
221
  async initial() {
178
222
  await waitForFonts();
179
223
 
224
+ if (prefersReducedMotion()) {
225
+ return;
226
+ }
227
+
180
228
  const elements = document.querySelectorAll(".a-line-split > *:first-child");
181
229
 
182
- elements.forEach((textElement, index) => {
183
-
230
+ elements.forEach((textElement) => {
184
231
  const split = SplitText.create(textElement, {
185
232
  type: "lines",
186
233
  mask: "lines",
@@ -198,6 +245,10 @@ const LineSplitAnimations = {
198
245
  async animate() {
199
246
  await waitForFonts();
200
247
 
248
+ if (prefersReducedMotion()) {
249
+ return;
250
+ }
251
+
201
252
  document.querySelectorAll(".a-line-split > *:first-child").forEach((textElement) => {
202
253
  const lines = textElement.querySelectorAll('.line');
203
254
  const tl = gsap.timeline({
@@ -227,6 +278,10 @@ const AppearAnimations = {
227
278
  async initial() {
228
279
  await waitForFonts();
229
280
 
281
+ if (prefersReducedMotion()) {
282
+ return;
283
+ }
284
+
230
285
  const elements = document.querySelectorAll('.a-appear');
231
286
  elements.forEach(element => {
232
287
  gsap.set(element, {
@@ -239,6 +294,10 @@ const AppearAnimations = {
239
294
  async animate() {
240
295
  await waitForFonts();
241
296
 
297
+ if (prefersReducedMotion()) {
298
+ return;
299
+ }
300
+
242
301
  document.querySelectorAll('.a-appear').forEach(element => {
243
302
  const tl = gsap.timeline({
244
303
  scrollTrigger: {
@@ -284,8 +343,13 @@ async function initAnimations() {
284
343
  }
285
344
 
286
345
  export async function init() {
287
- await setInitialStates();
288
- initAnimations();
346
+ if (prefersReducedMotion()) {
347
+ // For reduced motion, just show elements without animation
348
+ showElementsWithoutAnimation();
349
+ } else {
350
+ await setInitialStates();
351
+ initAnimations();
352
+ }
289
353
 
290
354
  window.addEventListener('resize', ScrollTrigger.refresh());
291
355
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@finsweet/attributes",
3
3
  "description": "Finsweet's Attributes monorepo.",
4
- "version": "2.0.0",
4
+ "version": "1.2.12",
5
5
  "type": "module",
6
6
  "private": true,
7
7
  "license": "Apache-2.0",
@@ -0,0 +1,37 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>CDN Version Debug Test</title>
5
+ </head>
6
+ <body>
7
+ <h1>CDN Version Debug Test</h1>
8
+ <div id="results"></div>
9
+
10
+ <!-- Test with major version @1 -->
11
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@1/index.js" data-hs-main data-hs-anim-hero></script>
12
+
13
+ <script>
14
+ setTimeout(() => {
15
+ const results = document.getElementById('results');
16
+
17
+ // Check what scripts are found
18
+ const scripts = [...document.querySelectorAll('script[type="module"]')];
19
+ results.innerHTML += `<h2>Found Scripts:</h2>`;
20
+ scripts.forEach((script, i) => {
21
+ results.innerHTML += `<p>Script ${i}: ${script.src}</p>`;
22
+ });
23
+
24
+ // Check if hsmain loaded and what scripts it found
25
+ if (window.hsmain) {
26
+ results.innerHTML += `<h2>HSMAIN Scripts Found:</h2>`;
27
+ results.innerHTML += `<p>Found ${window.hsmain.scripts.length} matching scripts</p>`;
28
+ window.hsmain.scripts.forEach((script, i) => {
29
+ results.innerHTML += `<p>HSMAIN Script ${i}: ${script.src}</p>`;
30
+ });
31
+ } else {
32
+ results.innerHTML += `<p>HSMAIN not loaded</p>`;
33
+ }
34
+ }, 2000);
35
+ </script>
36
+ </body>
37
+ </html>
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // ver 1.2.9
1
+ // ver 1.2.12
2
2
 
3
3
  const API_NAME = 'hsmain';
4
4
 
@@ -73,8 +73,21 @@ const initializeHsMain = () => {
73
73
  });
74
74
  };
75
75
 
76
- // Find script tags (Finsweet approach)
77
- const scripts = [...document.querySelectorAll(`script[type="module"][src="${import.meta.url}"]`)];
76
+ // Find script tags (with CDN version redirect support)
77
+ let scripts = [...document.querySelectorAll(`script[type="module"][src="${import.meta.url}"]`)];
78
+
79
+ // Handle CDN version redirects (e.g., @1 -> @1.2.11)
80
+ if (scripts.length === 0) {
81
+ const allScripts = [...document.querySelectorAll('script[type="module"][src*="@hortonstudio/main"]')];
82
+ scripts = allScripts.filter(script => {
83
+ const src = script.src;
84
+ const metaUrl = import.meta.url;
85
+ // Extract package name and check if they match (ignoring version differences)
86
+ const srcPackage = src.match(/@hortonstudio\/main(@[\d.]+)?/)?.[0];
87
+ const metaPackage = metaUrl.match(/@hortonstudio\/main(@[\d.]+)?/)?.[0];
88
+ return srcPackage && metaPackage && srcPackage.split('@')[0] === metaPackage.split('@')[0];
89
+ });
90
+ }
78
91
 
79
92
  // Module loading function
80
93
  const loadHsModule = async (moduleName) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hortonstudio/main",
3
- "version": "1.2.9",
3
+ "version": "1.2.12",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {