gclass-anims 1.0.0-beta.16 → 1.0.0-beta.18

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/AnimToggle.js CHANGED
@@ -116,6 +116,7 @@ let cleanup = null
116
116
  let bootCleanup = null
117
117
  let bootTimeout = null
118
118
  let bootStyle = null
119
+ let hasBooted = false // true after first hard-load boot, skips boot on SPA path changes (remains false until first boot, resets on hard reload)
119
120
 
120
121
  const readBootTime = (els, fallback) => {
121
122
  let max = null
@@ -137,18 +138,40 @@ const readBootTime = (els, fallback) => {
137
138
  // Boot stops all DOM rendering for defaults.bootTime (overwritten by boot-time-N class).
138
139
  export function initAnimations() {
139
140
  if (typeof window === 'undefined' || !getEnabled()) return
141
+ // boot already in progress (first mount in StrictMode) - ignore second mount
142
+ if (bootTimeout) {
143
+ console.log(`[initAnimations] boot already in progress - ignoring duplicate call`)
144
+ return
145
+ }
140
146
  if (cleanup) { cleanup(); cleanup = null }
141
147
  if (bootCleanup) { bootCleanup(); bootCleanup = null }
142
- if (bootTimeout) { clearTimeout(bootTimeout); bootTimeout = null }
143
148
  if (bootStyle) { bootStyle.remove(); bootStyle = null; document.documentElement.classList.remove('gclass-booting') }
144
149
 
145
- const bootEls = typeof document !== 'undefined' ? document.querySelectorAll(".boot-up") : []
150
+ const hideBootEls = (els) => {
151
+ // React-safe: don't el.remove() - React owns the nodes and will throw
152
+ // insertBefore/removeChild on next commit if we mutate outside React.
153
+ // Hiding keeps React's tree intact but visually removes boot screen.
154
+ els.forEach(el => {
155
+ el.style.display = 'none'
156
+ el.setAttribute('hidden', '')
157
+ el.setAttribute('data-gclass-boot-hidden', '1')
158
+ })
159
+ }
160
+
161
+ const bootEls = typeof document !== 'undefined' ? [...document.querySelectorAll(".boot-up")].filter(el => !el.hasAttribute('data-gclass-boot-hidden')) : []
146
162
  if (!bootEls.length) {
147
163
  // no .boot-up -> completely skip boot
148
164
  } else if (bootEls.length > 1) {
149
165
  console.error(`[initAnimations] Multiple .boot-up elements detected (${bootEls.length}) - skipping all boot animations`, bootEls)
150
- bootEls.forEach(el => el.remove())
166
+ hideBootEls(bootEls)
167
+ hasBooted = true
151
168
  // fall through to normal initListeners without pausing DOM
169
+ } else if (hasBooted && !bootTimeout) {
170
+ // path change after already booted (SPA navigation) - skip boot, hard reload resets hasBooted
171
+ console.log(`[initAnimations] skipping boot on path change (already booted)`, bootEls)
172
+ hideBootEls(bootEls)
173
+ hasBooted = true
174
+ // fall through
152
175
  } else {
153
176
  const bootEl = bootEls[0]
154
177
  const hasBootEnd = [...bootEl.classList].some(c => c.startsWith('boot-end-'))
@@ -160,6 +183,7 @@ export function initAnimations() {
160
183
  }
161
184
  const bootTime = readBootTime(bootEls, defaults.bootTime ?? 2)
162
185
  console.log(`[initAnimations] .boot-up found: ${bootEls.length} - pausing DOM for ${bootTime}s`, bootEls)
186
+ hasBooted = true
163
187
  // stop all DOM rendering except .boot-up
164
188
  bootStyle = document.createElement('style')
165
189
  bootStyle.id = 'gclass-boot-style'
@@ -175,11 +199,11 @@ export function initAnimations() {
175
199
  bootTimeout = setTimeout(() => {
176
200
  const bootEndCls = [...bootEl.classList].find(c => c.startsWith('boot-end-'))
177
201
  if (!bootEndCls) {
178
- // no boot-end -> skip exit animation, just remove
202
+ // no boot-end -> skip exit animation, just hide
179
203
  bootCleanup?.(); bootCleanup = null
180
204
  document.documentElement.classList.remove('gclass-booting')
181
205
  bootStyle?.remove(); bootStyle = null
182
- bootEls.forEach(el => el.remove())
206
+ hideBootEls(bootEls)
183
207
  bootTimeout = null
184
208
  cleanup = initListeners()
185
209
  return
@@ -198,7 +222,7 @@ export function initAnimations() {
198
222
  bootCleanup?.(); bootCleanup = null
199
223
  document.documentElement.classList.remove('gclass-booting')
200
224
  bootStyle?.remove(); bootStyle = null
201
- bootEls.forEach(el => el.remove())
225
+ hideBootEls(bootEls)
202
226
  bootTimeout = null
203
227
  cleanup = initListeners()
204
228
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to `gclass-anims` will be documented in this file.
4
4
 
5
+ ## [1.0.0-beta.18] - 2026-9-1
6
+ - Hopefully finally fixed `.boot-up` properly skipping on path changes
7
+
8
+ ## [1.0.0-beta.17] - 2026-9-1
9
+ - Fixed the `.boot-up` class firing on every path change
10
+
5
11
  ## [1.0.0-beta.16] - 2026-09-1
6
12
  - Added a new `.boot-up` class for boot up animations
7
13
  - Fixed text animations not taking formatting into account
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gclass-anims",
3
- "version": "1.0.0-beta.16",
3
+ "version": "1.0.0-beta.18",
4
4
  "description": "A Tailwind-style utility layer on top of GSAP. Framework-agnostic - works in vanilla JS, React, Vue, Svelte, or any bundler.",
5
5
  "type": "module",
6
6
  "main": "index.js",