refactor(project): remove the use of core internal bem syntax
parent
fed422e187
commit
ebf73b2df9
|
@ -35,6 +35,7 @@
|
||||||
"@vben/chart-ui": "workspace:*",
|
"@vben/chart-ui": "workspace:*",
|
||||||
"@vben/common-ui": "workspace:*",
|
"@vben/common-ui": "workspace:*",
|
||||||
"@vben/constants": "workspace:*",
|
"@vben/constants": "workspace:*",
|
||||||
|
"@vben/hooks": "workspace:*",
|
||||||
"@vben/icons": "workspace:*",
|
"@vben/icons": "workspace:*",
|
||||||
"@vben/layouts": "workspace:*",
|
"@vben/layouts": "workspace:*",
|
||||||
"@vben/styles": "workspace:*",
|
"@vben/styles": "workspace:*",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { AnalysisOverviewItem } from '@vben/common-ui';
|
import type { AnalysisOverviewItem } from '@vben/common-ui';
|
||||||
import type { TabsOption } from '@vben/types';
|
import type { TabOption } from '@vben/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AnalysisChartCard,
|
AnalysisChartCard,
|
||||||
|
@ -53,7 +53,7 @@ const overviewItems: AnalysisOverviewItem[] = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const chartTabs: TabsOption[] = [
|
const chartTabs: TabOption[] = [
|
||||||
{
|
{
|
||||||
label: '流量趋势',
|
label: '流量趋势',
|
||||||
value: 'trends',
|
value: 'trends',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { TabItem } from '@vben-core/typings';
|
import type { TabDefinition } from '@vben-core/typings';
|
||||||
import type { RouteRecordNormalized, Router } from 'vue-router';
|
import type { RouteRecordNormalized, Router } from 'vue-router';
|
||||||
|
|
||||||
import { toRaw } from 'vue';
|
import { toRaw } from 'vue';
|
||||||
|
@ -27,7 +27,7 @@ interface TabsState {
|
||||||
/**
|
/**
|
||||||
* @zh_CN 当前打开的标签页列表
|
* @zh_CN 当前打开的标签页列表
|
||||||
*/
|
*/
|
||||||
tabs: TabItem[];
|
tabs: TabDefinition[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,7 +49,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 关闭标签页
|
* @zh_CN 关闭标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
_close(tab: TabItem) {
|
_close(tab: TabDefinition) {
|
||||||
const { fullPath } = tab;
|
const { fullPath } = tab;
|
||||||
if (isAffixTab(tab)) {
|
if (isAffixTab(tab)) {
|
||||||
return;
|
return;
|
||||||
|
@ -72,7 +72,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 跳转到标签页
|
* @zh_CN 跳转到标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
async _goToTab(tab: TabItem, router: Router) {
|
async _goToTab(tab: TabDefinition, router: Router) {
|
||||||
const { params, path, query } = tab;
|
const { params, path, query } = tab;
|
||||||
const toParams = {
|
const toParams = {
|
||||||
params: params || {},
|
params: params || {},
|
||||||
|
@ -85,7 +85,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 添加标签页
|
* @zh_CN 添加标签页
|
||||||
* @param routeTab
|
* @param routeTab
|
||||||
*/
|
*/
|
||||||
addTab(routeTab: TabItem) {
|
addTab(routeTab: TabDefinition) {
|
||||||
const tab = cloneTab(routeTab);
|
const tab = cloneTab(routeTab);
|
||||||
if (!isTabShown(tab)) {
|
if (!isTabShown(tab)) {
|
||||||
return;
|
return;
|
||||||
|
@ -116,7 +116,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 关闭左侧标签页
|
* @zh_CN 关闭左侧标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
async closeLeftTabs(tab: TabItem) {
|
async closeLeftTabs(tab: TabDefinition) {
|
||||||
const index = this.tabs.findIndex(
|
const index = this.tabs.findIndex(
|
||||||
(item) => getTabPath(item) === getTabPath(tab),
|
(item) => getTabPath(item) === getTabPath(tab),
|
||||||
);
|
);
|
||||||
|
@ -139,7 +139,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 关闭其他标签页
|
* @zh_CN 关闭其他标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
async closeOtherTabs(tab: TabItem) {
|
async closeOtherTabs(tab: TabDefinition) {
|
||||||
const closePaths = this.tabs.map((item) => getTabPath(item));
|
const closePaths = this.tabs.map((item) => getTabPath(item));
|
||||||
|
|
||||||
const paths: string[] = [];
|
const paths: string[] = [];
|
||||||
|
@ -162,7 +162,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 关闭右侧标签页
|
* @zh_CN 关闭右侧标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
async closeRightTabs(tab: TabItem) {
|
async closeRightTabs(tab: TabDefinition) {
|
||||||
const index = this.tabs.findIndex(
|
const index = this.tabs.findIndex(
|
||||||
(item) => getTabPath(item) === getTabPath(tab),
|
(item) => getTabPath(item) === getTabPath(tab),
|
||||||
);
|
);
|
||||||
|
@ -185,7 +185,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @param tab
|
* @param tab
|
||||||
* @param router
|
* @param router
|
||||||
*/
|
*/
|
||||||
async closeTab(tab: TabItem, router: Router) {
|
async closeTab(tab: TabDefinition, router: Router) {
|
||||||
const { currentRoute } = router;
|
const { currentRoute } = router;
|
||||||
|
|
||||||
// 关闭不是激活选项卡
|
// 关闭不是激活选项卡
|
||||||
|
@ -230,7 +230,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 固定标签页
|
* @zh_CN 固定标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
async pinTab(tab: TabItem) {
|
async pinTab(tab: TabDefinition) {
|
||||||
const index = this.tabs.findIndex(
|
const index = this.tabs.findIndex(
|
||||||
(item) => getTabPath(item) === getTabPath(tab),
|
(item) => getTabPath(item) === getTabPath(tab),
|
||||||
);
|
);
|
||||||
|
@ -282,7 +282,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
* @zh_CN 取消固定标签页
|
* @zh_CN 取消固定标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
async unpinTab(tab: TabItem) {
|
async unpinTab(tab: TabDefinition) {
|
||||||
const index = this.tabs.findIndex(
|
const index = this.tabs.findIndex(
|
||||||
(item) => getTabPath(item) === getTabPath(tab),
|
(item) => getTabPath(item) === getTabPath(tab),
|
||||||
);
|
);
|
||||||
|
@ -318,7 +318,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
affixTabs(): TabItem[] {
|
affixTabs(): TabDefinition[] {
|
||||||
return this.tabs.filter((tab) => isAffixTab(tab));
|
return this.tabs.filter((tab) => isAffixTab(tab));
|
||||||
},
|
},
|
||||||
getCachedTabs(): string[] {
|
getCachedTabs(): string[] {
|
||||||
|
@ -327,7 +327,7 @@ const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||||
getExcludeCachedTabs(): string[] {
|
getExcludeCachedTabs(): string[] {
|
||||||
return [...this.excludeCachedTabs];
|
return [...this.excludeCachedTabs];
|
||||||
},
|
},
|
||||||
getTabs(): TabItem[] {
|
getTabs(): TabDefinition[] {
|
||||||
const affixTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
const affixTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
||||||
const normalTabs = this.tabs.filter((tab) => !isAffixTab(tab));
|
const normalTabs = this.tabs.filter((tab) => !isAffixTab(tab));
|
||||||
return [...affixTabs, ...normalTabs].filter(Boolean);
|
return [...affixTabs, ...normalTabs].filter(Boolean);
|
||||||
|
@ -359,7 +359,7 @@ if (hot) {
|
||||||
* @zh_CN 克隆路由,防止路由被修改
|
* @zh_CN 克隆路由,防止路由被修改
|
||||||
* @param route
|
* @param route
|
||||||
*/
|
*/
|
||||||
function cloneTab(route: TabItem): TabItem {
|
function cloneTab(route: TabDefinition): TabDefinition {
|
||||||
if (!route) {
|
if (!route) {
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ function cloneTab(route: TabItem): TabItem {
|
||||||
* @zh_CN 是否是固定标签页
|
* @zh_CN 是否是固定标签页
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
function isAffixTab(tab: TabItem) {
|
function isAffixTab(tab: TabDefinition) {
|
||||||
return tab?.meta?.affixTab ?? false;
|
return tab?.meta?.affixTab ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ function isAffixTab(tab: TabItem) {
|
||||||
* @zh_CN 是否显示标签
|
* @zh_CN 是否显示标签
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
function isTabShown(tab: TabItem) {
|
function isTabShown(tab: TabDefinition) {
|
||||||
return !tab.meta.hideInTab;
|
return !tab.meta.hideInTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,8 +396,8 @@ function isTabShown(tab: TabItem) {
|
||||||
* @zh_CN 获取标签页路径
|
* @zh_CN 获取标签页路径
|
||||||
* @param tab
|
* @param tab
|
||||||
*/
|
*/
|
||||||
function getTabPath(tab: RouteRecordNormalized | TabItem) {
|
function getTabPath(tab: RouteRecordNormalized | TabDefinition) {
|
||||||
return decodeURIComponent((tab as TabItem).fullPath || tab.path);
|
return decodeURIComponent((tab as TabDefinition).fullPath || tab.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function routeToTab(route: RouteRecordNormalized) {
|
function routeToTab(route: RouteRecordNormalized) {
|
||||||
|
@ -405,7 +405,7 @@ function routeToTab(route: RouteRecordNormalized) {
|
||||||
meta: route.meta,
|
meta: route.meta,
|
||||||
name: route.name,
|
name: route.name,
|
||||||
path: route.path,
|
path: route.path,
|
||||||
} as TabItem;
|
} as TabDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { useCoreTabbarStore };
|
export { useCoreTabbarStore };
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sortablejs": "^1.15.2",
|
"radix-vue": "^1.9.1",
|
||||||
"vue": "^3.4.31"
|
"sortablejs": "^1.15.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/sortablejs": "^1.15.8"
|
"@types/sortablejs": "^1.15.8"
|
||||||
|
|
|
@ -1 +1,8 @@
|
||||||
|
export * from './use-namespace';
|
||||||
export * from './use-sortable';
|
export * from './use-sortable';
|
||||||
|
export {
|
||||||
|
useEmitAsProps,
|
||||||
|
useForwardExpose,
|
||||||
|
useForwardProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue';
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { useSortable } from './use-sortable';
|
||||||
|
|
||||||
describe('useSortable', () => {
|
describe('useSortable', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.mock('sortablejs', () => ({
|
vi.mock('sortablejs/modular/sortable.complete.esm.js', () => ({
|
||||||
default: {
|
default: {
|
||||||
create: vi.fn(),
|
create: vi.fn(),
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,10 @@ describe('useSortable', () => {
|
||||||
await initializeSortable();
|
await initializeSortable();
|
||||||
|
|
||||||
// Import sortablejs to access the mocked create function
|
// Import sortablejs to access the mocked create function
|
||||||
const Sortable = await import('sortablejs');
|
const Sortable = await import(
|
||||||
|
// @ts-expect-error - This is a dynamic import
|
||||||
|
'sortablejs/modular/sortable.complete.esm.js'
|
||||||
|
);
|
||||||
|
|
||||||
// Verify that Sortable.create was called with the correct parameters
|
// Verify that Sortable.create was called with the correct parameters
|
||||||
expect(Sortable.default.create).toHaveBeenCalledTimes(1);
|
expect(Sortable.default.create).toHaveBeenCalledTimes(1);
|
||||||
|
|
|
@ -6,7 +6,6 @@ export * from './dom';
|
||||||
export * from './inference';
|
export * from './inference';
|
||||||
export * from './letter';
|
export * from './letter';
|
||||||
export * from './merge';
|
export * from './merge';
|
||||||
export * from './namespace';
|
|
||||||
export * from './nprogress';
|
export * from './nprogress';
|
||||||
export * from './tree';
|
export * from './tree';
|
||||||
export * from './unique';
|
export * from './unique';
|
||||||
|
|
|
@ -5,7 +5,7 @@ interface BasicOption {
|
||||||
|
|
||||||
interface SelectOption extends BasicOption {}
|
interface SelectOption extends BasicOption {}
|
||||||
|
|
||||||
interface TabsOption extends BasicOption {}
|
interface TabOption extends BasicOption {}
|
||||||
|
|
||||||
interface BasicUserInfo {
|
interface BasicUserInfo {
|
||||||
/**
|
/**
|
||||||
|
@ -30,4 +30,4 @@ interface BasicUserInfo {
|
||||||
username: string;
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { BasicOption, BasicUserInfo, SelectOption, TabsOption };
|
export type { BasicOption, BasicUserInfo, SelectOption, TabOption };
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import type { RouteLocationNormalized } from 'vue-router';
|
import type { RouteLocationNormalized } from 'vue-router';
|
||||||
|
|
||||||
export type TabItem = RouteLocationNormalized;
|
export type TabDefinition = RouteLocationNormalized;
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { defineBuildConfig } from 'unbuild';
|
||||||
|
|
||||||
|
export default defineBuildConfig({
|
||||||
|
clean: true,
|
||||||
|
declaration: true,
|
||||||
|
entries: [
|
||||||
|
{
|
||||||
|
builder: 'mkdist',
|
||||||
|
input: './src',
|
||||||
|
pattern: ['**/*'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
builder: 'mkdist',
|
||||||
|
input: './src',
|
||||||
|
loaders: ['vue'],
|
||||||
|
pattern: ['**/*.vue'],
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// builder: 'mkdist',
|
||||||
|
// format: 'cjs',
|
||||||
|
// input: './src',
|
||||||
|
// loaders: ['js'],
|
||||||
|
// pattern: ['**/*.ts'],
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
builder: 'mkdist',
|
||||||
|
format: 'esm',
|
||||||
|
input: './src',
|
||||||
|
loaders: ['js'],
|
||||||
|
pattern: ['**/*.ts'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
|
@ -11,7 +11,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm vite build",
|
"build": "pnpm unbuild",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vben-core/design": "workspace:*",
|
"@vben-core/hooks": "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/toolkit": "workspace:*",
|
||||||
|
|
|
@ -3,8 +3,8 @@ import type { MenuItemProps, MenuItemRegistered } from '../interface';
|
||||||
|
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, useSlots } from 'vue';
|
import { computed, onBeforeUnmount, onMounted, reactive, useSlots } from 'vue';
|
||||||
|
|
||||||
|
import { useNamespace } from '@vben-core/hooks';
|
||||||
import { VbenIcon, VbenMenuBadge, VbenTooltip } from '@vben-core/shadcn-ui';
|
import { VbenIcon, VbenMenuBadge, VbenTooltip } from '@vben-core/shadcn-ui';
|
||||||
import { useNamespace } from '@vben-core/toolkit';
|
|
||||||
|
|
||||||
import { useMenu, useMenuContext, useSubMenuContext } from '../hooks';
|
import { useMenu, useMenuContext, useSubMenuContext } from '../hooks';
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@ import {
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
|
|
||||||
|
import { useNamespace } from '@vben-core/hooks';
|
||||||
import { IcRoundMoreHoriz } from '@vben-core/iconify';
|
import { IcRoundMoreHoriz } from '@vben-core/iconify';
|
||||||
import { isHttpUrl, useNamespace } from '@vben-core/toolkit';
|
import { isHttpUrl } from '@vben-core/toolkit';
|
||||||
|
|
||||||
import { UseResizeObserverReturn, useResizeObserver } from '@vueuse/core';
|
import { UseResizeObserverReturn, useResizeObserver } from '@vueuse/core';
|
||||||
|
|
||||||
|
@ -348,3 +349,512 @@ function removeMenuItem(item: MenuItemRegistered) {
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
$namespace: vben;
|
||||||
|
|
||||||
|
@mixin menu-item-active {
|
||||||
|
color: var(--menu-item-active-color);
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--menu-item-active-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin menu-item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
// gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
height: var(--menu-item-height);
|
||||||
|
padding: var(--menu-item-padding-y) var(--menu-item-padding-x);
|
||||||
|
margin: 0 var(--menu-item-margin-x) var(--menu-item-margin-y)
|
||||||
|
var(--menu-item-margin-x);
|
||||||
|
font-size: var(--menu-font-size);
|
||||||
|
color: var(--menu-item-color);
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
list-style: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--menu-item-background-color);
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--menu-item-radius);
|
||||||
|
transition:
|
||||||
|
background 0.15s ease,
|
||||||
|
color 0.15s ease,
|
||||||
|
padding 0.15s ease,
|
||||||
|
border-color 0.15s ease;
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background: none !important;
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-menu__icon {
|
||||||
|
transition: transform 0.25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.#{$namespace}-menu__icon {
|
||||||
|
transform: scale(1.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin menu-title {
|
||||||
|
max-width: var(--menu-title-width);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-menu__popup-container,
|
||||||
|
.#{$namespace}-menu {
|
||||||
|
--menu-title-width: 140px;
|
||||||
|
--menu-item-icon-width: 20px;
|
||||||
|
--menu-item-height: 38px;
|
||||||
|
--menu-item-padding-y: 26px;
|
||||||
|
--menu-item-padding-x: 12px;
|
||||||
|
--menu-item-popup-padding-y: 22px;
|
||||||
|
--menu-item-popup-padding-x: 12px;
|
||||||
|
--menu-item-margin-y: 4px;
|
||||||
|
--menu-item-margin-x: 0px;
|
||||||
|
--menu-item-collapse-padding-y: 25px;
|
||||||
|
--menu-item-collapse-padding-x: 0px;
|
||||||
|
--menu-item-collapse-margin-y: 4px;
|
||||||
|
--menu-item-collapse-margin-x: 0px;
|
||||||
|
--menu-item-radius: 0px;
|
||||||
|
--menu-item-indent: 16px;
|
||||||
|
--menu-font-size: 14px;
|
||||||
|
--menu-dark-background: 0deg 0% 100% / 10%;
|
||||||
|
--menu-light-background: 192deg 1% 93%;
|
||||||
|
|
||||||
|
&.is-dark {
|
||||||
|
--menu-background-color: hsl(var(--menu-dark));
|
||||||
|
// --menu-submenu-opened-background-color: hsl(var(--menu-opened-dark));
|
||||||
|
--menu-item-background-color: var(--menu-background-color);
|
||||||
|
--menu-item-color: hsl(var(--dark-foreground) / 80%);
|
||||||
|
--menu-item-hover-color: hsl(var(--primary-foreground));
|
||||||
|
--menu-item-hover-background-color: hsl(var(--menu-dark-background));
|
||||||
|
--menu-item-active-color: hsl(var(--primary-foreground));
|
||||||
|
--menu-item-active-background-color: hsl(var(--primary));
|
||||||
|
--menu-submenu-hover-color: hsl(var(--dark-foreground));
|
||||||
|
--menu-submenu-hover-background-color: hsl(var(--menu-dark-background));
|
||||||
|
--menu-submenu-active-color: hsl(var(--dark-foreground));
|
||||||
|
--menu-submenu-active-background-color: transparent;
|
||||||
|
--menu-submenu-background-color: var(--menu-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-light {
|
||||||
|
--menu-background-color: hsl(var(--menu));
|
||||||
|
// --menu-submenu-opened-background-color: hsl(var(--menu-opened));
|
||||||
|
--menu-item-background-color: var(--menu-background-color);
|
||||||
|
--menu-item-color: hsl(var(--foreground));
|
||||||
|
--menu-item-hover-color: var(--menu-item-color);
|
||||||
|
--menu-item-hover-background-color: hsl(var(--menu-light-background));
|
||||||
|
--menu-item-active-color: hsl(var(--primary-foreground));
|
||||||
|
--menu-item-active-background-color: hsl(var(--primary));
|
||||||
|
--menu-submenu-hover-color: hsl(var(--primary));
|
||||||
|
--menu-submenu-hover-background-color: hsl(var(--menu-light-background));
|
||||||
|
--menu-submenu-active-color: hsl(var(--primary));
|
||||||
|
--menu-submenu-active-background-color: transparent;
|
||||||
|
--menu-submenu-background-color: var(--menu-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-rounded {
|
||||||
|
--menu-item-margin-x: 8px;
|
||||||
|
--menu-item-collapse-margin-x: 6px;
|
||||||
|
--menu-item-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-horizontal:not(.is-rounded) {
|
||||||
|
--menu-item-height: 60px;
|
||||||
|
--menu-item-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-horizontal.is-rounded {
|
||||||
|
--menu-item-height: 40px;
|
||||||
|
--menu-item-radius: 6px;
|
||||||
|
--menu-item-padding-x: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .vben-menu__popup,
|
||||||
|
&.is-horizontal {
|
||||||
|
--menu-item-padding-y: 0px;
|
||||||
|
--menu-item-padding-x: 10px;
|
||||||
|
--menu-item-margin-y: 0px;
|
||||||
|
--menu-item-margin-x: 1px;
|
||||||
|
--menu-background-color: transparent;
|
||||||
|
|
||||||
|
&.is-dark {
|
||||||
|
--menu-item-hover-color: var(--foreground);
|
||||||
|
--menu-item-hover-background-color: hsl(var(--menu-dark-background));
|
||||||
|
--menu-item-active-color: hsl(var(--foreground));
|
||||||
|
--menu-item-active-background-color: hsl(var(--menu-dark-background));
|
||||||
|
--menu-submenu-active-color: hsl(var(--foreground));
|
||||||
|
--menu-submenu-active-background-color: hsl(var(--menu-dark-background));
|
||||||
|
--menu-submenu-hover-color: hsl(var(--foreground));
|
||||||
|
--menu-submenu-hover-background-color: hsl(var(--menu-dark-background));
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-light {
|
||||||
|
--menu-item-active-color: hsl(var(--foreground));
|
||||||
|
--menu-item-active-background-color: hsl(var(--menu-light-background));
|
||||||
|
--menu-item-hover-background-color: hsl(var(--menu-light-background));
|
||||||
|
--menu-item-hover-color: hsl(var(--primary));
|
||||||
|
--menu-submenu-hover-color: hsl(var(--primary));
|
||||||
|
--menu-submenu-hover-background-color: hsl(var(--menu-light-background));
|
||||||
|
--menu-submenu-active-color: hsl(var(--foreground));
|
||||||
|
--menu-submenu-active-background-color: hsl(var(--menu-light-background));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-menu {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
background: hsl(var(--menu-background-color));
|
||||||
|
|
||||||
|
// 垂直菜单
|
||||||
|
&.is-vertical {
|
||||||
|
&:not(.#{$namespace}-menu.is-collapse) {
|
||||||
|
& .#{$namespace}-menu-item,
|
||||||
|
& .#{$namespace}-sub-menu-content,
|
||||||
|
& .#{$namespace}-menu-item-group__title {
|
||||||
|
padding-left: calc(
|
||||||
|
var(--menu-item-indent) + var(--menu-level) * var(--menu-item-indent)
|
||||||
|
);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .#{$namespace}-sub-menu {
|
||||||
|
// .#{$namespace}-menu {
|
||||||
|
// background: var(--menu-submenu-opened-background-color);
|
||||||
|
|
||||||
|
// .#{$namespace}-sub-menu,
|
||||||
|
// .#{$namespace}-menu-item:not(.is-active),
|
||||||
|
// .#{$namespace}-sub-menu-content:not(.is-active) {
|
||||||
|
// background: var(--menu-submenu-opened-background-color);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
& > .#{$namespace}-menu {
|
||||||
|
& > .#{$namespace}-menu-item {
|
||||||
|
padding-left: calc(
|
||||||
|
0px + var(--menu-item-indent) + var(--menu-level) *
|
||||||
|
var(--menu-item-indent)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .#{$namespace}-sub-menu-content {
|
||||||
|
padding-left: calc(var(--menu-item-indent) - 8px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > .#{$namespace}-menu-item {
|
||||||
|
padding-left: calc(var(--menu-item-indent) - 8px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-horizontal {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
max-width: 100%;
|
||||||
|
height: var(--height-horizontal-height);
|
||||||
|
border-right: none;
|
||||||
|
|
||||||
|
.#{$namespace}-menu-item {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: var(--menu-item-height);
|
||||||
|
padding-right: calc(var(--menu-item-padding-x) + 6px);
|
||||||
|
margin: 0;
|
||||||
|
margin-right: 2px;
|
||||||
|
// border-bottom: 2px solid transparent;
|
||||||
|
border-radius: var(--menu-item-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .#{$namespace}-sub-menu {
|
||||||
|
height: var(--menu-item-height);
|
||||||
|
margin-right: 2px;
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:hover {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .#{$namespace}-sub-menu-content {
|
||||||
|
height: 100%;
|
||||||
|
padding-right: 40px;
|
||||||
|
// border-bottom: 2px solid transparent;
|
||||||
|
border-radius: var(--menu-item-radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .#{$namespace}-menu-item:not(.is-disabled):hover,
|
||||||
|
& .#{$namespace}-menu-item:not(.is-disabled):focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .#{$namespace}-menu-item.is-active {
|
||||||
|
color: var(--menu-item-active-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// &.is-light {
|
||||||
|
// & > .#{$namespace}-sub-menu {
|
||||||
|
// &.is-active {
|
||||||
|
// border-bottom: 2px solid var(--menu-item-active-color);
|
||||||
|
// }
|
||||||
|
// &:not(.is-active) .#{$namespace}-sub-menu-content {
|
||||||
|
// &:hover {
|
||||||
|
// border-bottom: 2px solid var(--menu-item-active-color);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// & > .#{$namespace}-menu-item.is-active {
|
||||||
|
// border-bottom: 2px solid var(--menu-item-active-color);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// & .#{$namespace}-menu-item:not(.is-disabled):hover,
|
||||||
|
// & .#{$namespace}-menu-item:not(.is-disabled):focus {
|
||||||
|
// border-bottom: 2px solid var(--menu-item-active-color);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
// 折叠菜单
|
||||||
|
|
||||||
|
&.is-collapse {
|
||||||
|
.#{$namespace}-menu__icon {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.#{$namespace}-sub-menu__icon-arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-sub-menu-content,
|
||||||
|
.#{$namespace}-menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: var(--menu-item-collapse-padding-y)
|
||||||
|
var(--menu-item-collapse-padding-x);
|
||||||
|
margin: var(--menu-item-collapse-margin-y)
|
||||||
|
var(--menu-item-collapse-margin-x);
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background: var(--menu-item-active-background-color) !important;
|
||||||
|
border-radius: var(--menu-item-radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-light {
|
||||||
|
.#{$namespace}-sub-menu-content,
|
||||||
|
.#{$namespace}-menu-item {
|
||||||
|
&.is-active {
|
||||||
|
color: hsl(var(--primary-foreground)) !important;
|
||||||
|
background: var(--menu-item-active-background-color) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-rounded {
|
||||||
|
.#{$namespace}-sub-menu-content,
|
||||||
|
.#{$namespace}-menu-item {
|
||||||
|
&.is-collapse-show-title {
|
||||||
|
// padding: 32px 0 !important;
|
||||||
|
margin: 4px 8px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__popup-container {
|
||||||
|
max-width: 240px;
|
||||||
|
height: unset;
|
||||||
|
padding: 0;
|
||||||
|
background: var(--menu-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__popup {
|
||||||
|
padding: 4px 0;
|
||||||
|
border-radius: var(--menu-item-radius);
|
||||||
|
|
||||||
|
.#{$namespace}-sub-menu-content,
|
||||||
|
.#{$namespace}-menu-item {
|
||||||
|
padding: var(--menu-item-popup-padding-y) var(--menu-item-popup-padding-x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
// width: var(--menu-item-icon-width);
|
||||||
|
max-height: var(--menu-item-icon-width);
|
||||||
|
margin-right: 12px;
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-menu-item {
|
||||||
|
fill: var(--menu-item-color);
|
||||||
|
stroke: var(--menu-item-color);
|
||||||
|
|
||||||
|
@include menu-item;
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
fill: var(--menu-item-active-color);
|
||||||
|
stroke: var(--menu-item-active-color);
|
||||||
|
|
||||||
|
@include menu-item-active;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: var(--menu-item-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-collapse-show-title {
|
||||||
|
padding: 32px 0 !important;
|
||||||
|
// margin: 4px 8px !important;
|
||||||
|
.#{$namespace}-menu-tooltip__trigger {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.#{$namespace}-menu__icon {
|
||||||
|
display: block;
|
||||||
|
font-size: 20px !important;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-menu__name {
|
||||||
|
display: inline-flex;
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.is-active):hover {
|
||||||
|
color: var(--menu-item-hover-color);
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--menu-item-hover-background-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-menu-tooltip__trigger {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 var(--menu-item-padding-x);
|
||||||
|
font-size: var(--menu-font-size);
|
||||||
|
line-height: var(--menu-item-height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-sub-menu {
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
background: var(--menu-submenu-background-color);
|
||||||
|
fill: var(--menu-item-color);
|
||||||
|
stroke: var(--menu-item-color);
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
div[data-state='open'] > .#{$namespace}-sub-menu-content,
|
||||||
|
> .#{$namespace}-sub-menu-content {
|
||||||
|
color: var(--menu-submenu-active-color);
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--menu-submenu-active-background-color);
|
||||||
|
fill: var(--menu-submenu-active-color);
|
||||||
|
stroke: var(--menu-submenu-active-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-sub-menu-content {
|
||||||
|
height: var(--menu-item-height);
|
||||||
|
|
||||||
|
@include menu-item;
|
||||||
|
|
||||||
|
&__icon-arrow {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 6px;
|
||||||
|
width: inherit;
|
||||||
|
margin-top: -8px;
|
||||||
|
margin-right: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: normal;
|
||||||
|
opacity: 1;
|
||||||
|
transition: transform 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
@include menu-title;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-collapse-show-title {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 32px 0 !important;
|
||||||
|
// margin: 4px 8px !important;
|
||||||
|
.#{$namespace}-menu__icon {
|
||||||
|
display: block;
|
||||||
|
font-size: 20px !important;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
.#{$namespace}-sub-menu-content__title {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-more {
|
||||||
|
padding-right: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// &:not(.is-active):hover {
|
||||||
|
&:hover {
|
||||||
|
color: var(--menu-submenu-hover-color);
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--menu-submenu-hover-background-color) !important;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: var(--menu-submenu-hover-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -3,8 +3,8 @@ import type { MenuRecordRaw } from '@vben-core/typings';
|
||||||
|
|
||||||
import type { NormalMenuProps } from './normal-menu';
|
import type { NormalMenuProps } from './normal-menu';
|
||||||
|
|
||||||
|
import { useNamespace } from '@vben-core/hooks';
|
||||||
import { VbenIcon } from '@vben-core/shadcn-ui';
|
import { VbenIcon } from '@vben-core/shadcn-ui';
|
||||||
import { useNamespace } from '@vben-core/toolkit';
|
|
||||||
|
|
||||||
interface Props extends NormalMenuProps {}
|
interface Props extends NormalMenuProps {}
|
||||||
|
|
||||||
|
@ -58,9 +58,9 @@ function handleMouseenter(menu: MenuRecordRaw) {
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '@vben-core/design/bem';
|
$namespace: vben;
|
||||||
|
|
||||||
@include b('normal-menu') {
|
.#{$namespace}-normal-menu {
|
||||||
--menu-item-margin-y: 4px;
|
--menu-item-margin-y: 4px;
|
||||||
--menu-item-margin-x: 0px;
|
--menu-item-margin-x: 0px;
|
||||||
--menu-item-padding-y: 11px;
|
--menu-item-padding-y: 11px;
|
||||||
|
@ -70,18 +70,37 @@ function handleMouseenter(menu: MenuRecordRaw) {
|
||||||
|
|
||||||
height: calc(100% - 4px);
|
height: calc(100% - 4px);
|
||||||
|
|
||||||
@include is('rounded') {
|
&.is-rounded {
|
||||||
--menu-item-radius: 6px;
|
--menu-item-radius: 6px;
|
||||||
--menu-item-margin-x: 8px;
|
--menu-item-margin-x: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include is('dark') {
|
&.is-dark {
|
||||||
.#{$namespace}-normal-menu__item {
|
.#{$namespace}-normal-menu__item {
|
||||||
color: hsl(var(--dark-foreground) / 80%);
|
color: hsl(var(--dark-foreground) / 80%);
|
||||||
|
|
||||||
|
&:not(.is-active):hover {
|
||||||
|
color: hsl(var(--primary-foreground));
|
||||||
|
background-color: hsl(var(--menu-dark-background));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include e('item') {
|
&.is-collapse {
|
||||||
|
.#{$namespace}-normal-menu__name {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$namespace}-normal-menu__icon {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -100,7 +119,7 @@ function handleMouseenter(menu: MenuRecordRaw) {
|
||||||
padding 0.15s ease,
|
padding 0.15s ease,
|
||||||
border-color 0.15s ease;
|
border-color 0.15s ease;
|
||||||
|
|
||||||
@include is('active') {
|
&.is-active {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: hsl(var(--primary-foreground));
|
color: hsl(var(--primary-foreground));
|
||||||
background-color: hsl(var(--primary));
|
background-color: hsl(var(--primary));
|
||||||
|
@ -126,36 +145,13 @@ function handleMouseenter(menu: MenuRecordRaw) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include is('dark') {
|
&__icon {
|
||||||
.#{$namespace}-normal-menu__item {
|
|
||||||
&:not(.is-active):hover {
|
|
||||||
color: hsl(var(--primary-foreground));
|
|
||||||
background-color: hsl(var(--menu-dark-background));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include is('collapse') {
|
|
||||||
.#{$namespace}-normal-menu__name {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.#{$namespace}-normal-menu__icon {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include e('icon') {
|
|
||||||
max-height: 20px;
|
max-height: 20px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
transition: all 0.25s ease;
|
transition: all 0.25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include e('name') {
|
&__name {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
|
@ -3,12 +3,12 @@ import type { MenuItemProps } from '../interface';
|
||||||
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { useNamespace } from '@vben-core/hooks';
|
||||||
import {
|
import {
|
||||||
IcRoundChevronRight,
|
IcRoundChevronRight,
|
||||||
IcRoundKeyboardArrowDown,
|
IcRoundKeyboardArrowDown,
|
||||||
} from '@vben-core/iconify';
|
} from '@vben-core/iconify';
|
||||||
import { VbenIcon } from '@vben-core/shadcn-ui';
|
import { VbenIcon } from '@vben-core/shadcn-ui';
|
||||||
import { useNamespace } from '@vben-core/toolkit';
|
|
||||||
|
|
||||||
import { useMenuContext } from '../hooks';
|
import { useMenuContext } from '../hooks';
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ import type {
|
||||||
|
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
import { useNamespace } from '@vben-core/hooks';
|
||||||
import { VbenHoverCard } from '@vben-core/shadcn-ui';
|
import { VbenHoverCard } from '@vben-core/shadcn-ui';
|
||||||
import { useNamespace } from '@vben-core/toolkit';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createSubMenuContext,
|
createSubMenuContext,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import './styles/index.scss';
|
|
||||||
|
|
||||||
export * from './components/normal-menu';
|
export * from './components/normal-menu';
|
||||||
export type * from './interface';
|
export type * from './interface';
|
||||||
export { default as Menu } from './menu.vue';
|
export { default as Menu } from './menu.vue';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { MenuRecordRaw } from '@vben-core/typings';
|
import type { MenuRecordRaw } from '@vben-core/typings';
|
||||||
|
|
||||||
import { useForwardProps } from '@vben-core/shadcn-ui';
|
import { useForwardProps } from '@vben-core/hooks';
|
||||||
|
|
||||||
import { Menu } from './components';
|
import { Menu } from './components';
|
||||||
import { MenuProps } from './interface';
|
import { MenuProps } from './interface';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import '@vben-core/design/bem';
|
$namespace: vben;
|
||||||
|
|
||||||
.#{$namespace}-menu__popup-container,
|
.#{$namespace}-menu__popup-container,
|
||||||
.#{$namespace}-menu {
|
.#{$namespace}-menu {
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
padding 0.15s ease,
|
padding 0.15s ease,
|
||||||
border-color 0.15s ease;
|
border-color 0.15s ease;
|
||||||
|
|
||||||
@include is(disabled) {
|
&.is-disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
background: none !important;
|
background: none !important;
|
||||||
opacity: 0.25;
|
opacity: 0.25;
|
||||||
|
@ -167,7 +167,7 @@
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include b('menu') {
|
.#{$namespace}-menu {
|
||||||
position: relative;
|
position: relative;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
@ -176,50 +176,47 @@
|
||||||
background: hsl(var(--menu-background-color));
|
background: hsl(var(--menu-background-color));
|
||||||
|
|
||||||
// 垂直菜单
|
// 垂直菜单
|
||||||
@include is('vertical') {
|
&.is-vertical {
|
||||||
& {
|
&:not(.#{$namespace}-menu.is-collapse) {
|
||||||
&:not(.#{$namespace}-menu.is-collapse) {
|
& .#{$namespace}-menu-item,
|
||||||
& .#{$namespace}-menu-item,
|
& .#{$namespace}-sub-menu-content,
|
||||||
& .#{$namespace}-sub-menu-content,
|
& .#{$namespace}-menu-item-group__title {
|
||||||
& .#{$namespace}-menu-item-group__title {
|
padding-left: calc(
|
||||||
padding-left: calc(
|
var(--menu-item-indent) + var(--menu-level) * var(--menu-item-indent)
|
||||||
var(--menu-item-indent) + var(--menu-level) *
|
);
|
||||||
var(--menu-item-indent)
|
white-space: nowrap;
|
||||||
);
|
}
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .#{$namespace}-sub-menu {
|
& > .#{$namespace}-sub-menu {
|
||||||
// .#{$namespace}-menu {
|
// .#{$namespace}-menu {
|
||||||
// background: var(--menu-submenu-opened-background-color);
|
// background: var(--menu-submenu-opened-background-color);
|
||||||
|
|
||||||
// .#{$namespace}-sub-menu,
|
// .#{$namespace}-sub-menu,
|
||||||
// .#{$namespace}-menu-item:not(.is-active),
|
// .#{$namespace}-menu-item:not(.is-active),
|
||||||
// .#{$namespace}-sub-menu-content:not(.is-active) {
|
// .#{$namespace}-sub-menu-content:not(.is-active) {
|
||||||
// background: var(--menu-submenu-opened-background-color);
|
// background: var(--menu-submenu-opened-background-color);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
& > .#{$namespace}-menu {
|
& > .#{$namespace}-menu {
|
||||||
& > .#{$namespace}-menu-item {
|
& > .#{$namespace}-menu-item {
|
||||||
padding-left: calc(
|
padding-left: calc(
|
||||||
0px + var(--menu-item-indent) + var(--menu-level) *
|
0px + var(--menu-item-indent) + var(--menu-level) *
|
||||||
var(--menu-item-indent)
|
var(--menu-item-indent)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .#{$namespace}-sub-menu-content {
|
|
||||||
padding-left: calc(var(--menu-item-indent) - 8px);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
& > .#{$namespace}-menu-item {
|
|
||||||
|
& > .#{$namespace}-sub-menu-content {
|
||||||
padding-left: calc(var(--menu-item-indent) - 8px);
|
padding-left: calc(var(--menu-item-indent) - 8px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
& > .#{$namespace}-menu-item {
|
||||||
|
padding-left: calc(var(--menu-item-indent) - 8px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include is('horizontal') {
|
&.is-horizontal {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
@ -287,7 +284,7 @@
|
||||||
}
|
}
|
||||||
// 折叠菜单
|
// 折叠菜单
|
||||||
|
|
||||||
@include is('collapse') {
|
&.is-collapse {
|
||||||
.#{$namespace}-menu__icon {
|
.#{$namespace}-menu__icon {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
@ -333,14 +330,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include e('popup-container') {
|
&__popup-container {
|
||||||
max-width: 240px;
|
max-width: 240px;
|
||||||
height: unset;
|
height: unset;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: var(--menu-background-color);
|
background: var(--menu-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@include e('popup') {
|
&__popup {
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
border-radius: var(--menu-item-radius);
|
border-radius: var(--menu-item-radius);
|
||||||
|
|
||||||
|
@ -350,7 +347,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include e('icon') {
|
&__icon {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
// width: var(--menu-item-icon-width);
|
// width: var(--menu-item-icon-width);
|
||||||
max-height: var(--menu-item-icon-width);
|
max-height: var(--menu-item-icon-width);
|
||||||
|
@ -361,27 +358,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include b('menu-item') {
|
.#{$namespace}-menu-item {
|
||||||
fill: var(--menu-item-color);
|
fill: var(--menu-item-color);
|
||||||
stroke: var(--menu-item-color);
|
stroke: var(--menu-item-color);
|
||||||
|
|
||||||
@include menu-item;
|
@include menu-item;
|
||||||
|
|
||||||
@include is(active) {
|
&.is-active {
|
||||||
fill: var(--menu-item-active-color);
|
fill: var(--menu-item-active-color);
|
||||||
stroke: var(--menu-item-active-color);
|
stroke: var(--menu-item-active-color);
|
||||||
|
|
||||||
@include menu-item-active;
|
@include menu-item-active;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include e('content') {
|
&__content {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--menu-item-height);
|
height: var(--menu-item-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@include is('collapse-show-title') {
|
&.is-collapse-show-title {
|
||||||
padding: 32px 0 !important;
|
padding: 32px 0 !important;
|
||||||
// margin: 4px 8px !important;
|
// margin: 4px 8px !important;
|
||||||
.#{$namespace}-menu-tooltip__trigger {
|
.#{$namespace}-menu-tooltip__trigger {
|
||||||
|
@ -427,7 +424,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include b('sub-menu') {
|
.#{$namespace}-sub-menu {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
@ -435,7 +432,7 @@
|
||||||
fill: var(--menu-item-color);
|
fill: var(--menu-item-color);
|
||||||
stroke: var(--menu-item-color);
|
stroke: var(--menu-item-color);
|
||||||
|
|
||||||
@include is('active') {
|
&.is-active {
|
||||||
div[data-state='open'] > .#{$namespace}-sub-menu-content,
|
div[data-state='open'] > .#{$namespace}-sub-menu-content,
|
||||||
> .#{$namespace}-sub-menu-content {
|
> .#{$namespace}-sub-menu-content {
|
||||||
color: var(--menu-submenu-active-color);
|
color: var(--menu-submenu-active-color);
|
||||||
|
@ -448,12 +445,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include b('sub-menu-content') {
|
.#{$namespace}-sub-menu-content {
|
||||||
height: var(--menu-item-height);
|
height: var(--menu-item-height);
|
||||||
|
|
||||||
@include menu-item;
|
@include menu-item;
|
||||||
|
|
||||||
@include e('icon-arrow') {
|
&__icon-arrow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
right: 6px;
|
right: 6px;
|
||||||
|
@ -466,11 +463,11 @@
|
||||||
transition: transform 0.25s ease;
|
transition: transform 0.25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include e('title') {
|
&__title {
|
||||||
@include menu-title;
|
@include menu-title;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include is('collapse-show-title') {
|
&.is-collapse-show-title {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 32px 0 !important;
|
padding: 32px 0 !important;
|
||||||
// margin: 4px 8px !important;
|
// margin: 4px 8px !important;
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import { defineConfig } from '@vben/vite-config';
|
|
||||||
|
|
||||||
export default defineConfig();
|
|
|
@ -1,10 +1,4 @@
|
||||||
import './styles/index.css';
|
import './styles/index.css';
|
||||||
|
|
||||||
export * from './components';
|
export * from './components';
|
||||||
export {
|
export { VisuallyHidden } from 'radix-vue';
|
||||||
VisuallyHidden,
|
|
||||||
useEmitAsProps,
|
|
||||||
useForwardExpose,
|
|
||||||
useForwardProps,
|
|
||||||
useForwardPropsEmits,
|
|
||||||
} from 'radix-vue';
|
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vben-core/design": "workspace:*",
|
|
||||||
"@vben-core/hooks": "workspace:*",
|
"@vben-core/hooks": "workspace:*",
|
||||||
"@vben-core/iconify": "workspace:*",
|
"@vben-core/iconify": "workspace:*",
|
||||||
"@vben-core/shadcn-ui": "workspace:*",
|
"@vben-core/shadcn-ui": "workspace:*",
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
export { default as Tabs } from './tabs/tabs.vue';
|
||||||
export { default as TabsChrome } from './tabs-chrome/tabs.vue';
|
export { default as TabsChrome } from './tabs-chrome/tabs.vue';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TabItem } from '@vben-core/typings';
|
import type { TabDefinition } from '@vben-core/typings';
|
||||||
|
|
||||||
import type { TabsProps } from '../../types';
|
import type { TabConfig, TabsProps } from '../../types';
|
||||||
|
|
||||||
import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
tabs: () => [],
|
tabs: () => [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{ close: [string]; unpin: [TabItem] }>();
|
const emit = defineEmits<{ close: [string]; unpin: [TabDefinition] }>();
|
||||||
const active = defineModel<string>('active');
|
const active = defineModel<string>('active');
|
||||||
|
|
||||||
const contentRef = ref();
|
const contentRef = ref();
|
||||||
|
@ -56,12 +56,14 @@ const layout = () => {
|
||||||
tabWidth.value = width;
|
tabWidth.value = width;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tabsView = computed(() => {
|
const tabsView = computed((): TabConfig[] => {
|
||||||
return props.tabs.map((tab) => {
|
return props.tabs.map((tab) => {
|
||||||
return {
|
return {
|
||||||
...tab,
|
...tab,
|
||||||
affixTab: !!tab.meta?.affixTab,
|
affixTab: !!tab.meta?.affixTab,
|
||||||
closable: tab.meta?.tabClosable ?? true,
|
closable: Reflect.has(tab.meta, 'tabClosable')
|
||||||
|
? !!tab.meta.tabClosable
|
||||||
|
: true,
|
||||||
icon: tab.meta.icon as string,
|
icon: tab.meta.icon as string,
|
||||||
key: tab.fullPath || tab.path,
|
key: tab.fullPath || tab.path,
|
||||||
title: (tab.meta?.title || tab.name) as string,
|
title: (tab.meta?.title || tab.name) as string,
|
||||||
|
@ -85,7 +87,8 @@ onMounted(() => {
|
||||||
function handleClose(key: string) {
|
function handleClose(key: string) {
|
||||||
emit('close', key);
|
emit('close', key);
|
||||||
}
|
}
|
||||||
function handleUnpinTab(tab: TabItem) {
|
|
||||||
|
function handleUnpinTab(tab: TabConfig) {
|
||||||
emit('unpin', tab);
|
emit('unpin', tab);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<script lang="ts" setup></script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div></div>
|
|
||||||
</template>
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { VbenScrollbar } from '@vben-core/shadcn-ui';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bg-accent size-full">
|
||||||
|
<VbenScrollbar>
|
||||||
|
<slot></slot>
|
||||||
|
</VbenScrollbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,10 +1,9 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TabItem } from '@vben-core/typings';
|
import type { TabDefinition } from '@vben-core/typings';
|
||||||
|
|
||||||
import { nextTick, onMounted } from 'vue';
|
import { nextTick, onMounted } from 'vue';
|
||||||
|
|
||||||
import { useSortable } from '@vben-core/hooks';
|
import { useForwardPropsEmits, useSortable } from '@vben-core/hooks';
|
||||||
import { useForwardPropsEmits } from '@vben-core/shadcn-ui';
|
|
||||||
|
|
||||||
import { TabsChrome } from './components';
|
import { TabsChrome } from './components';
|
||||||
import { TabsProps } from './types';
|
import { TabsProps } from './types';
|
||||||
|
@ -23,7 +22,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
close: [string];
|
close: [string];
|
||||||
sortTabs: [number, number];
|
sortTabs: [number, number];
|
||||||
unpin: [TabItem];
|
unpin: [TabDefinition];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const forward = useForwardPropsEmits(props, emit);
|
const forward = useForwardPropsEmits(props, emit);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { IContextMenuItem } from '@vben-core/shadcn-ui';
|
import type { IContextMenuItem } from '@vben-core/shadcn-ui';
|
||||||
import type { TabItem } from '@vben-core/typings';
|
import type { TabDefinition } from '@vben-core/typings';
|
||||||
|
|
||||||
interface TabsProps {
|
interface TabsProps {
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +41,15 @@ interface TabsProps {
|
||||||
/**
|
/**
|
||||||
* @zh_CN 选项卡数据
|
* @zh_CN 选项卡数据
|
||||||
*/
|
*/
|
||||||
tabs?: TabItem[];
|
tabs?: TabDefinition[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { TabsProps };
|
interface TabConfig extends TabDefinition {
|
||||||
|
affixTab: boolean;
|
||||||
|
closable: boolean;
|
||||||
|
icon: string;
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { TabConfig, TabsProps };
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vben-core/hooks": "workspace:*",
|
||||||
"@vben-core/iconify": "workspace:*",
|
"@vben-core/iconify": "workspace:*",
|
||||||
"@vben-core/locales": "workspace:*",
|
"@vben-core/locales": "workspace:*",
|
||||||
"@vben-core/shadcn-ui": "workspace:*",
|
"@vben-core/shadcn-ui": "workspace:*",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useForwardPropsEmits } from '@vben-core/hooks';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
VisuallyHidden,
|
VisuallyHidden,
|
||||||
useForwardPropsEmits,
|
|
||||||
} from '@vben-core/shadcn-ui';
|
} from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
import AuthenticationLogin from './login.vue';
|
import AuthenticationLogin from './login.vue';
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TabsOption } from '@vben/types';
|
import type { TabOption } from '@vben/types';
|
||||||
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@vben-core/shadcn-ui';
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tabs: TabsOption[];
|
tabs: TabOption[];
|
||||||
}
|
}
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { IContextMenuItem } from '@vben-core/tabs-ui';
|
import type { IContextMenuItem } from '@vben-core/tabs-ui';
|
||||||
import type { TabItem } from '@vben-core/typings';
|
import type { TabDefinition } from '@vben-core/typings';
|
||||||
import type {
|
import type {
|
||||||
RouteLocationNormalized,
|
RouteLocationNormalized,
|
||||||
RouteLocationNormalizedGeneric,
|
RouteLocationNormalizedGeneric,
|
||||||
|
@ -105,7 +105,7 @@ function useTabs() {
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const createContextMenus = (tab: TabItem) => {
|
const createContextMenus = (tab: TabDefinition) => {
|
||||||
const tabs = coreTabbarStore.getTabs;
|
const tabs = coreTabbarStore.getTabs;
|
||||||
const affixTabs = coreTabbarStore.affixTabs;
|
const affixTabs = coreTabbarStore.affixTabs;
|
||||||
const index = tabs.findIndex((item) => item.path === tab.path);
|
const index = tabs.findIndex((item) => item.path === tab.path);
|
||||||
|
@ -228,7 +228,7 @@ function useTabs() {
|
||||||
/**
|
/**
|
||||||
* 取消固定标签页
|
* 取消固定标签页
|
||||||
*/
|
*/
|
||||||
const handleUnpinTab = async (tab: TabItem) => {
|
const handleUnpinTab = async (tab: TabDefinition) => {
|
||||||
await coreTabbarStore.unpinTab(tab);
|
await coreTabbarStore.unpinTab(tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { computed, nextTick } from 'vue';
|
import { computed, nextTick } from 'vue';
|
||||||
|
|
||||||
import { VbenButton } from '@vben-core/shadcn-ui';
|
import { VbenButton } from '@vben-core/shadcn-ui';
|
||||||
import { useNamespace } from '@vben-core/toolkit';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
|
@ -21,8 +20,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const isDark = defineModel<boolean>();
|
const isDark = defineModel<boolean>();
|
||||||
|
|
||||||
const { b, e, is } = useNamespace('theme-toggle');
|
|
||||||
|
|
||||||
const theme = computed(() => {
|
const theme = computed(() => {
|
||||||
return isDark.value ? 'light' : 'dark';
|
return isDark.value ? 'light' : 'dark';
|
||||||
});
|
});
|
||||||
|
@ -86,7 +83,7 @@ function toggleTheme(event: MouseEvent) {
|
||||||
<template>
|
<template>
|
||||||
<VbenButton
|
<VbenButton
|
||||||
:aria-label="theme"
|
:aria-label="theme"
|
||||||
:class="[b(), is(theme), `is-${theme}`]"
|
:class="[`is-${theme}`]"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
class="theme-toggle cursor-pointer border-none bg-none"
|
class="theme-toggle cursor-pointer border-none bg-none"
|
||||||
v-bind="bindProps"
|
v-bind="bindProps"
|
||||||
|
@ -95,7 +92,6 @@ function toggleTheme(event: MouseEvent) {
|
||||||
<svg aria-hidden="true" height="24" viewBox="0 0 24 24" width="24">
|
<svg aria-hidden="true" height="24" viewBox="0 0 24 24" width="24">
|
||||||
<mask
|
<mask
|
||||||
id="theme-toggle-moon"
|
id="theme-toggle-moon"
|
||||||
:class="e('moon')"
|
|
||||||
class="theme-toggle__moon"
|
class="theme-toggle__moon"
|
||||||
fill="hsl(var(--foreground)/80%)"
|
fill="hsl(var(--foreground)/80%)"
|
||||||
stroke="none"
|
stroke="none"
|
||||||
|
@ -105,14 +101,13 @@ function toggleTheme(event: MouseEvent) {
|
||||||
</mask>
|
</mask>
|
||||||
<circle
|
<circle
|
||||||
id="sun"
|
id="sun"
|
||||||
:class="e('sun')"
|
|
||||||
class="theme-toggle__sun"
|
class="theme-toggle__sun"
|
||||||
cx="12"
|
cx="12"
|
||||||
cy="12"
|
cy="12"
|
||||||
mask="url(#theme-toggle-moon)"
|
mask="url(#theme-toggle-moon)"
|
||||||
r="11"
|
r="11"
|
||||||
/>
|
/>
|
||||||
<g :class="e('sun-beams')" class="theme-toggle__sun-beams">
|
<g class="theme-toggle__sun-beams">
|
||||||
<line x1="12" x2="12" y1="1" y2="3" />
|
<line x1="12" x2="12" y1="1" y2="3" />
|
||||||
<line x1="12" x2="12" y1="21" y2="23" />
|
<line x1="12" x2="12" y1="21" y2="23" />
|
||||||
<line x1="4.22" x2="5.64" y1="4.22" y2="5.64" />
|
<line x1="4.22" x2="5.64" y1="4.22" y2="5.64" />
|
||||||
|
|
|
@ -36,5 +36,8 @@
|
||||||
"default": "./dist/index.mjs"
|
"default": "./dist/index.mjs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vben-core/hooks": "workspace:*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export {};
|
export * from '@vben-core/hooks';
|
||||||
|
|
|
@ -210,6 +210,9 @@ importers:
|
||||||
'@vben/constants':
|
'@vben/constants':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/constants
|
version: link:../../packages/constants
|
||||||
|
'@vben/hooks':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/hooks
|
||||||
'@vben/icons':
|
'@vben/icons':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/icons
|
version: link:../../packages/icons
|
||||||
|
@ -655,12 +658,12 @@ importers:
|
||||||
|
|
||||||
packages/@core/shared/hooks:
|
packages/@core/shared/hooks:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
radix-vue:
|
||||||
|
specifier: ^1.9.1
|
||||||
|
version: 1.9.1(vue@3.4.31(typescript@5.5.3))
|
||||||
sortablejs:
|
sortablejs:
|
||||||
specifier: ^1.15.2
|
specifier: ^1.15.2
|
||||||
version: 1.15.2
|
version: 1.15.2
|
||||||
vue:
|
|
||||||
specifier: ^3.4.31
|
|
||||||
version: 3.4.31(typescript@5.5.3)
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/sortablejs':
|
'@types/sortablejs':
|
||||||
specifier: ^1.15.8
|
specifier: ^1.15.8
|
||||||
|
@ -741,9 +744,9 @@ importers:
|
||||||
|
|
||||||
packages/@core/ui-kit/menu-ui:
|
packages/@core/ui-kit/menu-ui:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vben-core/design':
|
'@vben-core/hooks':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../shared/design
|
version: link:../../shared/hooks
|
||||||
'@vben-core/iconify':
|
'@vben-core/iconify':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../shared/iconify
|
version: link:../../shared/iconify
|
||||||
|
@ -795,9 +798,6 @@ importers:
|
||||||
|
|
||||||
packages/@core/ui-kit/tabs-ui:
|
packages/@core/ui-kit/tabs-ui:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vben-core/design':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../shared/design
|
|
||||||
'@vben-core/hooks':
|
'@vben-core/hooks':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../shared/hooks
|
version: link:../../shared/hooks
|
||||||
|
@ -858,6 +858,9 @@ importers:
|
||||||
|
|
||||||
packages/effects/common-ui:
|
packages/effects/common-ui:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@vben-core/hooks':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../@core/shared/hooks
|
||||||
'@vben-core/iconify':
|
'@vben-core/iconify':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../@core/shared/iconify
|
version: link:../../@core/shared/iconify
|
||||||
|
@ -935,7 +938,11 @@ importers:
|
||||||
specifier: ^4.4.0
|
specifier: ^4.4.0
|
||||||
version: 4.4.0(vue@3.4.31(typescript@5.5.3))
|
version: 4.4.0(vue@3.4.31(typescript@5.5.3))
|
||||||
|
|
||||||
packages/hooks: {}
|
packages/hooks:
|
||||||
|
dependencies:
|
||||||
|
'@vben-core/hooks':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../@core/shared/hooks
|
||||||
|
|
||||||
packages/icons:
|
packages/icons:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Reference in New Issue