uikit
Version:
UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.
128 lines (106 loc) • 4.19 kB
JavaScript
import { addClass, hasClass, removeClass } from './class';
import { once, trigger } from './event';
import { toNodes } from './lang';
import { css, propName } from './style';
const clsTransition = 'uk-transition';
const transitionEnd = 'transitionend';
const transitionCanceled = 'transitioncanceled';
function transition(element, props, duration = 400, timing = 'linear') {
duration = Math.round(duration);
return Promise.all(
toNodes(element).map(
(element) =>
new Promise((resolve, reject) => {
for (const name in props) {
// Force reflow: transition won't run for previously hidden element
css(element, name);
}
const timer = setTimeout(() => trigger(element, transitionEnd), duration);
once(
element,
[transitionEnd, transitionCanceled],
({ type }) => {
clearTimeout(timer);
removeClass(element, clsTransition);
css(element, {
transitionProperty: '',
transitionDuration: '',
transitionTimingFunction: '',
});
type === transitionCanceled ? reject() : resolve(element);
},
{ self: true },
);
addClass(element, clsTransition);
css(element, {
transitionProperty: Object.keys(props).map(propName).join(','),
transitionDuration: `${duration}ms`,
transitionTimingFunction: timing,
...props,
});
}),
),
);
}
export const Transition = {
start: transition,
async stop(element) {
trigger(element, transitionEnd);
await Promise.resolve();
},
async cancel(element) {
trigger(element, transitionCanceled);
await Promise.resolve();
},
inProgress(element) {
return hasClass(element, clsTransition);
},
};
const clsAnimation = 'uk-animation';
const animationEnd = 'animationend';
const animationCanceled = 'animationcanceled';
function animate(element, animation, duration = 200, origin, out) {
return Promise.all(
toNodes(element).map(
(element) =>
new Promise((resolve, reject) => {
if (hasClass(element, clsAnimation)) {
trigger(element, animationCanceled);
}
const classes = [
animation,
clsAnimation,
`${clsAnimation}-${out ? 'leave' : 'enter'}`,
origin && `uk-transform-origin-${origin}`,
out && `${clsAnimation}-reverse`,
];
const timer = setTimeout(() => trigger(element, animationEnd), duration);
once(
element,
[animationEnd, animationCanceled],
({ type }) => {
clearTimeout(timer);
type === animationCanceled ? reject() : resolve(element);
css(element, 'animationDuration', '');
removeClass(element, classes);
},
{ self: true },
);
css(element, 'animationDuration', `${duration}ms`);
addClass(element, classes);
}),
),
);
}
export const Animation = {
in: animate,
out(element, animation, duration, origin) {
return animate(element, animation, duration, origin, true);
},
inProgress(element) {
return hasClass(element, clsAnimation);
},
cancel(element) {
trigger(element, animationCanceled);
},
};