Last active
March 8, 2021 04:37
-
-
Save coagmano/f63546db3c6867e051d3501a972ba41c to your computer and use it in GitHub Desktop.
Blaze animate HOC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{{> UI.ContentBlock }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import './animate.html'; | |
import { Meteor } from 'meteor/meteor'; | |
import { Template } from 'meteor/templating'; | |
Template.animate.onRendered(function() { | |
if (this.firstNode.parentNode && this.firstNode.parentNode._uihooks) { | |
throw new Error( | |
'The parent of this animate component already has _uihooks set', | |
this | |
); | |
} | |
const animationElements = this.findAll('.animate'); | |
// HACK: initial animation rendered, as insertElement, doesn't seem to fire | |
requestAnimationFrame(() => { | |
[...animationElements].forEach(node => { | |
node.classList.remove('animate'); | |
}); | |
}); | |
// add the parentNode te the instance, so we can access it in the destroyed function | |
this.parentNode = this.firstNode.parentNode; | |
this.parentNode._uihooks = { | |
insertElement: (node, next) => { | |
this.parentNode.insertBefore(node, next); | |
if (node.classList.contains('animate')) { | |
animationElements.push(node); | |
// animate | |
requestAnimationFrame(() => { | |
node.classList.remove('animate'); | |
}); | |
} | |
}, | |
removeElement: node => { | |
const indexOfElement = animationElements.indexOf(node); | |
if ( | |
document.hasFocus() && | |
indexOfElement !== -1 && | |
!Meteor.isTest | |
) { | |
// remove from animation elements array | |
const onTransitionEnd = () => { | |
node.remove(); | |
node.removeEventListener('transitionend', onTransitionEnd); | |
node = null; | |
}; | |
animationElements.splice(indexOfElement, 1); | |
node.addEventListener('transitionend', onTransitionEnd); | |
node.classList.add('animate'); | |
} else { | |
// otherwise remove immediately | |
node.remove(); | |
node = null; | |
} | |
}, | |
}; | |
}); | |
/** | |
The destroyed method, which remove the hooks to make sure, they work again next time. | |
*/ | |
Template.animate.onDestroyed(function() { | |
Meteor.defer(() => { | |
if (this._parentNode) this._parentNode._uihooks = null; | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.todo-list li { | |
opacity: 1; | |
transition: opacity 1s; | |
} | |
.todo-list li.animate { | |
opacity: 0 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template name="todoList"> | |
<div class="todo-list-container"> | |
<ul class="todo-list"> | |
{{#animate}} | |
{{#each todo in todos}} | |
<li class="animate">{{todo.body}}</li> | |
{{/each}} | |
{{/animate}} | |
</ul> | |
</div> | |
</template> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment