import { layoutConfig } from '@layouts/config' import { AppContentLayoutNav } from '@layouts/enums' import { useLayoutConfigStore } from '@layouts/stores/config' export const openGroups = ref([]) /** * Return nav link props to use // @param {Object, String} item navigation routeName or route Object provided in navigation data */ export const getComputedNavLinkToProp = computed(() => link => { const props = { target: link.target, rel: link.rel, } // If route is string => it assumes string is route name => Create route object from route name // If route is not string => It assumes it's route object => returns passed route object if (link.to) props.to = typeof link.to === 'string' ? { name: link.to } : link.to else props.href = link.href return props }) /** * Return route name for navigation link * If link is string then it will assume it is route-name * IF link is object it will resolve the object and will return the link // @param {Object, String} link navigation link object/string */ export const resolveNavLinkRouteName = (link, router) => { if (!link.to) return null if (typeof link.to === 'string') return link.to return router.resolve(link.to).name } /** * Check if nav-link is active * @param {object} link nav-link object */ export const isNavLinkActive = (link, router) => { // Matched routes array of current route const matchedRoutes = router.currentRoute.value.matched; const currentRoute = router.currentRoute.value; // Check if the parent menu item should be active if (isParentActive(currentRoute,router,link)) { return true; } // Check if provided route matches route's matched route const resolveRoutedName = resolveNavLinkRouteName(link, router); if (!resolveRoutedName) { return false; } return matchedRoutes.some(route => { return route.name === resolveRoutedName || route.meta.navActiveLink === resolveRoutedName; }); }; const ParentMenuItemName = 'admin-patients'; export const isParentActive = (route, router,link) => { // Get the current route's activeParent meta property const activeParent = route.meta.activeParent; // Check if the activeParent is defined and not an empty string if (activeParent && activeParent.trim().length > 0) { // Find the parent route configuration const parentRoute = router.options.routes.find(r => r.name === activeParent); console.log('fffff', link.to) // Check if the parent route configuration exists if (link.to) { // Use the parent route's name or any other property as the parent menu item name return link.to === activeParent; } } // If the activeParent is not defined, an empty string, or the parent route configuration is not found, return false return false; }; /** * Check if nav group is active * @param {Array} children Group children */ export const isNavGroupActive = (children, router) => children.some(child => { // If child have children => It's group => Go deeper(recursive) if ('children' in child) return isNavGroupActive(child.children, router) // else it's link => Check for matched Route return isNavLinkActive(child, router) }) /** * Change `dir` attribute based on direction * @param dir 'ltr' | 'rtl' */ export const _setDirAttr = dir => { // Check if document exists for SSR if (typeof document !== 'undefined') document.documentElement.setAttribute('dir', dir) } /** * Return dynamic i18n props based on i18n plugin is enabled or not * @param key i18n translation key * @param tag tag to wrap the translation with */ export const getDynamicI18nProps = (key, tag = 'span') => { if (!layoutConfig.app.i18n.enable) return {} return { keypath: key, tag, scope: 'global', } } export const switchToVerticalNavOnLtOverlayNavBreakpoint = () => { const configStore = useLayoutConfigStore() /* ℹ️ This is flag will hold nav type need to render when switching between lgAndUp from mdAndDown window width Requirement: When we nav is set to `horizontal` and we hit the `mdAndDown` breakpoint nav type shall change to `vertical` nav Now if we go back to `lgAndUp` breakpoint from `mdAndDown` how we will know which was previous nav type in large device? Let's assign value of `appContentLayoutNav` as default value of lgAndUpNav. Why 🤔? If template is viewed in lgAndUp We will assign `appContentLayoutNav` value to `lgAndUpNav` because at this point both constant is same Hence, for `lgAndUpNav` it will take value from theme config file else It will always show vertical nav and if user increase the window width it will fallback to `appContentLayoutNav` value But `appContentLayoutNav` will be value set in theme config file */ const lgAndUpNav = ref(configStore.appContentLayoutNav) /* There might be case where we manually switch from vertical to horizontal nav and vice versa in `lgAndUp` screen So when user comes back from `mdAndDown` to `lgAndUp` we can set updated nav type For this we need to update the `lgAndUpNav` value if screen is `lgAndUp` */ watch(() => configStore.appContentLayoutNav, value => { if (!configStore.isLessThanOverlayNavBreakpoint) lgAndUpNav.value = value }) /* This is layout switching part If it's `mdAndDown` => We will use vertical nav no matter what previous nav type was Or if it's `lgAndUp` we need to switch back to `lgAndUp` nav type. For this we will tracker property `lgAndUpNav` */ watch(() => configStore.isLessThanOverlayNavBreakpoint, val => { configStore.appContentLayoutNav = val ? AppContentLayoutNav.Vertical : lgAndUpNav.value }, { immediate: true }) } /** * Convert Hex color to rgb * @param hex */ export const hexToRgb = hex => { // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i hex = hex.replace(shorthandRegex, (m, r, g, b) => { return r + r + g + g + b + b }) const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) return result ? `${Number.parseInt(result[1], 16)},${Number.parseInt(result[2], 16)},${Number.parseInt(result[3], 16)}` : null } /** *RGBA color to Hex color with / without opacity */ export const rgbaToHex = (rgba, forceRemoveAlpha = false) => { return (`#${rgba .replace(/^rgba?\(|\s+|\)$/g, '') // Get's rgba / rgb string values .split(',') // splits them at "," .filter((string, index) => !forceRemoveAlpha || index !== 3) .map(string => Number.parseFloat(string)) // Converts them to numbers .map((number, index) => (index === 3 ? Math.round(number * 255) : number)) // Converts alpha to 255 number .map(number => number.toString(16)) // Converts numbers to hex .map(string => (string.length === 1 ? `0${string}` : string)) // Adds 0 when length of one number is 1 .join('')}`) }