diff --git a/components/layout/Sider.tsx b/components/layout/Sider.tsx index b130fe359..ca7651c36 100644 --- a/components/layout/Sider.tsx +++ b/components/layout/Sider.tsx @@ -46,9 +46,10 @@ export const SiderProps = { // belowShow?: boolean; // } -// export interface SiderContext { -// siderCollapsed: boolean; -// } +export interface SiderContextProps { + sCollapsed?: boolean; + collapsedWidth?: string | number; +} const generateId = (() => { let i = 0; diff --git a/components/menu/MenuItem.jsx b/components/menu/MenuItem.tsx similarity index 77% rename from components/menu/MenuItem.jsx rename to components/menu/MenuItem.tsx index 96ddaad5d..7f952dcc8 100644 --- a/components/menu/MenuItem.jsx +++ b/components/menu/MenuItem.tsx @@ -1,8 +1,9 @@ import { defineComponent, inject } from 'vue'; import { Item, itemProps } from '../vc-menu'; import { getOptionProps, getSlot } from '../_util/props-util'; -import Tooltip from '../tooltip'; -function noop() {} +import Tooltip, { TooltipProps } from '../tooltip'; +import { SiderContextProps } from '../layout/Sider'; + export default defineComponent({ name: 'MenuItem', inheritAttrs: false, @@ -10,13 +11,13 @@ export default defineComponent({ isMenuItem: true, setup() { return { - getInlineCollapsed: inject('getInlineCollapsed', noop), - layoutSiderContext: inject('layoutSiderContext', {}), + getInlineCollapsed: inject<() => boolean>('getInlineCollapsed', () => false), + layoutSiderContext: inject('layoutSiderContext', {}), }; }, methods: { - onKeyDown(e) { - this.$refs.menuItem.onKeyDown(e); + onKeyDown(e: HTMLElement) { + (this.$refs.menuItem as any).onKeyDown(e); }, }, render() { @@ -31,7 +32,7 @@ export default defineComponent({ } else if (title === false) { tooltipTitle = ''; } - const tooltipProps = { + const tooltipProps: TooltipProps = { title: tooltipTitle, }; const siderCollapsed = this.layoutSiderContext.sCollapsed; @@ -48,7 +49,7 @@ export default defineComponent({ ...attrs, ref: 'menuItem', }; - const toolTipProps = { + const toolTipProps: TooltipProps = { ...tooltipProps, placement: 'right', overlayClassName: `${rootPrefixCls}-inline-collapsed-tooltip`, diff --git a/components/menu/SubMenu.jsx b/components/menu/SubMenu.tsx similarity index 70% rename from components/menu/SubMenu.jsx rename to components/menu/SubMenu.tsx index 989866306..8da036938 100644 --- a/components/menu/SubMenu.jsx +++ b/components/menu/SubMenu.tsx @@ -1,22 +1,29 @@ -import { inject } from 'vue'; +import { defineComponent, inject } from 'vue'; import { SubMenu as VcSubMenu } from '../vc-menu'; import classNames from '../_util/classNames'; import Omit from 'omit.js'; 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', isSubMenu: true, inheritAttrs: false, props: { ...VcSubMenu.props }, setup() { return { - menuPropsContext: inject('menuPropsContext', {}), + menuPropsContext: inject('menuPropsContext', {}), }; }, methods: { onKeyDown(e) { - this.$refs.subMenu.onKeyDown(e); + (this.$refs.subMenu as any).onKeyDown(e); }, }, @@ -33,4 +40,4 @@ export default { }; return {getSlot(this)}; }, -}; +}); diff --git a/components/menu/index.jsx b/components/menu/index.tsx similarity index 92% rename from components/menu/index.jsx rename to components/menu/index.tsx index 16050fc27..e7e613ff0 100644 --- a/components/menu/index.jsx +++ b/components/menu/index.tsx @@ -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 VcMenu, { Divider, ItemGroup } from '../vc-menu'; import SubMenu from './SubMenu'; @@ -10,6 +10,8 @@ import { hasProp, getOptionProps, getSlot } from '../_util/props-util'; import BaseMixin from '../_util/BaseMixin'; import commonPropsType from '../vc-menu/commonPropsType'; import { defaultConfigProvider } from '../config-provider'; +import { SiderContextProps } from '../layout/Sider'; +import { tuple } from '../_util/type'; // import raf from '../_util/raf'; export const MenuMode = PropTypes.oneOf([ @@ -22,7 +24,7 @@ export const MenuMode = PropTypes.oneOf([ export const menuProps = { ...commonPropsType, - theme: PropTypes.oneOf(['light', 'dark']).def('light'), + theme: PropTypes.oneOf(tuple('light', 'dark')).def('light'), mode: MenuMode.def('vertical'), selectable: PropTypes.looseBool, selectedKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), @@ -43,10 +45,10 @@ export const menuProps = { onClick: PropTypes.func, onMouseenter: PropTypes.func, onSelectChange: PropTypes.func, - 'onUpdate:selectedKeys': PropTypes.func, - 'onUpdate:openKeys': PropTypes.func, }; +export type MenuProps = Partial>; + const Menu = defineComponent({ name: 'AMenu', inheritAttrs: false, @@ -56,23 +58,33 @@ const Menu = defineComponent({ SubMenu: { ...SubMenu, name: 'ASubMenu' }, ItemGroup: { ...ItemGroup, name: 'AMenuItemGroup' }, mixins: [BaseMixin], + emits: [ + 'update:selectedKeys', + 'update:openKeys', + 'mouseenter', + 'openChange', + 'click', + 'selectChange', + 'select', + 'deselect', + ], created() { provide('getInlineCollapsed', this.getInlineCollapsed); provide('menuPropsContext', this.$props); }, setup() { - const layoutSiderContext = inject('layoutSiderContext', {}); + const layoutSiderContext = inject('layoutSiderContext', {}); const layoutSiderCollapsed = toRef(layoutSiderContext, 'sCollapsed'); return { configProvider: inject('configProvider', defaultConfigProvider), layoutSiderContext, layoutSiderCollapsed, + propsUpdating: false, + switchingModeFromInline: false, + leaveAnimationExecutedWhenInlineCollapsed: false, + inlineOpenKeys: [], }; }, - // model: { - // prop: 'selectedKeys', - // event: 'selectChange', - // }, updated() { this.propsUpdating = false; }, @@ -96,15 +108,12 @@ const Menu = defineComponent({ }, }, data() { - const props = getOptionProps(this); + const props: MenuProps = getOptionProps(this); warning( !('inlineCollapsed' in props && props.mode !== 'inline'), 'Menu', "`inlineCollapsed` should only be used when Menu's `mode` is inline.", ); - this.switchingModeFromInline = false; - this.leaveAnimationExecutedWhenInlineCollapsed = false; - this.inlineOpenKeys = []; let sOpenKeys; if ('openKeys' in props) { @@ -244,7 +253,7 @@ const Menu = defineComponent({ const menuOpenAnimation = this.getMenuOpenAnimation(menuMode); const { class: className, ...otherAttrs } = this.$attrs; const menuClassName = { - [className]: className, + [className as string]: className, [`${prefixCls}-${theme}`]: true, [`${prefixCls}-inline-collapsed`]: this.getInlineCollapsed(), }; @@ -297,7 +306,7 @@ const Menu = defineComponent({ }); /* istanbul ignore next */ -Menu.install = function(app) { +Menu.install = function(app: App) { app.component(Menu.name, Menu); app.component(Menu.Item.name, Menu.Item); app.component(Menu.SubMenu.name, Menu.SubMenu); diff --git a/components/menu/style/index.js b/components/menu/style/index.ts similarity index 100% rename from components/menu/style/index.js rename to components/menu/style/index.ts diff --git a/components/tooltip/Tooltip.tsx b/components/tooltip/Tooltip.tsx index 9e05524fa..a466b060a 100644 --- a/components/tooltip/Tooltip.tsx +++ b/components/tooltip/Tooltip.tsx @@ -1,4 +1,4 @@ -import { defineComponent, inject } from 'vue'; +import { defineComponent, ExtractPropTypes, inject } from 'vue'; import VcTooltip from '../vc-tooltip'; import classNames from '../_util/classNames'; import getPlacements from './placements'; @@ -27,13 +27,18 @@ const splitObject = (obj: any, keys: string[]) => { return { picked, omitted }; }; const props = abstractTooltipProps(); + +const tooltipProps = { + ...props, + title: PropTypes.VNodeChild, +}; + +export type TooltipProps = Partial>; + export default defineComponent({ name: 'ATooltip', inheritAttrs: false, - props: { - ...props, - title: PropTypes.VNodeChild, - }, + props: tooltipProps, emits: ['update:visible', 'visibleChange'], setup() { return { @@ -192,7 +197,7 @@ export default defineComponent({ [openClassName || `${prefixCls}-open`]: sVisible, [child.props && child.props.class]: child.props && child.props.class, }); - const tooltipProps = { + const vcTooltipProps = { ...$attrs, ...$props, prefixCls, @@ -205,7 +210,7 @@ export default defineComponent({ onPopupAlign: this.onPopupAlign, }; return ( - + {sVisible ? cloneElement(child, { class: childCls }) : child} ); diff --git a/components/tooltip/index.ts b/components/tooltip/index.ts index a3b35afd7..1e41360cf 100644 --- a/components/tooltip/index.ts +++ b/components/tooltip/index.ts @@ -1,6 +1,8 @@ import { App } from 'vue'; import ToolTip from './Tooltip'; +export { TooltipProps } from './Tooltip'; + /* istanbul ignore next */ ToolTip.install = function(app: App) { app.component(ToolTip.name, ToolTip); diff --git a/components/vc-mentions/src/mentionsProps.ts b/components/vc-mentions/src/mentionsProps.ts index d2aacc16b..a3b391af6 100644 --- a/components/vc-mentions/src/mentionsProps.ts +++ b/components/vc-mentions/src/mentionsProps.ts @@ -1,6 +1,6 @@ import { PropType } from 'vue'; import PropTypes from '../../_util/vue-types'; -import initDefaultProps from '../../_util/props-util/initDefaultProps'; +import { initDefaultProps } from '../../_util/props-util'; import { filterOption as defaultFilterOption, validateSearch as defaultValidateSearch, @@ -20,12 +20,8 @@ export const mentionsProps = { placement: PropTypes.oneOf(PlaceMent), character: PropTypes.any, characterRender: PropTypes.func, - filterOption: { - type: [Boolean, Function] as PropType, - }, - validateSearch: { - type: Function as PropType, - }, + filterOption: PropTypes.func, + validateSearch: PropTypes.func, getPopupContainer: { type: Function as PropType<() => HTMLElement>, }, diff --git a/components/vc-menu/Menu.jsx b/components/vc-menu/Menu.jsx index 66e1968e9..cc88bd8cd 100644 --- a/components/vc-menu/Menu.jsx +++ b/components/vc-menu/Menu.jsx @@ -47,7 +47,7 @@ const Menu = { this.updateMiniStore(); }, methods: { - onSelect(selectInfo) { + handleSelect(selectInfo) { const props = this.$props; if (props.selectable) { // root menu @@ -70,7 +70,7 @@ const Menu = { } }, - onClick(e) { + handleClick(e) { this.__emit('click', e); }, // onKeyDown needs to be exposed as a instance method @@ -112,7 +112,7 @@ const Menu = { } }, - onDeselect(selectInfo) { + handleDeselect(selectInfo) { const props = this.$props; if (props.selectable) { const selectedKeys = this.store.getState().selectedKeys.concat(); @@ -172,10 +172,10 @@ const Menu = { overflowedIndicator: getComponent(this, 'overflowedIndicator', props) || ยทยทยท, openTransitionName: this.getOpenTransitionName(), children: filterEmpty(props.children), - onClick: this.onClick, + onClick: this.handleClick, onOpenChange: this.onOpenChange, - onDeselect: this.onDeselect, - onSelect: this.onSelect, + onDeselect: this.handleDeselect, + onSelect: this.handleSelect, ref: this.saveInnerMenu, };