@postnord/web-components
Version:
PostNord Web Components
72 lines (71 loc) • 2.85 kB
JavaScript
import { reduceMotion } from "../../index";
/** Import the State and functions needed to easily animate the height of an element. */
function animateHeightFactory(Base) {
class AnimateHeightMixin extends Base {
constructor() {
super();
}
animation;
animationDurationDefault = 400;
animationDuration = this.animationDurationDefault;
isClosing = false;
isExpanding = false;
animateDropdown(element, open, startHeight, endHeight) {
this.cancelAnimations();
this.setAnimationDuration();
element.dataset.moving = '';
this.animation = element.animate({
height: [startHeight, endHeight],
}, {
duration: this.animationDuration,
easing: 'cubic-bezier(0.6, 0, 0.2, 1)',
});
this.animation.onfinish = () => this.animationFinish(element);
this.animation.oncancel = () => (open ? (this.isExpanding = false) : (this.isClosing = false));
}
/** Open the dropdown by assigning the HTML element you want to animate. */
openDropdown(element, heightOverride) {
const { clientHeight, scrollHeight } = element;
const height = this.isClosing ? clientHeight : 0;
element.style.height = `${scrollHeight}px`;
this.isExpanding = true;
this.animateDropdown(element, true, `${height}px`, `${heightOverride || element.scrollHeight}px`);
}
/** Close the dropdown by assigning the HTML element you want to animate. */
closeDropdown(element, heightOverride) {
const { scrollHeight, clientHeight } = element;
const height = this.isExpanding ? clientHeight : scrollHeight;
element.style.height = `0px`;
this.isClosing = true;
this.animateDropdown(element, false, `${heightOverride || height}px`, `0px`);
}
animationFinish(element) {
this.cancelAnimations();
element.style.height = this.isClosing ? '0px' : '';
delete element.dataset.moving;
this.isClosing = false;
this.isExpanding = false;
}
cancelAnimations() {
if (this.animation)
this.animation.cancel();
}
setAnimationDuration() {
if (reduceMotion())
this.animationDuration = 0;
else
this.animationDuration = this.animationDurationDefault;
}
isMoving() {
return this.isClosing || this.isExpanding;
}
static get states() {
return {
"isClosing": {},
"isExpanding": {}
};
}
}
return AnimateHeightMixin;
}
export { animateHeightFactory };