UNPKG

@coreui/vue

Version:

UI Components Library for Vue.js

182 lines (178 loc) 5.94 kB
'use strict'; var vue = require('vue'); var CBackdrop = require('../backdrop/CBackdrop.js'); var vCVisible = require('../../directives/v-c-visible.js'); var transition = require('../../utils/transition.js'); const COffcanvas = vue.defineComponent({ name: 'COffcanvas', inheritAttrs: false, props: { /** * Apply a backdrop on body while offcanvas is open. * * @values boolean | 'static' */ backdrop: { type: [Boolean, String], default: true, validator: (value) => { if (typeof value === 'string') { return ['static'].includes(value); } if (typeof value === 'boolean') { return true; } return false; }, }, /** * Sets a darker color scheme. */ dark: Boolean, /** * Closes the offcanvas when escape key is pressed. */ keyboard: { type: Boolean, default: true, }, /** * Components placement, there’s no default placement. * * @values 'start', 'end', 'top', 'bottom' */ placement: { type: String, require: true, validator: (value) => { return ['start', 'end', 'top', 'bottom'].includes(value); }, }, /** * Responsive offcanvas property hide content outside the viewport from a specified breakpoint and down. * * @values boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' * @since 4.7.0 */ responsive: { type: [Boolean, String], default: true, validator: (value) => { if (typeof value === 'string') { return ['sm', 'md', 'lg', 'xl', 'xxl'].includes(value); } if (typeof value === 'boolean') { return true; } return false; }, }, /** * Allow body scrolling while offcanvas is open */ scroll: { type: Boolean, default: false, }, /** * Toggle the visibility of offcanvas component. */ visible: { type: Boolean, default: false, }, }, emits: [ /** * Callback fired when the component requests to be hidden. */ 'hide', /** * Callback fired when the component requests to be shown. */ 'show', ], setup(props, { attrs, emit, slots }) { const offcanvasRef = vue.ref(); const visible = vue.ref(props.visible); vue.watch(() => props.visible, () => { visible.value = props.visible; }); vue.watch(visible, () => { if (visible.value && !props.scroll) { document.body.style.overflow = 'hidden'; document.body.style.paddingRight = '0px'; return; } if (!props.scroll) { document.body.style.removeProperty('overflow'); document.body.style.removeProperty('padding-right'); } }); const handleEnter = (el, done) => { emit('show'); transition.executeAfterTransition(() => done(), el); setTimeout(() => { el.classList.add('show'); }, 1); }; const handleAfterEnter = () => { offcanvasRef.value.focus(); }; // eslint-disable-next-line unicorn/consistent-function-scoping const handleLeave = (el, done) => { transition.executeAfterTransition(() => done(), el); el.classList.add('hiding'); }; // eslint-disable-next-line unicorn/consistent-function-scoping const handleAfterLeave = (el) => { el.classList.remove('show', 'hiding'); }; const handleDismiss = () => { visible.value = false; emit('hide'); }; const handleBackdropDismiss = () => { if (props.backdrop !== 'static') { handleDismiss(); } }; const handleKeyDown = (event) => { if (event.key === 'Escape' && props.keyboard) { handleDismiss(); } }; return () => [ vue.h(vue.Transition, { appear: visible.value, css: false, onEnter: (el, done) => handleEnter(el, done), onAfterEnter: () => handleAfterEnter(), onLeave: (el, done) => handleLeave(el, done), onAfterLeave: (el) => handleAfterLeave(el), }, () => vue.withDirectives(vue.h('div', { ...attrs, class: [ { [`offcanvas${typeof props.responsive === 'boolean' ? '' : '-' + props.responsive}`]: props.responsive, [`offcanvas-${props.placement}`]: props.placement, }, attrs.class, ], onKeydown: (event) => handleKeyDown(event), ref: offcanvasRef, role: 'dialog', tabindex: -1, ...(props.dark && { 'data-coreui-theme': 'dark' }), }, slots.default && slots.default()), [[vCVisible.vVisible, props.visible]])), props.backdrop && vue.h(CBackdrop.CBackdrop, { class: 'offcanvas-backdrop', onClick: handleBackdropDismiss, visible: visible.value, }), ]; }, }); exports.COffcanvas = COffcanvas; //# sourceMappingURL=COffcanvas.js.map