UNPKG

vue3-loading-overlay

Version:

Vue.js component for full screen loading indicator, compatible for vue3.

511 lines (491 loc) 12.9 kB
/** * Vue 3 Loading Overlay 0.0.0 * (c) 2020 * @license MIT */ import { defineComponent, openBlock, createBlock, createVNode, ref, computed, onMounted, onUnmounted, watch, Transition, withCtx, withDirectives, withModifiers, renderSlot, resolveDynamicComponent, vShow, h, render as render$4 } from 'vue'; var script = defineComponent({ name: "spinner", props: { color: { type: String, default: "#000", }, height: { type: Number, default: 64, }, width: { type: Number, default: 64, }, }, }); const _hoisted_1 = /*#__PURE__*/createVNode("g", { fill: "none", "fill-rule": "evenodd" }, [ /*#__PURE__*/createVNode("g", { transform: "translate(1 1)", "stroke-width": "2" }, [ /*#__PURE__*/createVNode("circle", { "stroke-opacity": ".25", cx: "18", cy: "18", r: "18" }), /*#__PURE__*/createVNode("path", { d: "M36 18c0-9.94-8.06-18-18-18" }, [ /*#__PURE__*/createVNode("animateTransform", { attributeName: "transform", type: "rotate", from: "0 18 18", to: "360 18 18", dur: "0.8s", repeatCount: "indefinite" }) ]) ]) ], -1 /* HOISTED */); function render(_ctx, _cache, $props, $setup, $data, $options) { return (openBlock(), createBlock("svg", { viewBox: "0 0 38 38", xmlns: "http://www.w3.org/2000/svg", width: _ctx.width, height: _ctx.height, stroke: _ctx.color }, [ _hoisted_1 ], 8 /* PROPS */, ["width", "height", "stroke"])) } script.render = render; script.__file = "src/loaders/Spinner.vue"; var script$1 = defineComponent({ name: "dots", props: { color: { type: String, default: "#000", }, height: { type: Number, default: 240, }, width: { type: Number, default: 60, }, }, }); const _hoisted_1$1 = /*#__PURE__*/createVNode("circle", { cx: "15", cy: "15", r: "15" }, [ /*#__PURE__*/createVNode("animate", { attributeName: "r", from: "15", to: "15", begin: "0s", dur: "0.8s", values: "15;9;15", calcMode: "linear", repeatCount: "indefinite" }), /*#__PURE__*/createVNode("animate", { attributeName: "fill-opacity", from: "1", to: "1", begin: "0s", dur: "0.8s", values: "1;.5;1", calcMode: "linear", repeatCount: "indefinite" }) ], -1 /* HOISTED */); const _hoisted_2 = /*#__PURE__*/createVNode("circle", { cx: "60", cy: "15", r: "9", "fill-opacity": "0.3" }, [ /*#__PURE__*/createVNode("animate", { attributeName: "r", from: "9", to: "9", begin: "0s", dur: "0.8s", values: "9;15;9", calcMode: "linear", repeatCount: "indefinite" }), /*#__PURE__*/createVNode("animate", { attributeName: "fill-opacity", from: "0.5", to: "0.5", begin: "0s", dur: "0.8s", values: ".5;1;.5", calcMode: "linear", repeatCount: "indefinite" }) ], -1 /* HOISTED */); const _hoisted_3 = /*#__PURE__*/createVNode("circle", { cx: "105", cy: "15", r: "15" }, [ /*#__PURE__*/createVNode("animate", { attributeName: "r", from: "15", to: "15", begin: "0s", dur: "0.8s", values: "15;9;15", calcMode: "linear", repeatCount: "indefinite" }), /*#__PURE__*/createVNode("animate", { attributeName: "fill-opacity", from: "1", to: "1", begin: "0s", dur: "0.8s", values: "1;.5;1", calcMode: "linear", repeatCount: "indefinite" }) ], -1 /* HOISTED */); function render$1(_ctx, _cache, $props, $setup, $data, $options) { return (openBlock(), createBlock("svg", { viewBox: "0 0 120 30", xmlns: "http://www.w3.org/2000/svg", fill: _ctx.color, width: _ctx.width, height: _ctx.height }, [ _hoisted_1$1, _hoisted_2, _hoisted_3 ], 8 /* PROPS */, ["fill", "width", "height"])) } script$1.render = render$1; script$1.__file = "src/loaders/Dots.vue"; var script$2 = defineComponent({ name: "bars", props: { color: { type: String, default: "#000", }, height: { type: Number, default: 40, }, width: { type: Number, default: 40, }, }, }); const _hoisted_1$2 = /*#__PURE__*/createVNode("rect", { x: "0", y: "13", width: "4", height: "5" }, [ /*#__PURE__*/createVNode("animate", { attributeName: "height", attributeType: "XML", values: "5;21;5", begin: "0s", dur: "0.6s", repeatCount: "indefinite" }), /*#__PURE__*/createVNode("animate", { attributeName: "y", attributeType: "XML", values: "13; 5; 13", begin: "0s", dur: "0.6s", repeatCount: "indefinite" }) ], -1 /* HOISTED */); const _hoisted_2$1 = /*#__PURE__*/createVNode("rect", { x: "10", y: "13", width: "4", height: "5" }, [ /*#__PURE__*/createVNode("animate", { attributeName: "height", attributeType: "XML", values: "5;21;5", begin: "0.15s", dur: "0.6s", repeatCount: "indefinite" }), /*#__PURE__*/createVNode("animate", { attributeName: "y", attributeType: "XML", values: "13; 5; 13", begin: "0.15s", dur: "0.6s", repeatCount: "indefinite" }) ], -1 /* HOISTED */); const _hoisted_3$1 = /*#__PURE__*/createVNode("rect", { x: "20", y: "13", width: "4", height: "5" }, [ /*#__PURE__*/createVNode("animate", { attributeName: "height", attributeType: "XML", values: "5;21;5", begin: "0.3s", dur: "0.6s", repeatCount: "indefinite" }), /*#__PURE__*/createVNode("animate", { attributeName: "y", attributeType: "XML", values: "13; 5; 13", begin: "0.3s", dur: "0.6s", repeatCount: "indefinite" }) ], -1 /* HOISTED */); function render$2(_ctx, _cache, $props, $setup, $data, $options) { return (openBlock(), createBlock("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 30 30", height: _ctx.height, width: _ctx.width, fill: _ctx.color }, [ _hoisted_1$2, _hoisted_2$1, _hoisted_3$1 ], 8 /* PROPS */, ["height", "width", "fill"])) } script$2.render = render$2; script$2.__file = "src/loaders/Bars.vue"; var Loaders = { Spinner: script, Dots: script$1, Bars: script$2, }; var script$3 = defineComponent({ name: "vue-loading", props: { active: Boolean, programmatic: Boolean, container: [Object, Function, HTMLElement], isFullPage: { type: Boolean, default: true, }, enforceFocus: { type: Boolean, default: true, }, lockScroll: { type: Boolean, default: false, }, transition: { type: String, default: "fade", }, /** * Allow user to hide the loader */ canCancel: Boolean, /** * Do something on cancel */ onCancel: { type: Function, default: () => { return; }, }, color: String, backgroundColor: String, blur: { type: String, default: "2px", }, opacity: Number, width: Number, height: Number, zIndex: { type: Number, default: 100, }, loader: { type: String, default: "spinner", }, }, setup(props, context) { const isActive = ref(props.active); const bgStyle = computed(() => { let ret = { background: props.backgroundColor, opacity: props.opacity, backdropFilter: `blur(${props.blur})`, }; return ret; }); const hide = () => { // Timeout for the animation complete before destroying if (props.programmatic) { isActive.value = false; setTimeout(() => { return; }, 150); } }; const cancel = () => { if (!props.canCancel || !isActive.value) return; hide(); props.onCancel(); }; const keyUp = (event) => { if (event.keyCode === 27) { cancel(); } }; const disableScroll = () => { if (props.isFullPage && props.lockScroll) { document.body.classList.add("vld-shown"); } }; const enableScroll = () => { if (props.isFullPage && props.lockScroll) { document.body.classList.remove("vld-shown"); } }; onMounted(() => { if (props.programmatic) { isActive.value = true; document.addEventListener("keyup", keyUp); } }); onUnmounted(() => { document.removeEventListener("keyup", keyUp); }); watch(() => props.active, () => { isActive.value = props.active; }); watch(isActive, () => { if (isActive.value) { disableScroll(); } else { enableScroll(); } }); return { isActive, bgStyle, hide, cancel, }; }, components: Loaders, }); const _hoisted_1$3 = { class: "vld-icon" }; function render$3(_ctx, _cache, $props, $setup, $data, $options) { return (openBlock(), createBlock(Transition, { ref: "root", name: _ctx.transition }, { default: withCtx(() => [ withDirectives(createVNode("div", { tabindex: "0", class: ["vld-overlay is-active", { 'is-full-page': _ctx.isFullPage }], "aria-busy": _ctx.isActive, "aria-label": "Loading", style: { zIndex: _ctx.zIndex } }, [ createVNode("div", { class: "vld-background", onClick: _cache[1] || (_cache[1] = withModifiers((...args) => (_ctx.cancel && _ctx.cancel(...args)), ["prevent"])), style: _ctx.bgStyle }, null, 4 /* STYLE */), createVNode("div", _hoisted_1$3, [ renderSlot(_ctx.$slots, "before"), renderSlot(_ctx.$slots, "default", {}, () => [ (openBlock(), createBlock(resolveDynamicComponent(_ctx.loader), { color: _ctx.color, width: _ctx.width, height: _ctx.height }, null, 8 /* PROPS */, ["color", "width", "height"])) ]), renderSlot(_ctx.$slots, "after") ]) ], 14 /* CLASS, STYLE, PROPS */, ["aria-busy"]), [ [vShow, _ctx.isActive] ]) ]), _: 3 /* FORWARDED */ }, 8 /* PROPS */, ["name"])) } script$3.render = render$3; script$3.__file = "src/main/Component.vue"; function createComponent(component, props, parentContainer) { const vnode = h(component, props); const container = document.createElement('div'); parentContainer.appendChild(container); render$4(vnode, container); return vnode.component; } function removeElement(el) { var _a; if (typeof el.remove !== 'undefined') { el.remove(); } else { (_a = el.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(el); } } function useLoading(globalProps = {}, globalSlots = {}) { let instance = null; const loading = { show(props = globalProps, slots = globalSlots) { const forceProps = { programmatic: true, lockScroll: true, isFullPage: false }; const propsData = Object.assign({}, globalProps, props, forceProps); let container = propsData.container; if (!propsData.container) { container = document.body; propsData.isFullPage = true; } instance = createComponent(script$3, propsData, container); const mergedSlots = Object.assign({}, globalSlots, slots); Object.keys(mergedSlots).map((name) => { if (instance != null) { instance.slots[name] = mergedSlots[name]; } }); }, hide() { if (instance != null) { instance.ctx.hide(); let root = instance.vnode.el; removeElement(root.parentElement); } } }; return loading; } export default script$3; export { useLoading };