vue-pose
Version:
A declarative animation library for Vue
314 lines (305 loc) • 8.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var tslib_1 = require('tslib');
var Vue = _interopDefault(require('vue'));
var poseFactory = _interopDefault(require('popmotion-pose'));
var heyListen = require('hey-listen');
var supportedElements = [
'a',
'article',
'aside',
'audio',
'b',
'blockquote',
'body',
'br',
'button',
'canvas',
'caption',
'cite',
'code',
'col',
'colgroup',
'data',
'datalist',
'dialog',
'div',
'em',
'embed',
'fieldset',
'figcaption',
'figure',
'footer',
'form',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'head',
'header',
'hgroup',
'hr',
'i',
'iframe',
'img',
'input',
'label',
'legend',
'li',
'nav',
'object',
'ol',
'option',
'p',
'param',
'picture',
'pre',
'progress',
'q',
'section',
'select',
'span',
'strong',
'table',
'tbody',
'td',
'textarea',
'tfoot',
'th',
'thead',
'time',
'title',
'tr',
'ul',
'video',
'circle',
'clipPath',
'defs',
'ellipse',
'g',
'image',
'line',
'linearGradient',
'mask',
'path',
'pattern',
'polygon',
'polyline',
'radialGradient',
'rect',
'stop',
'svg',
'text',
'tspan'
];
var PoserMap = new WeakMap();
var props = {
pose: {
type: String,
default: 'init'
},
preEnterPose: {
type: String,
default: undefined
},
poseKey: {
type: [String, Number],
default: undefined
},
onValueChange: {
type: Object,
default: undefined
},
onPoseComplete: {
type: Function,
default: undefined
},
withParent: {
type: Boolean,
default: true
}
};
var watch = {
$attrs: function (newAttrs) {
this.poser.setProps(newAttrs);
},
pose: function (newPose, oldPose) {
if (newPose !== oldPose)
this.setPose(newPose);
},
poseKey: function (newPoseKey, oldPoseKey) {
if (newPoseKey !== oldPoseKey)
this.setPose(this.pose);
}
};
function destroyed() {
if (!this.poser || !this._poseDestroyOnUnmount)
return;
if (this._poseOnChildUnmount)
this._poseOnChildUnmount(this.poser);
PoserMap.delete(this.$el);
this.poser.destroy();
}
var methods = {
getInitialPose: function () {
var _a = this.$props, preEnterPose = _a.preEnterPose, pose = _a.pose;
return this._poseGetInitialPoseFromParent
? this._poseGetInitialPoseFromParent()
: preEnterPose || pose;
},
getFirstPoseToSet: function () {
var _a = this.$props, preEnterPose = _a.preEnterPose, pose = _a.pose;
return preEnterPose ? pose : false;
},
initPoser: function (poser) {
this.poser = poser;
this.flushChildren();
PoserMap.set(this.$el, poser);
var firstPose = this.getFirstPoseToSet();
if (firstPose)
this.setPose(firstPose);
},
setPose: function (pose) {
var _this = this;
this.poser.set(pose).then(function () { return _this.$emit('poseComplete', pose); });
},
flushChildren: function () {
var _this = this;
if (!this.children)
return;
this.children.forEach(function (_a) {
var element = _a.element, config = _a.config, onRegistered = _a.onRegistered;
onRegistered(_this.poser.addChild(element, tslib_1.__assign({}, config, { initialPose: _this.getInitialPose() })));
});
this.children.clear();
},
getPoserProps: function () {
return tslib_1.__assign({}, this.$attrs);
}
};
function provide() {
var parent = this;
return {
_poseRegisterChild: function (child) {
parent.children = parent.children || new Set();
parent.children.add(child);
if (parent.poser)
parent.flushChildren();
},
_poseOnChildUnmount: function (poser) {
parent.poser.removeChild(poser);
}
};
}
var inject = {
_poseRegisterChild: { default: false },
_poseOnChildUnmount: { default: false },
_poseGetInitialPoseFromParent: { default: false },
_poseDestroyOnUnmount: { default: true }
};
var createPosedComponentFactory = function (el) { return function (config) {
if (config === void 0) { config = {}; }
return Vue.extend({
props: props,
provide: provide,
inject: inject,
mounted: function () {
var _this = this;
heyListen.invariant(typeof this.$el !== 'undefined', "No DOM element found.");
var poserConfig = tslib_1.__assign({}, config, { initialPose: this.getInitialPose(), onDragStart: this.$listeners['drag-start']
? function (e) { return _this.$emit('drag-start', e); }
: undefined, onDragEnd: this.$listeners['drag-end']
? function (e) { return _this.$emit('drag-end', e); }
: undefined, onPressStart: this.$listeners['press-start']
? function (e) { return _this.$emit('press-start', e); }
: undefined, onPressEnd: this.$listeners['press-end']
? function (e) { return _this.$emit('press-end', e); }
: undefined, onChange: this.$props.onValueChange, props: this.getPoserProps() });
if (!this.$props.withParent || !this._poseRegisterChild) {
this.initPoser(poseFactory(this.$el, poserConfig));
}
else {
this._poseRegisterChild({
element: this.$el,
config: poserConfig,
onRegistered: function (poser) { return _this.initPoser(poser); }
});
}
},
watch: watch,
methods: methods,
destroyed: destroyed,
render: function (createElement) {
return createElement(el, {}, [this.$slots.default]);
}
});
}; };
var posed = supportedElements.reduce(function (acc, el) {
acc[el] = createPosedComponentFactory(el);
return acc;
}, {});
var setPoserTo = function (fromPose, toPose, defaultConfig, that) { return function (el, done) {
if (!PoserMap.has(el)) {
PoserMap.set(el, poseFactory(el, tslib_1.__assign({}, defaultConfig, { initialPose: fromPose })));
}
PoserMap.get(el)
.set(toPose)
.then(function () {
that.$emit('poseComplete', toPose);
done();
});
}; };
var initPoser = function (setPrePose, initialPose) { return function () { return setPrePose(initialPose); }; };
var PoseTransition = Vue.extend({
props: {
enterPose: {
type: String,
default: 'enter'
},
exitPose: {
type: String,
default: 'exit'
}
},
provide: function () {
var parent = this;
return {
_poseGetInitialPoseFromParent: function () {
return parent.prePose;
},
_poseDestroyOnUnmount: false
};
},
created: function () {
var _this = this;
var _a;
var _b = this.$props, enterPose = _b.enterPose, exitPose = _b.exitPose;
var appear = this.$attrs.appear;
var defaultConfig = (_a = {},
_a[enterPose] = { opacity: 1 },
_a[exitPose] = { opacity: 0 },
_a);
var setPrePose = function (pose) { return (_this.prePose = pose); };
this.on = {
beforeEnter: initPoser(setPrePose, exitPose),
beforeLeave: initPoser(setPrePose, enterPose),
enter: setPoserTo(exitPose, enterPose, defaultConfig, this),
leave: setPoserTo(enterPose, exitPose, defaultConfig, this)
};
if (appear !== undefined) {
this.on.appear = setPoserTo(exitPose, enterPose, defaultConfig, this);
this.on.beforeAppear = initPoser(setPrePose, exitPose);
}
},
render: function (createElement) {
return createElement('transition', {
props: tslib_1.__assign({ css: false }, this.$attrs),
on: this.on
}, [this.$slots.default]);
}
});
exports.default = posed;
exports.PoseTransition = PoseTransition;