UNPKG

buefy

Version:

Lightweight UI components for Vue.js (v3) based on Bulma

310 lines (303 loc) 9.02 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var vue = require('vue'); var config = require('./config-DR826Ki2.js'); var helpers = require('./helpers.js'); var _pluginVue_exportHelper = require('./_plugin-vue_export-helper-Die8u8yB.js'); var plugins = require('./plugins-DbyYGVpp.js'); const SIDEBAR_POSITIONS = ["fixed", "absolute", "static"]; const SCROLL_BEHAVIORS = ["clip", "keep"]; var _sfc_main = vue.defineComponent({ name: "BSidebar", props: { modelValue: Boolean, type: [String, Object], overlay: Boolean, position: { type: String, default: "fixed", validator: (value) => { return SIDEBAR_POSITIONS.indexOf(value) >= 0; } }, fullheight: Boolean, fullwidth: Boolean, right: Boolean, mobile: { type: String }, reduce: Boolean, expandOnHover: Boolean, expandOnHoverFixed: Boolean, delay: { type: [Number, null], default: () => config.config.defaultSidebarDelay }, canCancel: { type: [Array, Boolean], default: () => ["escape", "outside"] }, onCancel: { type: Function, default: () => { } }, scroll: { type: String, default: () => { return config.config.defaultModalScroll ? config.config.defaultModalScroll : "clip"; }, validator: (value) => { return SCROLL_BEHAVIORS.indexOf(value) >= 0; } } }, emits: { close: () => true, // eslint-disable-next-line @typescript-eslint/no-unused-vars "update:modelValue": (_value) => true }, data() { return { isOpen: this.modelValue, isDelayOver: false, transitionName: void 0, animating: true, savedScrollTop: null, hasLeaved: false, timer: void 0 }; }, computed: { rootClasses() { return [this.type, { "is-fixed": this.isFixed, "is-static": this.isStatic, "is-absolute": this.isAbsolute, "is-fullheight": this.fullheight, "is-fullwidth": this.fullwidth, "is-right": this.right, "is-mini": this.reduce && !this.isDelayOver, "is-mini-expand": this.expandOnHover || this.isDelayOver, "is-mini-expand-fixed": this.expandOnHover && this.expandOnHoverFixed || this.isDelayOver, "is-mini-delayed": this.delay !== null, "is-mini-mobile": this.mobile === "reduce", "is-hidden-mobile": this.mobile === "hide", "is-fullwidth-mobile": this.mobile === "fullwidth" }]; }, cancelOptions() { return typeof this.canCancel === "boolean" ? this.canCancel ? ["escape", "outside"] : [] : this.canCancel; }, isStatic() { return this.position === "static"; }, isFixed() { return this.position === "fixed"; }, isAbsolute() { return this.position === "absolute"; } }, watch: { modelValue: { handler(value) { this.isOpen = value; if (this.overlay) { this.handleScroll(); } const open = this.right ? !value : value; this.transitionName = !open ? "slide-prev" : "slide-next"; }, immediate: true } }, methods: { /* * Keypress event that is bound to the document. */ keyPress({ key }) { if (this.isFixed) { if (this.isOpen && (key === "Escape" || key === "Esc")) this.cancel("escape"); } }, /* * Close the Sidebar if canCancel and call the onCancel prop (function). */ // eslint-disable-next-line @typescript-eslint/no-explicit-any cancel(method, ...args) { if (this.cancelOptions.indexOf(method) < 0) return; if (this.isStatic) return; this.onCancel.call(null, method, ...args); this.close(); }, /* * Call the onCancel prop (function) and emit events */ close() { this.isOpen = false; this.$emit("close"); this.$emit("update:modelValue", false); }, /* * Close fixed sidebar if clicked outside. */ clickedOutside(event) { if (!this.isFixed || !this.isOpen || this.animating) { return; } if (!event.composedPath().includes(this.$refs.sidebarContent)) { this.cancel("outside"); } }, /* * Transition before-enter hook */ beforeEnter() { this.animating = true; }, /* * Transition after-leave hook */ afterEnter() { this.animating = false; }, handleScroll() { if (typeof window === "undefined") return; if (this.scroll === "clip") { if (this.modelValue) { document.documentElement.classList.add("is-clipped"); } else { document.documentElement.classList.remove("is-clipped"); } return; } this.savedScrollTop = !this.savedScrollTop ? document.documentElement.scrollTop : this.savedScrollTop; if (this.modelValue) { document.body.classList.add("is-noscroll"); } else { document.body.classList.remove("is-noscroll"); } if (this.modelValue) { document.body.style.top = `-${this.savedScrollTop}px`; return; } document.documentElement.scrollTop = this.savedScrollTop; document.body.style.top = ""; this.savedScrollTop = null; }, onHover() { if (this.delay) { this.hasLeaved = false; this.timer = setTimeout(() => { if (!this.hasLeaved) { this.isDelayOver = true; } this.timer = void 0; }, this.delay); } else { this.isDelayOver = false; } }, onHoverLeave() { this.hasLeaved = true; this.timer = void 0; this.isDelayOver = false; }, /* * Close sidebar if close button is clicked. */ clickedCloseButton() { if (this.isFixed) { if (this.isOpen && this.fullwidth) { this.cancel("outside"); } } } }, created() { if (typeof window !== "undefined") { document.addEventListener("keyup", this.keyPress); document.addEventListener("click", this.clickedOutside); } }, mounted() { if (typeof window !== "undefined") { if (this.isFixed) { document.body.appendChild(this.$el); } } if (this.overlay && this.modelValue) { this.handleScroll(); } }, beforeUnmount() { if (typeof window !== "undefined") { document.removeEventListener("keyup", this.keyPress); document.removeEventListener("click", this.clickedOutside); if (this.overlay) { document.documentElement.classList.remove("is-clipped"); const savedScrollTop = !this.savedScrollTop ? document.documentElement.scrollTop : this.savedScrollTop; document.body.classList.remove("is-noscroll"); document.documentElement.scrollTop = savedScrollTop; document.body.style.top = ""; } } if (this.isFixed) { helpers.removeElement(this.$el); } clearTimeout(this.timer); } }); const _hoisted_1 = { class: "b-sidebar" }; const _hoisted_2 = { key: 0, class: "sidebar-background" }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [ _ctx.overlay && _ctx.isOpen ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2)) : vue.createCommentVNode("v-if", true), vue.createVNode(vue.Transition, { name: _ctx.transitionName, onBeforeEnter: _ctx.beforeEnter, onAfterEnter: _ctx.afterEnter, persisted: "" }, { default: vue.withCtx(() => [ vue.withDirectives(vue.createElementVNode( "div", { ref: "sidebarContent", class: vue.normalizeClass(["sidebar-content navbar", _ctx.rootClasses]), onMouseenter: _cache[1] || (_cache[1] = (...args) => _ctx.onHover && _ctx.onHover(...args)), onMouseleave: _cache[2] || (_cache[2] = (...args) => _ctx.onHoverLeave && _ctx.onHoverLeave(...args)) }, [ _ctx.fullwidth ? (vue.openBlock(), vue.createElementBlock("button", { key: 0, type: "button", onClick: _cache[0] || (_cache[0] = (...args) => _ctx.clickedCloseButton && _ctx.clickedCloseButton(...args)), class: "modal-close is-large sidebar-close", "aria-label": "Close" })) : vue.createCommentVNode("v-if", true), vue.renderSlot(_ctx.$slots, "default") ], 34 /* CLASS, NEED_HYDRATION */ ), [ [vue.vShow, _ctx.isOpen] ]) ]), _: 3 /* FORWARDED */ }, 8, ["name", "onBeforeEnter", "onAfterEnter"]) ]); } var Sidebar = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["render", _sfc_render]]); const Plugin = { install(Vue) { plugins.registerComponent(Vue, Sidebar); } }; exports.BSidebar = Sidebar; exports.default = Plugin;