@coreui/vue
Version:
UI Components Library for Vue.js
193 lines (189 loc) • 6.76 kB
JavaScript
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
;