Skip to content

Instantly share code, notes, and snippets.

@barneycarroll
Last active March 5, 2021 01:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save barneycarroll/df0dc7b7390cea0351f8dc73ab07c5cf to your computer and use it in GitHub Desktop.
Save barneycarroll/df0dc7b7390cea0351f8dc73ab07c5cf to your computer and use it in GitHub Desktop.
import reflow from './reflow.js'
const startEvents = ['animationstart', 'transitionrun']
const endEvents = ['animationcancel', 'animationend', 'transitioncancel', 'transitionend']
export default function Presence({attrs: {
absent,
present,
entry,
exit,
}}){
const steps = [
[absent, entry],
[present],
[absent, exit],
]
.map(x => x.filter(Boolean))
return {
view: v =>
v.children,
oncreate: async ({dom}) => {
if(steps[0].length + steps[1].length === 0)
return
dom.classList.add(...steps[0])
void await reflow
dom.classList.remove(...steps[0])
dom.classList.add(...steps[1])
},
onbeforeremove: ({dom}) => new Promise(async done => {
let deferrals = 0
const increment = () => ++deferrals
void startEvents.forEach(event => {
dom.addEventListener(event, increment)
})
dom.classList.remove(...steps[1])
dom.classList.add(...steps[2])
await new Promise(requestAnimationFrame)
void startEvents.forEach(event => {
dom.removeEventListener(event, increment)
})
if(!deferrals)
done()
void endEvents.forEach(event => {
dom.addEventListener(event, () => --deferrals || done())
})
}),
}
}
let promise
export default {
then(done){
if(!promise)
promise = new Promise(done => {
requestAnimationFrame(() => {
promise = void document.body.clientWidth
done()
})
})
promise.then(done)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment