vue-loadable
Version:
Improves your loading state flow by providing methods and helpers to manage it.
165 lines (148 loc) • 5.01 kB
JavaScript
/*!
* vue-loadable v0.2.0
* (c) Vitor Cavalcanti <vitorluizc@outlook.com> (https://vitorluizc.github.io)
* Released under the MIT License.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) :
typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) :
(global = global || self, factory(global.VueLoadable = {}, global.Vue));
}(this, function (exports, Vue) { 'use strict';
Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue;
/**
* A mixin which adds loading states and helpers to Vue components.
* @example ```js
* Vue.component('SignUpForm', {
* mixins: [ LoadableMixin ],
* ...,
* mounted () {
* if (this.$isLoadingAny())
* console.log('Loading...');
* }
* })```
*/
var LoadableMixin = Vue.extend({
data: function data() {
return {
LOADING_STATES: Object.create(null)
};
},
methods: {
$isLoading: function $isLoading() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'unknown';
var value = this.LOADING_STATES[state];
return !!value && value > 0;
},
$isLoadingAny: function $isLoadingAny() {
return Object.keys(this.LOADING_STATES).some(this.$isLoading);
},
$setLoading: function $setLoading() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'unknown';
var value = this.LOADING_STATES[state];
this.$set(this.LOADING_STATES, state, value ? value + 1 : 1);
},
$unsetLoading: function $unsetLoading() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'unknown';
var value = this.LOADING_STATES[state];
this.$set(this.LOADING_STATES, state, value ? value - 1 : 0);
}
}
});
/**
* Call function and execute its hooks. Executes `onDone` when its done and
* `onError` when it throws an error.
* @param call
* @param onDone
* @param onError
*/
var callWithHooks = function callWithHooks(call, onDone) {
var onError = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : onDone;
var handleError = function handleError(error) {
onError();
return Promise.reject(error);
};
try {
return Promise.resolve(call()).then(function (value) {
onDone();
return Promise.resolve(value);
})["catch"](handleError);
} catch (error) {
return handleError(error);
}
};
/**
* Decorate a method to causes loading states changes during its execution. It
* sets state as loading when function is init and unsets on throws an error or
* resolve/return.
* @example
* Vue.component('SignInForm', {
* methods: {
* signIn: loadable(async function ({ email, password }) {
* // ...
* }, 'signIn')
* }
* });
* @param method - A method, commonly async, which causes loading state changes.
* @param [state] - Loading state name. It's "unknown" if not defined.
*/
var loadable = function loadable(method) {
var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'unknown';
return function () {
var _this = this,
_arguments = arguments;
this.$setLoading(state);
return callWithHooks(function () {
return method.apply(_this, _arguments);
}, function () {
return _this.$unsetLoading(state);
});
};
};
/**
* Maps an object, whose keys are `string` and the values are methods, to
* loadable methods that triggers loading states. It uses property's keys as
* loading state names.
* @example
* Vue.component('SignInForm', {
* ...,
* methods: {
* onClick() {
* if (this.$isLoading('signIn') || this.$isLoading('signUp'))
* return;
* // ...
* },
* ...mapLoadableMethods(
* mapActions('authentication', [
* 'signIn',
* 'signUp'
* ])
* )
* }
* });
*/
var mapLoadableMethods = function mapLoadableMethods(methods) {
var names = Object.keys(methods);
return names.reduce(function (loadableMethods, name) {
loadableMethods[name] = loadable(methods[name], name);
return loadableMethods;
}, Object.create(null));
};
/**
* Installs LoadableMixin globally.
* @example ```js
* Vue.use(install)```
* @param Vue - The Vue constructor.
*/
function install(Vue) {
Vue.mixin(LoadableMixin);
}
var vueLoadable = {
install: install
};
exports.LoadableMixin = LoadableMixin;
exports.default = vueLoadable;
exports.install = install;
exports.loadable = loadable;
exports.mapLoadableMethods = mapLoadableMethods;
Object.defineProperty(exports, '__esModule', { value: true });
}));