fix: layout error

pull/48/MERGE
vben 2024-06-09 15:39:11 +08:00
parent 35c3dd78ec
commit 640ad6d9e7
58 changed files with 678 additions and 679 deletions

View File

@ -35,7 +35,7 @@
"@vben/styles": "workspace:*", "@vben/styles": "workspace:*",
"@vben/types": "workspace:*", "@vben/types": "workspace:*",
"@vben/utils": "workspace:*", "@vben/utils": "workspace:*",
"@vueuse/core": "^10.10.0", "@vueuse/core": "^10.10.1",
"ant-design-vue": "^4.2.3", "ant-design-vue": "^4.2.3",
"axios": "^1.7.2", "axios": "^1.7.2",
"dayjs": "^1.11.11", "dayjs": "^1.11.11",

View File

@ -34,7 +34,7 @@
"@commitlint/cli": "^19.3.0", "@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2", "@commitlint/config-conventional": "^19.2.2",
"@vben/node-utils": "workspace:*", "@vben/node-utils": "workspace:*",
"cz-git": "^1.9.2", "cz-git": "^1.9.3",
"czg": "^1.9.2" "czg": "^1.9.3"
} }
} }

View File

@ -32,6 +32,6 @@
}, },
"dependencies": { "dependencies": {
"prettier": "3.3.0", "prettier": "3.3.0",
"prettier-plugin-tailwindcss": "^0.6.2" "prettier-plugin-tailwindcss": "^0.6.3"
} }
} }

View File

@ -46,7 +46,7 @@
"dayjs": "^1.11.11", "dayjs": "^1.11.11",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"rollup-plugin-visualizer": "^5.12.0", "rollup-plugin-visualizer": "^5.12.0",
"sass": "^1.77.4", "sass": "^1.77.5",
"unplugin-turbo-console": "^1.8.6", "unplugin-turbo-console": "^1.8.6",
"vite": "6.0.0-alpha.17", "vite": "6.0.0-alpha.17",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",

View File

@ -0,0 +1,88 @@
import { describe, expect, it } from 'vitest';
import { findMenuByPath, findRootMenuByPath } from './find-menu-by-path';
// 示例菜单数据
const menus: any[] = [
{ path: '/', children: [] },
{ path: '/about', children: [] },
{
path: '/contact',
children: [
{ path: '/contact/email', children: [] },
{ path: '/contact/phone', children: [] },
],
},
{
path: '/services',
children: [
{ path: '/services/design', children: [] },
{
path: '/services/development',
children: [{ path: '/services/development/web', children: [] }],
},
],
},
];
describe('menu Finder Tests', () => {
it('finds a top-level menu', () => {
const menu = findMenuByPath(menus, '/about');
expect(menu).toBeDefined();
expect(menu?.path).toBe('/about');
});
it('finds a nested menu', () => {
const menu = findMenuByPath(menus, '/services/development/web');
expect(menu).toBeDefined();
expect(menu?.path).toBe('/services/development/web');
});
it('returns null for a non-existent path', () => {
const menu = findMenuByPath(menus, '/non-existent');
expect(menu).toBeNull();
});
it('handles empty menus list', () => {
const menu = findMenuByPath([], '/about');
expect(menu).toBeNull();
});
it('handles menu items without children', () => {
const menu = findMenuByPath(
[{ path: '/only', children: undefined }] as any[],
'/only',
);
expect(menu).toBeDefined();
expect(menu?.path).toBe('/only');
});
it('finds root menu by path', () => {
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus,
'/services/development/web',
);
expect(findMenu).toBeDefined();
expect(rootMenu).toBeUndefined();
expect(rootMenuPath).toBeUndefined();
expect(findMenu?.path).toBe('/services/development/web');
});
it('returns null for undefined or empty path', () => {
const menuUndefinedPath = findMenuByPath(menus);
const menuEmptyPath = findMenuByPath(menus, '');
expect(menuUndefinedPath).toBeNull();
expect(menuEmptyPath).toBeNull();
});
it('checks for root menu when path does not exist', () => {
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus,
'/non-existent',
);
expect(findMenu).toBeNull();
expect(rootMenu).toBeUndefined();
expect(rootMenuPath).toBeUndefined();
});
});

View File

@ -8,11 +8,9 @@ function findMenuByPath(
if (menu.path === path) { if (menu.path === path) {
return menu; return menu;
} }
if (menu?.children?.length) { const findMenu = menu.children && findMenuByPath(menu.children, path);
const findMenu = findMenuByPath(menu.children, path); if (findMenu) {
if (findMenu) { return findMenu;
return findMenu;
}
} }
} }
return null; return null;

View File

@ -1,3 +1,4 @@
export * from './find-menu-by-path';
export * from './flatten-object'; export * from './flatten-object';
export * from './generator-menus'; export * from './generator-menus';
export * from './generator-routes'; export * from './generator-routes';

View File

@ -36,7 +36,7 @@
"@vben-core/helpers": "workspace:*", "@vben-core/helpers": "workspace:*",
"@vben-core/toolkit": "workspace:*", "@vben-core/toolkit": "workspace:*",
"@vben-core/typings": "workspace:*", "@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.10.0", "@vueuse/core": "^10.10.1",
"vue": "3.4.27" "vue": "3.4.27"
} }
} }

View File

