gclass-anims 1.0.0-beta.17 → 1.0.0-beta.19
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 +17 -6
- package/CHANGELOG.md +6 -0
- package/Listeners.js +24 -9
- package/index.d.ts +3 -4
- package/index.js +0 -1
- package/package.json +1 -2
- package/Boot.js +0 -12
package/AnimToggle.js
CHANGED
|
@@ -147,18 +147,29 @@ export function initAnimations() {
|
|
|
147
147
|
if (bootCleanup) { bootCleanup(); bootCleanup = null }
|
|
148
148
|
if (bootStyle) { bootStyle.remove(); bootStyle = null; document.documentElement.classList.remove('gclass-booting') }
|
|
149
149
|
|
|
150
|
-
const
|
|
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')) : []
|
|
151
162
|
if (!bootEls.length) {
|
|
152
163
|
// no .boot-up -> completely skip boot
|
|
153
164
|
} else if (bootEls.length > 1) {
|
|
154
165
|
console.error(`[initAnimations] Multiple .boot-up elements detected (${bootEls.length}) - skipping all boot animations`, bootEls)
|
|
155
|
-
bootEls
|
|
166
|
+
hideBootEls(bootEls)
|
|
156
167
|
hasBooted = true
|
|
157
168
|
// fall through to normal initListeners without pausing DOM
|
|
158
169
|
} else if (hasBooted && !bootTimeout) {
|
|
159
170
|
// path change after already booted (SPA navigation) - skip boot, hard reload resets hasBooted
|
|
160
171
|
console.log(`[initAnimations] skipping boot on path change (already booted)`, bootEls)
|
|
161
|
-
bootEls
|
|
172
|
+
hideBootEls(bootEls)
|
|
162
173
|
hasBooted = true
|
|
163
174
|
// fall through
|
|
164
175
|
} else {
|
|
@@ -188,11 +199,11 @@ export function initAnimations() {
|
|
|
188
199
|
bootTimeout = setTimeout(() => {
|
|
189
200
|
const bootEndCls = [...bootEl.classList].find(c => c.startsWith('boot-end-'))
|
|
190
201
|
if (!bootEndCls) {
|
|
191
|
-
// no boot-end -> skip exit animation, just
|
|
202
|
+
// no boot-end -> skip exit animation, just hide
|
|
192
203
|
bootCleanup?.(); bootCleanup = null
|
|
193
204
|
document.documentElement.classList.remove('gclass-booting')
|
|
194
205
|
bootStyle?.remove(); bootStyle = null
|
|
195
|
-
bootEls
|
|
206
|
+
hideBootEls(bootEls)
|
|
196
207
|
bootTimeout = null
|
|
197
208
|
cleanup = initListeners()
|
|
198
209
|
return
|
|
@@ -211,7 +222,7 @@ export function initAnimations() {
|
|
|
211
222
|
bootCleanup?.(); bootCleanup = null
|
|
212
223
|
document.documentElement.classList.remove('gclass-booting')
|
|
213
224
|
bootStyle?.remove(); bootStyle = null
|
|
214
|
-
bootEls
|
|
225
|
+
hideBootEls(bootEls)
|
|
215
226
|
bootTimeout = null
|
|
216
227
|
cleanup = initListeners()
|
|
217
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.19] - 2026-9-1
|
|
6
|
+
- Fixed the SplitText animations formatting and removed Boot.js
|
|
7
|
+
|
|
8
|
+
## [1.0.0-beta.18] - 2026-9-1
|
|
9
|
+
- Hopefully finally fixed `.boot-up` properly skipping on path changes
|
|
10
|
+
|
|
5
11
|
## [1.0.0-beta.17] - 2026-9-1
|
|
6
12
|
- Fixed the `.boot-up` class firing on every path change
|
|
7
13
|
|
package/Listeners.js
CHANGED
|
@@ -484,10 +484,7 @@ export default function initListeners(root = document) {
|
|
|
484
484
|
// would render it in its connecting form instead of its correct END form),
|
|
485
485
|
// but it should still be split into its own span so it animates too.
|
|
486
486
|
const RTL_LETTER = /[\u0621-\u064A\u066E-\u06D5\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/
|
|
487
|
-
const getRTLCharSplit = (el) => {
|
|
488
|
-
// Any element using SplitText gets pre-wrap so "\n" and formatting is preserved
|
|
489
|
-
if (el.style) el.style.whiteSpace = "pre-wrap"
|
|
490
|
-
return new SplitText(el, {
|
|
487
|
+
const getRTLCharSplit = (el) => new SplitText(el, {
|
|
491
488
|
type: "words",
|
|
492
489
|
linesClass: "gsap-line",
|
|
493
490
|
wordsClass: "gsap-word",
|
|
@@ -570,7 +567,6 @@ export default function initListeners(root = document) {
|
|
|
570
567
|
self.words.length = 0
|
|
571
568
|
},
|
|
572
569
|
})
|
|
573
|
-
}
|
|
574
570
|
|
|
575
571
|
// Flex targets can't be split directly: the split parts would become
|
|
576
572
|
// flex ITEMS, so justify-content/gap would apply per letter, whitespace-
|
|
@@ -611,22 +607,39 @@ export default function initListeners(root = document) {
|
|
|
611
607
|
}
|
|
612
608
|
|
|
613
609
|
const getSplit = (el, gran) => {
|
|
614
|
-
if (el.style) el.style.whiteSpace = "pre-wrap"
|
|
615
610
|
let s = splitCache.get(el)
|
|
616
611
|
const rtlChars = gran === "chars" && isRTLText(el)
|
|
617
612
|
const key = rtlChars ? "rtl-chars" : gran
|
|
618
613
|
if (!s || s.granularity !== key) {
|
|
619
614
|
if (s) revertSplitInstance(s)
|
|
615
|
+
const hasN = el.textContent.includes('\n')
|
|
616
|
+
// only set pre-wrap if element actually contains a newline, so \n renders without breaking other SplitText (flex/lines)
|
|
617
|
+
if (hasN && el.style) el.style.whiteSpace = 'pre-wrap'
|
|
620
618
|
s = rtlChars
|
|
621
619
|
? getRTLCharSplit(el)
|
|
622
620
|
: new SplitText(el, {
|
|
623
621
|
type: gran,
|
|
624
|
-
|
|
625
|
-
reduceWhiteSpace: false,
|
|
626
|
-
|
|
622
|
+
reduceWhiteSpace: hasN ? false : undefined,
|
|
627
623
|
linesClass: "gsap-line",
|
|
628
624
|
wordsClass: "gsap-word",
|
|
629
625
|
charsClass: "gsap-char",
|
|
626
|
+
onSplit(self) {
|
|
627
|
+
// make \n actually break line DURING split (not just after revert)
|
|
628
|
+
for (const c of self.chars || []) {
|
|
629
|
+
if (c.textContent === '\n') {
|
|
630
|
+
c.textContent = ''
|
|
631
|
+
c.style.display = 'block'
|
|
632
|
+
c.style.width = '100%'
|
|
633
|
+
c.style.height = '0'
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
// also handle words split where \n is between words
|
|
637
|
+
for (const w of self.words || []) {
|
|
638
|
+
if (w.textContent.includes('\n')) {
|
|
639
|
+
w.style.whiteSpace = 'pre-wrap'
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
630
643
|
})
|
|
631
644
|
s._gcFlexUnwrap = wrapFlexTarget(el)
|
|
632
645
|
s.granularity = key
|
|
@@ -642,8 +655,10 @@ export default function initListeners(root = document) {
|
|
|
642
655
|
// does this automatically for animated elements; Firefox is
|
|
643
656
|
// conservative and otherwise repaints these inline-block parts on the
|
|
644
657
|
// main thread every frame, which is what makes split-text lag there.
|
|
658
|
+
// A: keep inline flow so <strong> etc stays inline during split
|
|
645
659
|
for (let i = 0; i < parts.length; i++) {
|
|
646
660
|
parts[i].style.willChange = "transform, opacity"
|
|
661
|
+
if (gran === "chars" || gran === "words") parts[i].style.display = "inline-block"
|
|
647
662
|
}
|
|
648
663
|
return parts
|
|
649
664
|
}
|
package/index.d.ts
CHANGED
|
@@ -27,8 +27,9 @@ export function registerComplete(name: string, fn: CompleteHandler): CompleteHan
|
|
|
27
27
|
/**
|
|
28
28
|
* Boot the engine directly, bypassing AnimToggle. Returns a teardown function
|
|
29
29
|
* that removes all listeners/observers/tweens created by this run.
|
|
30
|
+
* Pass a root to scope to that subtree (used for .boot-up).
|
|
30
31
|
*/
|
|
31
|
-
export default function initListeners(): () => void
|
|
32
|
+
export default function initListeners(root?: Document | HTMLElement): () => void
|
|
32
33
|
|
|
33
34
|
// --- onComplete config -----------------------------------------------------
|
|
34
35
|
|
|
@@ -123,6 +124,7 @@ export interface Defaults {
|
|
|
123
124
|
minTextPartDuration: number
|
|
124
125
|
revealDelay: number
|
|
125
126
|
characterlist: string
|
|
127
|
+
bootTime: number
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
/** Global timing / ease defaults (edit to tweak global behaviour). */
|
|
@@ -221,6 +223,3 @@ export function marquee(target: TweenTarget, dir: string, duration: number, xOff
|
|
|
221
223
|
export function flip(state: any, ease: string, dur: number): any
|
|
222
224
|
export function animatecss(target: TweenTarget, dur: number, delay: number, ease: string, propertyS: any, propertySValue: any, propertyE: any, propertyEValue: any): any
|
|
223
225
|
|
|
224
|
-
|
|
225
|
-
export default function Boot()
|
|
226
|
-
|
package/index.js
CHANGED
|
@@ -2,5 +2,4 @@ export { initAnimations, toggleAnimations, enableReducedMotion, disableReducedMo
|
|
|
2
2
|
export { default as initListeners, registerComplete } from './Listeners.js'
|
|
3
3
|
export { customAnims } from './CustomAnims.js'
|
|
4
4
|
export { defaults, animations, normalize } from './Config.js'
|
|
5
|
-
export { Boot } from './Boot.js'
|
|
6
5
|
export * from './Animations.js'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gclass-anims",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.19",
|
|
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",
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"Animations.js",
|
|
22
22
|
"Config.js",
|
|
23
23
|
"CustomAnims.js",
|
|
24
|
-
"Boot.js",
|
|
25
24
|
"README.md",
|
|
26
25
|
"LICENSE",
|
|
27
26
|
"CHANGELOG.md"
|
package/Boot.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { initAnimations } from './AnimToggle.js'
|
|
2
|
-
|
|
3
|
-
export function Boot(){
|
|
4
|
-
const els = document.querySelectorAll(".boot-up")
|
|
5
|
-
console.log(`[Boot -> initAnimations] .boot-up count: ${els.length}`, els)
|
|
6
|
-
// rewired: Boot now just delegates to initAnimations (single entry point)
|
|
7
|
-
return initAnimations()
|
|
8
|
-
}
|
|
9
|
-
// keep named exports wired so index.js / dev don't break during test
|
|
10
|
-
export const initBoot = Boot
|
|
11
|
-
export const createBootOverlay = Boot
|
|
12
|
-
export default Boot
|