forked from element-plus/element-plus
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(components): refactor menu (element-plus#3639)
* refactor(menu): rename to kebab-case * refactor(menu): rename RootMenuProvider to MenuProvider * refactor(menu): rename menu.type to types * refactor(menu): extract menu props and emits * refactor(menu): change sub-menu.vue to ts * refactor(menu): extract menu-item-group props and emits * refactor(menu): extract menu-item props and emits * refactor(menu): extract sub-menu props and emits * refactor(menu): rename type RegisterMenuItem to MenuItemRegistered * refactor(menu): MenuProvider ref to reactive * refactor(menu): MenuProvider remove methods * refactor(menu): change submenus to subMenus * refactor(menu): remove RootMenuProps type * refactor(menu): MenuProvider improve types & rename submenu to subMenu * refactor(menu): menu add block to provide * refactor(menu): menu improve expose * refactor(menu): menu improve render types * refactor(menu): menu refactor types & change handle(Sub)MenuItemClick params * refactor(menu): menu refactor types * refactor(menu): menu-item-group improve types * refactor(menu): menu-item improve types * refactor(menu): sub-menu improve types * refactor(menu): use-menu improve types * refactor(menu): sub-menu fix types * refactor(menu): menu-collapse-transition improve types * refactor(menu): menu-item-group improve template * refactor(menu): menu-item rename emit param * refactor(menu): finally improve types * fix lint * chore: re-order import * chore: remove reactive
- Loading branch information
Showing
17 changed files
with
939 additions
and
1,014 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 45 additions & 44 deletions
89
packages/components/menu/src/menu-collapse-transition.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import type { ExtractPropTypes } from 'vue' | ||
|
||
export const menuItemGroupProps = { | ||
title: String, | ||
} as const | ||
export type MenuItemGroupProps = ExtractPropTypes<typeof menuItemGroupProps> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<template> | ||
<li class="el-menu-item-group"> | ||
<div | ||
class="el-menu-item-group__title" | ||
:style="{ paddingLeft: `${levelPadding}px` }" | ||
> | ||
<template v-if="!$slots.title">{{ title }}</template> | ||
<slot v-else name="title" /> | ||
</div> | ||
<ul> | ||
<slot /> | ||
</ul> | ||
</li> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { defineComponent, computed, getCurrentInstance, inject } from 'vue' | ||
import { throwError } from '@element-plus/utils/error' | ||
import { menuItemGroupProps } from './menu-item-group' | ||
import type { MenuProvider } from './types' | ||
const COMPONENT_NAME = 'ElMenuItemGroup' | ||
export default defineComponent({ | ||
name: COMPONENT_NAME, | ||
props: menuItemGroupProps, | ||
setup() { | ||
const instance = getCurrentInstance()! | ||
const menu = inject<MenuProvider>('rootMenu') | ||
if (!menu) throwError(COMPONENT_NAME, 'can not inject root menu') | ||
const levelPadding = computed(() => { | ||
if (menu.props.collapse) return 20 | ||
let padding = 20 | ||
let parent = instance.parent | ||
while (parent && parent.type.name !== 'ElMenu') { | ||
if (parent.type.name === 'ElSubMenu') { | ||
padding += 20 | ||
} | ||
parent = parent.parent | ||
} | ||
return padding | ||
}) | ||
return { | ||
levelPadding, | ||
} | ||
}, | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { buildProp, definePropType } from '@element-plus/utils/props' | ||
import { isString } from '@element-plus/utils/util' | ||
|
||
import type { ExtractPropTypes } from 'vue' | ||
import type { RouteLocationRaw } from 'vue-router' | ||
import type { MenuItemRegistered } from './types' | ||
|
||
export const menuItemProps = { | ||
index: { | ||
type: String, | ||
default: null, | ||
}, | ||
route: buildProp({ | ||
type: definePropType<RouteLocationRaw>([String, Object]), | ||
}), | ||
disabled: Boolean, | ||
} as const | ||
export type MenuItemProps = ExtractPropTypes<typeof menuItemProps> | ||
|
||
export const menuItemEmits = { | ||
click: (item: MenuItemRegistered) => | ||
isString(item.index) && Array.isArray(item.indexPath), | ||
} | ||
export type MenuItemEmits = typeof menuItemEmits |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<template> | ||
<li | ||
class="el-menu-item" | ||
role="menuitem" | ||
tabindex="-1" | ||
:style="paddingStyle" | ||
:class="{ | ||
'is-active': active, | ||
'is-disabled': disabled, | ||
}" | ||
@click="handleClick" | ||
> | ||
<el-tooltip | ||
v-if=" | ||
parentMenu.type.name === 'ElMenu' && | ||
rootMenu.props.collapse && | ||
$slots.title | ||
" | ||
:effect="Effect.DARK" | ||
placement="right" | ||
> | ||
<template #content> | ||
<slot name="title" /> | ||
</template> | ||
<div | ||
:style="{ | ||
position: 'absolute', | ||
left: 0, | ||
top: 0, | ||
height: '100%', | ||
width: '100%', | ||
display: 'inline-block', | ||
boxSizing: 'border-box', | ||
padding: '0 20px', | ||
}" | ||
> | ||
<slot /> | ||
</div> | ||
</el-tooltip> | ||
<template v-else> | ||
<slot /> | ||
<slot name="title" /> | ||
</template> | ||
</li> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { | ||
defineComponent, | ||
computed, | ||
onMounted, | ||
onBeforeUnmount, | ||
inject, | ||
getCurrentInstance, | ||
toRef, | ||
reactive, | ||
} from 'vue' | ||
import ElTooltip from '@element-plus/components/tooltip' | ||
import { Effect } from '@element-plus/components/popper' | ||
import { throwError } from '@element-plus/utils/error' | ||
import useMenu from './use-menu' | ||
import { menuItemEmits, menuItemProps } from './menu-item' | ||
import type { MenuItemRegistered, MenuProvider, SubMenuProvider } from './types' | ||
const COMPONENT_NAME = 'ElMenuItem' | ||
export default defineComponent({ | ||
name: COMPONENT_NAME, | ||
components: { | ||
ElTooltip, | ||
}, | ||
props: menuItemProps, | ||
emits: menuItemEmits, | ||
setup(props, { emit }) { | ||
const instance = getCurrentInstance()! | ||
const rootMenu = inject<MenuProvider>('rootMenu') | ||
if (!rootMenu) throwError(COMPONENT_NAME, 'can not inject root menu') | ||
const { parentMenu, paddingStyle, indexPath } = useMenu( | ||
instance, | ||
toRef(props, 'index') | ||
) | ||
const subMenu = inject<SubMenuProvider>(`subMenu:${parentMenu.value.uid}`) | ||
if (!subMenu) throwError(COMPONENT_NAME, 'can not inject sub menu') | ||
const active = computed(() => props.index === rootMenu.activeIndex) | ||
const item: MenuItemRegistered = reactive({ | ||
index: props.index, | ||
indexPath, | ||
active, | ||
}) | ||
const handleClick = () => { | ||
if (!props.disabled) { | ||
rootMenu.handleMenuItemClick({ | ||
index: props.index, | ||
indexPath: indexPath.value, | ||
route: props.route, | ||
}) | ||
emit('click', item) | ||
} | ||
} | ||
onMounted(() => { | ||
subMenu.addSubMenu(item) | ||
rootMenu.addMenuItem(item) | ||
}) | ||
onBeforeUnmount(() => { | ||
subMenu.removeSubMenu(item) | ||
rootMenu.removeMenuItem(item) | ||
}) | ||
return { | ||
Effect, | ||
parentMenu, | ||
rootMenu, | ||
paddingStyle, | ||
active, | ||
handleClick, | ||
} | ||
}, | ||
}) | ||
</script> |
Oops, something went wrong.