123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- <script setup lang="ts">
- import type { LayoutHeaderMode, LayoutType } from '@vben/types';
- import type { SegmentedItem } from '@vben-core/shadcn-ui';
- import { IcRoundFolderCopy, IcRoundRestartAlt } from '@vben-core/iconify';
- import {
- VbenButton,
- VbenIconButton,
- VbenSegmented,
- VbenSheet,
- toast,
- } from '@vben-core/shadcn-ui';
- import { $t } from '@vben/locales';
- import { preference, resetPreference, usePreference } from '@vben/preference';
- import { useClipboard } from '@vueuse/core';
- import { computed } from 'vue';
- import {
- Animation,
- Block,
- Breadcrumb,
- ColorMode,
- Content,
- Footer,
- General,
- Header,
- Layout,
- Navigation,
- Sidebar,
- Tabs,
- Theme,
- ThemeColor,
- } from './blocks';
- import Trigger from './trigger.vue';
- import { useOpenPreference } from './use-open-preference';
- withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
- colorPrimaryPresets: () => [],
- });
- const theme = defineModel<string>('theme');
- const locale = defineModel<string>('locale');
- const dynamicTitle = defineModel<boolean>('dynamicTitle');
- const semiDarkMenu = defineModel<boolean>('semiDarkMenu');
- const breadcrumbVisible = defineModel<boolean>('breadcrumbVisible');
- const breadcrumbIcon = defineModel<boolean>('breadcrumbIcon');
- const breadcrumbHome = defineModel<boolean>('breadcrumbHome');
- const breadcrumbStyle = defineModel<string>('breadcrumbStyle');
- const breadcrumbHideOnlyOne = defineModel<boolean>('breadcrumbHideOnlyOne');
- const sideCollapseShowTitle = defineModel<boolean>('sideCollapseShowTitle');
- const sideCollapse = defineModel<boolean>('sideCollapse');
- const colorWeakMode = defineModel<boolean>('colorWeakMode');
- const colorGrayMode = defineModel<boolean>('colorGrayMode');
- const colorPrimary = defineModel<string>('colorPrimary');
- const navigationStyle = defineModel<string>('navigationStyle');
- const navigationSplit = defineModel<boolean>('navigationSplit');
- const navigationAccordion = defineModel<boolean>('navigationAccordion');
- const pageProgress = defineModel<boolean>('pageProgress');
- const pageTransition = defineModel<string>('pageTransition');
- const pageTransitionEnable = defineModel<boolean>('pageTransitionEnable');
- const layout = defineModel<LayoutType>('layout');
- const contentCompact = defineModel<string>('contentCompact');
- const sideVisible = defineModel<boolean>('sideVisible');
- const shortcutKeys = defineModel<boolean>('shortcutKeys');
- const tabsVisible = defineModel<boolean>('tabsVisible');
- const tabsIcon = defineModel<boolean>('tabsIcon');
- // const logoVisible = defineModel<boolean>('logoVisible');
- const headerVisible = defineModel<boolean>('headerVisible');
- const headerMode = defineModel<LayoutHeaderMode>('headerMode');
- const footerVisible = defineModel<boolean>('footerVisible');
- const footerFixed = defineModel<boolean>('footerFixed');
- const {
- diffPreference,
- isFullContent,
- isHeaderNav,
- isMixedNav,
- isSideMixedNav,
- isSideMode,
- isSideNav,
- } = usePreference();
- const { copy } = useClipboard();
- const tabs = computed((): SegmentedItem[] => {
- return [
- {
- label: $t('preference.appearance'),
- value: 'appearance',
- },
- {
- label: $t('preference.layout'),
- value: 'layout',
- },
- {
- label: $t('preference.general'),
- value: 'general',
- },
- // {
- // label: $t('preference.shortcut-key'),
- // value: 'shortcutKey',
- // },
- ];
- });
- const showBreadcrumbConfig = computed(() => {
- return (
- !isFullContent.value &&
- !isMixedNav.value &&
- !isHeaderNav.value &&
- preference.headerVisible
- );
- });
- const { openPreference } = useOpenPreference();
- async function handleCopy() {
- await copy(JSON.stringify(diffPreference.value, null, 2));
- toast($t('preference.copy-success'));
- }
- function handleReset() {
- if (!diffPreference.value) {
- return;
- }
- resetPreference();
- toast($t('preference.reset-success'));
- }
- </script>
- <template>
- <div class="z-100 fixed right-0 top-1/3">
- <VbenSheet
- v-model:open="openPreference"
- :description="$t('preference.preferences-subtitle')"
- :title="$t('preference.preferences')"
- >
- <template #trigger>
- <Trigger />
- </template>
- <template #extra>
- <VbenIconButton
- class="relative"
- :disabled="!diffPreference"
- :tooltip="$t('preference.reset-tip')"
- >
- <span
- v-if="diffPreference"
- class="bg-primary absolute right-0.5 top-0.5 h-2 w-2 rounded"
- ></span>
- <IcRoundRestartAlt class="size-5" @click="handleReset" />
- </VbenIconButton>
- </template>
- <div class="p-5 pt-4">
- <VbenSegmented :tabs="tabs" default-value="appearance">
- <template #appearance>
- <Block :title="$t('preference.theme')">
- <Theme v-model="theme" v-model:semi-dark-menu="semiDarkMenu" />
- </Block>
- <Block :title="$t('preference.theme-color')">
- <ThemeColor
- v-model="colorPrimary"
- :color-primary-presets="colorPrimaryPresets"
- />
- </Block>
- <Block :title="$t('preference.other')">
- <ColorMode
- v-model:color-gray-mode="colorGrayMode"
- v-model:color-weak-mode="colorWeakMode"
- />
- </Block>
- </template>
- <template #layout>
- <Block :title="$t('preference.layout')">
- <Layout v-model="layout" />
- </Block>
- <Block :title="$t('preference.content')">
- <Content v-model="contentCompact" />
- </Block>
- <Block :title="$t('preference.sidebar')">
- <Sidebar
- v-model:side-visible="sideVisible"
- v-model:side-collapse="sideCollapse"
- v-model:side-collapse-show-title="sideCollapseShowTitle"
- :disabled="!isSideMode"
- />
- </Block>
- <Block :title="$t('preference.header')">
- <Header
- v-model:header-visible="headerVisible"
- v-model:headerMode="headerMode"
- :disabled="isFullContent"
- />
- </Block>
- <Block :title="$t('preference.navigation-menu')">
- <Navigation
- v-model:navigation-style="navigationStyle"
- v-model:navigation-split="navigationSplit"
- v-model:navigation-accordion="navigationAccordion"
- :disabled="isFullContent"
- :disabled-navigation-split="!isMixedNav"
- />
- </Block>
- <Block :title="$t('preference.breadcrumb')">
- <Breadcrumb
- v-model:breadcrumb-visible="breadcrumbVisible"
- v-model:breadcrumb-icon="breadcrumbIcon"
- v-model:breadcrumb-style="breadcrumbStyle"
- v-model:breadcrumb-home="breadcrumbHome"
- v-model:breadcrumb-hide-only-one="breadcrumbHideOnlyOne"
- :disabled="
- !showBreadcrumbConfig || !(isSideNav || isSideMixedNav)
- "
- />
- </Block>
- <Block :title="$t('preference.tabs')">
- <Tabs
- v-model:tabs-visible="tabsVisible"
- v-model:tabs-icon="tabsIcon"
- />
- </Block>
- <Block :title="$t('preference.footer')">
- <Footer
- v-model:footer-visible="footerVisible"
- v-model:footer-fixed="footerFixed"
- />
- </Block>
- </template>
- <template #general>
- <Block :title="$t('preference.general')">
- <General
- v-model:locale="locale"
- v-model:dynamic-title="dynamicTitle"
- v-model:shortcut-keys="shortcutKeys"
- />
- </Block>
- <Block :title="$t('preference.animation')">
- <Animation
- v-model:page-progress="pageProgress"
- v-model:page-transition="pageTransition"
- v-model:page-transition-enable="pageTransitionEnable"
- />
- </Block>
- </template>
- <template #shortcutKey>
- <Block :title="$t('preference.general')">
- <General
- v-model:locale="locale"
- v-model:dynamic-title="dynamicTitle"
- v-model:shortcut-keys="shortcutKeys"
- />
- </Block>
- <Block :title="$t('preference.animation')">
- <Animation
- v-model:page-progress="pageProgress"
- v-model:page-transition="pageTransition"
- v-model:page-transition-enable="pageTransitionEnable"
- />
- </Block>
- </template>
- </VbenSegmented>
- </div>
- <template #footer>
- <VbenButton
- class="mx-6 w-full"
- variant="default"
- size="sm"
- :disabled="!diffPreference"
- @click="handleCopy"
- >
- <IcRoundFolderCopy class="mr-2 size-3" />
- {{ $t('preference.copy') }}
- </VbenButton>
- </template>
- </VbenSheet>
- </div>
- </template>
|