()
| 229 | |
| 230 | // fallow-ignore-next-line complexity |
| 231 | const doReload = () => { |
| 232 | const timelines = win.__timelines; |
| 233 | const allTargets: Element[] = []; |
| 234 | |
| 235 | // Kill ONLY the target composition's timeline(s) — leaving every other |
| 236 | // composition's timeline (and its children on the global timeline) intact. |
| 237 | if (timelines) { |
| 238 | for (const key of targetKeys) { |
| 239 | const tl = timelines[key] as |
| 240 | | { |
| 241 | kill?: () => void; |
| 242 | getChildren?: (deep: boolean) => Array<{ targets?: () => Element[] }>; |
| 243 | } |
| 244 | | undefined; |
| 245 | if (!tl) continue; |
| 246 | if (tl.getChildren) { |
| 247 | try { |
| 248 | for (const child of tl.getChildren(true)) { |
| 249 | if (typeof child.targets === "function") { |
| 250 | for (const t of child.targets()) allTargets.push(t); |
| 251 | } |
| 252 | } |
| 253 | } catch {} |
| 254 | } |
| 255 | try { |
| 256 | tl.kill?.(); |
| 257 | } catch {} |
| 258 | delete timelines[key]; |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | // Also reset elements carrying a GSAP-applied inline `transform` that the |
| 263 | // timeline-children sweep above missed — a dragged element whose position |
| 264 | // was a standalone `gsap.set` (never a timeline child), or one whose |
| 265 | // keyframes were just removed (no longer in any timeline). Their last |
| 266 | // `gsap.set` transform is otherwise orphaned: the re-run won't re-set it |
| 267 | // and the sweep above can't see it, so the element renders offset from its |
| 268 | // source position (matching the overlay) until a full reload. The clear |
| 269 | // below runs BEFORE the re-run, which re-applies the transform for any |
| 270 | // element the new script still animates. |
| 271 | const seenTargets = new Set<Element>(allTargets); |
| 272 | for (const el of doc.querySelectorAll<HTMLElement>("[style*='transform']")) { |
| 273 | // Gate on the GSAP cache (`_gsap`) so we only reset transforms GSAP owns — |
| 274 | // never strip an authored, non-GSAP inline transform. |
| 275 | if (el.style.transform && "_gsap" in el && !seenTargets.has(el)) { |
| 276 | seenTargets.add(el); |
| 277 | allTargets.push(el); |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | // Reset GSAP's internal transform cache so from() tweens don't read stale |
| 282 | // end values. `clearProps: "all"` is needed to flush the cache, but it also |
| 283 | // nukes the element's CSS base (position, width, height, etc.) from the |
| 284 | // HTML `style=""` attribute. Save → clear → restore → strip `transform`. |
| 285 | if (allTargets.length > 0 && win.gsap?.set) { |
| 286 | const saved: Array<[Element, string]> = []; |
| 287 | for (const el of allTargets) { |
| 288 | const s = (el as HTMLElement).style; |
no test coverage detected