UNPKG

@coreui/vue

Version:

UI Components Library for Vue.js

193 lines (189 loc) 6.76 kB
'use strict'; var vue = require('vue'); var CBackdrop = require('../backdrop/CBackdrop.js'); var isInViewport = require('../../utils/isInViewport.js'); const isOnMobile = (element) => { if (!element) { return; } return Boolean(getComputedStyle(element).getPropertyValue('--cui-is-mobile')); }; const CSidebar = vue.defineComponent({ name: 'CSidebar', props: { /** * Sets if the color of text should be colored for a light or dark dark background. * * @values 'dark', light' */ colorScheme: { type: String, default: undefined, validator: (value) => { return ['dark', 'light'].includes(value); }, }, /** * Make sidebar narrow. */ narrow: Boolean, /** * Set sidebar to overlaid variant. */ overlaid: Boolean, /** * Components placement, there’s no default placement. * @values 'start', 'end' */ placement: { type: String, default: undefined, validator: (value) => { return ['start', 'end'].includes(value); }, }, /** * Place sidebar in non-static positions. */ position: { type: String, validator: (value) => { return ['fixed'].includes(value); }, }, /** * Size the component small, large, or extra large. */ size: { type: String, validator: (value) => { return ['sm', 'lg', 'xl'].includes(value); }, }, /** * Expand narrowed sidebar on hover. */ unfoldable: Boolean, /** * Toggle the visibility of sidebar component. */ visible: { type: Boolean, default: undefined, }, }, emits: [ /** * Callback fired when the component requests to be hidden. */ 'hide', /** * Callback fired when the component requests to be shown. */ 'show', /** * Event emitted after visibility of component changed. */ 'visible-change', ], setup(props, { attrs, slots, emit }) { const sidebarRef = vue.ref(); const inViewport = vue.ref(); const mobile = vue.ref(); const visibleMobile = vue.ref(false); const visibleDesktop = vue.ref(props.visible === undefined ? (props.overlaid ? false : true) : props.visible); vue.watch(inViewport, () => { emit('visible-change', inViewport.value); inViewport.value ? emit('show') : emit('hide'); }); vue.watch(() => props.visible, () => props.visible !== undefined && handleVisibleChange(props.visible)); vue.watch(mobile, () => { if (mobile.value) { console.log('mobile'); visibleMobile.value = false; } }); vue.onMounted(() => { mobile.value = isOnMobile(sidebarRef.value); inViewport.value = isInViewport.default(sidebarRef.value); window.addEventListener('resize', handleResize); window.addEventListener('mouseup', handleClickOutside); window.addEventListener('keyup', handleKeyup); sidebarRef.value.addEventListener('mouseup', handleOnClick); sidebarRef.value.addEventListener('transitionend', () => { inViewport.value = isInViewport.default(sidebarRef.value); }); }); vue.onBeforeUnmount(() => { window.removeEventListener('resize', handleResize); window.removeEventListener('mouseup', handleClickOutside); window.removeEventListener('keyup', handleKeyup); sidebarRef.value.removeEventListener('mouseup', handleOnClick); // eslint-disable-next-line unicorn/no-invalid-remove-event-listener sidebarRef.value.removeEventListener('transitionend', () => { inViewport.value = isInViewport.default(sidebarRef.value); }); }); const handleVisibleChange = (visible) => { if (mobile.value) { visibleMobile.value = visible; return; } visibleDesktop.value = visible; }; const handleHide = () => { handleVisibleChange(false); emit('visible-change', false); }; const handleResize = () => { mobile.value = isOnMobile(sidebarRef.value); inViewport.value = isInViewport.default(sidebarRef.value); }; const handleKeyup = (event) => { if (mobile.value && !sidebarRef.value.contains(event.target)) { handleHide(); } }; const handleClickOutside = (event) => { if (mobile.value && !sidebarRef.value.contains(event.target)) { handleHide(); } }; const handleOnClick = (event) => { const target = event.target; target && target.classList.contains('nav-link') && !target.classList.contains('nav-group-toggle') && mobile.value && handleHide(); }; return () => [ vue.h('div', { class: [ 'sidebar', { [`sidebar-${props.colorScheme}`]: props.colorScheme, 'sidebar-narrow': props.narrow, 'sidebar-overlaid': props.overlaid, [`sidebar-${props.placement}`]: props.placement, [`sidebar-${props.position}`]: props.position, [`sidebar-${props.size}`]: props.size, 'sidebar-narrow-unfoldable': props.unfoldable, show: (mobile.value && visibleMobile.value) || (props.overlaid && visibleDesktop.value), hide: visibleDesktop.value === false && !mobile.value && !props.overlaid, }, attrs.class, ], ref: sidebarRef, }, slots.default && slots.default()), mobile.value && vue.h(CBackdrop.CBackdrop, { class: 'sidebar-backdrop', visible: visibleMobile.value, onClick: () => handleHide(), }), ]; }, }); exports.CSidebar = CSidebar; //# sourceMappingURL=CSidebar.js.map