initial commit
This commit is contained in:
@@ -0,0 +1,367 @@
|
||||
<script setup>
|
||||
import { PerfectScrollbar } from 'vue3-perfect-scrollbar'
|
||||
import { useTheme } from 'vuetify'
|
||||
import { staticPrimaryColor } from '@/plugins/vuetify/theme'
|
||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
||||
import {
|
||||
RouteTransitions,
|
||||
Skins,
|
||||
} from '@core/enums'
|
||||
import {
|
||||
AppContentLayoutNav,
|
||||
ContentWidth,
|
||||
FooterType,
|
||||
NavbarType,
|
||||
} from '@layouts/enums'
|
||||
import { themeConfig } from '@themeConfig'
|
||||
|
||||
const isNavDrawerOpen = ref(false)
|
||||
const { theme, skin, appRouteTransition, navbarType, footerType, isVerticalNavCollapsed, isVerticalNavSemiDark, appContentWidth, appContentLayoutNav, isAppRtl, isNavbarBlurEnabled, isLessThanOverlayNavBreakpoint } = useThemeConfig()
|
||||
|
||||
// 👉 Primary Color
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
// const vuetifyThemesName = Object.keys(vuetifyTheme.themes.value)
|
||||
const initialThemeColors = JSON.parse(JSON.stringify(vuetifyTheme.current.value.colors))
|
||||
|
||||
const colors = [
|
||||
'primary',
|
||||
'secondary',
|
||||
'success',
|
||||
'info',
|
||||
'warning',
|
||||
'error',
|
||||
]
|
||||
|
||||
const setPrimaryColor = color => {
|
||||
const currentThemeName = vuetifyTheme.name.value
|
||||
|
||||
vuetifyTheme.themes.value[currentThemeName].colors.primary = color
|
||||
localStorage.setItem(`${ themeConfig.app.title }-${ currentThemeName }ThemePrimaryColor`, color)
|
||||
localStorage.setItem(`${ themeConfig.app.title }-initial-loader-color`, color)
|
||||
}
|
||||
|
||||
const getBoxColor = (color, index) => index ? color : staticPrimaryColor
|
||||
const { width: windowWidth } = useWindowSize()
|
||||
|
||||
const headerValues = computed(() => {
|
||||
const entries = Object.entries(NavbarType)
|
||||
if (appContentLayoutNav.value === AppContentLayoutNav.Horizontal)
|
||||
return entries.filter(([_, val]) => val !== NavbarType.Hidden)
|
||||
|
||||
return entries
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="!isLessThanOverlayNavBreakpoint(windowWidth)">
|
||||
<VBtn
|
||||
icon
|
||||
size="small"
|
||||
class="app-customizer-toggler rounded-s-lg rounded-0"
|
||||
style="z-index: 1001;"
|
||||
@click="isNavDrawerOpen = true"
|
||||
>
|
||||
<VIcon
|
||||
size="22"
|
||||
icon="tabler-settings"
|
||||
/>
|
||||
</VBtn>
|
||||
|
||||
<VNavigationDrawer
|
||||
v-model="isNavDrawerOpen"
|
||||
temporary
|
||||
border="0"
|
||||
location="end"
|
||||
width="400"
|
||||
:scrim="false"
|
||||
class="app-customizer"
|
||||
>
|
||||
<!-- 👉 Header -->
|
||||
<div class="customizer-heading d-flex align-center justify-space-between">
|
||||
<div>
|
||||
<h6 class="text-h6">
|
||||
THEME CUSTOMIZER
|
||||
</h6>
|
||||
<span class="text-body-1">Customize & Preview in Real Time</span>
|
||||
</div>
|
||||
<IconBtn @click="isNavDrawerOpen = false">
|
||||
<VIcon
|
||||
icon="tabler-x"
|
||||
size="20"
|
||||
/>
|
||||
</IconBtn>
|
||||
</div>
|
||||
|
||||
<VDivider />
|
||||
|
||||
<PerfectScrollbar
|
||||
tag="ul"
|
||||
:options="{ wheelPropagation: false }"
|
||||
>
|
||||
<!-- SECTION Theming -->
|
||||
<CustomizerSection
|
||||
title="THEMING"
|
||||
:divider="false"
|
||||
>
|
||||
<!-- 👉 Skin -->
|
||||
<h6 class="text-base font-weight-regular">
|
||||
Skins
|
||||
</h6>
|
||||
<VRadioGroup
|
||||
v-model="skin"
|
||||
inline
|
||||
>
|
||||
<VRadio
|
||||
v-for="[key, val] in Object.entries(Skins)"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="val"
|
||||
/>
|
||||
</VRadioGroup>
|
||||
|
||||
<!-- 👉 Theme -->
|
||||
<h6 class="mt-3 text-base font-weight-regular">
|
||||
Theme
|
||||
</h6>
|
||||
<VRadioGroup
|
||||
v-model="theme"
|
||||
inline
|
||||
>
|
||||
<VRadio
|
||||
v-for="themeOption in ['system', 'light', 'dark']"
|
||||
:key="themeOption"
|
||||
:label="themeOption"
|
||||
:value="themeOption"
|
||||
class="text-capitalize"
|
||||
/>
|
||||
</VRadioGroup>
|
||||
|
||||
<!-- 👉 Primary color -->
|
||||
<h6 class="mt-3 text-base font-weight-regular">
|
||||
Primary Color
|
||||
</h6>
|
||||
<div class="d-flex gap-x-4 mt-2">
|
||||
<div
|
||||
v-for="(color, index) in colors"
|
||||
:key="color"
|
||||
style=" border-radius: 0.5rem; block-size: 2.5rem;inline-size: 2.5rem; transition: all 0.25s ease;"
|
||||
:style="{ backgroundColor: getBoxColor(initialThemeColors[color], index) }"
|
||||
class="cursor-pointer d-flex align-center justify-center"
|
||||
:class="{ 'elevation-4': vuetifyTheme.current.value.colors.primary === getBoxColor(initialThemeColors[color], index) }"
|
||||
@click="setPrimaryColor(getBoxColor(initialThemeColors[color], index))"
|
||||
>
|
||||
<VFadeTransition>
|
||||
<VIcon
|
||||
v-show="vuetifyTheme.current.value.colors.primary === (getBoxColor(initialThemeColors[color], index))"
|
||||
icon="tabler-check"
|
||||
color="white"
|
||||
/>
|
||||
</VFadeTransition>
|
||||
</div>
|
||||
</div>
|
||||
</CustomizerSection>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- SECTION LAYOUT -->
|
||||
<CustomizerSection title="LAYOUT">
|
||||
<!-- 👉 Content Width -->
|
||||
<h6 class="text-base font-weight-regular">
|
||||
Content width
|
||||
</h6>
|
||||
<VRadioGroup
|
||||
v-model="appContentWidth"
|
||||
inline
|
||||
>
|
||||
<VRadio
|
||||
v-for="[key, val] in Object.entries(ContentWidth)"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="val"
|
||||
/>
|
||||
</VRadioGroup>
|
||||
<!-- 👉 Navbar Type -->
|
||||
<h6 class="mt-3 text-base font-weight-regular">
|
||||
{{ appContentLayoutNav === AppContentLayoutNav.Vertical ? 'Navbar' : 'Header' }} Type
|
||||
</h6>
|
||||
<VRadioGroup
|
||||
v-model="navbarType"
|
||||
inline
|
||||
>
|
||||
<VRadio
|
||||
v-for="[key, val] in headerValues"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="val"
|
||||
/>
|
||||
</VRadioGroup>
|
||||
<!-- 👉 Footer Type -->
|
||||
<h6 class="mt-3 text-base font-weight-regular">
|
||||
Footer Type
|
||||
</h6>
|
||||
<VRadioGroup
|
||||
v-model="footerType"
|
||||
inline
|
||||
>
|
||||
<VRadio
|
||||
v-for="[key, val] in Object.entries(FooterType)"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="val"
|
||||
/>
|
||||
</VRadioGroup>
|
||||
<!-- 👉 Navbar blur -->
|
||||
<div class="mt-4 d-flex align-center justify-space-between">
|
||||
<VLabel
|
||||
for="customizer-navbar-blur"
|
||||
class="text-high-emphasis"
|
||||
>
|
||||
Navbar Blur
|
||||
</VLabel>
|
||||
<div>
|
||||
<VSwitch
|
||||
id="customizer-navbar-blur"
|
||||
v-model="isNavbarBlurEnabled"
|
||||
class="ms-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CustomizerSection>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- SECTION Menu -->
|
||||
<CustomizerSection title="MENU">
|
||||
<!-- 👉 Menu Type -->
|
||||
<h6 class="text-base font-weight-regular">
|
||||
Menu Type
|
||||
</h6>
|
||||
<VRadioGroup
|
||||
v-model="appContentLayoutNav"
|
||||
inline
|
||||
>
|
||||
<VRadio
|
||||
v-for="[key, val] in Object.entries(AppContentLayoutNav)"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="val"
|
||||
/>
|
||||
</VRadioGroup>
|
||||
|
||||
<!-- 👉 Collapsed Menu -->
|
||||
<div
|
||||
v-if="appContentLayoutNav === AppContentLayoutNav.Vertical"
|
||||
class="mt-4 d-flex align-center justify-space-between"
|
||||
>
|
||||
<VLabel
|
||||
for="customizer-menu-collapsed"
|
||||
class="text-high-emphasis"
|
||||
>
|
||||
Collapsed Menu
|
||||
</VLabel>
|
||||
<div>
|
||||
<VSwitch
|
||||
id="customizer-menu-collapsed"
|
||||
v-model="isVerticalNavCollapsed"
|
||||
class="ms-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Semi Dark Menu -->
|
||||
<div
|
||||
class="mt-4 align-center justify-space-between"
|
||||
:class="vuetifyTheme.global.name.value === 'light' && appContentLayoutNav === AppContentLayoutNav.Vertical ? 'd-flex' : 'd-none'"
|
||||
>
|
||||
<VLabel
|
||||
for="customizer-menu-semi-dark"
|
||||
class="text-high-emphasis"
|
||||
>
|
||||
Semi Dark Menu
|
||||
</VLabel>
|
||||
<div>
|
||||
<VSwitch
|
||||
id="customizer-menu-semi-dark"
|
||||
v-model="isVerticalNavSemiDark"
|
||||
class="ms-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CustomizerSection>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- SECTION MISC -->
|
||||
<CustomizerSection title="MISC">
|
||||
<!-- 👉 RTL -->
|
||||
<div class="d-flex align-center justify-space-between">
|
||||
<VLabel
|
||||
for="customizer-rtl"
|
||||
class="text-high-emphasis"
|
||||
>
|
||||
RTL
|
||||
</VLabel>
|
||||
<div>
|
||||
<VSwitch
|
||||
id="customizer-rtl"
|
||||
v-model="isAppRtl"
|
||||
class="ms-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Route Transition -->
|
||||
<div class="mt-6">
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="5"
|
||||
class="d-flex align-center"
|
||||
>
|
||||
<VLabel
|
||||
for="route-transition"
|
||||
class="text-high-emphasis"
|
||||
>
|
||||
Router Transition
|
||||
</VLabel>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="7">
|
||||
<AppSelect
|
||||
id="route-transition"
|
||||
v-model="appRouteTransition"
|
||||
:items="Object.entries(RouteTransitions).map(([key, value]) => ({ key, value }))"
|
||||
item-title="key"
|
||||
item-value="value"
|
||||
single-line
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</div>
|
||||
</CustomizerSection>
|
||||
<!-- !SECTION -->
|
||||
</PerfectScrollbar>
|
||||
</VNavigationDrawer>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.app-customizer {
|
||||
.customizer-section {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.customizer-heading {
|
||||
padding-block: 0.875rem;
|
||||
padding-inline: 1.25rem;
|
||||
}
|
||||
|
||||
.v-navigation-drawer__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.app-customizer-toggler {
|
||||
position: fixed !important;
|
||||
inset-block-start: 50%;
|
||||
inset-inline-end: 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user