Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/design",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -52,12 +52,12 @@
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
|
||||
/* Used for accents such as hover effects on <DropdownMenuItem>, <SelectItem>...etc */
|
||||
--accent: 240 3.7% 15.9%;
|
||||
--accent-hover: 240 3.7% 20.9%;
|
||||
--accent: 216 5% 19%;
|
||||
--accent-hover: 216 5% 24%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
|
||||
/* Darker color */
|
||||
--heavy: 240 3.7% 20.9%;
|
||||
--heavy: 216 5% 24%;
|
||||
--heavy-foreground: var(--accent-foreground);
|
||||
|
||||
/* Default border color */
|
||||
@@ -82,15 +82,15 @@
|
||||
/* 基本文字大小 */
|
||||
--font-size-base: 16px;
|
||||
|
||||
/* 主体内容背景色 */
|
||||
--content: 240 11% 96%;
|
||||
|
||||
/* =============component & UI============= */
|
||||
|
||||
--sidebar: 222.34deg 10.43% 12.27%;
|
||||
--sidebar-deep: 220deg 13.06% 9%;
|
||||
--menu: var(--sidebar);
|
||||
|
||||
/* header */
|
||||
--header: 222.34deg 10.43% 12.27%;
|
||||
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
--ring: 263.4 70% 50.4%;
|
||||
--sidebar: 224 71.4% 4.1%;
|
||||
--sidebar-deep: 224 71.4% 4.1%;
|
||||
--header: 224 71.4% 4.1%;
|
||||
}
|
||||
|
||||
.dark[data-theme='pink'],
|
||||
@@ -142,6 +143,7 @@
|
||||
--ring: 346.8 77.2% 49.8%;
|
||||
--sidebar: 20 14.3% 4.1%;
|
||||
--sidebar-deep: 20 14.3% 4.1%;
|
||||
--header: 20 14.3% 4.1%;
|
||||
}
|
||||
|
||||
.dark[data-theme='rose'],
|
||||
@@ -167,6 +169,7 @@
|
||||
--ring: 0 72.2% 50.6%;
|
||||
--sidebar: 0 0% 3.9%;
|
||||
--sidebar-deep: 0 0% 3.9%;
|
||||
--header: 0 0% 3.9%;
|
||||
}
|
||||
|
||||
.dark[data-theme='sky-blue'],
|
||||
@@ -192,6 +195,7 @@
|
||||
--ring: 224.3 76.3% 48%;
|
||||
--sidebar: 222.2 84% 4.9%;
|
||||
--sidebar-deep: 222.2 84% 4.9%;
|
||||
--header: 222.2 84% 4.9%;
|
||||
}
|
||||
|
||||
.dark[data-theme='deep-blue'],
|
||||
@@ -217,6 +221,7 @@
|
||||
--ring: 224.3 76.3% 48%;
|
||||
--sidebar: 222.2 84% 4.9%;
|
||||
--sidebar-deep: 222.2 84% 4.9%;
|
||||
--header: 222.2 84% 4.9%;
|
||||
}
|
||||
|
||||
.dark[data-theme='green'],
|
||||
@@ -242,6 +247,7 @@
|
||||
--ring: 142.4 71.8% 29.2%;
|
||||
--sidebar: 20 14.3% 4.1%;
|
||||
--sidebar-deep: 20 14.3% 4.1%;
|
||||
--header: 20 14.3% 4.1%;
|
||||
}
|
||||
|
||||
.dark[data-theme='deep-green'],
|
||||
@@ -267,6 +273,7 @@
|
||||
--ring: 142.4 71.8% 29.2%;
|
||||
--sidebar: 20 14.3% 4.1%;
|
||||
--sidebar-deep: 20 14.3% 4.1%;
|
||||
--header: 20 14.3% 4.1%;
|
||||
}
|
||||
|
||||
.dark[data-theme='orange'],
|
||||
@@ -292,6 +299,7 @@
|
||||
--ring: 20.5 90.2% 48.2%;
|
||||
--sidebar: 20 14.3% 4.1%;
|
||||
--sidebar-deep: 20 14.3% 4.1%;
|
||||
--header: 20 14.3% 4.1%;
|
||||
}
|
||||
|
||||
.dark[data-theme='yellow'],
|
||||
@@ -317,6 +325,7 @@
|
||||
--ring: 35.5 91.7% 32.9%;
|
||||
--sidebar: 20 14.3% 4.1%;
|
||||
--sidebar-deep: 20 14.3% 4.1%;
|
||||
--header: 20 14.3% 4.1%;
|
||||
}
|
||||
|
||||
.dark[data-theme='zinc'],
|
||||
@@ -342,6 +351,7 @@
|
||||
--ring: 240 4.9% 83.9%;
|
||||
--sidebar: 240 10% 3.9%;
|
||||
--sidebar-deep: 240 10% 3.9%;
|
||||
--header: 240 4.9% 83.9%;
|
||||
}
|
||||
|
||||
.dark[data-theme='neutral'],
|
||||
@@ -367,6 +377,7 @@
|
||||
--ring: 0 0% 83.1%;
|
||||
--sidebar: 0 0% 3.9%;
|
||||
--sidebar-deep: 0 0% 3.9%;
|
||||
--header: 0 0% 3.9%;
|
||||
}
|
||||
|
||||
.dark[data-theme='slate'],
|
||||
@@ -392,6 +403,7 @@
|
||||
--ring: 212.7 26.8% 83.9;
|
||||
--sidebar: 222.2 84% 4.9%;
|
||||
--sidebar-deep: 222.2 84% 4.9%;
|
||||
--header: 222.2 84% 4.9%;
|
||||
}
|
||||
|
||||
.dark[data-theme='gray'],
|
||||
@@ -417,4 +429,5 @@
|
||||
--ring: 216 12.2% 83.9%;
|
||||
--sidebar: 224 71.4% 4.1%;
|
||||
--sidebar-deep: 224 71.4% 4.1%;
|
||||
--header: 224 71.4% 4.1%;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
/* 主体区域背景色 */
|
||||
--background-deep: 210 11.11% 96.47%;
|
||||
--foreground: 222 84% 5%;
|
||||
--foreground: 210 6% 21%;
|
||||
|
||||
/* Background color for <Card /> */
|
||||
--card: 0 0% 100%;
|
||||
@@ -82,16 +82,16 @@
|
||||
/* 基本文字大小 */
|
||||
--font-size-base: 16px;
|
||||
|
||||
/* 主体内容背景色 */
|
||||
--content: 240 11% 96%;
|
||||
|
||||
/* =============component & UI============= */
|
||||
|
||||
/* menu */
|
||||
--sidebar: 0 0% 100%;
|
||||
--sidebar-deep: 210 11.11% 96.47%;
|
||||
--sidebar-deep: 0 0% 100%;
|
||||
--menu: var(--sidebar);
|
||||
|
||||
/* header */
|
||||
--header: 0 0% 100%;
|
||||
|
||||
accent-color: var(--primary);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/icons",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -38,7 +38,7 @@ export {
|
||||
RotateCw,
|
||||
Search,
|
||||
SearchX,
|
||||
Settings2,
|
||||
Settings,
|
||||
Sun,
|
||||
SunMoon,
|
||||
SwatchBook,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/shared",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/typings",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
8
packages/@core/base/typings/src/app.d.ts
vendored
8
packages/@core/base/typings/src/app.d.ts
vendored
@@ -7,6 +7,13 @@ type LayoutType =
|
||||
|
||||
type ThemeModeType = 'auto' | 'dark' | 'light';
|
||||
|
||||
/**
|
||||
* 偏好设置按钮位置
|
||||
* fixed 固定在右侧
|
||||
* header 顶栏
|
||||
*/
|
||||
type PreferencesButtonPositionType = 'fixed' | 'header';
|
||||
|
||||
type BuiltinThemeType =
|
||||
| 'custom'
|
||||
| 'deep-blue'
|
||||
@@ -92,6 +99,7 @@ export type {
|
||||
LoginExpiredModeType,
|
||||
NavigationStyleType,
|
||||
PageTransitionType,
|
||||
PreferencesButtonPositionType,
|
||||
TabsStyleType,
|
||||
ThemeModeType,
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/composables",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/preferences",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -19,6 +19,7 @@ const defaultPreferences: Preferences = {
|
||||
locale: 'zh-CN',
|
||||
loginExpiredMode: 'modal',
|
||||
name: 'Vben Admin',
|
||||
preferencesButtonPosition: 'fixed',
|
||||
watermark: false,
|
||||
},
|
||||
breadcrumb: {
|
||||
@@ -90,7 +91,8 @@ const defaultPreferences: Preferences = {
|
||||
colorWarning: 'hsl(42 84% 61%)',
|
||||
mode: 'auto',
|
||||
radius: '0.5',
|
||||
semiDarkMenu: true,
|
||||
semiDarkHeader: false,
|
||||
semiDarkSidebar: true,
|
||||
},
|
||||
transition: {
|
||||
enable: true,
|
||||
|
@@ -10,6 +10,7 @@ import type {
|
||||
LoginExpiredModeType,
|
||||
NavigationStyleType,
|
||||
PageTransitionType,
|
||||
PreferencesButtonPositionType,
|
||||
TabsStyleType,
|
||||
ThemeModeType,
|
||||
} from '@vben-core/typings';
|
||||
@@ -49,6 +50,8 @@ interface AppPreferences {
|
||||
loginExpiredMode: LoginExpiredModeType;
|
||||
/** 应用名 */
|
||||
name: string;
|
||||
/** 偏好设置按钮位置 */
|
||||
preferencesButtonPosition: PreferencesButtonPositionType;
|
||||
/**
|
||||
* @zh_CN 是否开启水印
|
||||
*/
|
||||
@@ -183,8 +186,10 @@ interface ThemePreferences {
|
||||
mode: ThemeModeType;
|
||||
/** 圆角 */
|
||||
radius: string;
|
||||
/** 是否开启半深色header(只在theme='light'时生效) */
|
||||
semiDarkHeader: boolean;
|
||||
/** 是否开启半深色菜单(只在theme='light'时生效) */
|
||||
semiDarkMenu: boolean;
|
||||
semiDarkSidebar: boolean;
|
||||
}
|
||||
|
||||
interface TransitionPreferences {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/layout-ui",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -36,6 +36,10 @@ interface Props {
|
||||
* 侧边菜单宽度
|
||||
*/
|
||||
sidebarWidth: number;
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
theme: string | undefined;
|
||||
/**
|
||||
* 宽度
|
||||
*/
|
||||
@@ -76,15 +80,16 @@ function handleToggleMenu() {
|
||||
|
||||
<template>
|
||||
<header
|
||||
:class="theme"
|
||||
:style="style"
|
||||
class="border-border bg-background top-0 flex w-full flex-[0_0_auto] items-center border-b transition-[margin-top] duration-200"
|
||||
class="border-border bg-header top-0 flex w-full flex-[0_0_auto] items-center border-b transition-[margin-top] duration-200"
|
||||
>
|
||||
<div v-if="slots.logo" :style="logoStyle">
|
||||
<slot name="logo"></slot>
|
||||
</div>
|
||||
<VbenIconButton
|
||||
v-if="showToggleBtn || isMobile"
|
||||
class="my-0 ml-2 mr-1 rounded"
|
||||
class="my-0 ml-2 mr-1 rounded-md"
|
||||
@click="handleToggleMenu"
|
||||
>
|
||||
<Menu class="size-4" />
|
||||
|
@@ -24,9 +24,8 @@ interface Props {
|
||||
domVisible?: boolean;
|
||||
/**
|
||||
* 扩展区域宽度
|
||||
* @default 180
|
||||
*/
|
||||
extraWidth?: number;
|
||||
extraWidth: number;
|
||||
/**
|
||||
* 固定扩展区域
|
||||
* @default false
|
||||
@@ -69,13 +68,12 @@ interface Props {
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
theme?: string;
|
||||
theme: string;
|
||||
|
||||
/**
|
||||
* 宽度
|
||||
* @default 180
|
||||
*/
|
||||
width?: number;
|
||||
width: number;
|
||||
/**
|
||||
* zIndex
|
||||
* @default 0
|
||||
@@ -87,7 +85,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
collapseHeight: 42,
|
||||
collapseWidth: 48,
|
||||
domVisible: true,
|
||||
extraWidth: 180,
|
||||
fixedExtra: false,
|
||||
isSidebarMixed: false,
|
||||
marginTop: 0,
|
||||
@@ -95,8 +92,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
paddingTop: 0,
|
||||
show: true,
|
||||
showCollapseButton: true,
|
||||
theme: 'dark',
|
||||
width: 180,
|
||||
zIndex: 0,
|
||||
});
|
||||
|
||||
@@ -181,10 +176,8 @@ const extraContentStyle = computed((): CSSProperties => {
|
||||
});
|
||||
|
||||
const collapseStyle = computed((): CSSProperties => {
|
||||
const { collapseHeight } = props;
|
||||
|
||||
return {
|
||||
height: `${collapseHeight}px`,
|
||||
height: `${props.collapseHeight}px`,
|
||||
};
|
||||
});
|
||||
|
||||
|
41
packages/@core/ui-kit/layout-ui/src/hooks/use-layout.ts
Normal file
41
packages/@core/ui-kit/layout-ui/src/hooks/use-layout.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { LayoutType } from '@vben-core/typings';
|
||||
|
||||
import type { VbenLayoutProps } from '../vben-layout';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
export function useLayout(props: VbenLayoutProps) {
|
||||
const currentLayout = computed(() =>
|
||||
props.isMobile ? 'sidebar-nav' : (props.layout as LayoutType),
|
||||
);
|
||||
|
||||
/**
|
||||
* 是否全屏显示content,不需要侧边、底部、顶部、tab区域
|
||||
*/
|
||||
const isFullContent = computed(() => currentLayout.value === 'full-content');
|
||||
|
||||
/**
|
||||
* 是否侧边混合模式
|
||||
*/
|
||||
const isSidebarMixedNav = computed(
|
||||
() => currentLayout.value === 'sidebar-mixed-nav',
|
||||
);
|
||||
|
||||
/**
|
||||
* 是否为头部导航模式
|
||||
*/
|
||||
const isHeaderNav = computed(() => currentLayout.value === 'header-nav');
|
||||
|
||||
/**
|
||||
* 是否为混合导航模式
|
||||
*/
|
||||
const isMixedNav = computed(() => currentLayout.value === 'mixed-nav');
|
||||
|
||||
return {
|
||||
currentLayout,
|
||||
isFullContent,
|
||||
isHeaderNav,
|
||||
isMixedNav,
|
||||
isSidebarMixedNav,
|
||||
};
|
||||
}
|
@@ -62,12 +62,6 @@ interface VbenLayoutProps {
|
||||
* @default 48
|
||||
*/
|
||||
headerHeight?: number;
|
||||
/**
|
||||
* header高度增加高度
|
||||
* 在顶部存在导航时,额外加高header高度
|
||||
* @default 10
|
||||
*/
|
||||
headerHeightOffset?: number;
|
||||
/**
|
||||
* 顶栏是否隐藏
|
||||
* @default false
|
||||
@@ -78,6 +72,10 @@ interface VbenLayoutProps {
|
||||
* @default 'fixed'
|
||||
*/
|
||||
headerMode?: LayoutHeaderModeType;
|
||||
/**
|
||||
* header 顶栏主题
|
||||
*/
|
||||
headerTheme?: ThemeModeType;
|
||||
/**
|
||||
* 是否显示header切换侧边栏按钮
|
||||
* @default
|
||||
@@ -133,11 +131,6 @@ interface VbenLayoutProps {
|
||||
* @default 80
|
||||
*/
|
||||
sidebarMixedWidth?: number;
|
||||
/**
|
||||
* 侧边栏是否半深色
|
||||
* @default false
|
||||
*/
|
||||
sidebarSemiDark?: boolean;
|
||||
/**
|
||||
* 侧边栏
|
||||
* @default dark
|
||||
|
@@ -13,6 +13,7 @@ import {
|
||||
LayoutSidebar,
|
||||
LayoutTabbar,
|
||||
} from './components';
|
||||
import { useLayout } from './hooks/use-layout';
|
||||
|
||||
interface Props extends VbenLayoutProps {}
|
||||
|
||||
@@ -32,7 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
footerFixed: true,
|
||||
footerHeight: 32,
|
||||
headerHeight: 50,
|
||||
headerHeightOffset: 10,
|
||||
headerHidden: false,
|
||||
headerMode: 'fixed',
|
||||
headerToggleSidebarButton: true,
|
||||
@@ -43,7 +43,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
sidebarExtraCollapsedWidth: 60,
|
||||
sidebarHidden: false,
|
||||
sidebarMixedWidth: 80,
|
||||
sidebarSemiDark: true,
|
||||
sidebarTheme: 'dark',
|
||||
sidebarWidth: 180,
|
||||
sideCollapseWidth: 60,
|
||||
@@ -73,57 +72,23 @@ const {
|
||||
|
||||
const { y: mouseY } = useMouse({ target: contentRef, type: 'client' });
|
||||
|
||||
const realLayout = computed(() =>
|
||||
props.isMobile ? 'sidebar-nav' : props.layout,
|
||||
);
|
||||
|
||||
/**
|
||||
* 是否全屏显示content,不需要侧边、底部、顶部、tab区域
|
||||
*/
|
||||
const fullContent = computed(() => realLayout.value === 'full-content');
|
||||
|
||||
/**
|
||||
* 是否侧边混合模式
|
||||
*/
|
||||
const isSidebarMixedNav = computed(
|
||||
() => realLayout.value === 'sidebar-mixed-nav',
|
||||
);
|
||||
|
||||
/**
|
||||
* 是否为头部导航模式
|
||||
*/
|
||||
const isHeaderNav = computed(() => realLayout.value === 'header-nav');
|
||||
|
||||
/**
|
||||
* 是否为混合导航模式
|
||||
*/
|
||||
const isMixedNav = computed(() => realLayout.value === 'mixed-nav');
|
||||
const {
|
||||
currentLayout,
|
||||
isFullContent,
|
||||
isHeaderNav,
|
||||
isMixedNav,
|
||||
isSidebarMixedNav,
|
||||
} = useLayout(props);
|
||||
|
||||
/**
|
||||
* 顶栏是否自动隐藏
|
||||
*/
|
||||
const isHeaderAutoMode = computed(() => props.headerMode === 'auto');
|
||||
|
||||
/**
|
||||
* header区域高度
|
||||
*/
|
||||
const getHeaderHeight = computed(() => {
|
||||
const { headerHeight, headerHeightOffset } = props;
|
||||
|
||||
// if (!headerVisible) {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// 顶部存在导航时,增加10
|
||||
const offset = isMixedNav.value || isHeaderNav.value ? headerHeightOffset : 0;
|
||||
|
||||
return headerHeight + offset;
|
||||
});
|
||||
|
||||
const headerWrapperHeight = computed(() => {
|
||||
let height = 0;
|
||||
if (props.headerVisible && !props.headerHidden) {
|
||||
height += getHeaderHeight.value;
|
||||
height += props.headerHeight;
|
||||
}
|
||||
if (props.tabbarEnable) {
|
||||
height += props.tabbarHeight;
|
||||
@@ -151,8 +116,8 @@ const sidebarEnableState = computed(() => {
|
||||
* 侧边区域离顶部高度
|
||||
*/
|
||||
const sidebarMarginTop = computed(() => {
|
||||
const { isMobile } = props;
|
||||
return isMixedNav.value && !isMobile ? getHeaderHeight.value : 0;
|
||||
const { headerHeight, isMobile } = props;
|
||||
return isMixedNav.value && !isMobile ? headerHeight : 0;
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -195,30 +160,13 @@ const sidebarExtraWidth = computed(() => {
|
||||
/**
|
||||
* 是否侧边栏模式,包含混合侧边
|
||||
*/
|
||||
const isSideMode = computed(() =>
|
||||
['mixed-nav', 'sidebar-mixed-nav', 'sidebar-nav'].includes(realLayout.value),
|
||||
const isSideMode = computed(
|
||||
() =>
|
||||
currentLayout.value === 'mixed-nav' ||
|
||||
currentLayout.value === 'sidebar-mixed-nav' ||
|
||||
currentLayout.value === 'sidebar-nav',
|
||||
);
|
||||
|
||||
const showSidebar = computed(() => {
|
||||
// if (isMixedNav.value && !props.sideHidden) {
|
||||
// return false;
|
||||
// }
|
||||
return isSideMode.value && sidebarEnable.value;
|
||||
});
|
||||
|
||||
const sidebarFace = computed(() => {
|
||||
const { sidebarSemiDark, sidebarTheme } = props;
|
||||
const isDark = sidebarTheme === 'dark' || sidebarSemiDark;
|
||||
return {
|
||||
theme: isDark ? 'dark' : 'light',
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* 遮罩可见性
|
||||
*/
|
||||
const maskVisible = computed(() => !sidebarCollapse.value && props.isMobile);
|
||||
|
||||
/**
|
||||
* header fixed值
|
||||
*/
|
||||
@@ -232,13 +180,25 @@ const headerFixed = computed(() => {
|
||||
);
|
||||
});
|
||||
|
||||
const showSidebar = computed(() => {
|
||||
// if (isMixedNav.value && !props.sideHidden) {
|
||||
// return false;
|
||||
// }
|
||||
return isSideMode.value && sidebarEnable.value;
|
||||
});
|
||||
|
||||
/**
|
||||
* 遮罩可见性
|
||||
*/
|
||||
const maskVisible = computed(() => !sidebarCollapse.value && props.isMobile);
|
||||
|
||||
const mainStyle = computed(() => {
|
||||
let width = '100%';
|
||||
let sidebarAndExtraWidth = 'unset';
|
||||
if (
|
||||
headerFixed.value &&
|
||||
realLayout.value !== 'header-nav' &&
|
||||
realLayout.value !== 'mixed-nav' &&
|
||||
currentLayout.value !== 'header-nav' &&
|
||||
currentLayout.value !== 'mixed-nav' &&
|
||||
showSidebar.value &&
|
||||
!props.isMobile
|
||||
) {
|
||||
@@ -253,7 +213,7 @@ const mainStyle = computed(() => {
|
||||
? getSideCollapseWidth.value
|
||||
: props.sidebarMixedWidth;
|
||||
const sideWidth = sidebarExtraCollapse.value
|
||||
? getSideCollapseWidth.value
|
||||
? props.sidebarExtraCollapsedWidth
|
||||
: props.sidebarWidth;
|
||||
|
||||
// 100% - 侧边菜单混合宽度 - 菜单宽度
|
||||
@@ -312,7 +272,7 @@ const contentStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
marginTop:
|
||||
fixed &&
|
||||
!fullContent.value &&
|
||||
!isFullContent.value &&
|
||||
!headerIsHidden.value &&
|
||||
(!isHeaderAutoMode.value || scrollY.value < headerWrapperHeight.value)
|
||||
? `${headerWrapperHeight.value}px`
|
||||
@@ -330,11 +290,11 @@ const headerZIndex = computed(() => {
|
||||
const headerWrapperStyle = computed((): CSSProperties => {
|
||||
const fixed = headerFixed.value;
|
||||
return {
|
||||
height: fullContent.value ? '0' : `${headerWrapperHeight.value}px`,
|
||||
height: isFullContent.value ? '0' : `${headerWrapperHeight.value}px`,
|
||||
left: isMixedNav.value ? 0 : mainStyle.value.sidebarAndExtraWidth,
|
||||
position: fixed ? 'fixed' : 'static',
|
||||
top:
|
||||
headerIsHidden.value || fullContent.value
|
||||
headerIsHidden.value || isFullContent.value
|
||||
? `-${headerWrapperHeight.value}px`
|
||||
: 0,
|
||||
width: mainStyle.value.width,
|
||||
@@ -403,7 +363,10 @@ watch(
|
||||
watch(
|
||||
[() => props.headerMode, () => mouseY.value],
|
||||
() => {
|
||||
if (!isHeaderAutoMode.value || isMixedNav.value || fullContent.value) {
|
||||
if (!isHeaderAutoMode.value || isMixedNav.value || isFullContent.value) {
|
||||
if (props.headerMode !== 'auto-scroll') {
|
||||
headerIsHidden.value = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
headerIsHidden.value = true;
|
||||
@@ -439,7 +402,7 @@ watch(
|
||||
if (
|
||||
props.headerMode !== 'auto-scroll' ||
|
||||
isMixedNav.value ||
|
||||
fullContent.value
|
||||
isFullContent.value
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -465,8 +428,6 @@ function handleOpenMenu() {
|
||||
|
||||
<template>
|
||||
<div class="relative flex min-h-full w-full">
|
||||
<slot name="preferences"></slot>
|
||||
<slot name="floating-groups"></slot>
|
||||
<LayoutSidebar
|
||||
v-if="sidebarEnableState"
|
||||
v-model:collapse="sidebarCollapse"
|
||||
@@ -478,12 +439,12 @@ function handleOpenMenu() {
|
||||
:dom-visible="!isMobile"
|
||||
:extra-width="sidebarExtraWidth"
|
||||
:fixed-extra="sidebarExpandOnHover"
|
||||
:header-height="isMixedNav ? 0 : getHeaderHeight"
|
||||
:header-height="isMixedNav ? 0 : headerHeight"
|
||||
:is-sidebar-mixed="isSidebarMixedNav"
|
||||
:margin-top="sidebarMarginTop"
|
||||
:mixed-width="sidebarMixedWidth"
|
||||
:show="showSidebar"
|
||||
:theme="sidebarFace.theme"
|
||||
:theme="sidebarTheme"
|
||||
:width="getSidebarWidth"
|
||||
:z-index="sidebarZIndex"
|
||||
@leave="() => emit('sideMouseLeave')"
|
||||
@@ -518,12 +479,13 @@ function handleOpenMenu() {
|
||||
<LayoutHeader
|
||||
v-if="headerVisible"
|
||||
:full-width="!isSideMode"
|
||||
:height="getHeaderHeight"
|
||||
:height="headerHeight"
|
||||
:is-mixed-nav="isMixedNav"
|
||||
:is-mobile="isMobile"
|
||||
:show="!fullContent && !headerHidden"
|
||||
:show="!isFullContent && !headerHidden"
|
||||
:show-toggle-btn="showHeaderToggleButton"
|
||||
:sidebar-width="sidebarWidth"
|
||||
:theme="headerTheme"
|
||||
:width="mainStyle.width"
|
||||
:z-index="headerZIndex"
|
||||
@open-menu="handleOpenMenu"
|
||||
@@ -563,7 +525,7 @@ function handleOpenMenu() {
|
||||
v-if="footerEnable"
|
||||
:fixed="footerFixed"
|
||||
:height="footerHeight"
|
||||
:show="!fullContent"
|
||||
:show="!isFullContent"
|
||||
:width="footerWidth"
|
||||
:z-index="zIndex"
|
||||
>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/menu-ui",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -479,8 +479,8 @@ $namespace: vben;
|
||||
}
|
||||
|
||||
&.is-horizontal:not(.is-rounded) {
|
||||
--menu-item-height: 60px;
|
||||
--menu-item-radius: 0px;
|
||||
--menu-item-height: 40px;
|
||||
--menu-item-radius: 6px;
|
||||
}
|
||||
|
||||
&.is-horizontal.is-rounded {
|
||||
@@ -498,13 +498,13 @@ $namespace: vben;
|
||||
--menu-background-color: transparent;
|
||||
|
||||
&.is-dark {
|
||||
--menu-item-hover-color: var(--foreground);
|
||||
--menu-item-hover-color: hsl(var(--accent-foreground));
|
||||
--menu-item-hover-background-color: hsl(var(--accent));
|
||||
--menu-item-active-color: hsl(var(--foreground));
|
||||
--menu-item-active-color: hsl(var(--accent-foreground));
|
||||
--menu-item-active-background-color: hsl(var(--accent));
|
||||
--menu-submenu-active-color: hsl(var(--foreground));
|
||||
--menu-submenu-active-background-color: hsl(var(--accent));
|
||||
--menu-submenu-hover-color: hsl(var(--foreground));
|
||||
--menu-submenu-hover-color: hsl(var(--accent-foreground));
|
||||
--menu-submenu-hover-background-color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ $namespace: vben;
|
||||
--menu-item-hover-background-color: hsl(var(--accent));
|
||||
--menu-item-hover-color: hsl(var(--primary));
|
||||
--menu-submenu-active-color: hsl(var(--primary));
|
||||
--menu-submenu-active-background-color: hsl(var(--primary) / 30%);
|
||||
--menu-submenu-active-background-color: hsl(var(--primary) / 15%);
|
||||
--menu-submenu-hover-color: hsl(var(--primary));
|
||||
--menu-submenu-hover-background-color: hsl(var(--accent));
|
||||
}
|
||||
@@ -776,7 +776,7 @@ $namespace: vben;
|
||||
&.is-active {
|
||||
div[data-state='open'] > .#{$namespace}-sub-menu-content,
|
||||
> .#{$namespace}-sub-menu-content {
|
||||
font-weight: 500;
|
||||
// font-weight: 500;
|
||||
color: var(--menu-submenu-active-color);
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/shadcn-ui",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -22,6 +22,7 @@ export * from './scrollbar';
|
||||
export * from './segmented';
|
||||
export * from './sheet';
|
||||
export * from './spinner';
|
||||
export * from './swap';
|
||||
export * from './tooltip';
|
||||
export * from './ui/alert-dialog';
|
||||
export * from './ui/avatar';
|
||||
|
@@ -1 +1 @@
|
||||
export { default as Spinner } from './spinner.vue';
|
||||
export { default as VbenSpinner } from './spinner.vue';
|
||||
|
@@ -0,0 +1 @@
|
||||
export { default as VbenSwap } from './swap.vue';
|
126
packages/@core/ui-kit/shadcn-ui/src/components/swap/swap.vue
Normal file
126
packages/@core/ui-kit/shadcn-ui/src/components/swap/swap.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
/**
|
||||
* @zh_CN 交换模式
|
||||
*/
|
||||
mode?: 'flip' | 'rotate';
|
||||
/**
|
||||
* @zh_CN 开启时的样式
|
||||
*/
|
||||
offClass?: string;
|
||||
/**
|
||||
* @zh_CN 关闭时的样式
|
||||
*/
|
||||
onClass?: string;
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
name: 'Swap',
|
||||
});
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
mode: 'rotate',
|
||||
onClass: '',
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label
|
||||
:class="{
|
||||
'swap-flip': mode === 'flip',
|
||||
'swap-rotate': mode === 'rotate',
|
||||
}"
|
||||
class="swap"
|
||||
>
|
||||
<input class="hidden" type="checkbox" />
|
||||
|
||||
<div :class="onClass" class="swap-on">
|
||||
<slot name="swap-on"></slot>
|
||||
</div>
|
||||
|
||||
<div :class="offClass" class="swap-off">
|
||||
<slot name="swap-off"></slot>
|
||||
</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.swap {
|
||||
@apply relative inline-grid cursor-pointer select-none place-content-center;
|
||||
}
|
||||
|
||||
.swap > * {
|
||||
@apply col-start-1 row-start-1 duration-300 ease-out;
|
||||
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.swap-rotate .swap-on,
|
||||
.swap-rotate .swap-indeterminate,
|
||||
.swap-rotate input:indeterminate ~ .swap-on {
|
||||
@apply rotate-45;
|
||||
}
|
||||
|
||||
.swap-rotate input:checked ~ .swap-off,
|
||||
.swap-active:where(.swap-rotate) .swap-off,
|
||||
.swap-rotate input:indeterminate ~ .swap-off {
|
||||
@apply -rotate-45;
|
||||
}
|
||||
|
||||
.swap-rotate input:checked ~ .swap-on,
|
||||
.swap-active:where(.swap-rotate) .swap-on,
|
||||
.swap-rotate input:indeterminate ~ .swap-indeterminate {
|
||||
@apply rotate-0;
|
||||
}
|
||||
|
||||
.swap-flip {
|
||||
transform-style: preserve-3d;
|
||||
perspective: 16em;
|
||||
}
|
||||
|
||||
.swap-flip .swap-on,
|
||||
.swap-flip .swap-indeterminate,
|
||||
.swap-flip input:indeterminate ~ .swap-on {
|
||||
@apply opacity-100;
|
||||
|
||||
transform: rotateY(180deg);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.swap-flip input:checked ~ .swap-off,
|
||||
.swap-active:where(.swap-flip) .swap-off,
|
||||
.swap-flip input:indeterminate ~ .swap-off {
|
||||
@apply opacity-100;
|
||||
|
||||
transform: rotateY(-180deg);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.swap-flip input:checked ~ .swap-on,
|
||||
.swap-active:where(.swap-flip) .swap-on,
|
||||
.swap-flip input:indeterminate ~ .swap-indeterminate {
|
||||
transform: rotateY(0deg);
|
||||
}
|
||||
|
||||
.swap input {
|
||||
@apply appearance-none;
|
||||
}
|
||||
|
||||
.swap .swap-on,
|
||||
.swap .swap-indeterminate,
|
||||
.swap input:indeterminate ~ .swap-on {
|
||||
@apply opacity-0;
|
||||
}
|
||||
|
||||
.swap input:checked ~ .swap-off,
|
||||
.swap-active .swap-off,
|
||||
.swap input:indeterminate ~ .swap-off {
|
||||
@apply opacity-0;
|
||||
}
|
||||
|
||||
.swap input:checked ~ .swap-on,
|
||||
.swap-active .swap-on,
|
||||
.swap input:indeterminate ~ .swap-indeterminate {
|
||||
@apply opacity-100;
|
||||
}
|
||||
</style>
|
@@ -30,7 +30,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
<template>
|
||||
<DialogPortal>
|
||||
<DialogOverlay
|
||||
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 border-border fixed inset-0 z-[1000] grid place-items-center overflow-y-auto bg-black/80"
|
||||
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 border-border fixed inset-0 z-[1000] grid place-items-center overflow-y-auto border bg-black/80"
|
||||
>
|
||||
<DialogContent
|
||||
:class="
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, type HTMLAttributes } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from 'radix-vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{ class?: HTMLAttributes['class'] } & HoverCardContentProps>(),
|
||||
defineProps<{ class?: any } & HoverCardContentProps>(),
|
||||
{
|
||||
sideOffset: 4,
|
||||
},
|
||||
|
@@ -9,10 +9,10 @@ export const sheetVariants = cva(
|
||||
variants: {
|
||||
side: {
|
||||
bottom:
|
||||
'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
|
||||
'inset-x-0 bottom-0 border-t border-border data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
|
||||
left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
|
||||
right:
|
||||
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
|
||||
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
|
||||
top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
|
||||
},
|
||||
},
|
||||
|
@@ -5,7 +5,7 @@ import type { HTMLAttributes } from 'vue';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
|
||||
export const toastVariants = cva(
|
||||
'group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
|
||||
'group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border border-border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
|
||||
{
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
|
@@ -41,7 +41,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
v-bind="{ ...forwarded, ...$attrs }"
|
||||
:class="
|
||||
cn(
|
||||
'bg-accent text-accent-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-[1000] overflow-hidden rounded-sm px-4 py-2 text-xs shadow-md',
|
||||
'bg-accent text-accent-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border shadow-float z-[1000] overflow-hidden rounded-sm border px-4 py-2 text-xs',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/tabs-ui",
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -109,7 +109,7 @@ function scrollIntoView() {
|
||||
<!-- divider -->
|
||||
<div
|
||||
v-if="i !== 0 && tab.key !== active"
|
||||
class="tabs-chrome__divider bg-foreground/80 absolute left-[var(--gap)] top-1/2 z-0 h-4 w-[1px] translate-y-[-50%] transition-all"
|
||||
class="tabs-chrome__divider bg-foreground/60 absolute left-[var(--gap)] top-1/2 z-0 h-4 w-[1px] translate-y-[-50%] transition-all"
|
||||
></div>
|
||||
<!-- background -->
|
||||
<div
|
||||
|
Reference in New Issue
Block a user