@ -12,7 +12,7 @@ const defaultPreferences: Preferences = {
'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.0/source/avatar-v1.webp', 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.0/source/avatar-v1.webp',
dynamicTitle: true, dynamicTitle: true,
isMobile: false, isMobile: false,
layout: 'side-nav', layout: 'sidebar-nav',
locale: 'zh-CN', locale: 'zh-CN',
name: 'Vben Admin Pro', name: 'Vben Admin Pro',
semiDarkMenu: true, semiDarkMenu: true,
@ -47,8 +47,8 @@ const defaultPreferences: Preferences = {
}, },
shortcutKeys: { enable: true }, shortcutKeys: { enable: true },
sidebar: { sidebar: {
collapse: false, collapsed: false,
collapseShowTitle: true, collapsedShowTitle: true,
enable: true, enable: true,
expandOnHover: true, expandOnHover: true,
extraCollapse: true, extraCollapse: true,

View File

@ -94,9 +94,9 @@ interface NavigationPreferences {
interface SidebarPreferences { interface SidebarPreferences {
/** 侧边栏是否折叠 */ /** 侧边栏是否折叠 */
collapse: boolean; collapsed: boolean;
/** 侧边栏折叠时是否显示title */ /** 侧边栏折叠时是否显示title */
collapseShowTitle: boolean; collapsedShowTitle: boolean;
/** 侧边栏是否可见 */ /** 侧边栏是否可见 */
enable: boolean; enable: boolean;
/** 菜单自动展开状态 */ /** 菜单自动展开状态 */

View File

@ -33,7 +33,7 @@ function usePreferences() {
* @zh_CN * @zh_CN
*/ */
const layout = computed(() => const layout = computed(() =>
appPreferences.value.isMobile ? 'side-nav' : appPreferences.value.layout, appPreferences.value.isMobile ? 'sidebar-nav' : appPreferences.value.layout,
); );
/** /**
@ -46,13 +46,15 @@ function usePreferences() {
/** /**
* @zh_CN * @zh_CN
*/ */
const isSideNav = computed(() => appPreferences.value.layout === 'side-nav'); const isSideNav = computed(
() => appPreferences.value.layout === 'sidebar-nav',
);
/** /**
* @zh_CN * @zh_CN
*/ */
const isSideMixedNav = computed( const isSideMixedNav = computed(
() => appPreferences.value.layout === 'side-mixed-nav', () => appPreferences.value.layout === 'sidebar-mixed-nav',
); );
/** /**

View File

@ -4,8 +4,8 @@ type LayoutType =
| 'full-content' | 'full-content'
| 'header-nav' | 'header-nav'
| 'mixed-nav' | 'mixed-nav'
| 'side-mixed-nav' | 'sidebar-mixed-nav'
| 'side-nav'; | 'sidebar-nav';
type ThemeModeType = 'auto' | 'dark' | 'light'; type ThemeModeType = 'auto' | 'dark' | 'light';

View File

@ -41,12 +41,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@vben-core/design": "workspace:*",
"@vben-core/iconify": "workspace:*", "@vben-core/iconify": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*", "@vben-core/shadcn-ui": "workspace:*",
"@vben-core/toolkit": "workspace:*",
"@vben-core/typings": "workspace:*", "@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.10.0", "@vueuse/core": "^10.10.1",
"vue": "3.4.27" "vue": "3.4.27"
} }
} }

View File

@ -1,5 +1,5 @@
export { default as LayoutContent } from './layout-content.vue'; export { default as LayoutContent } from './layout-content.vue';
export { default as LayoutFooter } from './layout-footer.vue'; export { default as LayoutFooter } from './layout-footer.vue';
export { default as LayoutHeader } from './layout-header.vue'; export { default as LayoutHeader } from './layout-header.vue';
export { default as LayoutSide } from './layout-side.vue'; export { default as LayoutSidebar } from './layout-sidebar.vue';
export { default as LayoutTabs } from './layout-tabs.vue'; export { default as LayoutTabbar } from './layout-tabbar.vue';

View File

@ -42,8 +42,6 @@ interface Props {
paddingTop?: number; paddingTop?: number;
} }
defineOptions({ name: 'LayoutContent' });
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
contentCompact: 'wide', contentCompact: 'wide',
contentCompactWidth: 1200, contentCompactWidth: 1200,
@ -65,7 +63,9 @@ const style = computed((): CSSProperties => {
} = props; } = props;
const compactStyle: CSSProperties = const compactStyle: CSSProperties =
contentCompact === 'compact' ? { margin: '0 auto', width: `1200px` } : {}; contentCompact === 'compact'
? { margin: '0 auto', width: `${props.contentCompactWidth}px` }
: {};
return { return {
...compactStyle, ...compactStyle,
flex: 1, flex: 1,

View File

@ -2,8 +2,6 @@
import type { CSSProperties } from 'vue'; import type { CSSProperties } from 'vue';
import { computed } from 'vue'; import { computed } from 'vue';
import { useNamespace } from '@vben-core/toolkit';
interface Props { interface Props {
/** /**
* 背景颜色 * 背景颜色
@ -36,8 +34,6 @@ interface Props {
zIndex?: number; zIndex?: number;
} }
defineOptions({ name: 'LayoutFooter' });
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
backgroundColor: 'hsl(var(--color-background))', backgroundColor: 'hsl(var(--color-background))',
fixed: true, fixed: true,
@ -47,8 +43,6 @@ const props = withDefaults(defineProps<Props>(), {
zIndex: 0, zIndex: 0,
}); });
const { b } = useNamespace('footer');
const style = computed((): CSSProperties => { const style = computed((): CSSProperties => {
const { backgroundColor, fixed, height, show, width, zIndex } = props; const { backgroundColor, fixed, height, show, width, zIndex } = props;
return { return {
@ -63,11 +57,7 @@ const style = computed((): CSSProperties => {
</script> </script>
<template> <template>
<footer <footer :style="style" class="bottom-0 w-full transition-all duration-200">
:class="b()"
:style="style"
class="bottom-0 w-full transition-all duration-200"
>
<slot></slot> <slot></slot>
</footer> </footer>
</template> </template>

View File

@ -41,15 +41,12 @@ interface Props {
* @default true * @default true
*/ */
showToggleBtn?: boolean; showToggleBtn?: boolean;
/**
* 侧边是否显示
*/
sideHidden?: boolean;
/** /**
* 侧边菜单宽度 * 侧边菜单宽度
* @default 0 * @default 0
*/ */
sideWidth?: number; sidebarWidth?: number;
/** /**
* 宽度 * 宽度
* @default 100% * @default 100%
@ -62,8 +59,6 @@ interface Props {
zIndex?: number; zIndex?: number;
} }
defineOptions({ name: 'LayoutHeader' });
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
backgroundColor: 'hsl(var(--color-background))', backgroundColor: 'hsl(var(--color-background))',
// fixed: true, // fixed: true,
@ -71,12 +66,12 @@ const props = withDefaults(defineProps<Props>(), {
isMixedNav: false, isMixedNav: false,
show: true, show: true,
showToggleBtn: false, showToggleBtn: false,
sideWidth: 0, sidebarWidth: 0,
width: '100%', width: '100%',
zIndex: 0, zIndex: 0,
}); });
const emit = defineEmits<{ openMenu: []; toggleMenu: [] }>(); const emit = defineEmits<{ openMenu: []; toggleSidebar: [] }>();
const slots = useSlots(); const slots = useSlots();
@ -95,16 +90,16 @@ const style = computed((): CSSProperties => {
const logoStyle = computed((): CSSProperties => { const logoStyle = computed((): CSSProperties => {
return { return {
minWidth: `${props.isMobile ? 40 : props.sideWidth}px`, minWidth: `${props.isMobile ? 40 : props.sidebarWidth}px`,
}; };
}); });
function handleToggleMenu() { function handleToggleMenu() {
emit('toggleMenu'); if (props.isMobile) {
} emit('openMenu');
} else {
function handleOpenMenu() { emit('toggleSidebar');
emit('openMenu'); }
} }
</script> </script>
@ -117,21 +112,12 @@ function handleOpenMenu() {
<slot name="logo"></slot> <slot name="logo"></slot>
</div> </div>
<VbenIconButton <VbenIconButton
v-if="showToggleBtn" v-if="showToggleBtn || isMobile"
class="my-0 ml-2 mr-1 rounded" class="my-0 ml-2 mr-1 rounded"
@click="handleToggleMenu" @click="handleToggleMenu"
> >
<IcRoundMenu class="size-5" /> <IcRoundMenu class="size-5" />
</VbenIconButton> </VbenIconButton>
<VbenIconButton
v-if="isMobile"
class="my-0 ml-2 mr-1 rounded"
@click="handleOpenMenu"
>
<IcRoundMenu class="size-5" />
</VbenIconButton>
<slot></slot> <slot></slot>
</header> </header>
</template> </template>

View File

@ -1,12 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { CSSProperties } from 'vue'; import type { CSSProperties } from 'vue';
// import { onClickOutside } from '@vueuse/core'; import { computed, shallowRef, useSlots, watchEffect } from 'vue';
import { computed, ref, shallowRef, useSlots, watchEffect } from 'vue';
import { ScrollArea } from '@vben-core/shadcn-ui'; import { VbenScrollbar } from '@vben-core/shadcn-ui';
import { useNamespace } from '@vben-core/toolkit';
import { SideCollapseButton, SidePinButton } from './widgets'; import { SidebarCollapseButton, SidebarFixedButton } from './widgets';
interface Props { interface Props {
/** /**
@ -50,7 +48,7 @@ interface Props {
* 是否侧边混合模式 * 是否侧边混合模式
* @default false * @default false
*/ */
isSideMixed?: boolean; isSidebarMixed?: boolean;
/** /**
* 混合菜单宽度 * 混合菜单宽度
* @default 80 * @default 80
@ -88,8 +86,6 @@ interface Props {
zIndex?: number; zIndex?: number;
} }
defineOptions({ name: 'LayoutSide' });
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
collapseHeight: 42, collapseHeight: 42,
collapseWidth: 48, collapseWidth: 48,
@ -113,11 +109,9 @@ const expandOnHovering = defineModel<boolean>('expandOnHovering');
const expandOnHover = defineModel<boolean>('expandOnHover'); const expandOnHover = defineModel<boolean>('expandOnHover');
const extraVisible = defineModel<boolean>('extraVisible'); const extraVisible = defineModel<boolean>('extraVisible');
const { b, e, is } = useNamespace('side');
const slots = useSlots(); const slots = useSlots();
const asideRef = shallowRef<HTMLDivElement | null>(); const asideRef = shallowRef<HTMLDivElement | null>();
const scrolled = ref(false);
const hiddenSideStyle = computed((): CSSProperties => { const hiddenSideStyle = computed((): CSSProperties => {
return calcMenuWidthStyle(true); return calcMenuWidthStyle(true);
@ -244,54 +238,51 @@ function handleMouseleave() {
collapse.value = true; collapse.value = true;
extraVisible.value = false; extraVisible.value = false;
} }
function handleScroll(event: Event) {
const target = event.target as HTMLElement;
scrolled.value = (target?.scrollTop ?? 0) > 0;
}
</script> </script>
<template> <template>
<div v-if="domVisible" :class="e('hide')" :style="hiddenSideStyle"></div> <div
v-if="domVisible"
:style="hiddenSideStyle"
class="h-full transition-all duration-200"
></div>
<aside <aside
:class="[b(), is(theme, true)]"
:style="style" :style="style"
class="fixed left-0 top-0 h-full transition-all duration-200"
@mouseenter="handleMouseenter" @mouseenter="handleMouseenter"
@mouseleave="handleMouseleave" @mouseleave="handleMouseleave"
> >
<SidePinButton <SidebarFixedButton
v-if="!collapse && !isSideMixed" v-if="!collapse && !isSidebarMixed"
v-model:expand-on-hover="expandOnHover" v-model:expand-on-hover="expandOnHover"
:theme="theme" :theme="theme"
/> />
<div v-if="slots.logo" :style="headerStyle"> <div v-if="slots.logo" :style="headerStyle">
<slot name="logo"></slot> <slot name="logo"></slot>
</div> </div>
<ScrollArea :on-scroll="handleScroll" :style="contentStyle"> <VbenScrollbar :style="contentStyle">
<div :class="[e('shadow'), { scrolled }]"></div>
<slot></slot> <slot></slot>
</ScrollArea> </VbenScrollbar>
<div :style="collapseStyle"></div> <div :style="collapseStyle"></div>
<SideCollapseButton <SidebarCollapseButton
v-if="showCollapseButton && !isSideMixed" v-if="showCollapseButton && !isSidebarMixed"
v-model:collapse="collapse" v-model:collapsed="collapse"
:theme="theme" :theme="theme"
/> />
<div <div
v-if="isSideMixed" v-if="isSidebarMixed"
ref="asideRef" ref="asideRef"
:class="e('extra')"
:style="extraStyle" :style="extraStyle"
class="transition-[width] duration-200" class="fixed top-0 h-full overflow-hidden transition-all duration-200"
> >
<SideCollapseButton <SidebarCollapseButton
v-if="isSideMixed && expandOnHover" v-if="isSidebarMixed && expandOnHover"
v-model:collapse="extraCollapse" v-model:collapsed="extraCollapse"
:theme="theme" :theme="theme"
/> />
<SidePinButton <SidebarFixedButton
v-if="!extraCollapse" v-if="!extraCollapse"
v-model:expand-on-hover="expandOnHover" v-model:expand-on-hover="expandOnHover"
:theme="theme" :theme="theme"
@ -299,79 +290,49 @@ function handleScroll(event: Event) {
<div v-if="!extraCollapse" :style="extraTitleStyle"> <div v-if="!extraCollapse" :style="extraTitleStyle">
<slot name="extra-title"></slot> <slot name="extra-title"></slot>
</div> </div>
<ScrollArea <VbenScrollbar :style="extraContentStyle" class="py-4">
:class="e('extra-content')"
:on-scroll="handleScroll"
:style="extraContentStyle"
>
<div :class="[e('shadow'), { scrolled }]"></div>
<slot name="extra"></slot> <slot name="extra"></slot>
</ScrollArea> </VbenScrollbar>
</div> </div>
</aside> </aside>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
@import '@vben-core/design/global'; // @include b('sidebar') {
// --color-surface: var(--color-menu);
@include b('side') { // @include is('dark') {
--color-surface: var(--color-menu); // --color-surface: var(--color-menu-dark);
// }
position: fixed; // @include e('shadow') {
top: 0; // position: absolute;
left: 0; // top: 0;
height: 100%; // z-index: 1;
transition: all 0.2s ease 0s; // inline-size: 100%;
// block-size: 40px;
// height: 50px;
// pointer-events: none;
// background: linear-gradient(
// to bottom,
// hsl(var(--color-surface)),
// transparent
// );
// opacity: 0;
// transition: opacity 0.15s ease-in-out;
// will-change: opacity;
@include is('dark') { // &.scrolled {
--color-surface: var(--color-menu-dark); // opacity: 1;
} // }
// }
@include e('shadow') { // @include is('dark') {
position: absolute; // .#{$namespace}-side__extra {
top: 0; // &-content {
z-index: 1; // border-color: hsl(var(--color-dark-border)) !important;
inline-size: 100%; // }
block-size: 40px; // }
height: 50px; // }
pointer-events: none; // }
background: linear-gradient(
to bottom,
hsl(var(--color-surface)),
transparent
);
opacity: 0;
transition: opacity 0.15s ease-in-out;
will-change: opacity;
&.scrolled {
opacity: 1;
}
}
@include is('dark') {
.#{$namespace}-side__extra {
&-content {
border-color: hsl(var(--color-dark-border)) !important;
}
}
}
@include e('hide') {
height: 100%;
transition: all 0.2s ease 0s;
}
@include e('extra') {
position: fixed;
top: 0;
height: 100%;
overflow: hidden;
transition: all 0.2s ease 0s;
&-content {
padding: 4px 0;
}
}
}
</style> </style>

View File

@ -14,8 +14,6 @@ interface Props {
height?: number; height?: number;
} }
defineOptions({ name: 'LayoutTabs' });
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
backgroundColor: 'hsl(var(--color-background))', backgroundColor: 'hsl(var(--color-background))',
fixed: true, fixed: true,
@ -34,7 +32,6 @@ const style = computed((): CSSProperties => {
return { return {
...hiddenStyle.value, ...hiddenStyle.value,
backgroundColor, backgroundColor,
display: 'flex',
}; };
}); });
</script> </script>

View File

@ -1,2 +1,2 @@
export { default as SideCollapseButton } from './side-collapse-button.vue'; export { default as SidebarCollapseButton } from './sidebar-collapse-button.vue';
export { default as SidePinButton } from './side-pin-button.vue'; export { default as SidebarFixedButton } from './sidebar-fixed-button.vue';

View File

@ -1,63 +0,0 @@
<script setup lang="ts">
import { MdiMenuClose, MdiMenuOpen } from '@vben-core/iconify';
import { useNamespace } from '@vben-core/toolkit';
interface Props {
theme: string;
}
defineOptions({ name: 'SideCollapseButton' });
withDefaults(defineProps<Props>(), {});
const collapse = defineModel<boolean>('collapse');
const { b, is } = useNamespace('side-collapse');
function handleCollapse() {
collapse.value = !collapse.value;
}
</script>
<template>
<div :class="[b(), is(theme, true)]" @click.stop="handleCollapse">
<MdiMenuClose v-if="collapse" />
<MdiMenuOpen v-else />
</div>
</template>
<style scoped lang="scss">
@import '@vben-core/design/global';
@include b('side-collapse') {
position: absolute;
bottom: 6px;
left: 10px;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
color: hsl(var(--color-foreground) / 60%);
cursor: pointer;
background: hsl(var(--color-accent)) !important;
border-radius: 4px;
opacity: 1;
transition: all 0.3s ease;
@include is('dark') {
color: hsl(var(--color-dark-foreground) / 60%) !important;
background: hsl(var(--color-dark-accent)) !important;
&:hover {
color: hsl(var(--color-dark-foreground)) !important;
background: hsl(var(--color-dark-accent-hover)) !important;
}
}
&:hover {
color: hsl(var(--color-foreground));
background: hsl(var(--color-accent-hover));
}
}
</style>

View File

@ -1,64 +0,0 @@
<script setup lang="ts">
import { MdiPin, MdiPinOff } from '@vben-core/iconify';
import { useNamespace } from '@vben-core/toolkit';
interface Props {
theme: string;
}
defineOptions({ name: 'SidePinButton' });
withDefaults(defineProps<Props>(), {});
const expandOnHover = defineModel<boolean>('expandOnHover');
const { b, is } = useNamespace('side-pin');
function togglePined() {
expandOnHover.value = !expandOnHover.value;
}
</script>
<template>
<div :class="[b(), is(theme, true)]" @click="togglePined">
<MdiPinOff v-if="!expandOnHover" />
<MdiPin v-else />
</div>
</template>
<style scoped lang="scss">
@import '@vben-core/design/global';
@include b('side-pin') {
position: absolute;
right: 10px;
bottom: 6px;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
color: hsl(var(--color-foreground) / 60%);
cursor: pointer;
background: hsl(var(--color-accent)) !important;
border-radius: 4px;
opacity: 1;
transition: all 0.3s ease;
@include is('dark') {
color: hsl(var(--color-dark-foreground) / 60%) !important;
background: unset;
background: hsl(var(--color-dark-accent)) !important;
&:hover {
color: hsl(var(--color-dark-foreground)) !important;
background: hsl(var(--color-dark-accent-hover)) !important;
}
}
&:hover {
color: hsl(var(--color-foreground));
background: hsl(var(--color-accent-hover));
}
}
</style>

View File

@ -0,0 +1,26 @@
<script setup lang="ts">
import { MdiMenuClose, MdiMenuOpen } from '@vben-core/iconify';
interface Props {
theme: string;
}
withDefaults(defineProps<Props>(), {});
const collapsed = defineModel<boolean>('collapsed');
function handleCollapsed() {
collapsed.value = !collapsed.value;
}
</script>
<template>
<div
:data-theme="theme"
class="flex-center hover:text-foreground text-foreground/60 hover:bg-accent-hover bg-accent absolute bottom-2 left-3 z-10 cursor-pointer rounded-sm p-1 transition-all duration-300 data-[theme=dark]:bg-[hsl(var(--color-dark-accent))] data-[theme=dark]:text-[hsl(var(--color-dark-foreground)/60%)] data-[theme=dark]:hover:bg-[hsl(var(--color-dark-accent-hover))] data-[theme=dark]:hover:text-[hsl(var(--color-dark-foreground))]"
@click.stop="handleCollapsed"
>
<MdiMenuClose v-if="collapsed" />
<MdiMenuOpen v-else />
</div>
</template>

View File

@ -0,0 +1,26 @@
<script setup lang="ts">
import { MdiPin, MdiPinOff } from '@vben-core/iconify';
interface Props {
theme: string;
}
withDefaults(defineProps<Props>(), {});
const expandOnHover = defineModel<boolean>('expandOnHover');
function toggleFixed() {
expandOnHover.value = !expandOnHover.value;
}
</script>
<template>
<div
:data-theme="theme"
class="flex-center hover:text-foreground text-foreground/60 hover:bg-accent-hover bg-accent absolute bottom-2 right-3 z-10 cursor-pointer rounded-sm p-1 transition-all duration-300 data-[theme=dark]:bg-[hsl(var(--color-dark-accent))] data-[theme=dark]:text-[hsl(var(--color-dark-foreground)/60%)] data-[theme=dark]:hover:bg-[hsl(var(--color-dark-accent-hover))] data-[theme=dark]:hover:text-[hsl(var(--color-dark-foreground))]"
@click="toggleFixed"
>
<MdiPinOff v-if="!expandOnHover" />
<MdiPin v-else />
</div>
</template>

View File

@ -99,64 +99,64 @@ interface VbenLayoutProps {
isMobile?: boolean; isMobile?: boolean;
/** /**
* *
* side-nav * sidebar-nav
* header-nav * header-nav
* mixed-nav & * mixed-nav &
* side-mixed-nav * sidebar-mixed-nav
* full-content * full-content
* @default side-nav * @default sidebar-nav
*/ */
layout?: LayoutType; layout?: LayoutType;
/**
*
* @default false
*/
sideCollapse?: boolean;
/**
* title
* @default true
*/
sideCollapseShowTitle?: boolean;
/** /**
* *
* @default 48 * @default 48
*/ */
sideCollapseWidth?: number; sideCollapseWidth?: number;
/** /**
* *
* @default false * @default false
*/ */
sideHidden?: boolean; sidebarCollapse?: boolean;
/** /**
* * title
* @default false * @default true
*/ */
sideMixedExtraVisible?: boolean; sidebarCollapseShowTitle?: boolean;
/**
*
* @default 80
*/
sideMixedWidth?: number;
/**
*
* @default false
*/
sideSemiDark?: boolean;
/**
*
* @default dark
*/
sideTheme?: ThemeModeType;
/** /**
* *
* @default true * @default true
*/ */
sideVisible?: boolean; sidebarEnable?: boolean;
/**
*
* @default false
*/
sidebarHidden?: boolean;
/**
*
* @default 80
*/
sidebarMixedWidth?: number;
/**
*
* @default false
*/
sidebarSemiDark?: boolean;
/**
*
* @default dark
*/
sidebarTheme?: ThemeModeType;
/** /**
* *
* @default 210 * @default 210
*/ */
sideWidth?: number; sidebarWidth?: number;
/**
* tab
* @default true
*/
tabbarEnable?: boolean;
/** /**
* footer * footer
* @default #fff * @default #fff
@ -167,11 +167,6 @@ interface VbenLayoutProps {
* @default 30 * @default 30
*/ */
tabsHeight?: number; tabsHeight?: number;
/**
* tab
* @default true
*/
tabsVisible?: boolean;
/** /**
* zIndex * zIndex
* @default 100 * @default 100

View File

@ -8,8 +8,8 @@ import {
LayoutContent, LayoutContent,
LayoutFooter, LayoutFooter,
LayoutHeader, LayoutHeader,
LayoutSide, LayoutSidebar,
LayoutTabs, LayoutTabbar,
} from './components'; } from './components';
import { VbenLayoutProps } from './vben-layout'; import { VbenLayoutProps } from './vben-layout';
@ -38,27 +38,27 @@ const props = withDefaults(defineProps<Props>(), {
headerMode: 'fixed', headerMode: 'fixed',
headerVisible: true, headerVisible: true,
isMobile: false, isMobile: false,
layout: 'side-nav', layout: 'sidebar-nav',
sideCollapseShowTitle: false,
// sideCollapse: false, // sideCollapse: false,
sideCollapseWidth: 60, sideCollapseWidth: 60,
sideHidden: false, sidebarCollapseShowTitle: false,
sideMixedWidth: 80, sidebarHidden: false,
sideSemiDark: true, sidebarMixedWidth: 80,
sideTheme: 'dark', sidebarSemiDark: true,
sideWidth: 180, sidebarTheme: 'dark',
sidebarWidth: 180,
tabbarEnable: true,
// tabsBackgroundColor: 'hsl(var(--color-background))', // tabsBackgroundColor: 'hsl(var(--color-background))',
tabsHeight: 36, tabsHeight: 36,
tabsVisible: true,
zIndex: 200, zIndex: 200,
}); });
const emit = defineEmits<{ sideMouseLeave: [] }>(); const emit = defineEmits<{ sideMouseLeave: []; toggleSidebar: [] }>();
const sideCollapse = defineModel<boolean>('sideCollapse'); const sidebarCollapse = defineModel<boolean>('sidebarCollapse');
const sideExtraVisible = defineModel<boolean>('sideExtraVisible'); const sidebarExtraVisible = defineModel<boolean>('sidebarExtraVisible');
const sideExtraCollapse = defineModel<boolean>('sideExtraCollapse'); const sidebarExtraCollapse = defineModel<boolean>('sidebarExtraCollapse');
const sideExpandOnHover = defineModel<boolean>('sideExpandOnHover'); const sidebarExpandOnHover = defineModel<boolean>('sidebarExpandOnHover');
const sideVisible = defineModel<boolean>('sideVisible', { default: true }); const sidebarEnable = defineModel<boolean>('sidebarEnable', { default: true });
const { const {
arrivedState, arrivedState,
@ -69,12 +69,12 @@ const {
const { y: mouseY } = useMouse({ type: 'client' }); const { y: mouseY } = useMouse({ type: 'client' });
// sidehover // sidehover
const sideExpandOnHovering = ref(false); const sidebarExpandOnHovering = ref(false);
// const sideHidden = ref(false); // const sideHidden = ref(false);
const headerIsHidden = ref(false); const headerIsHidden = ref(false);
const realLayout = computed(() => { const realLayout = computed(() => {
return props.isMobile ? 'side-nav' : props.layout; return props.isMobile ? 'sidebar-nav' : props.layout;
}); });
/** /**
@ -85,7 +85,9 @@ const fullContent = computed(() => realLayout.value === 'full-content');
/** /**
* 是否侧边混合模式 * 是否侧边混合模式
*/ */
const isSideMixedNav = computed(() => realLayout.value === 'side-mixed-nav'); const isSidebarMixedNav = computed(
() => realLayout.value === 'sidebar-mixed-nav',
);
/** /**
* 是否为头部导航模式 * 是否为头部导航模式
@ -123,25 +125,25 @@ const headerWrapperHeight = computed(() => {
if (props.headerVisible && !props.headerHidden) { if (props.headerVisible && !props.headerHidden) {
height += getHeaderHeight.value; height += getHeaderHeight.value;
} }
if (props.tabsVisible) { if (props.tabbarEnable) {
height += props.tabsHeight; height += props.tabsHeight;
} }
return height; return height;
}); });
const getSideCollapseWidth = computed(() => { const getSideCollapseWidth = computed(() => {
const { sideCollapseShowTitle, sideCollapseWidth, sideMixedWidth } = props; const { sideCollapseWidth, sidebarCollapseShowTitle, sidebarMixedWidth } =
return sideCollapseShowTitle || isSideMixedNav props;
? sideMixedWidth return sidebarCollapseShowTitle || isSidebarMixedNav.value
? sidebarMixedWidth
: sideCollapseWidth; : sideCollapseWidth;
}); });
/** /**
* 动态获取侧边区域是否可见 * 动态获取侧边区域是否可见
*/ */
const sideVisibleState = computed(() => { const sidebarEnableState = computed(() => {
return !isHeaderNav.value && sideVisible.value; return !isHeaderNav.value && sidebarEnable.value;
}); });
/** /**
@ -155,27 +157,27 @@ const sidePaddingTop = computed(() => {
/** /**
* 动态获取侧边宽度 * 动态获取侧边宽度
*/ */
const getSideWidth = computed(() => { const getSidebarWidth = computed(() => {
const { isMobile, sideHidden, sideMixedWidth, sideWidth } = props; const { isMobile, sidebarHidden, sidebarMixedWidth, sidebarWidth } = props;
let width = 0; let width = 0;
if (sideHidden) { if (sidebarHidden) {
return width; return width;
} }
if ( if (
!sideVisibleState.value || !sidebarEnableState.value ||
(sideHidden && !isSideMixedNav.value && !isMixedNav.value) (sidebarHidden && !isSidebarMixedNav.value && !isMixedNav.value)
) { ) {
return width; return width;
} }
if (isSideMixedNav.value && !isMobile) { if (isSidebarMixedNav.value && !isMobile) {
width = sideMixedWidth; width = sidebarMixedWidth;
} else if (sideCollapse.value) { } else if (sidebarCollapse.value) {
width = isMobile ? 0 : getSideCollapseWidth.value; width = isMobile ? 0 : getSideCollapseWidth.value;
} else { } else {
width = sideWidth; width = sidebarWidth;
} }
return width; return width;
}); });
@ -184,37 +186,37 @@ const getSideWidth = computed(() => {
* 获取扩展区域宽度 * 获取扩展区域宽度
*/ */
const getExtraWidth = computed(() => { const getExtraWidth = computed(() => {
const { sideWidth } = props; const { sidebarWidth } = props;
return sideExtraCollapse.value ? getSideCollapseWidth.value : sideWidth; return sidebarExtraCollapse.value ? getSideCollapseWidth.value : sidebarWidth;
}); });
/** /**
* 是否侧边栏模式包含混合侧边 * 是否侧边栏模式包含混合侧边
*/ */
const isSideMode = computed(() => const isSideMode = computed(() =>
['mixed-nav', 'side-mixed-nav', 'side-nav'].includes(realLayout.value), ['mixed-nav', 'sidebar-mixed-nav', 'sidebar-nav'].includes(realLayout.value),
); );
const showSide = computed(() => { const showSidebar = computed(() => {
// if (isMixedNav.value && !props.sideHidden) { // if (isMixedNav.value && !props.sideHidden) {
// return false; // return false;
// } // }
return isSideMode.value && sideVisible.value; return isSideMode.value && sidebarEnable.value;
}); });
const sideFace = computed(() => { const sidebarFace = computed(() => {
const { sideSemiDark, sideTheme } = props; const { sidebarSemiDark, sidebarTheme } = props;
const isDark = sideTheme === 'dark' || sideSemiDark; const isDark = sidebarTheme === 'dark' || sidebarSemiDark;
let backgroundColor = ''; let backgroundColor = '';
let extraBackgroundColor = ''; let extraBackgroundColor = '';
if (isDark) { if (isDark) {
backgroundColor = isSideMixedNav.value backgroundColor = isSidebarMixedNav.value
? 'hsl(var(--color-menu-dark-darken))' ? 'hsl(var(--color-menu-dark-darken))'
: 'hsl(var(--color-menu-dark))'; : 'hsl(var(--color-menu-dark))';
} else { } else {
backgroundColor = isSideMixedNav.value backgroundColor = isSidebarMixedNav.value
? 'hsl(var(--color-menu-darken))' ? 'hsl(var(--color-menu-darken))'
: 'hsl(var(--color-menu))'; : 'hsl(var(--color-menu))';
} }
@ -233,7 +235,7 @@ const sideFace = computed(() => {
/** /**
* 遮罩可见性 * 遮罩可见性
*/ */
const maskVisible = computed(() => !sideCollapse.value && props.isMobile); const maskVisible = computed(() => !sidebarCollapse.value && props.isMobile);
/** /**
* header fixed值 * header fixed值
@ -247,53 +249,55 @@ const headerFixed = computed(() => {
const mainStyle = computed(() => { const mainStyle = computed(() => {
let width = '100%'; let width = '100%';
let sidebarWidth = 'unset'; let sidebarAndExtraWidth = 'unset';
if ( if (
headerFixed.value && headerFixed.value &&
!['header-nav', 'mixed-nav'].includes(realLayout.value) && !['header-nav', 'mixed-nav'].includes(realLayout.value) &&
showSide.value && showSidebar.value &&
!props.isMobile !props.isMobile
) { ) {
// pin // fixed
const isSideNavEffective = const isSideNavEffective =
isSideMixedNav.value && sideExpandOnHover.value && sideExtraVisible.value; isSidebarMixedNav.value &&
sidebarExpandOnHover.value &&
sidebarExtraVisible.value;
if (isSideNavEffective) { if (isSideNavEffective) {
const sideCollapseWidth = sideCollapse.value const sideCollapseWidth = sidebarCollapse.value
? getSideCollapseWidth.value ? getSideCollapseWidth.value
: props.sideMixedWidth; : props.sidebarMixedWidth;
const sideWidth = sideExtraCollapse.value const sideWidth = sidebarExtraCollapse.value
? getSideCollapseWidth.value ? getSideCollapseWidth.value
: props.sideWidth; : props.sidebarWidth;
// 100% - - // 100% - -
sidebarWidth = `${sideCollapseWidth + sideWidth}px`; sidebarAndExtraWidth = `${sideCollapseWidth + sideWidth}px`;
width = `calc(100% - ${sidebarWidth})`; width = `calc(100% - ${sidebarAndExtraWidth})`;
} else { } else {
sidebarWidth = sidebarAndExtraWidth =
sideExpandOnHovering.value && !sideExpandOnHover.value sidebarExpandOnHovering.value && !sidebarExpandOnHover.value
? `${getSideCollapseWidth.value}px` ? `${getSideCollapseWidth.value}px`
: `${getSideWidth.value}px`; : `${getSidebarWidth.value}px`;
width = `calc(100% - ${sidebarWidth})`; width = `calc(100% - ${sidebarAndExtraWidth})`;
} }
} }
return { return {
sidebarWidth, sidebarAndExtraWidth,
width, width,
}; };
}); });
const tabsStyle = computed((): CSSProperties => { const tabbarStyle = computed((): CSSProperties => {
let width = ''; let width = '';
let marginLeft = 0; let marginLeft = 0;
if (!isMixedNav.value) { if (!isMixedNav.value) {
width = '100%'; width = '100%';
} else if (sideVisible.value) { } else if (sidebarEnable.value) {
marginLeft = sideCollapse.value marginLeft = sidebarCollapse.value
? getSideCollapseWidth.value ? getSideCollapseWidth.value
: props.sideWidth; : props.sidebarWidth;
width = `calc(100% - ${getSideWidth.value}px)`; width = `calc(100% - ${getSidebarWidth.value}px)`;
} else { } else {
width = '100%'; width = '100%';
} }
@ -304,14 +308,6 @@ const tabsStyle = computed((): CSSProperties => {
}; };
}); });
const footerWidth = computed(() => {
if (!props.footerFixed) {
return '100%';
}
return mainStyle.value.width;
});
const contentStyle = computed((): CSSProperties => { const contentStyle = computed((): CSSProperties => {
const fixed = headerFixed.value; const fixed = headerFixed.value;
@ -337,7 +333,7 @@ const headerWrapperStyle = computed((): CSSProperties => {
const fixed = headerFixed.value; const fixed = headerFixed.value;
return { return {
height: fullContent.value ? '0' : `${headerWrapperHeight.value}px`, height: fullContent.value ? '0' : `${headerWrapperHeight.value}px`,
left: isMixedNav.value ? 0 : mainStyle.value.sidebarWidth, left: isMixedNav.value ? 0 : mainStyle.value.sidebarAndExtraWidth,
position: fixed ? 'fixed' : 'static', position: fixed ? 'fixed' : 'static',
top: top:
headerIsHidden.value || fullContent.value headerIsHidden.value || fullContent.value
@ -351,26 +347,31 @@ const headerWrapperStyle = computed((): CSSProperties => {
/** /**
* 侧边栏z-index * 侧边栏z-index
*/ */
const sideZIndex = computed(() => { const sidebarZIndex = computed(() => {
const { isMobile, zIndex } = props; const { isMobile, zIndex } = props;
const offset = isMobile || isSideMode.value ? 1 : -1; const offset = isMobile || isSideMode.value ? 1 : -1;
return zIndex + offset; return zIndex + offset;
}); });
const footerWidth = computed(() => {
if (!props.footerFixed) {
return '100%';
}
return mainStyle.value.width;
});
const maskStyle = computed((): CSSProperties => { const maskStyle = computed((): CSSProperties => {
return { return { zIndex: props.zIndex };
zIndex: props.zIndex,
};
}); });
const showHeaderToggleButton = computed(() => { const showHeaderToggleButton = computed(() => {
return ( return (
isSideMode.value && isSideMode.value &&
!isSideMixedNav.value && !isSidebarMixedNav.value &&
!isMixedNav.value && !isMixedNav.value &&
!props.isMobile !props.isMobile
); );
// return false;
}); });
const showHeaderLogo = computed(() => { const showHeaderLogo = computed(() => {
@ -380,7 +381,7 @@ const showHeaderLogo = computed(() => {
watch( watch(
() => props.isMobile, () => props.isMobile,
(val) => { (val) => {
sideCollapse.value = val; sidebarCollapse.value = val;
}, },
); );
@ -445,49 +446,48 @@ watch(
} }
function handleClickMask() { function handleClickMask() {
sideCollapse.value = true; sidebarCollapse.value = true;
} }
function handleToggleMenu() { function handleToggleSidebar() {
// sideVisible.value = !sideVisible.value; emit('toggleSidebar');
// sideHidden.value = !sideHidden.value;
} }
function handleOpenMenu() { function handleOpenMenu() {
sideCollapse.value = false; sidebarCollapse.value = false;
} }
</script> </script>
<template> <template>
<div class="relative flex min-h-full w-full"> <div class="relative flex min-h-full w-full">
<slot name="preferences"></slot> <slot name="preferences"></slot>
<slot name="floating-button-group"></slot> <slot name="floating-groups"></slot>
<LayoutSide <LayoutSidebar
v-if="sideVisibleState" v-if="sidebarEnableState"
v-model:collapse="sideCollapse" v-model:collapse="sidebarCollapse"
v-model:expand-on-hover="sideExpandOnHover" v-model:expand-on-hover="sidebarExpandOnHover"
v-model:expand-on-hovering="sideExpandOnHovering" v-model:expand-on-hovering="sidebarExpandOnHovering"
v-model:extra-collapse="sideExtraCollapse" v-model:extra-collapse="sidebarExtraCollapse"
v-model:extra-visible="sideExtraVisible" v-model:extra-visible="sidebarExtraVisible"
:collapse-width="getSideCollapseWidth" :collapse-width="getSideCollapseWidth"
:dom-visible="!isMobile" :dom-visible="!isMobile"
:extra-width="getExtraWidth" :extra-width="getExtraWidth"
:fixed-extra="sideExpandOnHover" :fixed-extra="sidebarExpandOnHover"
:header-height="isMixedNav ? 0 : getHeaderHeight" :header-height="isMixedNav ? 0 : getHeaderHeight"
:is-side-mixed="isSideMixedNav" :is-sidebar-mixed="isSidebarMixedNav"
:mixed-width="sideMixedWidth" :mixed-width="sidebarMixedWidth"
:padding-top="sidePaddingTop" :padding-top="sidePaddingTop"
:show="showSide" :show="showSidebar"
:width="getSideWidth" :width="getSidebarWidth"
:z-index="sideZIndex" :z-index="sidebarZIndex"
v-bind="sideFace" v-bind="sidebarFace"
@leave="() => emit('sideMouseLeave')" @leave="() => emit('sideMouseLeave')"
> >
<template v-if="isSideMode && !isMixedNav" #logo> <template v-if="isSideMode && !isMixedNav" #logo>
<slot name="logo"></slot> <slot name="logo"></slot>
</template> </template>
<template v-if="isSideMixedNav"> <template v-if="isSidebarMixedNav">
<slot name="mixed-menu"></slot> <slot name="mixed-menu"></slot>
</template> </template>
<template v-else> <template v-else>
@ -500,7 +500,7 @@ function handleOpenMenu() {
<template #extra-title> <template #extra-title>
<slot name="side-extra-title"></slot> <slot name="side-extra-title"></slot>
</template> </template>
</LayoutSide> </LayoutSidebar>
<div <div
class="flex flex-1 flex-col overflow-hidden transition-all duration-300 ease-in" class="flex flex-1 flex-col overflow-hidden transition-all duration-300 ease-in"
@ -517,12 +517,11 @@ function handleOpenMenu() {
:is-mobile="isMobile" :is-mobile="isMobile"
:show="!fullContent && !headerHidden" :show="!fullContent && !headerHidden"
:show-toggle-btn="showHeaderToggleButton" :show-toggle-btn="showHeaderToggleButton"
:side-hidden="sideHidden" :sidebar-width="sidebarWidth"
:side-width="sideWidth"
:width="mainStyle.width" :width="mainStyle.width"
:z-index="headerZIndex" :z-index="headerZIndex"
@open-menu="handleOpenMenu" @open-menu="handleOpenMenu"
@toggle-menu="handleToggleMenu" @toggle-sidebar="handleToggleSidebar"
> >
<template v-if="showHeaderLogo" #logo> <template v-if="showHeaderLogo" #logo>
<slot name="logo"></slot> <slot name="logo"></slot>
@ -530,12 +529,16 @@ function handleOpenMenu() {
<slot name="header"></slot> <slot name="header"></slot>
</LayoutHeader> </LayoutHeader>
<LayoutTabs v-if="tabsVisible" :height="tabsHeight" :style="tabsStyle"> <LayoutTabbar
<slot name="tabs"></slot> v-if="tabbarEnable"
:height="tabsHeight"
:style="tabbarStyle"
>
<slot name="tabbar"></slot>
<template #toolbar> <template #toolbar>
<slot name="tabs-toolbar"></slot> <slot name="tabbar-tools"></slot>
</template> </template>
</LayoutTabs> </LayoutTabbar>
</div> </div>
<!-- </div> --> <!-- </div> -->

View File

@ -46,7 +46,7 @@
"@vben-core/shadcn-ui": "workspace:*", "@vben-core/shadcn-ui": "workspace:*",
"@vben-core/toolkit": "workspace:*", "@vben-core/toolkit": "workspace:*",
"@vben-core/typings": "workspace:*", "@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.10.0", "@vueuse/core": "^10.10.1",
"vue": "3.4.27" "vue": "3.4.27"
} }
} }

View File

@ -50,7 +50,7 @@
"@vben-core/iconify": "workspace:*", "@vben-core/iconify": "workspace:*",
"@vben-core/toolkit": "workspace:*", "@vben-core/toolkit": "workspace:*",
"@vben-core/typings": "workspace:*", "@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.10.0", "@vueuse/core": "^10.10.1",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "2.1.1", "clsx": "2.1.1",
"radix-vue": "^1.8.3", "radix-vue": "^1.8.3",

View File

@ -17,6 +17,7 @@ export * from './logo';
export * from './menu-badge'; export * from './menu-badge';
export * from './pin-input'; export * from './pin-input';
export * from './popover'; export * from './popover';
export * from './scrollbar';
export * from './segmented'; export * from './segmented';
export * from './sheet'; export * from './sheet';
export * from './spinner'; export * from './spinner';

View File

@ -0,0 +1 @@
export { default as VbenScrollbar } from './scrollbar.vue';

View File

@ -0,0 +1,45 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue';
import { ref } from 'vue';
import { ScrollArea } from '#/components/ui/scroll-area';
import { cn } from '#/lib/utils';
interface Props {
class?: HTMLAttributes['class'];
}
const props = withDefaults(defineProps<Props>(), {
class: '',
});
const isAtTop = ref(true);
const isAtBottom = ref(false);
function handleScroll(event: Event) {
const target = event.target as HTMLElement;
const scrollTop = target?.scrollTop ?? 0;
const offsetHeight = target?.offsetHeight ?? 0;
const scrollHeight = target?.scrollHeight ?? 0;
isAtTop.value = scrollTop <= 0;
isAtBottom.value = scrollTop + offsetHeight >= scrollHeight;
}
</script>
<template>
<ScrollArea
:class="[
cn(props.class),
{
// 'shadow-none': isAtTop && isAtBottom,
// shadow: !isAtTop || !isAtBottom,
// 'dark:shadow-white/20': !isAtTop || !isAtBottom,
// 'shadow-inner': !isAtBottom,
// 'dark:shadow-inner-white/20': !isAtBottom,
},
]"
:on-scroll="handleScroll"
>
<slot></slot>
</ScrollArea>
</template>

View File

@ -4,7 +4,7 @@ import { computed, useSlots } from 'vue';
import { Cross2Icon } from '@radix-icons/vue'; import { Cross2Icon } from '@radix-icons/vue';
import { VbenButton, VbenIconButton } from '#/components/button'; import { VbenButton, VbenIconButton } from '#/components/button';
import { ScrollArea } from '#/components/ui/scroll-area'; import { VbenScrollbar } from '#/components/scrollbar';
import { import {
Sheet, Sheet,
SheetClose, SheetClose,
@ -89,9 +89,9 @@ function handlerSubmit() {
</SheetClose> </SheetClose>
</SheetHeader> </SheetHeader>
<div class="h-full pb-16"> <div class="h-full pb-16">
<ScrollArea class="h-full"> <VbenScrollbar class="h-full">
<slot></slot> <slot></slot>
</ScrollArea> </VbenScrollbar>
</div> </div>
<SheetFooter v-if="showFooter || slots.footer" as-child> <SheetFooter v-if="showFooter || slots.footer" as-child>
<div <div

View File

@ -1,3 +1 @@
export { default as ChromeTabs } from './chrome-tabs/tabs.vue'; export { default as ChromeTabs } from './chrome-tabs/tabs.vue';
export { default as TabsMore } from './tabs-more.vue';
export { default as TabsScreen } from './tabs-screen.vue';

View File

@ -1,3 +1,3 @@
export { TabsMore, TabsScreen } from './components';
export { default as TabsView } from './tabs-view.vue'; export { default as TabsView } from './tabs-view.vue';
export * from './widgets';
export type { IContextMenuItem } from '@vben-core/shadcn-ui'; export type { IContextMenuItem } from '@vben-core/shadcn-ui';

View File

@ -0,0 +1,2 @@
export { default as TabsToolMore } from './tool-more.vue';
export { default as TabsToolScreen } from './tool-screen.vue';

View File

@ -50,8 +50,8 @@
"@vben-core/shadcn-ui": "workspace:*", "@vben-core/shadcn-ui": "workspace:*",
"@vben-core/toolkit": "workspace:*", "@vben-core/toolkit": "workspace:*",
"@vben/locales": "workspace:*", "@vben/locales": "workspace:*",
"@vueuse/core": "^10.10.0", "@vueuse/core": "^10.10.1",
"@vueuse/integrations": "^10.10.0", "@vueuse/integrations": "^10.10.1",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"vue": "3.4.27", "vue": "3.4.27",
"vue-router": "^4.3.3" "vue-router": "^4.3.3"

View File

@ -6,7 +6,7 @@ import { useRouter } from 'vue-router';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { IcRoundClose, IcRoundSearchOff } from '@vben-core/iconify'; import { IcRoundClose, IcRoundSearchOff } from '@vben-core/iconify';
import { ScrollArea, VbenIcon } from '@vben-core/shadcn-ui'; import { VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui';
import { mapTree, traverseTreeValues } from '@vben-core/toolkit'; import { mapTree, traverseTreeValues } from '@vben-core/toolkit';
import { onKeyStroke, useLocalStorage, useThrottleFn } from '@vueuse/core'; import { onKeyStroke, useLocalStorage, useThrottleFn } from '@vueuse/core';
@ -214,7 +214,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<ScrollArea> <VbenScrollbar>
<div class="!flex h-full justify-center px-4 sm:max-h-[450px]"> <div class="!flex h-full justify-center px-4 sm:max-h-[450px]">
<!-- 无搜索结果 --> <!-- 无搜索结果 -->
<div <div
@ -275,5 +275,5 @@ onMounted(() => {
</li> </li>
</ul> </ul>
</div> </div>
</ScrollArea> </VbenScrollbar>
</template> </template>

View File

@ -7,10 +7,10 @@ import {
IcRoundNotificationsNone, IcRoundNotificationsNone,
} from '@vben-core/iconify'; } from '@vben-core/iconify';
import { import {
ScrollArea,
VbenButton, VbenButton,
VbenIconButton, VbenIconButton,
VbenPopover, VbenPopover,
VbenScrollbar,
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
import { useToggle } from '@vueuse/core'; import { useToggle } from '@vueuse/core';
@ -81,7 +81,7 @@ function handleClick(item: NotificationItem) {
</template> </template>
<div class="relative"> <div class="relative">
<div class="flex items-center justify-between border-b p-4 py-3"> <div class="flex items-center justify-between p-4 py-3">
<div class="text-foreground">{{ $t('widgets.notifications') }}</div> <div class="text-foreground">{{ $t('widgets.notifications') }}</div>
<VbenIconButton <VbenIconButton
:tooltip="$t('widgets.make-all-as-read')" :tooltip="$t('widgets.make-all-as-read')"
@ -90,11 +90,11 @@ function handleClick(item: NotificationItem) {
<IcRoundMarkEmailRead /> <IcRoundMarkEmailRead />
</VbenIconButton> </VbenIconButton>
</div> </div>
<ScrollArea v-if="notifications.length > 0"> <VbenScrollbar v-if="notifications.length > 0">
<ul class="!flex max-h-[360px] w-full flex-col"> <ul class="!flex max-h-[360px] w-full flex-col">
<template v-for="item in notifications" :key="item.title"> <template v-for="item in notifications" :key="item.title">
<li <li
class="hover:bg-accent relative flex w-full cursor-pointer items-start gap-5 border-t px-3 py-3" class="hover:bg-accent border-border relative flex w-full cursor-pointer items-start gap-5 border-t px-3 py-3"
@click="handleClick(item)" @click="handleClick(item)"
> >
<span <span
@ -123,7 +123,7 @@ function handleClick(item: NotificationItem) {
</li> </li>
</template> </template>
</ul> </ul>
</ScrollArea> </VbenScrollbar>
<template v-else> <template v-else>
<div class="flex-center text-muted-foreground min-h-[150px] w-full"> <div class="flex-center text-muted-foreground min-h-[150px] w-full">
@ -131,7 +131,9 @@ function handleClick(item: NotificationItem) {
</div> </div>
</template> </template>
<div class="flex items-center justify-between border-t px-4 py-3"> <div
class="border-border flex items-center justify-between border-t px-4 py-3"
>
<VbenButton size="sm" variant="ghost" @click="handleClear"> <VbenButton size="sm" variant="ghost" @click="handleClear">
{{ $t('widgets.clear-notifications') }} {{ $t('widgets.clear-notifications') }}
</VbenButton> </VbenButton>

View File

@ -11,8 +11,8 @@ import {
FullContent, FullContent,
HeaderNav, HeaderNav,
MixedNav, MixedNav,
SideMixedNav, SidebarMixedNav,
SideNav, SidebarNav,
} from '../../icons'; } from '../../icons';
interface PresetItem { interface PresetItem {
@ -25,26 +25,26 @@ defineOptions({
name: 'PreferenceLayout', name: 'PreferenceLayout',
}); });
const modelValue = defineModel<LayoutType>({ default: 'side-nav' }); const modelValue = defineModel<LayoutType>({ default: 'sidebar-nav' });
const components: Record<LayoutType, Component> = { const components: Record<LayoutType, Component> = {
'full-content': FullContent, 'full-content': FullContent,
'header-nav': HeaderNav, 'header-nav': HeaderNav,
'mixed-nav': MixedNav, 'mixed-nav': MixedNav,
'side-mixed-nav': SideMixedNav, 'sidebar-mixed-nav': SidebarMixedNav,
'side-nav': SideNav, 'sidebar-nav': SidebarNav,
}; };
const PRESET = computed((): PresetItem[] => [ const PRESET = computed((): PresetItem[] => [
{ {
name: $t('preference.vertical'), name: $t('preference.vertical'),
tip: $t('preference.vertical-tip'), tip: $t('preference.vertical-tip'),
type: 'side-nav', type: 'sidebar-nav',
}, },
{ {
name: $t('preference.two-column'), name: $t('preference.two-column'),
tip: $t('preference.two-column-tip'), tip: $t('preference.two-column-tip'),
type: 'side-mixed-nav', type: 'sidebar-mixed-nav',
}, },
{ {
name: $t('preference.horizontal'), name: $t('preference.horizontal'),

View File

@ -10,21 +10,21 @@ defineOptions({
defineProps<{ disabled: boolean }>(); defineProps<{ disabled: boolean }>();
const sidebarEnable = defineModel<boolean>('sidebarEnable'); const sidebarEnable = defineModel<boolean>('sidebarEnable');
const sidebarCollapseShowTitle = defineModel<boolean>( const sidebarCollapsedShowTitle = defineModel<boolean>(
'sidebarCollapseShowTitle', 'sidebarCollapsedShowTitle',
); );
const sidebarCollapse = defineModel<boolean>('sidebarCollapse'); const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
</script> </script>
<template> <template>
<SwitchItem v-model="sidebarEnable" :disabled="disabled"> <SwitchItem v-model="sidebarEnable" :disabled="disabled">
{{ $t('preference.side-visible') }} {{ $t('preference.side-visible') }}
</SwitchItem> </SwitchItem>
<SwitchItem v-model="sidebarCollapse" :disabled="!sidebarEnable || disabled"> <SwitchItem v-model="sidebarCollapsed" :disabled="!sidebarEnable || disabled">
{{ $t('preference.collapse') }} {{ $t('preference.collapse') }}
</SwitchItem> </SwitchItem>
<SwitchItem <SwitchItem
v-model="sidebarCollapseShowTitle" v-model="sidebarCollapsedShowTitle"
:disabled="!sidebarEnable || disabled" :disabled="!sidebarEnable || disabled"
> >
{{ $t('preference.collapse-show-title') }} {{ $t('preference.collapse-show-title') }}

View File

@ -3,8 +3,8 @@ import HeaderNav from './header-nav.vue';
export { default as ContentCompact } from './content-compact.vue'; export { default as ContentCompact } from './content-compact.vue';
export { default as FullContent } from './full-content.vue'; export { default as FullContent } from './full-content.vue';
export { default as MixedNav } from './mixed-nav.vue'; export { default as MixedNav } from './mixed-nav.vue';
export { default as SideMixedNav } from './side-mixed-nav.vue'; export { default as SidebarMixedNav } from './sidebar-mixed-nav.vue';
export { default as SideNav } from './side-nav.vue'; export { default as SidebarNav } from './sidebar-nav.vue';
const ContentWide = HeaderNav; const ContentWide = HeaderNav;
export { ContentWide, HeaderNav }; export { ContentWide, HeaderNav };

View File

@ -22,7 +22,7 @@ import Preferences from './preferences.vue';
:breadcrumb-hide-only-one="preferences.breadcrumb.hideOnlyOne" :breadcrumb-hide-only-one="preferences.breadcrumb.hideOnlyOne"
:breadcrumb-home="preferences.breadcrumb.showHome" :breadcrumb-home="preferences.breadcrumb.showHome"
:breadcrumb-icon="preferences.breadcrumb.showIcon" :breadcrumb-icon="preferences.breadcrumb.showIcon"
:breadcrumb-style="preferences.breadcrumb.styleType" :breadcrumb-style-type="preferences.breadcrumb.styleType"
:color-primary-presets="COLOR_PRIMARY_RESETS" :color-primary-presets="COLOR_PRIMARY_RESETS"
:footer-enable="preferences.footer.enable" :footer-enable="preferences.footer.enable"
:footer-fixed="preferences.footer.fixed" :footer-fixed="preferences.footer.fixed"
@ -32,8 +32,8 @@ import Preferences from './preferences.vue';
:navigation-split="preferences.navigation.split" :navigation-split="preferences.navigation.split"
:navigation-style-type="preferences.navigation.styleType" :navigation-style-type="preferences.navigation.styleType"
:shortcut-keys-enable="preferences.shortcutKeys.enable" :shortcut-keys-enable="preferences.shortcutKeys.enable"
:sidebar-collapse="preferences.sidebar.collapse" :sidebar-collapsed="preferences.sidebar.collapsed"
:sidebar-collapse-show-title="preferences.sidebar.collapseShowTitle" :sidebar-collapsed-show-title="preferences.sidebar.collapsedShowTitle"
:sidebar-enable="preferences.sidebar.enable" :sidebar-enable="preferences.sidebar.enable"
:tabbar-enable="preferences.tabbar.enable" :tabbar-enable="preferences.tabbar.enable"
:tabbar-show-icon="preferences.tabbar.showIcon" :tabbar-show-icon="preferences.tabbar.showIcon"
@ -103,11 +103,11 @@ import Preferences from './preferences.vue';
@update:shortcut-keys-enable=" @update:shortcut-keys-enable="
(val) => updatePreferences({ shortcutKeys: { enable: val } }) (val) => updatePreferences({ shortcutKeys: { enable: val } })
" "
@update:sidebar-collapse=" @update:sidebar-collapsed="
(val) => updatePreferences({ sidebar: { collapse: val } }) (val) => updatePreferences({ sidebar: { collapsed: val } })
" "
@update:sidebar-collapse-show-title=" @update:sidebar-collapsed-show-title="
(val) => updatePreferences({ sidebar: { collapseShowTitle: val } }) (val) => updatePreferences({ sidebar: { collapsedShowTitle: val } })
" "
@update:sidebar-enable=" @update:sidebar-enable="
(val) => updatePreferences({ sidebar: { enable: val } }) (val) => updatePreferences({ sidebar: { enable: val } })

View File

@ -70,9 +70,9 @@ const transitionEnable = defineModel<boolean>('transitionEnable');
const themeColorPrimary = defineModel<string>('themeColorPrimary'); const themeColorPrimary = defineModel<string>('themeColorPrimary');
const sidebarEnable = defineModel<boolean>('sidebarEnable'); const sidebarEnable = defineModel<boolean>('sidebarEnable');
const sidebarCollapse = defineModel<boolean>('sidebarCollapse'); const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
const sidebarCollapseShowTitle = defineModel<boolean>( const sidebarCollapsedShowTitle = defineModel<boolean>(
'sidebarCollapseShowTitle', 'sidebarCollapsedShowTitle',
); );
const headerEnable = defineModel<boolean>('headerEnable'); const headerEnable = defineModel<boolean>('headerEnable');
@ -216,8 +216,8 @@ function handleReset() {
<Block :title="$t('preference.sidebar')"> <Block :title="$t('preference.sidebar')">
<Sidebar <Sidebar
v-model:side-collapse-show-title="sidebarCollapseShowTitle" v-model:sidebar-collapsed="sidebarCollapsed"
v-model:sidebar-collapse="sidebarCollapse" v-model:sidebar-collapsed-show-title="sidebarCollapsedShowTitle"
v-model:sidebar-enable="sidebarEnable" v-model:sidebar-enable="sidebarEnable"
:disabled="!isSideMode" :disabled="!isSideMode"
/> />

View File

@ -41,6 +41,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@vben-core/helpers": "workspace:*",
"@vben-core/iconify": "workspace:*", "@vben-core/iconify": "workspace:*",
"@vben-core/layout-ui": "workspace:*", "@vben-core/layout-ui": "workspace:*",
"@vben-core/menu-ui": "workspace:*", "@vben-core/menu-ui": "workspace:*",

View File

@ -9,11 +9,7 @@ import {
updatePreferences, updatePreferences,
usePreferences, usePreferences,
} from '@vben-core/preferences'; } from '@vben-core/preferences';
import { import { VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';
VbenBackTop,
// VbenFloatingButtonGroup,
VbenLogo,
} from '@vben-core/shadcn-ui';
import { mapTree } from '@vben-core/toolkit'; import { mapTree } from '@vben-core/toolkit';
import { MenuRecordRaw } from '@vben-core/typings'; import { MenuRecordRaw } from '@vben-core/typings';
@ -27,7 +23,7 @@ import {
useExtraMenu, useExtraMenu,
useMixedMenu, useMixedMenu,
} from './menu'; } from './menu';
import { LayoutTabs, LayoutTabsToolbar } from './tabs'; import { LayoutTabbar, LayoutTabbarTools } from './tabbar';
import { Breadcrumb } from './widgets'; import { Breadcrumb } from './widgets';
defineOptions({ name: 'BasicLayout' }); defineOptions({ name: 'BasicLayout' });
@ -45,8 +41,8 @@ const theme = computed(() => {
}); });
const logoClass = computed(() => { const logoClass = computed(() => {
const { collapse, collapseShowTitle } = preferences.sidebar; const { collapsed, collapsedShowTitle } = preferences.sidebar;
return collapseShowTitle && collapse && !isMixedNav.value ? 'mx-auto' : ''; return collapsedShowTitle && collapsed && !isMixedNav.value ? 'mx-auto' : '';
}); });
const isMenuRounded = computed(() => { const isMenuRounded = computed(() => {
@ -59,12 +55,12 @@ const logoCollapse = computed(() => {
} }
const { isMobile } = preferences.app; const { isMobile } = preferences.app;
const { collapse } = preferences.sidebar; const { collapsed } = preferences.sidebar;
if (!collapse && isMobile) { if (!collapsed && isMobile) {
return false; return false;
} }
return collapse || isSideMixedNav.value; return collapsed || isSideMixedNav.value;
}); });
const showHeaderNav = computed(() => { const showHeaderNav = computed(() => {
@ -74,11 +70,11 @@ const showHeaderNav = computed(() => {
const { const {
extraActiveMenu, extraActiveMenu,
extraMenus, extraMenus,
extraVisible,
handleDefaultSelect, handleDefaultSelect,
handleMenuMouseEnter, handleMenuMouseEnter,
handleMixedMenuSelect, handleMixedMenuSelect,
handleSideMouseLeave, handleSideMouseLeave,
sidebarExtraVisible,
} = useExtraMenu(); } = useExtraMenu();
const { const {
@ -92,17 +88,22 @@ const {
function wrapperMenus(menus: MenuRecordRaw[]) { function wrapperMenus(menus: MenuRecordRaw[]) {
return mapTree(menus, (item) => { return mapTree(menus, (item) => {
return { return { ...item, name: $t(item.name) };
...item, });
name: $t(item.name), }
};
function toggleSidebar() {
updatePreferences({
sidebar: {
hidden: !preferences.sidebar.hidden,
},
}); });
} }
</script> </script>
<template> <template>
<VbenAdminLayout <VbenAdminLayout
v-model:side-extra-visible="extraVisible" v-model:sidebar-extra-visible="sidebarExtraVisible"
:content-compact="preferences.app.contentCompact" :content-compact="preferences.app.contentCompact"
:footer-enable="preferences.footer.enable" :footer-enable="preferences.footer.enable"
:footer-fixed="preferences.footer.fixed" :footer-fixed="preferences.footer.fixed"
@ -111,37 +112,38 @@ function wrapperMenus(menus: MenuRecordRaw[]) {
:header-visible="preferences.header.enable" :header-visible="preferences.header.enable"
:is-mobile="preferences.app.isMobile" :is-mobile="preferences.app.isMobile"
:layout="layout" :layout="layout"
:side-collapse="preferences.sidebar.collapse" :sidebar-collapse="preferences.sidebar.collapsed"
:side-collapse-show-title="preferences.sidebar.collapseShowTitle" :sidebar-collapse-show-title="preferences.sidebar.collapsedShowTitle"
:side-expand-on-hover="preferences.sidebar.expandOnHover" :sidebar-enable="sideVisible"
:side-extra-collapse="preferences.sidebar.extraCollapse" :sidebar-expand-on-hover="preferences.sidebar.expandOnHover"
:side-hidden="preferences.sidebar.hidden" :sidebar-extra-collapse="preferences.sidebar.extraCollapse"
:side-semi-dark="preferences.app.semiDarkMenu" :sidebar-hidden="preferences.sidebar.hidden"
:side-theme="theme" :sidebar-semi-dark="preferences.app.semiDarkMenu"
:side-visible="sideVisible" :sidebar-theme="theme"
:side-width="preferences.sidebar.width" :sidebar-width="preferences.sidebar.width"
:tabs-visible="preferences.tabbar.enable" :tabbar-enable="preferences.tabbar.enable"
@side-mouse-leave="handleSideMouseLeave" @side-mouse-leave="handleSideMouseLeave"
@update:side-collapse=" @toggle-sidebar="toggleSidebar"
(value: boolean) => updatePreferences({ sidebar: { collapse: value } }) @update:sidebar-collapse="
(value: boolean) => updatePreferences({ sidebar: { collapsed: value } })
" "
@update:side-expand-on-hover=" @update:sidebar-enable="
(value: boolean) => updatePreferences({ sidebar: { enable: value } })
"
@update:sidebar-expand-on-hover="
(value: boolean) => (value: boolean) =>
updatePreferences({ sidebar: { expandOnHover: value } }) updatePreferences({ sidebar: { expandOnHover: value } })
" "
@update:side-extra-collapse=" @update:sidebar-extra-collapse="
(value: boolean) => (value: boolean) =>
updatePreferences({ sidebar: { extraCollapse: value } }) updatePreferences({ sidebar: { extraCollapse: value } })
" "
@update:side-visible="
(value: boolean) => updatePreferences({ sidebar: { enable: value } })
"
> >
<template v-if="preferences.app.showPreference" #preferences> <template v-if="preferences.app.showPreference" #preferences>
<PreferencesWidget /> <PreferencesWidget />
</template> </template>
<template #floating-button-group> <template #floating-groups>
<VbenBackTop /> <VbenBackTop />
<!-- <VbenFloatingButtonGroup /> --> <!-- <VbenFloatingButtonGroup /> -->
</template> </template>
@ -194,8 +196,8 @@ function wrapperMenus(menus: MenuRecordRaw[]) {
<template #menu> <template #menu>
<LayoutMenu <LayoutMenu
:accordion="preferences.navigation.accordion" :accordion="preferences.navigation.accordion"
:collapse="preferences.sidebar.collapse" :collapse="preferences.sidebar.collapsed"
:collapse-show-title="preferences.sidebar.collapseShowTitle" :collapse-show-title="preferences.sidebar.collapsedShowTitle"
:default-active="sideActive" :default-active="sideActive"
:menus="wrapperMenus(sideMenus)" :menus="wrapperMenus(sideMenus)"
:rounded="isMenuRounded" :rounded="isMenuRounded"
@ -207,7 +209,8 @@ function wrapperMenus(menus: MenuRecordRaw[]) {
<template #mixed-menu> <template #mixed-menu>
<LayoutMixedMenu <LayoutMixedMenu
:active-path="extraActiveMenu" :active-path="extraActiveMenu"
:collapse="!preferences.sidebar.collapseShowTitle" :collapse="!preferences.sidebar.collapsedShowTitle"
:menus="wrapperMenus(headerMenus)"
:rounded="isMenuRounded" :rounded="isMenuRounded"
:theme="theme" :theme="theme"
@default-select="handleDefaultSelect" @default-select="handleDefaultSelect"
@ -234,14 +237,14 @@ function wrapperMenus(menus: MenuRecordRaw[]) {
/> />
</template> </template>
<template #tabs> <template #tabbar>
<LayoutTabs <LayoutTabbar
v-if="preferences.tabbar.enable" v-if="preferences.tabbar.enable"
:show-icon="preferences.tabbar.showIcon" :show-icon="preferences.tabbar.showIcon"
/> />
</template> </template>
<template #tabs-toolbar> <template #tabbar-tools>
<LayoutTabsToolbar v-if="preferences.tabbar.enable" /> <LayoutTabbarTools v-if="preferences.tabbar.enable" />
</template> </template>
<!-- 主体内容 --> <!-- 主体内容 -->

View File

@ -2,17 +2,15 @@
import type { NormalMenuProps } from '@vben-core/menu-ui'; import type { NormalMenuProps } from '@vben-core/menu-ui';
import type { MenuRecordRaw } from '@vben-core/typings'; import type { MenuRecordRaw } from '@vben-core/typings';
import { computed, onBeforeMount } from 'vue'; import { onBeforeMount } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { findMenuByPath } from '@vben-core/helpers';
import { NormalMenu } from '@vben-core/menu-ui'; import { NormalMenu } from '@vben-core/menu-ui';
import { useAccessStore } from '@vben-core/stores';
import { findMenuByPath } from './helper';
interface Props extends NormalMenuProps {} interface Props extends NormalMenuProps {}
defineProps<Props>(); const props = defineProps<Props>();
const emit = defineEmits<{ const emit = defineEmits<{
defaultSelect: [MenuRecordRaw, MenuRecordRaw?]; defaultSelect: [MenuRecordRaw, MenuRecordRaw?];
@ -20,19 +18,16 @@ const emit = defineEmits<{
select: [MenuRecordRaw]; select: [MenuRecordRaw];
}>(); }>();
const accessStore = useAccessStore();
const route = useRoute(); const route = useRoute();
const menus = computed(() => accessStore.getAccessMenus);
function handleSelect(menu: MenuRecordRaw) { function handleSelect(menu: MenuRecordRaw) {
emit('select', menu); emit('select', menu);
} }
onBeforeMount(() => { onBeforeMount(() => {
const menu = findMenuByPath(menus.value, route.path); const menu = findMenuByPath(props.menus || [], route.path);
if (menu) { if (menu) {
const rootMenu = menus.value.find( const rootMenu = (props.menus || []).find(
(item) => item.path === menu.parents?.[0], (item) => item.path === menu.parents?.[0],
); );
emit('defaultSelect', menu, rootMenu); emit('defaultSelect', menu, rootMenu);

View File

@ -3,10 +3,10 @@ import type { MenuRecordRaw } from '@vben-core/typings';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { findRootMenuByPath } from '@vben-core/helpers';
import { preferences } from '@vben-core/preferences'; import { preferences } from '@vben-core/preferences';
import { useAccessStore } from '@vben-core/stores'; import { useAccessStore } from '@vben-core/stores';
import { findRootMenuByPath } from './helper';
import { useNavigation } from './use-navigation'; import { useNavigation } from './use-navigation';
function useExtraMenu() { function useExtraMenu() {
@ -17,7 +17,7 @@ function useExtraMenu() {
const route = useRoute(); const route = useRoute();
const extraMenus = ref<MenuRecordRaw[]>([]); const extraMenus = ref<MenuRecordRaw[]>([]);
const extraVisible = ref<boolean>(false); const sidebarExtraVisible = ref<boolean>(false);
const extraActiveMenu = ref(''); const extraActiveMenu = ref('');
/** /**
@ -29,7 +29,7 @@ function useExtraMenu() {
extraActiveMenu.value = menu.parents?.[0] ?? menu.path; extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
const hasChildren = extraMenus.value.length > 0; const hasChildren = extraMenus.value.length > 0;
extraVisible.value = hasChildren; sidebarExtraVisible.value = hasChildren;
if (!hasChildren) { if (!hasChildren) {
await navigation(menu.path); await navigation(menu.path);
} }
@ -48,7 +48,7 @@ function useExtraMenu() {
extraActiveMenu.value = menu.parents?.[0] ?? menu.path; extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
if (preferences.sidebar.expandOnHover) { if (preferences.sidebar.expandOnHover) {
extraVisible.value = extraMenus.value.length > 0; sidebarExtraVisible.value = extraMenus.value.length > 0;
} }
}; };
@ -59,7 +59,7 @@ function useExtraMenu() {
if (preferences.sidebar.expandOnHover) { if (preferences.sidebar.expandOnHover) {
return; return;
} }
extraVisible.value = false; sidebarExtraVisible.value = false;
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath( const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus.value, menus.value,
@ -74,18 +74,18 @@ function useExtraMenu() {
const { findMenu } = findRootMenuByPath(menus.value, menu.path); const { findMenu } = findRootMenuByPath(menus.value, menu.path);
extraMenus.value = findMenu?.children ?? []; extraMenus.value = findMenu?.children ?? [];
extraActiveMenu.value = menu.parents?.[0] ?? menu.path; extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
extraVisible.value = extraMenus.value.length > 0; sidebarExtraVisible.value = extraMenus.value.length > 0;
} }
}; };
return { return {
extraActiveMenu, extraActiveMenu,
extraMenus, extraMenus,
extraVisible,
handleDefaultSelect, handleDefaultSelect,
handleMenuMouseEnter, handleMenuMouseEnter,
handleMixedMenuSelect, handleMixedMenuSelect,
handleSideMouseLeave, handleSideMouseLeave,
sidebarExtraVisible,
}; };
} }

View File

@ -3,10 +3,10 @@ import type { MenuRecordRaw } from '@vben-core/typings';
import { computed, onBeforeMount, ref } from 'vue'; import { computed, onBeforeMount, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { findRootMenuByPath } from '@vben-core/helpers';
import { preferences, usePreferences } from '@vben-core/preferences'; import { preferences, usePreferences } from '@vben-core/preferences';
import { useAccessStore } from '@vben-core/stores'; import { useAccessStore } from '@vben-core/stores';
import { findRootMenuByPath } from './helper';
import { useNavigation } from './use-navigation'; import { useNavigation } from './use-navigation';
function useMixedMenu() { function useMixedMenu() {

View File

@ -0,0 +1,3 @@
export { default as LayoutTabbar } from './tabbar.vue';
export { default as LayoutTabbarTools } from './tabbar-tools.vue';
export * from './use-tabs';

View File

@ -3,7 +3,7 @@ import { computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { preferences, updatePreferences } from '@vben-core/preferences'; import { preferences, updatePreferences } from '@vben-core/preferences';
import { TabsMore, TabsScreen } from '@vben-core/tabs-ui'; import { TabsToolMore, TabsToolScreen } from '@vben-core/tabs-ui';
import { useTabs } from './use-tabs'; import { useTabs } from './use-tabs';
@ -29,8 +29,8 @@ function handleScreenChange(screen: boolean) {
<template> <template>
<div class="flex-center h-full"> <div class="flex-center h-full">
<TabsMore :menus="menus" /> <TabsToolMore :menus="menus" />
<TabsScreen <TabsToolScreen
:screen="preferences.sidebar.hidden" :screen="preferences.sidebar.hidden"
@change="handleScreenChange" @change="handleScreenChange"
@update:screen="handleScreenChange" @update:screen="handleScreenChange"

View File

@ -4,7 +4,7 @@ import { TabsView } from '@vben-core/tabs-ui';
import { useTabs } from './use-tabs'; import { useTabs } from './use-tabs';
defineOptions({ defineOptions({
name: 'LayoutTabs', name: 'LayoutTabbar',
}); });
defineProps<{ showIcon?: boolean }>(); defineProps<{ showIcon?: boolean }>();

View File

@ -1,3 +0,0 @@
export { default as LayoutTabs } from './tabs.vue';
export { default as LayoutTabsToolbar } from './tabs-toolbar.vue';
export * from './use-tabs';

View File

@ -81,13 +81,13 @@ importers:
version: 5.4.5 version: 5.4.5
unbuild: unbuild:
specifier: ^2.0.0 specifier: ^2.0.0
version: 2.0.0(sass@1.77.4)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5)) version: 2.0.0(sass@1.77.5)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5))
vite: vite:
specifier: 6.0.0-alpha.17 specifier: 6.0.0-alpha.17
version: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) version: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vitest: vitest:
specifier: ^2.0.0-beta.3 specifier: ^2.0.0-beta.3
version: 2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.4)(terser@5.31.0) version: 2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.5)(terser@5.31.0)
vue-tsc: vue-tsc:
specifier: ^2.0.21 specifier: ^2.0.21
version: 2.0.21(typescript@5.4.5) version: 2.0.21(typescript@5.4.5)
@ -134,8 +134,8 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../packages/utils version: link:../../packages/utils
'@vueuse/core': '@vueuse/core':
specifier: ^10.10.0 specifier: ^10.10.1
version: 10.10.0(vue@3.4.27(typescript@5.4.5)) version: 10.10.1(vue@3.4.27(typescript@5.4.5))
ant-design-vue: ant-design-vue:
specifier: ^4.2.3 specifier: ^4.2.3
version: 4.2.3(vue@3.4.27(typescript@5.4.5)) version: 4.2.3(vue@3.4.27(typescript@5.4.5))
@ -157,7 +157,7 @@ importers:
devDependencies: devDependencies:
vite-plugin-mock: vite-plugin-mock:
specifier: ^3.0.2 specifier: ^3.0.2
version: 3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) version: 3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
internal/lint-configs/commitlint-config: internal/lint-configs/commitlint-config:
dependencies: dependencies:
@ -171,11 +171,11 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../node-utils version: link:../../node-utils
cz-git: cz-git:
specifier: ^1.9.2 specifier: ^1.9.3
version: 1.9.2 version: 1.9.3
czg: czg:
specifier: ^1.9.2 specifier: ^1.9.3
version: 1.9.2 version: 1.9.3
internal/lint-configs/eslint-config: internal/lint-configs/eslint-config:
dependencies: dependencies:
@ -236,7 +236,7 @@ importers:
version: 4.0.0(@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) version: 4.0.0(@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)
eslint-plugin-vitest: eslint-plugin-vitest:
specifier: ^0.5.4 specifier: ^0.5.4
version: 0.5.4(@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)(vitest@2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.4)(terser@5.31.0)) version: 0.5.4(@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)(vitest@2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.5)(terser@5.31.0))
eslint-plugin-vue: eslint-plugin-vue:
specifier: ^9.26.0 specifier: ^9.26.0
version: 9.26.0(eslint@8.57.0) version: 9.26.0(eslint@8.57.0)
@ -262,8 +262,8 @@ importers:
specifier: 3.3.0 specifier: 3.3.0
version: 3.3.0 version: 3.3.0
prettier-plugin-tailwindcss: prettier-plugin-tailwindcss:
specifier: ^0.6.2 specifier: ^0.6.3
version: 0.6.2(prettier@3.3.0) version: 0.6.3(prettier@3.3.0)
internal/lint-configs/stylelint-config: internal/lint-configs/stylelint-config:
dependencies: dependencies:
@ -394,7 +394,7 @@ importers:
version: link:../../packages/types version: link:../../packages/types
vite: vite:
specifier: 6.0.0-alpha.17 specifier: 6.0.0-alpha.17
version: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) version: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
internal/vite-config: internal/vite-config:
dependencies: dependencies:
@ -415,10 +415,10 @@ importers:
version: 2.0.2 version: 2.0.2
vite-plugin-lib-inject-css: vite-plugin-lib-inject-css:
specifier: ^2.1.1 specifier: ^2.1.1
version: 2.1.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) version: 2.1.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
vite-plugin-vue-devtools: vite-plugin-vue-devtools:
specifier: ^7.2.1 specifier: ^7.2.1
version: 7.2.1(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)) version: 7.2.1(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))
devDependencies: devDependencies:
'@types/html-minifier-terser': '@types/html-minifier-terser':
specifier: ^7.0.2 specifier: ^7.0.2
@ -428,10 +428,10 @@ importers:
version: link:../node-utils version: link:../node-utils
'@vitejs/plugin-vue': '@vitejs/plugin-vue':
specifier: ^5.0.5 specifier: ^5.0.5
version: 5.0.5(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)) version: 5.0.5(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))
'@vitejs/plugin-vue-jsx': '@vitejs/plugin-vue-jsx':
specifier: ^4.0.0 specifier: ^4.0.0
version: 4.0.0(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)) version: 4.0.0(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))
dayjs: dayjs:
specifier: ^1.11.11 specifier: ^1.11.11
version: 1.11.11 version: 1.11.11
@ -442,26 +442,26 @@ importers:
specifier: ^5.12.0 specifier: ^5.12.0
version: 5.12.0(rollup@4.18.0) version: 5.12.0(rollup@4.18.0)
sass: sass:
specifier: ^1.77.4 specifier: ^1.77.5
version: 1.77.4 version: 1.77.5
unplugin-turbo-console: unplugin-turbo-console:
specifier: ^1.8.6 specifier: ^1.8.6
version: 1.8.6(esbuild@0.20.2)(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)) version: 1.8.6(esbuild@0.20.2)(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))
vite: vite:
specifier: 6.0.0-alpha.17 specifier: 6.0.0-alpha.17
version: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) version: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vite-plugin-compression: vite-plugin-compression:
specifier: ^0.5.1 specifier: ^0.5.1
version: 0.5.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) version: 0.5.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
vite-plugin-dts: vite-plugin-dts:
specifier: ^3.9.1 specifier: ^3.9.1
version: 3.9.1(@types/node@20.14.2)(rollup@4.18.0)(typescript@5.4.5)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) version: 3.9.1(@types/node@20.14.2)(rollup@4.18.0)(typescript@5.4.5)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
vite-plugin-html: vite-plugin-html:
specifier: ^3.2.2 specifier: ^3.2.2
version: 3.2.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) version: 3.2.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
vite-plugin-mock: vite-plugin-mock:
specifier: ^3.0.2 specifier: ^3.0.2
version: 3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) version: 3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
packages/@core/forward/helpers: packages/@core/forward/helpers:
dependencies: dependencies:
@ -490,8 +490,8 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../shared/typings version: link:../../shared/typings
'@vueuse/core': '@vueuse/core':
specifier: ^10.10.0 specifier: ^10.10.1
version: 10.10.0(vue@3.4.27(typescript@5.4.5)) version: 10.10.1(vue@3.4.27(typescript@5.4.5))
vue: vue:
specifier: 3.4.27 specifier: 3.4.27
version: 3.4.27(typescript@5.4.5) version: 3.4.27(typescript@5.4.5)
@ -585,24 +585,18 @@ importers:
packages/@core/uikit/layout-ui: packages/@core/uikit/layout-ui:
dependencies: dependencies:
'@vben-core/design':
specifier: workspace:*
version: link:../../shared/design
'@vben-core/iconify': '@vben-core/iconify':
specifier: workspace:* specifier: workspace:*
version: link:../../shared/iconify version: link:../../shared/iconify
'@vben-core/shadcn-ui': '@vben-core/shadcn-ui':
specifier: workspace:* specifier: workspace:*
version: link:../shadcn-ui version: link:../shadcn-ui
'@vben-core/toolkit':
specifier: workspace:*
version: link:../../shared/toolkit
'@vben-core/typings': '@vben-core/typings':
specifier: workspace:* specifier: workspace:*
version: link:../../shared/typings version: link:../../shared/typings
'@vueuse/core': '@vueuse/core':
specifier: ^10.10.0 specifier: ^10.10.1
version: 10.10.0(vue@3.4.27(typescript@5.4.5)) version: 10.10.1(vue@3.4.27(typescript@5.4.5))
vue: vue:
specifier: 3.4.27 specifier: 3.4.27
version: 3.4.27(typescript@5.4.5) version: 3.4.27(typescript@5.4.5)
@ -625,8 +619,8 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../shared/typings version: link:../../shared/typings
'@vueuse/core': '@vueuse/core':
specifier: ^10.10.0 specifier: ^10.10.1
version: 10.10.0(vue@3.4.27(typescript@5.4.5)) version: 10.10.1(vue@3.4.27(typescript@5.4.5))
vue: vue:
specifier: 3.4.27 specifier: 3.4.27
version: 3.4.27(typescript@5.4.5) version: 3.4.27(typescript@5.4.5)
@ -646,8 +640,8 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../shared/typings version: link:../../shared/typings
'@vueuse/core': '@vueuse/core':
specifier: ^10.10.0 specifier: ^10.10.1
version: 10.10.0(vue@3.4.27(typescript@5.4.5)) version: 10.10.1(vue@3.4.27(typescript@5.4.5))
class-variance-authority: class-variance-authority:
specifier: ^0.7.0 specifier: ^0.7.0
version: 0.7.0 version: 0.7.0
@ -709,11 +703,11 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../locales version: link:../../locales
'@vueuse/core': '@vueuse/core':
specifier: ^10.10.0 specifier: ^10.10.1
version: 10.10.0(vue@3.4.27(typescript@5.4.5)) version: 10.10.1(vue@3.4.27(typescript@5.4.5))
'@vueuse/integrations': '@vueuse/integrations':
specifier: ^10.10.0 specifier: ^10.10.1
version: 10.10.0(async-validator@4.2.5)(axios@1.7.2)(focus-trap@7.5.4)(nprogress@0.2.0)(qrcode@1.5.3)(vue@3.4.27(typescript@5.4.5)) version: 10.10.1(async-validator@4.2.5)(axios@1.7.2)(focus-trap@7.5.4)(nprogress@0.2.0)(qrcode@1.5.3)(vue@3.4.27(typescript@5.4.5))
qrcode: qrcode:
specifier: ^1.5.3 specifier: ^1.5.3
version: 1.5.3 version: 1.5.3
@ -733,6 +727,9 @@ importers:
packages/business/layouts: packages/business/layouts:
dependencies: dependencies:
'@vben-core/helpers':
specifier: workspace:*
version: link:../../@core/forward/helpers
'@vben-core/iconify': '@vben-core/iconify':
specifier: workspace:* specifier: workspace:*
version: link:../../@core/shared/iconify version: link:../../@core/shared/iconify
@ -852,7 +849,7 @@ importers:
devDependencies: devDependencies:
vitepress: vitepress:
specifier: ^1.2.3 specifier: ^1.2.3
version: 1.2.3(@algolia/client-search@4.23.3)(@types/node@20.14.2)(async-validator@4.2.5)(axios@1.7.2)(nprogress@0.2.0)(postcss@8.4.38)(qrcode@1.5.3)(sass@1.77.4)(search-insights@2.14.0)(terser@5.31.0)(typescript@5.4.5) version: 1.2.3(@algolia/client-search@4.23.3)(@types/node@20.14.2)(async-validator@4.2.5)(axios@1.7.2)(nprogress@0.2.0)(postcss@8.4.38)(qrcode@1.5.3)(sass@1.77.5)(search-insights@2.14.0)(terser@5.31.0)(typescript@5.4.5)
vue: vue:
specifier: 3.4.27 specifier: 3.4.27
version: 3.4.27(typescript@5.4.5) version: 3.4.27(typescript@5.4.5)
@ -2682,11 +2679,11 @@ packages:
'@vue/test-utils@2.4.6': '@vue/test-utils@2.4.6':
resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==} resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==}
'@vueuse/core@10.10.0': '@vueuse/core@10.10.1':
resolution: {integrity: sha512-vexJ/YXYs2S42B783rI95lMt3GzEwkxzC8Hb0Ndpd8rD+p+Lk/Za4bd797Ym7yq4jXqdSyj3JLChunF/vyYjUw==} resolution: {integrity: sha512-8Vr8wxILdK+qfBjbngav8LVI+6UuM2TQCufRKMPz/GrpLHQ6dbY6kL5PLa9Eobq8JRrMaDyArPX9Jj18fMTPew==}
'@vueuse/integrations@10.10.0': '@vueuse/integrations@10.10.1':
resolution: {integrity: sha512-vHGeK7X6mkdkpcm1eE9t3Cpm21pNVfZRwrjwwbrEs9XftnSgszF4831G2rei8Dt9cIYJIfFV+iyx/29muimJPQ==} resolution: {integrity: sha512-b4iPz4NLk2g5u9GNgTpYqNN1pzYWPpIglHTg6eDjJwKB7OfzJP4m5kQlzn2oRH7U0OlEOCVPrdDfqneuS9YNTg==}
peerDependencies: peerDependencies:
async-validator: '*' async-validator: '*'
axios: '*' axios: '*'
@ -2726,12 +2723,15 @@ packages:
universal-cookie: universal-cookie:
optional: true optional: true
'@vueuse/metadata@10.10.0': '@vueuse/metadata@10.10.1':
resolution: {integrity: sha512-UNAo2sTCAW5ge6OErPEHb5z7NEAg3XcO9Cj7OK45aZXfLLH1QkexDcZD77HBi5zvEiLOm1An+p/4b5K3Worpug==} resolution: {integrity: sha512-dpEL5afVLUqbchwGiLrV6spkl4/6UOKJ3YgxFE+wWLj/LakyIZUC83bfeFgbHkRcNhsAqTQCGR74jImsLfK8pg==}
'@vueuse/shared@10.10.0': '@vueuse/shared@10.10.0':
resolution: {integrity: sha512-2aW33Ac0Uk0U+9yo3Ypg9s5KcR42cuehRWl7vnUHadQyFvCktseyxxEPBi1Eiq4D2yBGACOnqLZpx1eMc7g5Og==} resolution: {integrity: sha512-2aW33Ac0Uk0U+9yo3Ypg9s5KcR42cuehRWl7vnUHadQyFvCktseyxxEPBi1Eiq4D2yBGACOnqLZpx1eMc7g5Og==}
'@vueuse/shared@10.10.1':
resolution: {integrity: sha512-edqexI+RQpoeqDxTatqBZa+K87ganbrwpoP++Fd9828U3js5jzwcEDeyrYcUgkKZ5LLL8q7M5SOMvSpMrxBPxg==}
JSONStream@1.3.5: JSONStream@1.3.5:
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
hasBin: true hasBin: true
@ -3402,12 +3402,12 @@ packages:
resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==}
engines: {node: '>= 0.1.90'} engines: {node: '>= 0.1.90'}
cz-git@1.9.2: cz-git@1.9.3:
resolution: {integrity: sha512-HqwSIZBl/Vtlq56wsHuQHhQ0CF7rABEvhvbSAaGViLeM5YucLu5o+U2XLow1Y2bwIAfAIKZHfgg9fxP7P3XU3Q==} resolution: {integrity: sha512-v7+vYOparImLLo6J5tAsi/cz+EAK7FI/TDnemi11xgEax4k+ZVqxsmkiEc68n+MJLp1l5THhB2KTDhjpW+ellg==}
engines: {node: '>=v12.20.0'} engines: {node: '>=v12.20.0'}
czg@1.9.2: czg@1.9.3:
resolution: {integrity: sha512-uPSKTIsAhZp1Tu7DRO7K68qPixVFyheRKlOGhuKXo2wdlpcE0hoCmTQAwsUTerKtjcFRnhRTpJ5j0bC6SOj01Q==} resolution: {integrity: sha512-2RDFcHpVrG0eWGPodkcDQ9QdaF8xVf54PMP0GdXyiz3sCKvxsHvQ/AEvz9TPndZONCajHgU7uN64MQdrHLDSYA==}
engines: {node: '>=v12.20.0'} engines: {node: '>=v12.20.0'}
hasBin: true hasBin: true
@ -5955,8 +5955,8 @@ packages:
resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
prettier-plugin-tailwindcss@0.6.2: prettier-plugin-tailwindcss@0.6.3:
resolution: {integrity: sha512-eFefm4cg+1c2B57+H274Qm//CTWBdtQN9ansl0YTP/8TC8x3bugCTQSS/e4FC5Ctl9djhTzsbcMrZ7x2/abIow==} resolution: {integrity: sha512-GeJ9bqXN4APAP0V5T2a1J/o6a50MWevEUCPWxijpdXFDQkBCoAfz4pQfv+YMXSqZ5GXLMDYio0mUOfrYL7gf4w==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
peerDependencies: peerDependencies:
'@ianvs/prettier-plugin-sort-imports': '*' '@ianvs/prettier-plugin-sort-imports': '*'
@ -6305,8 +6305,8 @@ packages:
safer-buffer@2.1.2: safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sass@1.77.4: sass@1.77.5:
resolution: {integrity: sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==} resolution: {integrity: sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
hasBin: true hasBin: true
@ -9323,24 +9323,24 @@ snapshots:
'@ungap/structured-clone@1.2.0': {} '@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-vue-jsx@4.0.0(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))': '@vitejs/plugin-vue-jsx@4.0.0(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))':
dependencies: dependencies:
'@babel/core': 7.24.6 '@babel/core': 7.24.6
'@babel/plugin-transform-typescript': 7.24.6(@babel/core@7.24.6) '@babel/plugin-transform-typescript': 7.24.6(@babel/core@7.24.6)
'@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.24.6) '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.24.6)
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vue: 3.4.27(typescript@5.4.5) vue: 3.4.27(typescript@5.4.5)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@vitejs/plugin-vue@5.0.5(vite@5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))': '@vitejs/plugin-vue@5.0.5(vite@5.2.12(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))':
dependencies: dependencies:
vite: 5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 5.2.12(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vue: 3.4.27(typescript@5.4.5) vue: 3.4.27(typescript@5.4.5)
'@vitejs/plugin-vue@5.0.5(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))': '@vitejs/plugin-vue@5.0.5(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))':
dependencies: dependencies:
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vue: 3.4.27(typescript@5.4.5) vue: 3.4.27(typescript@5.4.5)
'@vitest/expect@2.0.0-beta.3': '@vitest/expect@2.0.0-beta.3':
@ -9466,14 +9466,14 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- vue - vue
'@vue/devtools-core@7.2.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))': '@vue/devtools-core@7.2.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))':
dependencies: dependencies:
'@vue/devtools-kit': 7.2.1(vue@3.4.27(typescript@5.4.5)) '@vue/devtools-kit': 7.2.1(vue@3.4.27(typescript@5.4.5))
'@vue/devtools-shared': 7.2.1 '@vue/devtools-shared': 7.2.1
mitt: 3.0.1 mitt: 3.0.1
nanoid: 3.3.7 nanoid: 3.3.7
pathe: 1.1.2 pathe: 1.1.2
vite-hot-client: 0.2.3(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) vite-hot-client: 0.2.3(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
transitivePeerDependencies: transitivePeerDependencies:
- vite - vite
- vue - vue
@ -9545,20 +9545,20 @@ snapshots:
js-beautify: 1.15.1 js-beautify: 1.15.1
vue-component-type-helpers: 2.0.19 vue-component-type-helpers: 2.0.19
'@vueuse/core@10.10.0(vue@3.4.27(typescript@5.4.5))': '@vueuse/core@10.10.1(vue@3.4.27(typescript@5.4.5))':
dependencies: dependencies:
'@types/web-bluetooth': 0.0.20 '@types/web-bluetooth': 0.0.20
'@vueuse/metadata': 10.10.0 '@vueuse/metadata': 10.10.1
'@vueuse/shared': 10.10.0(vue@3.4.27(typescript@5.4.5)) '@vueuse/shared': 10.10.1(vue@3.4.27(typescript@5.4.5))
vue-demi: 0.14.8(vue@3.4.27(typescript@5.4.5)) vue-demi: 0.14.8(vue@3.4.27(typescript@5.4.5))
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
- vue - vue
'@vueuse/integrations@10.10.0(async-validator@4.2.5)(axios@1.7.2)(focus-trap@7.5.4)(nprogress@0.2.0)(qrcode@1.5.3)(vue@3.4.27(typescript@5.4.5))': '@vueuse/integrations@10.10.1(async-validator@4.2.5)(axios@1.7.2)(focus-trap@7.5.4)(nprogress@0.2.0)(qrcode@1.5.3)(vue@3.4.27(typescript@5.4.5))':
dependencies: dependencies:
'@vueuse/core': 10.10.0(vue@3.4.27(typescript@5.4.5)) '@vueuse/core': 10.10.1(vue@3.4.27(typescript@5.4.5))
'@vueuse/shared': 10.10.0(vue@3.4.27(typescript@5.4.5)) '@vueuse/shared': 10.10.1(vue@3.4.27(typescript@5.4.5))
vue-demi: 0.14.8(vue@3.4.27(typescript@5.4.5)) vue-demi: 0.14.8(vue@3.4.27(typescript@5.4.5))
optionalDependencies: optionalDependencies:
async-validator: 4.2.5 async-validator: 4.2.5
@ -9570,7 +9570,7 @@ snapshots:
- '@vue/composition-api' - '@vue/composition-api'
- vue - vue
'@vueuse/metadata@10.10.0': {} '@vueuse/metadata@10.10.1': {}
'@vueuse/shared@10.10.0(vue@3.4.27(typescript@5.4.5))': '@vueuse/shared@10.10.0(vue@3.4.27(typescript@5.4.5))':
dependencies: dependencies:
@ -9579,6 +9579,13 @@ snapshots:
- '@vue/composition-api' - '@vue/composition-api'
- vue - vue
'@vueuse/shared@10.10.1(vue@3.4.27(typescript@5.4.5))':
dependencies:
vue-demi: 0.14.8(vue@3.4.27(typescript@5.4.5))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
JSONStream@1.3.5: JSONStream@1.3.5:
dependencies: dependencies:
jsonparse: 1.3.1 jsonparse: 1.3.1
@ -10344,9 +10351,9 @@ snapshots:
csv-stringify: 5.6.5 csv-stringify: 5.6.5
stream-transform: 2.1.3 stream-transform: 2.1.3
cz-git@1.9.2: {} cz-git@1.9.3: {}
czg@1.9.2: {} czg@1.9.3: {}
dargs@8.1.0: {} dargs@8.1.0: {}
@ -10926,13 +10933,13 @@ snapshots:
optionalDependencies: optionalDependencies:
'@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)(vitest@2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.4)(terser@5.31.0)): eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)(vitest@2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
'@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.4.5)
eslint: 8.57.0 eslint: 8.57.0
optionalDependencies: optionalDependencies:
'@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
vitest: 2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.4)(terser@5.31.0) vitest: 2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.5)(terser@5.31.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
- typescript - typescript
@ -12216,7 +12223,7 @@ snapshots:
mkdirp@1.0.4: {} mkdirp@1.0.4: {}
mkdist@1.5.1(sass@1.77.4)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5)): mkdist@1.5.1(sass@1.77.5)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5)):
dependencies: dependencies:
autoprefixer: 10.4.19(postcss@8.4.38) autoprefixer: 10.4.19(postcss@8.4.38)
citty: 0.1.6 citty: 0.1.6
@ -12234,7 +12241,7 @@ snapshots:
postcss-nested: 6.0.1(postcss@8.4.38) postcss-nested: 6.0.1(postcss@8.4.38)
semver: 7.6.2 semver: 7.6.2
optionalDependencies: optionalDependencies:
sass: 1.77.4 sass: 1.77.5
typescript: 5.4.5 typescript: 5.4.5
vue-tsc: 2.0.21(typescript@5.4.5) vue-tsc: 2.0.21(typescript@5.4.5)
@ -13034,7 +13041,7 @@ snapshots:
dependencies: dependencies:
fast-diff: 1.3.0 fast-diff: 1.3.0
prettier-plugin-tailwindcss@0.6.2(prettier@3.3.0): prettier-plugin-tailwindcss@0.6.3(prettier@3.3.0):
dependencies: dependencies:
prettier: 3.3.0 prettier: 3.3.0
@ -13108,7 +13115,7 @@ snapshots:
'@internationalized/date': 3.5.4 '@internationalized/date': 3.5.4
'@internationalized/number': 3.5.3 '@internationalized/number': 3.5.3
'@tanstack/vue-virtual': 3.5.0(vue@3.4.27(typescript@5.4.5)) '@tanstack/vue-virtual': 3.5.0(vue@3.4.27(typescript@5.4.5))
'@vueuse/core': 10.10.0(vue@3.4.27(typescript@5.4.5)) '@vueuse/core': 10.10.1(vue@3.4.27(typescript@5.4.5))
'@vueuse/shared': 10.10.0(vue@3.4.27(typescript@5.4.5)) '@vueuse/shared': 10.10.0(vue@3.4.27(typescript@5.4.5))
aria-hidden: 1.2.4 aria-hidden: 1.2.4
defu: 6.1.4 defu: 6.1.4
@ -13335,7 +13342,7 @@ snapshots:
safer-buffer@2.1.2: {} safer-buffer@2.1.2: {}
sass@1.77.4: sass@1.77.5:
dependencies: dependencies:
chokidar: 3.6.0 chokidar: 3.6.0
immutable: 4.3.6 immutable: 4.3.6
@ -14014,7 +14021,7 @@ snapshots:
has-symbols: 1.0.3 has-symbols: 1.0.3
which-boxed-primitive: 1.0.2 which-boxed-primitive: 1.0.2
unbuild@2.0.0(sass@1.77.4)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5)): unbuild@2.0.0(sass@1.77.5)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5)):
dependencies: dependencies:
'@rollup/plugin-alias': 5.1.0(rollup@3.29.4) '@rollup/plugin-alias': 5.1.0(rollup@3.29.4)
'@rollup/plugin-commonjs': 25.0.8(rollup@3.29.4) '@rollup/plugin-commonjs': 25.0.8(rollup@3.29.4)
@ -14031,7 +14038,7 @@ snapshots:
hookable: 5.5.3 hookable: 5.5.3
jiti: 1.21.0 jiti: 1.21.0
magic-string: 0.30.10 magic-string: 0.30.10
mkdist: 1.5.1(sass@1.77.4)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5)) mkdist: 1.5.1(sass@1.77.5)(typescript@5.4.5)(vue-tsc@2.0.21(typescript@5.4.5))
mlly: 1.7.0 mlly: 1.7.0
pathe: 1.1.2 pathe: 1.1.2
pkg-types: 1.1.1 pkg-types: 1.1.1
@ -14087,7 +14094,7 @@ snapshots:
unpipe@1.0.0: {} unpipe@1.0.0: {}
unplugin-turbo-console@1.8.6(esbuild@0.20.2)(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)): unplugin-turbo-console@1.8.6(esbuild@0.20.2)(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)):
dependencies: dependencies:
'@rollup/pluginutils': 5.1.0(rollup@4.18.0) '@rollup/pluginutils': 5.1.0(rollup@4.18.0)
ast-kit: 0.12.2 ast-kit: 0.12.2
@ -14100,7 +14107,7 @@ snapshots:
optionalDependencies: optionalDependencies:
esbuild: 0.20.2 esbuild: 0.20.2
rollup: 4.18.0 rollup: 4.18.0
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vue: 3.4.27(typescript@5.4.5) vue: 3.4.27(typescript@5.4.5)
transitivePeerDependencies: transitivePeerDependencies:
- uWebSockets.js - uWebSockets.js
@ -14165,17 +14172,17 @@ snapshots:
validator@13.12.0: {} validator@13.12.0: {}
vite-hot-client@0.2.3(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-hot-client@0.2.3(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vite-node@2.0.0-beta.3(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0): vite-node@2.0.0-beta.3(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0):
dependencies: dependencies:
cac: 6.7.14 cac: 6.7.14
debug: 4.3.5 debug: 4.3.5
pathe: 1.1.2 pathe: 1.1.2
picocolors: 1.0.1 picocolors: 1.0.1
vite: 5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 5.2.12(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- less - less
@ -14186,16 +14193,16 @@ snapshots:
- supports-color - supports-color
- terser - terser
vite-plugin-compression@0.5.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-plugin-compression@0.5.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
chalk: 4.1.2 chalk: 4.1.2
debug: 4.3.5 debug: 4.3.5
fs-extra: 10.1.0 fs-extra: 10.1.0
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vite-plugin-dts@3.9.1(@types/node@20.14.2)(rollup@4.18.0)(typescript@5.4.5)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-plugin-dts@3.9.1(@types/node@20.14.2)(rollup@4.18.0)(typescript@5.4.5)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
'@microsoft/api-extractor': 7.43.0(@types/node@20.14.2) '@microsoft/api-extractor': 7.43.0(@types/node@20.14.2)
'@rollup/pluginutils': 5.1.0(rollup@4.18.0) '@rollup/pluginutils': 5.1.0(rollup@4.18.0)
@ -14206,13 +14213,13 @@ snapshots:
typescript: 5.4.5 typescript: 5.4.5
vue-tsc: 1.8.27(typescript@5.4.5) vue-tsc: 1.8.27(typescript@5.4.5)
optionalDependencies: optionalDependencies:
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- rollup - rollup
- supports-color - supports-color
vite-plugin-html@3.2.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-plugin-html@3.2.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
colorette: 2.0.20 colorette: 2.0.20
@ -14226,9 +14233,9 @@ snapshots:
html-minifier-terser: 6.1.0 html-minifier-terser: 6.1.0
node-html-parser: 5.4.2 node-html-parser: 5.4.2
pathe: 0.2.0 pathe: 0.2.0
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vite-plugin-inspect@0.8.4(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-plugin-inspect@0.8.4(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
'@antfu/utils': 0.7.8 '@antfu/utils': 0.7.8
'@rollup/pluginutils': 5.1.0(rollup@4.18.0) '@rollup/pluginutils': 5.1.0(rollup@4.18.0)
@ -14239,19 +14246,19 @@ snapshots:
perfect-debounce: 1.0.0 perfect-debounce: 1.0.0
picocolors: 1.0.1 picocolors: 1.0.1
sirv: 2.0.4 sirv: 2.0.4
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
- supports-color - supports-color
vite-plugin-lib-inject-css@2.1.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-plugin-lib-inject-css@2.1.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
'@ast-grep/napi': 0.22.4 '@ast-grep/napi': 0.22.4
magic-string: 0.30.10 magic-string: 0.30.10
picocolors: 1.0.1 picocolors: 1.0.1
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vite-plugin-mock@3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-plugin-mock@3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
bundle-require: 4.2.1(esbuild@0.20.2) bundle-require: 4.2.1(esbuild@0.20.2)
chokidar: 3.6.0 chokidar: 3.6.0
@ -14262,27 +14269,27 @@ snapshots:
mockjs: 1.1.0 mockjs: 1.1.0
path-to-regexp: 6.2.2 path-to-regexp: 6.2.2
picocolors: 1.0.1 picocolors: 1.0.1
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vite-plugin-vue-devtools@7.2.1(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)): vite-plugin-vue-devtools@7.2.1(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)):
dependencies: dependencies:
'@vue/devtools-core': 7.2.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)) '@vue/devtools-core': 7.2.1(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))
'@vue/devtools-kit': 7.2.1(vue@3.4.27(typescript@5.4.5)) '@vue/devtools-kit': 7.2.1(vue@3.4.27(typescript@5.4.5))
'@vue/devtools-shared': 7.2.1 '@vue/devtools-shared': 7.2.1
execa: 8.0.1 execa: 8.0.1
sirv: 2.0.4 sirv: 2.0.4
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vite-plugin-inspect: 0.8.4(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) vite-plugin-inspect: 0.8.4(rollup@4.18.0)(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
vite-plugin-vue-inspector: 5.1.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)) vite-plugin-vue-inspector: 5.1.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))
transitivePeerDependencies: transitivePeerDependencies:
- '@nuxt/kit' - '@nuxt/kit'
- rollup - rollup
- supports-color - supports-color
- vue - vue
vite-plugin-vue-inspector@5.1.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0)): vite-plugin-vue-inspector@5.1.2(vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)):
dependencies: dependencies:
'@babel/core': 7.24.6 '@babel/core': 7.24.6
'@babel/plugin-proposal-decorators': 7.24.6(@babel/core@7.24.6) '@babel/plugin-proposal-decorators': 7.24.6(@babel/core@7.24.6)
@ -14293,11 +14300,11 @@ snapshots:
'@vue/compiler-dom': 3.4.27 '@vue/compiler-dom': 3.4.27
kolorist: 1.8.0 kolorist: 1.8.0
magic-string: 0.30.10 magic-string: 0.30.10
vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vite@5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0): vite@5.2.12(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0):
dependencies: dependencies:
esbuild: 0.20.2 esbuild: 0.20.2
postcss: 8.4.38 postcss: 8.4.38
@ -14305,10 +14312,10 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/node': 20.14.2 '@types/node': 20.14.2
fsevents: 2.3.3 fsevents: 2.3.3
sass: 1.77.4 sass: 1.77.5
terser: 5.31.0 terser: 5.31.0
vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0): vite@6.0.0-alpha.17(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0):
dependencies: dependencies:
esbuild: 0.20.2 esbuild: 0.20.2
postcss: 8.4.38 postcss: 8.4.38
@ -14316,26 +14323,26 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/node': 20.14.2 '@types/node': 20.14.2
fsevents: 2.3.3 fsevents: 2.3.3
sass: 1.77.4 sass: 1.77.5
terser: 5.31.0 terser: 5.31.0
vitepress@1.2.3(@algolia/client-search@4.23.3)(@types/node@20.14.2)(async-validator@4.2.5)(axios@1.7.2)(nprogress@0.2.0)(postcss@8.4.38)(qrcode@1.5.3)(sass@1.77.4)(search-insights@2.14.0)(terser@5.31.0)(typescript@5.4.5): vitepress@1.2.3(@algolia/client-search@4.23.3)(@types/node@20.14.2)(async-validator@4.2.5)(axios@1.7.2)(nprogress@0.2.0)(postcss@8.4.38)(qrcode@1.5.3)(sass@1.77.5)(search-insights@2.14.0)(terser@5.31.0)(typescript@5.4.5):
dependencies: dependencies:
'@docsearch/css': 3.6.0 '@docsearch/css': 3.6.0
'@docsearch/js': 3.6.0(@algolia/client-search@4.23.3)(search-insights@2.14.0) '@docsearch/js': 3.6.0(@algolia/client-search@4.23.3)(search-insights@2.14.0)
'@shikijs/core': 1.6.2 '@shikijs/core': 1.6.2
'@shikijs/transformers': 1.6.2 '@shikijs/transformers': 1.6.2
'@types/markdown-it': 14.1.1 '@types/markdown-it': 14.1.1
'@vitejs/plugin-vue': 5.0.5(vite@5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5)) '@vitejs/plugin-vue': 5.0.5(vite@5.2.12(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0))(vue@3.4.27(typescript@5.4.5))
'@vue/devtools-api': 7.2.1(vue@3.4.27(typescript@5.4.5)) '@vue/devtools-api': 7.2.1(vue@3.4.27(typescript@5.4.5))
'@vue/shared': 3.4.27 '@vue/shared': 3.4.27
'@vueuse/core': 10.10.0(vue@3.4.27(typescript@5.4.5)) '@vueuse/core': 10.10.1(vue@3.4.27(typescript@5.4.5))
'@vueuse/integrations': 10.10.0(async-validator@4.2.5)(axios@1.7.2)(focus-trap@7.5.4)(nprogress@0.2.0)(qrcode@1.5.3)(vue@3.4.27(typescript@5.4.5)) '@vueuse/integrations': 10.10.1(async-validator@4.2.5)(axios@1.7.2)(focus-trap@7.5.4)(nprogress@0.2.0)(qrcode@1.5.3)(vue@3.4.27(typescript@5.4.5))
focus-trap: 7.5.4 focus-trap: 7.5.4
mark.js: 8.11.1 mark.js: 8.11.1
minisearch: 6.3.0 minisearch: 6.3.0
shiki: 1.6.2 shiki: 1.6.2
vite: 5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 5.2.12(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vue: 3.4.27(typescript@5.4.5) vue: 3.4.27(typescript@5.4.5)
optionalDependencies: optionalDependencies:
postcss: 8.4.38 postcss: 8.4.38
@ -14366,7 +14373,7 @@ snapshots:
- typescript - typescript
- universal-cookie - universal-cookie
vitest@2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.4)(terser@5.31.0): vitest@2.0.0-beta.3(@types/node@20.14.2)(jsdom@24.1.0)(sass@1.77.5)(terser@5.31.0):
dependencies: dependencies:
'@vitest/expect': 2.0.0-beta.3 '@vitest/expect': 2.0.0-beta.3
'@vitest/runner': 2.0.0-beta.3 '@vitest/runner': 2.0.0-beta.3
@ -14382,8 +14389,8 @@ snapshots:
std-env: 3.7.0 std-env: 3.7.0
tinybench: 2.8.0 tinybench: 2.8.0
tinypool: 0.9.0 tinypool: 0.9.0
vite: 5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite: 5.2.12(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
vite-node: 2.0.0-beta.3(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0) vite-node: 2.0.0-beta.3(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.0)
why-is-node-running: 2.2.2 why-is-node-running: 2.2.2
optionalDependencies: optionalDependencies:
'@types/node': 20.14.2 '@types/node': 20.14.2