uikit
Version:
UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.
74 lines (56 loc) • 2.15 kB
JavaScript
import { clamp, createEvent, css, noop, resetProps, Transition, trigger } from 'uikit-util';
export default function Transitioner(prev, next, dir, { animation, easing }) {
const { percent, translate, show = noop } = animation;
const props = show(dir);
const { promise, resolve } = withResolvers();
return {
dir,
show(duration, percent = 0, linear) {
const timing = linear ? 'linear' : easing;
duration -= Math.round(duration * clamp(percent, -1, 1));
this.translate(percent);
triggerUpdate(next, 'itemin', { percent, duration, timing, dir });
triggerUpdate(prev, 'itemout', { percent: 1 - percent, duration, timing, dir });
Promise.all([
Transition.start(next, props[1], duration, timing),
Transition.start(prev, props[0], duration, timing),
]).then(() => {
this.reset();
resolve();
}, noop);
return promise;
},
cancel() {
return Transition.cancel([next, prev]);
},
reset() {
resetProps([next, prev], props[0]);
},
async forward(duration, percent = this.percent()) {
await this.cancel();
return this.show(duration, percent, true);
},
translate(percent) {
this.reset();
const props = translate(percent, dir);
css(next, props[1]);
css(prev, props[0]);
triggerUpdate(next, 'itemtranslatein', { percent, dir });
triggerUpdate(prev, 'itemtranslateout', { percent: 1 - percent, dir });
},
percent() {
return percent(prev || next, next, dir);
},
getDistance() {
return prev?.offsetWidth;
},
};
}
export function triggerUpdate(el, type, data) {
trigger(el, createEvent(type, false, false, data));
}
// Use Promise.withResolvers() once it becomes baseline
export function withResolvers() {
let resolve;
return { promise: new Promise((res) => (resolve = res)), resolve };
}