refactor: menu to ts

pull/3053/head
Amour1688 2020-10-24 22:38:25 +08:00
parent 873ecf0312
commit 3b14396a08
9 changed files with 72 additions and 51 deletions

View File

@ -46,9 +46,10 @@ export const SiderProps = {
// belowShow?: boolean; // belowShow?: boolean;
// } // }
// export interface SiderContext { export interface SiderContextProps {
// siderCollapsed: boolean; sCollapsed?: boolean;
// } collapsedWidth?: string | number;
}
const generateId = (() => { const generateId = (() => {
let i = 0; let i = 0;

View File

@ -1,8 +1,9 @@
import { defineComponent, inject } from 'vue'; import { defineComponent, inject } from 'vue';
import { Item, itemProps } from '../vc-menu'; import { Item, itemProps } from '../vc-menu';
import { getOptionProps, getSlot } from '../_util/props-util'; import { getOptionProps, getSlot } from '../_util/props-util';
import Tooltip from '../tooltip'; import Tooltip, { TooltipProps } from '../tooltip';
function noop() {} import { SiderContextProps } from '../layout/Sider';
export default defineComponent({ export default defineComponent({
name: 'MenuItem', name: 'MenuItem',
inheritAttrs: false, inheritAttrs: false,
@ -10,13 +11,13 @@ export default defineComponent({
isMenuItem: true, isMenuItem: true,
setup() { setup() {
return { return {
getInlineCollapsed: inject('getInlineCollapsed', noop), getInlineCollapsed: inject<() => boolean>('getInlineCollapsed', () => false),
layoutSiderContext: inject('layoutSiderContext', {}), layoutSiderContext: inject<SiderContextProps>('layoutSiderContext', {}),
}; };
}, },
methods: { methods: {
onKeyDown(e) { onKeyDown(e: HTMLElement) {
this.$refs.menuItem.onKeyDown(e); (this.$refs.menuItem as any).onKeyDown(e);
}, },
}, },
render() { render() {
@ -31,7 +32,7 @@ export default defineComponent({
} else if (title === false) { } else if (title === false) {
tooltipTitle = ''; tooltipTitle = '';
} }
const tooltipProps = { const tooltipProps: TooltipProps = {
title: tooltipTitle, title: tooltipTitle,
}; };
const siderCollapsed = this.layoutSiderContext.sCollapsed; const siderCollapsed = this.layoutSiderContext.sCollapsed;
@ -48,7 +49,7 @@ export default defineComponent({
...attrs, ...attrs,
ref: 'menuItem', ref: 'menuItem',
}; };
const toolTipProps = { const toolTipProps: TooltipProps = {
...tooltipProps, ...tooltipProps,
placement: 'right', placement: 'right',
overlayClassName: `${rootPrefixCls}-inline-collapsed-tooltip`, overlayClassName: `${rootPrefixCls}-inline-collapsed-tooltip`,

View File

@ -1,22 +1,29 @@
import { inject } from 'vue'; import { defineComponent, inject } from 'vue';
import { SubMenu as VcSubMenu } from '../vc-menu'; import { SubMenu as VcSubMenu } from '../vc-menu';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import Omit from 'omit.js'; import Omit from 'omit.js';
import { getSlot } from '../_util/props-util'; import { getSlot } from '../_util/props-util';
export default { export type MenuTheme = 'light' | 'dark';
export interface MenuContextProps {
inlineCollapsed?: boolean;
theme?: MenuTheme;
}
export default defineComponent({
name: 'ASubMenu', name: 'ASubMenu',
isSubMenu: true, isSubMenu: true,
inheritAttrs: false, inheritAttrs: false,
props: { ...VcSubMenu.props }, props: { ...VcSubMenu.props },
setup() { setup() {
return { return {
menuPropsContext: inject('menuPropsContext', {}), menuPropsContext: inject<MenuContextProps>('menuPropsContext', {}),
}; };
}, },
methods: { methods: {
onKeyDown(e) { onKeyDown(e) {
this.$refs.subMenu.onKeyDown(e); (this.$refs.subMenu as any).onKeyDown(e);
}, },
}, },
@ -33,4 +40,4 @@ export default {
}; };
return <VcSubMenu {...props}>{getSlot(this)}</VcSubMenu>; return <VcSubMenu {...props}>{getSlot(this)}</VcSubMenu>;
}, },
}; });

View File

@ -1,4 +1,4 @@
import { defineComponent, inject, provide, toRef } from 'vue'; import { defineComponent, inject, provide, toRef, App, ExtractPropTypes } from 'vue';
import omit from 'omit.js'; import omit from 'omit.js';
import VcMenu, { Divider, ItemGroup } from '../vc-menu'; import VcMenu, { Divider, ItemGroup } from '../vc-menu';
import SubMenu from './SubMenu'; import SubMenu from './SubMenu';
@ -10,6 +10,8 @@ import { hasProp, getOptionProps, getSlot } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import commonPropsType from '../vc-menu/commonPropsType'; import commonPropsType from '../vc-menu/commonPropsType';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { SiderContextProps } from '../layout/Sider';
import { tuple } from '../_util/type';
// import raf from '../_util/raf'; // import raf from '../_util/raf';
export const MenuMode = PropTypes.oneOf([ export const MenuMode = PropTypes.oneOf([
@ -22,7 +24,7 @@ export const MenuMode = PropTypes.oneOf([
export const menuProps = { export const menuProps = {
...commonPropsType, ...commonPropsType,
theme: PropTypes.oneOf(['light', 'dark']).def('light'), theme: PropTypes.oneOf(tuple('light', 'dark')).def('light'),
mode: MenuMode.def('vertical'), mode: MenuMode.def('vertical'),
selectable: PropTypes.looseBool, selectable: PropTypes.looseBool,
selectedKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), selectedKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
@ -43,10 +45,10 @@ export const menuProps = {
onClick: PropTypes.func, onClick: PropTypes.func,
onMouseenter: PropTypes.func, onMouseenter: PropTypes.func,
onSelectChange: PropTypes.func, onSelectChange: PropTypes.func,
'onUpdate:selectedKeys': PropTypes.func,
'onUpdate:openKeys': PropTypes.func,
}; };
export type MenuProps = Partial<ExtractPropTypes<typeof menuProps>>;
const Menu = defineComponent({ const Menu = defineComponent({
name: 'AMenu', name: 'AMenu',
inheritAttrs: false, inheritAttrs: false,
@ -56,23 +58,33 @@ const Menu = defineComponent({
SubMenu: { ...SubMenu, name: 'ASubMenu' }, SubMenu: { ...SubMenu, name: 'ASubMenu' },
ItemGroup: { ...ItemGroup, name: 'AMenuItemGroup' }, ItemGroup: { ...ItemGroup, name: 'AMenuItemGroup' },
mixins: [BaseMixin], mixins: [BaseMixin],
emits: [
'update:selectedKeys',
'update:openKeys',
'mouseenter',
'openChange',
'click',
'selectChange',
'select',
'deselect',
],
created() { created() {
provide('getInlineCollapsed', this.getInlineCollapsed); provide('getInlineCollapsed', this.getInlineCollapsed);
provide('menuPropsContext', this.$props); provide('menuPropsContext', this.$props);
}, },
setup() { setup() {
const layoutSiderContext = inject('layoutSiderContext', {}); const layoutSiderContext = inject<SiderContextProps>('layoutSiderContext', {});
const layoutSiderCollapsed = toRef(layoutSiderContext, 'sCollapsed'); const layoutSiderCollapsed = toRef(layoutSiderContext, 'sCollapsed');
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
layoutSiderContext, layoutSiderContext,
layoutSiderCollapsed, layoutSiderCollapsed,
propsUpdating: false,
switchingModeFromInline: false,
leaveAnimationExecutedWhenInlineCollapsed: false,
inlineOpenKeys: [],
}; };
}, },
// model: {
// prop: 'selectedKeys',
// event: 'selectChange',
// },
updated() { updated() {
this.propsUpdating = false; this.propsUpdating = false;
}, },
@ -96,15 +108,12 @@ const Menu = defineComponent({
}, },
}, },
data() { data() {
const props = getOptionProps(this); const props: MenuProps = getOptionProps(this);
warning( warning(
!('inlineCollapsed' in props && props.mode !== 'inline'), !('inlineCollapsed' in props && props.mode !== 'inline'),
'Menu', 'Menu',
"`inlineCollapsed` should only be used when Menu's `mode` is inline.", "`inlineCollapsed` should only be used when Menu's `mode` is inline.",
); );
this.switchingModeFromInline = false;
this.leaveAnimationExecutedWhenInlineCollapsed = false;
this.inlineOpenKeys = [];
let sOpenKeys; let sOpenKeys;
if ('openKeys' in props) { if ('openKeys' in props) {
@ -244,7 +253,7 @@ const Menu = defineComponent({
const menuOpenAnimation = this.getMenuOpenAnimation(menuMode); const menuOpenAnimation = this.getMenuOpenAnimation(menuMode);
const { class: className, ...otherAttrs } = this.$attrs; const { class: className, ...otherAttrs } = this.$attrs;
const menuClassName = { const menuClassName = {
[className]: className, [className as string]: className,
[`${prefixCls}-${theme}`]: true, [`${prefixCls}-${theme}`]: true,
[`${prefixCls}-inline-collapsed`]: this.getInlineCollapsed(), [`${prefixCls}-inline-collapsed`]: this.getInlineCollapsed(),
}; };
@ -297,7 +306,7 @@ const Menu = defineComponent({
}); });
/* istanbul ignore next */ /* istanbul ignore next */
Menu.install = function(app) { Menu.install = function(app: App) {
app.component(Menu.name, Menu); app.component(Menu.name, Menu);
app.component(Menu.Item.name, Menu.Item); app.component(Menu.Item.name, Menu.Item);
app.component(Menu.SubMenu.name, Menu.SubMenu); app.component(Menu.SubMenu.name, Menu.SubMenu);

View File

@ -1,4 +1,4 @@
import { defineComponent, inject } from 'vue'; import { defineComponent, ExtractPropTypes, inject } from 'vue';
import VcTooltip from '../vc-tooltip'; import VcTooltip from '../vc-tooltip';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import getPlacements from './placements'; import getPlacements from './placements';
@ -27,13 +27,18 @@ const splitObject = (obj: any, keys: string[]) => {
return { picked, omitted }; return { picked, omitted };
}; };
const props = abstractTooltipProps(); const props = abstractTooltipProps();
const tooltipProps = {
...props,
title: PropTypes.VNodeChild,
};
export type TooltipProps = Partial<ExtractPropTypes<typeof tooltipProps>>;
export default defineComponent({ export default defineComponent({
name: 'ATooltip', name: 'ATooltip',
inheritAttrs: false, inheritAttrs: false,
props: { props: tooltipProps,
...props,
title: PropTypes.VNodeChild,
},
emits: ['update:visible', 'visibleChange'], emits: ['update:visible', 'visibleChange'],
setup() { setup() {
return { return {
@ -192,7 +197,7 @@ export default defineComponent({
[openClassName || `${prefixCls}-open`]: sVisible, [openClassName || `${prefixCls}-open`]: sVisible,
[child.props && child.props.class]: child.props && child.props.class, [child.props && child.props.class]: child.props && child.props.class,
}); });
const tooltipProps = { const vcTooltipProps = {
...$attrs, ...$attrs,
...$props, ...$props,
prefixCls, prefixCls,
@ -205,7 +210,7 @@ export default defineComponent({
onPopupAlign: this.onPopupAlign, onPopupAlign: this.onPopupAlign,
}; };
return ( return (
<VcTooltip {...tooltipProps}> <VcTooltip {...vcTooltipProps}>
{sVisible ? cloneElement(child, { class: childCls }) : child} {sVisible ? cloneElement(child, { class: childCls }) : child}
</VcTooltip> </VcTooltip>
); );

View File

@ -1,6 +1,8 @@
import { App } from 'vue'; import { App } from 'vue';
import ToolTip from './Tooltip'; import ToolTip from './Tooltip';
export { TooltipProps } from './Tooltip';
/* istanbul ignore next */ /* istanbul ignore next */
ToolTip.install = function(app: App) { ToolTip.install = function(app: App) {
app.component(ToolTip.name, ToolTip); app.component(ToolTip.name, ToolTip);

View File

@ -1,6 +1,6 @@
import { PropType } from 'vue'; import { PropType } from 'vue';
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import initDefaultProps from '../../_util/props-util/initDefaultProps'; import { initDefaultProps } from '../../_util/props-util';
import { import {
filterOption as defaultFilterOption, filterOption as defaultFilterOption,
validateSearch as defaultValidateSearch, validateSearch as defaultValidateSearch,
@ -20,12 +20,8 @@ export const mentionsProps = {
placement: PropTypes.oneOf(PlaceMent), placement: PropTypes.oneOf(PlaceMent),
character: PropTypes.any, character: PropTypes.any,
characterRender: PropTypes.func, characterRender: PropTypes.func,
filterOption: { filterOption: PropTypes.func,
type: [Boolean, Function] as PropType<false | typeof defaultFilterOption>, validateSearch: PropTypes.func,
},
validateSearch: {
type: Function as PropType<typeof defaultValidateSearch>,
},
getPopupContainer: { getPopupContainer: {
type: Function as PropType<() => HTMLElement>, type: Function as PropType<() => HTMLElement>,
}, },

View File

@ -47,7 +47,7 @@ const Menu = {
this.updateMiniStore(); this.updateMiniStore();
}, },
methods: { methods: {
onSelect(selectInfo) { handleSelect(selectInfo) {
const props = this.$props; const props = this.$props;
if (props.selectable) { if (props.selectable) {
// root menu // root menu
@ -70,7 +70,7 @@ const Menu = {
} }
}, },
onClick(e) { handleClick(e) {
this.__emit('click', e); this.__emit('click', e);
}, },
// onKeyDown needs to be exposed as a instance method // onKeyDown needs to be exposed as a instance method
@ -112,7 +112,7 @@ const Menu = {
} }
}, },
onDeselect(selectInfo) { handleDeselect(selectInfo) {
const props = this.$props; const props = this.$props;
if (props.selectable) { if (props.selectable) {
const selectedKeys = this.store.getState().selectedKeys.concat(); const selectedKeys = this.store.getState().selectedKeys.concat();
@ -172,10 +172,10 @@ const Menu = {
overflowedIndicator: getComponent(this, 'overflowedIndicator', props) || <span>···</span>, overflowedIndicator: getComponent(this, 'overflowedIndicator', props) || <span>···</span>,
openTransitionName: this.getOpenTransitionName(), openTransitionName: this.getOpenTransitionName(),
children: filterEmpty(props.children), children: filterEmpty(props.children),
onClick: this.onClick, onClick: this.handleClick,
onOpenChange: this.onOpenChange, onOpenChange: this.onOpenChange,
onDeselect: this.onDeselect, onDeselect: this.handleDeselect,
onSelect: this.onSelect, onSelect: this.handleSelect,
ref: this.saveInnerMenu, ref: this.saveInnerMenu,
}; };