diff --git a/.changeset/fix-enter-anim-detached-element.md b/.changeset/fix-enter-anim-detached-element.md deleted file mode 100644 index ecdd6a5..0000000 --- a/.changeset/fix-enter-anim-detached-element.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -"@effex/dom": patch ---- - -Fix enter animations firing against a detached element on nested -client-mode re-mounts (e.g. router nav-back on pages with animations -deep inside the route's tree). - -`forkSlotEnter` forks the animation fiber via `Effect.forkIn(slotScope)` -from inside `addSlot`. Effect's scheduler can hand that fiber control -on the next microtask, before the outer synchronous render flow has -finished appending the wrapper's ancestor chain into the document. -When that happens, `onBeforeEnter` fires against a node whose ancestors -aren't yet in the DOM — `getComputedStyle` returns empty strings on -disconnected nodes, and browsers won't compute or transition styles -against them, so the enter transition never fires and the animation -stalls to the timeout. - -On first render this didn't surface because hydration walks pre-existing -DOM: every element was already connected when the fiber ran. It only -broke on subsequent client-mode mounts, and only when the animated -block sat inside another wrapper element (its own ancestor had to be -appended AFTER the fork). - -The animation fiber now yields microtasks until the element is -connected, up to a small bound. In practice the outer flow completes -within one or two microtasks; the bound ensures callers that never -insert their result (e.g. tests that yield an animated element without -appending it to the document) still make progress instead of hanging. - -Regression test in `Control.test.ts` asserts `element.isConnected` is -true at `onBeforeEnter` on both the initial mount AND the toggle-back -of a `when`-nested animated block that lives two wrappers deep. diff --git a/apps/docs/CHANGELOG.md b/apps/docs/CHANGELOG.md index edbc000..950c0d7 100644 --- a/apps/docs/CHANGELOG.md +++ b/apps/docs/CHANGELOG.md @@ -1,5 +1,13 @@ # docs +## 0.0.27 + +### Patch Changes + +- Updated dependencies [ec2ad34] + - @effex/dom@1.4.4 + - @effex/router@1.3.4 + ## 0.0.26 ### Patch Changes diff --git a/apps/docs/package.json b/apps/docs/package.json index 44ae3d2..ebb6cd7 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -1,6 +1,6 @@ { "name": "docs", - "version": "0.0.26", + "version": "0.0.27", "private": true, "type": "module", "scripts": { diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index b193fcc..2c8d86d 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -1,5 +1,39 @@ # @effex/dom +## 1.4.4 + +### Patch Changes + +- ec2ad34: Fix enter animations firing against a detached element on nested + client-mode re-mounts (e.g. router nav-back on pages with animations + deep inside the route's tree). + + `forkSlotEnter` forks the animation fiber via `Effect.forkIn(slotScope)` + from inside `addSlot`. Effect's scheduler can hand that fiber control + on the next microtask, before the outer synchronous render flow has + finished appending the wrapper's ancestor chain into the document. + When that happens, `onBeforeEnter` fires against a node whose ancestors + aren't yet in the DOM — `getComputedStyle` returns empty strings on + disconnected nodes, and browsers won't compute or transition styles + against them, so the enter transition never fires and the animation + stalls to the timeout. + + On first render this didn't surface because hydration walks pre-existing + DOM: every element was already connected when the fiber ran. It only + broke on subsequent client-mode mounts, and only when the animated + block sat inside another wrapper element (its own ancestor had to be + appended AFTER the fork). + + The animation fiber now yields microtasks until the element is + connected, up to a small bound. In practice the outer flow completes + within one or two microtasks; the bound ensures callers that never + insert their result (e.g. tests that yield an animated element without + appending it to the document) still make progress instead of hanging. + + Regression test in `Control.test.ts` asserts `element.isConnected` is + true at `onBeforeEnter` on both the initial mount AND the toggle-back + of a `when`-nested animated block that lives two wrappers deep. + ## 1.4.3 ### Patch Changes diff --git a/packages/dom/package.json b/packages/dom/package.json index f7dfc45..f4ee3a3 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@effex/dom", - "version": "1.4.3", + "version": "1.4.4", "description": "DOM rendering for Effex - a reactive UI framework built on Effect.ts", "type": "module", "license": "MIT", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index ec7cb2b..c7390cb 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -1,5 +1,12 @@ # @effex/router +## 1.3.4 + +### Patch Changes + +- Updated dependencies [ec2ad34] + - @effex/dom@1.4.4 + ## 1.3.3 ### Patch Changes diff --git a/packages/router/package.json b/packages/router/package.json index c5b0e20..fc7e60b 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@effex/router", - "version": "1.3.3", + "version": "1.3.4", "description": "Router for Effex applications", "type": "module", "license": "MIT",