diff --git a/components/alert/index.tsx b/components/alert/index.tsx index ab8debcfd..6c6b0d3d8 100644 --- a/components/alert/index.tsx +++ b/components/alert/index.tsx @@ -18,8 +18,6 @@ import { cloneElement } from '../_util/vnode'; import type { NodeMouseEventHandler } from '../vc-tree/contextTypes'; import useConfigInject from '../_util/hooks/useConfigInject'; -function noop() {} - const iconMapFilled = { success: CheckCircleFilled, info: InfoCircleFilled, @@ -52,7 +50,7 @@ export const alertProps = () => ({ /** Additional content of Alert */ description: PropTypes.any, /** Trigger when animation ending of Alert */ - afterClose: PropTypes.func.def(noop), + afterClose: Function as PropType<() => void>, /** Whether to show icon */ showIcon: { type: Boolean, default: undefined }, prefixCls: String, diff --git a/components/anchor/AnchorLink.tsx b/components/anchor/AnchorLink.tsx index 8f747b800..049790643 100644 --- a/components/anchor/AnchorLink.tsx +++ b/components/anchor/AnchorLink.tsx @@ -1,23 +1,23 @@ import type { ExtractPropTypes } from 'vue'; import { defineComponent, nextTick, onBeforeUnmount, onMounted, watch } from 'vue'; import PropTypes from '../_util/vue-types'; -import { getPropsSlot } from '../_util/props-util'; +import { getPropsSlot, initDefaultProps } from '../_util/props-util'; import classNames from '../_util/classNames'; import useConfigInject from '../_util/hooks/useConfigInject'; import { useInjectAnchor } from './context'; -export const anchorLinkProps = { +export const anchorLinkProps = () => ({ prefixCls: String, - href: PropTypes.string.def('#'), + href: String, title: PropTypes.any, target: String, -}; +}); -export type AnchorLinkProps = Partial>; +export type AnchorLinkProps = Partial>>; export default defineComponent({ name: 'AAnchorLink', - props: anchorLinkProps, + props: initDefaultProps(anchorLinkProps(), { href: '#' }), slots: ['title'], setup(props, { slots }) { let mergedTitle = null; diff --git a/components/auto-complete/index.tsx b/components/auto-complete/index.tsx index c9765c35a..1cca93153 100644 --- a/components/auto-complete/index.tsx +++ b/components/auto-complete/index.tsx @@ -1,7 +1,6 @@ -import type { App, VNode, ExtractPropTypes } from 'vue'; +import type { App, VNode, ExtractPropTypes, CSSProperties, PropType } from 'vue'; import { defineComponent, ref } from 'vue'; import Select, { selectProps } from '../select'; -import PropTypes from '../_util/vue-types'; import { isValidElement, flattenChildren } from '../_util/props-util'; import warning from '../_util/warning'; import Option from './Option'; @@ -13,15 +12,27 @@ function isSelectOptionOrSelectOptGroup(child: any): boolean { return child?.type?.isSelectOption || child?.type?.isSelectOptGroup; } -export const autoCompleteProps = { +export const autoCompleteProps = () => ({ ...omit(selectProps(), ['loading', 'mode', 'optionLabelProp', 'labelInValue']), - dataSource: PropTypes.array, - dropdownMenuStyle: PropTypes.style, + dataSource: Array as PropType<{ value: any; text: any }[] | string[]>, + dropdownMenuStyle: { + type: Object as PropType, + default: undefined as CSSProperties, + }, // optionLabelProp: String, dropdownMatchSelectWidth: { type: [Number, Boolean], default: true }, -}; + prefixCls: String, + showSearch: { type: Boolean, default: undefined }, + transitionName: String, + choiceTransitionName: { type: String, default: 'zoom' }, + autofocus: { type: Boolean, default: undefined }, + backfill: { type: Boolean, default: undefined }, + // optionLabelProp: PropTypes.string.def('children'), + filterOption: { type: [Boolean, Function], default: false }, + defaultActiveFirstOption: { type: Boolean, default: true }, +}); -export type AutoCompleteProps = Partial>; +export type AutoCompleteProps = Partial>>; export const AutoCompleteOption = Option; @@ -30,19 +41,8 @@ export const AutoCompleteOptGroup = OptGroup; const AutoComplete = defineComponent({ name: 'AAutoComplete', inheritAttrs: false, - props: { - ...autoCompleteProps, - prefixCls: String, - showSearch: { type: Boolean, default: undefined }, - transitionName: String, - choiceTransitionName: PropTypes.string.def('zoom'), - autofocus: { type: Boolean, default: undefined }, - backfill: { type: Boolean, default: undefined }, - // optionLabelProp: PropTypes.string.def('children'), - filterOption: PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func]).def(false), - defaultActiveFirstOption: PropTypes.looseBool.def(true), - }, - emits: ['change', 'select', 'focus', 'blur'], + props: autoCompleteProps(), + // emits: ['change', 'select', 'focus', 'blur'], slots: ['option'], setup(props, { slots, attrs, expose }) { warning( diff --git a/components/avatar/Avatar.tsx b/components/avatar/Avatar.tsx index 2294bbd73..157f53d40 100644 --- a/components/avatar/Avatar.tsx +++ b/components/avatar/Avatar.tsx @@ -1,5 +1,5 @@ import type { VueNode } from '../_util/type'; -import { tuple } from '../_util/type'; + import type { CSSProperties, ExtractPropTypes, PropType } from 'vue'; import { computed, defineComponent, nextTick, onMounted, ref, watch } from 'vue'; import { getPropsSlot } from '../_util/props-util'; @@ -16,7 +16,7 @@ export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap; export const avatarProps = () => ({ prefixCls: String, - shape: PropTypes.oneOf(tuple('circle', 'square')).def('circle'), + shape: { type: String as PropType<'circle' | 'square'>, default: 'circle' }, size: { type: [Number, String, Object] as PropType, default: (): AvatarSize => 'default', @@ -27,7 +27,7 @@ export const avatarProps = () => ({ icon: PropTypes.any, alt: String, gap: Number, - draggable: PropTypes.bool, + draggable: { type: Boolean, default: undefined }, crossOrigin: String as PropType<'' | 'anonymous' | 'use-credentials'>, loadError: { type: Function as PropType<() => boolean>, diff --git a/components/avatar/Group.tsx b/components/avatar/Group.tsx index 3806c1630..6777c5324 100644 --- a/components/avatar/Group.tsx +++ b/components/avatar/Group.tsx @@ -4,9 +4,7 @@ import Avatar from './Avatar'; import Popover from '../popover'; import type { PropType, ExtractPropTypes, CSSProperties } from 'vue'; import { defineComponent } from 'vue'; -import PropTypes from '../_util/vue-types'; import { flattenChildren, getPropsSlot } from '../_util/props-util'; -import { tuple } from '../_util/type'; import useConfigInject from '../_util/hooks/useConfigInject'; import useProvideSize from '../_util/hooks/useSize'; @@ -15,9 +13,9 @@ export const groupProps = () => ({ maxCount: Number, maxStyle: { type: Object as PropType, - default: () => ({} as CSSProperties), + default: undefined as CSSProperties, }, - maxPopoverPlacement: PropTypes.oneOf(tuple('top', 'bottom')).def('top'), + maxPopoverPlacement: { type: String as PropType<'top' | 'bottom'>, default: 'top' }, maxPopoverTrigger: String as PropType<'hover' | 'focus' | 'click'>, /* * Size of avatar, options: `large`, `small`, `default` @@ -25,7 +23,7 @@ export const groupProps = () => ({ * */ size: { type: [Number, String, Object] as PropType, - default: (): AvatarSize => 'default', + default: 'default' as AvatarSize, }, }); diff --git a/components/back-top/index.tsx b/components/back-top/index.tsx index 95fc4c2cd..2abef7ac1 100644 --- a/components/back-top/index.tsx +++ b/components/back-top/index.tsx @@ -11,7 +11,6 @@ import { onDeactivated, } from 'vue'; import VerticalAlignTopOutlined from '@ant-design/icons-vue/VerticalAlignTopOutlined'; -import PropTypes from '../_util/vue-types'; import addEventListener from '../vc-util/Dom/addEventListener'; import getScroll from '../_util/getScroll'; import { getTransitionProps, Transition } from '../_util/transition'; @@ -19,23 +18,24 @@ import scrollTo from '../_util/scrollTo'; import { withInstall } from '../_util/type'; import throttleByAnimationFrame from '../_util/throttleByAnimationFrame'; import useConfigInject from '../_util/hooks/useConfigInject'; +import type { MouseEventHandler } from '../_util/EventInterface'; -export const backTopProps = { - visibilityHeight: PropTypes.number.def(400), - duration: PropTypes.number.def(450), +export const backTopProps = () => ({ + visibilityHeight: { type: Number, default: 400 }, + duration: { type: Number, default: 450 }, target: Function as PropType<() => HTMLElement | Window | Document>, prefixCls: String, - onClick: Function, + onClick: Function as PropType, // visible: { type: Boolean, default: undefined }, // Only for test. Don't use it. -}; +}); export type BackTopProps = Partial>; const BackTop = defineComponent({ name: 'ABackTop', inheritAttrs: false, - props: backTopProps, - emits: ['click'], + props: backTopProps(), + // emits: ['click'], setup(props, { slots, attrs, emit }) { const { prefixCls, direction } = useConfigInject('back-top', props); const domRef = ref(); diff --git a/components/badge/Badge.tsx b/components/badge/Badge.tsx index efd8e1cf9..082dd84b2 100644 --- a/components/badge/Badge.tsx +++ b/components/badge/Badge.tsx @@ -4,41 +4,40 @@ import classNames from '../_util/classNames'; import { getPropsSlot, flattenChildren } from '../_util/props-util'; import { cloneElement } from '../_util/vnode'; import { getTransitionProps, Transition } from '../_util/transition'; -import type { ExtractPropTypes, CSSProperties } from 'vue'; +import type { ExtractPropTypes, CSSProperties, PropType } from 'vue'; import { defineComponent, computed, ref, watch } from 'vue'; -import { tuple } from '../_util/type'; import Ribbon from './Ribbon'; import { isPresetColor } from './utils'; import useConfigInject from '../_util/hooks/useConfigInject'; import isNumeric from '../_util/isNumeric'; +import type { PresetStatusColorType } from '../_util/colors'; -export const badgeProps = { +export const badgeProps = () => ({ /** Number to show in badge */ count: PropTypes.any, showZero: { type: Boolean, default: undefined }, /** Max count to show */ - overflowCount: PropTypes.number.def(99), + overflowCount: { type: Number, default: 99 }, /** whether to show red dot without number */ dot: { type: Boolean, default: undefined }, prefixCls: String, scrollNumberPrefixCls: String, - status: PropTypes.oneOf(tuple('success', 'processing', 'default', 'error', 'warning')), - // sync antd@4.6.0 - size: PropTypes.oneOf(tuple('default', 'small')).def('default'), + status: { type: String as PropType }, + size: { type: String as PropType<'default' | 'small'>, default: 'default' }, color: String, text: PropTypes.any, - offset: PropTypes.arrayOf(PropTypes.oneOfType([String, Number])), - numberStyle: PropTypes.style, + offset: Array as unknown as PropType<[number | string, number | string]>, + numberStyle: Object as PropType, title: String, -}; +}); -export type BadgeProps = Partial>; +export type BadgeProps = Partial>>; export default defineComponent({ name: 'ABadge', Ribbon, inheritAttrs: false, - props: badgeProps, + props: badgeProps(), slots: ['text', 'count'], setup(props, { slots, attrs }) { const { prefixCls, direction } = useConfigInject('badge', props); @@ -197,7 +196,7 @@ export default defineComponent({ const transitionProps = getTransitionProps(children ? `${pre}-zoom` : '', { appear: false, }); - let scrollNumberStyle: CSSProperties = { ...mergedStyle, ...props.numberStyle }; + let scrollNumberStyle: CSSProperties = { ...mergedStyle, ...(props.numberStyle as object) }; if (color && !isPresetColor(color)) { scrollNumberStyle = scrollNumberStyle || {}; scrollNumberStyle.background = color; diff --git a/components/badge/Ribbon.tsx b/components/badge/Ribbon.tsx index ddffd5e13..7fba9933a 100644 --- a/components/badge/Ribbon.tsx +++ b/components/badge/Ribbon.tsx @@ -1,5 +1,4 @@ import type { LiteralUnion } from '../_util/type'; -import { tuple } from '../_util/type'; import type { PresetColorType } from '../_util/colors'; import { isPresetColor } from './utils'; import type { CSSProperties, PropType, ExtractPropTypes } from 'vue'; @@ -7,19 +6,19 @@ import { defineComponent, computed } from 'vue'; import PropTypes from '../_util/vue-types'; import useConfigInject from '../_util/hooks/useConfigInject'; -export const ribbonProps = { +export const ribbonProps = () => ({ prefix: String, color: { type: String as PropType> }, text: PropTypes.any, - placement: PropTypes.oneOf(tuple('start', 'end')).def('end'), -}; + placement: { type: String as PropType<'start' | 'end'>, default: 'end' }, +}); -export type RibbonProps = Partial>; +export type RibbonProps = Partial>>; export default defineComponent({ name: 'ABadgeRibbon', inheritAttrs: false, - props: ribbonProps, + props: ribbonProps(), slots: ['text'], setup(props, { attrs, slots }) { const { prefixCls, direction } = useConfigInject('ribbon', props); diff --git a/components/badge/ScrollNumber.tsx b/components/badge/ScrollNumber.tsx index c2267a8df..f7a83a21b 100644 --- a/components/badge/ScrollNumber.tsx +++ b/components/badge/ScrollNumber.tsx @@ -7,11 +7,11 @@ import useConfigInject from '../_util/hooks/useConfigInject'; import SingleNumber from './SingleNumber'; import { filterEmpty } from '../_util/props-util'; -export const scrollNumberProps = { +const scrollNumberProps = { prefixCls: String, count: PropTypes.any, component: String, - title: PropTypes.oneOfType([PropTypes.number, PropTypes.string, null]), + title: PropTypes.any, show: Boolean, }; diff --git a/components/breadcrumb/Breadcrumb.tsx b/components/breadcrumb/Breadcrumb.tsx index 01e312482..cbb49077d 100644 --- a/components/breadcrumb/Breadcrumb.tsx +++ b/components/breadcrumb/Breadcrumb.tsx @@ -14,7 +14,7 @@ export interface Route { children?: Omit[]; } -export const breadcrumbProps = { +export const breadcrumbProps = () => ({ prefixCls: String, routes: { type: Array as PropType }, params: PropTypes.any, @@ -24,9 +24,9 @@ export const breadcrumbProps = { (opt: { route: Route; params: unknown; routes: Route[]; paths: string[] }) => VueNode >, }, -}; +}); -export type BreadcrumbProps = Partial>; +export type BreadcrumbProps = Partial>>; function getBreadcrumbName(route: Route, params: unknown) { if (!route.breadcrumbName) { @@ -53,7 +53,7 @@ function defaultItemRender(opt: { export default defineComponent({ name: 'ABreadcrumb', - props: breadcrumbProps, + props: breadcrumbProps(), slots: ['separator', 'itemRender'], setup(props, { slots }) { const { prefixCls, direction } = useConfigInject('breadcrumb', props); diff --git a/components/breadcrumb/BreadcrumbItem.tsx b/components/breadcrumb/BreadcrumbItem.tsx index 91fd079f3..a1ce51757 100644 --- a/components/breadcrumb/BreadcrumbItem.tsx +++ b/components/breadcrumb/BreadcrumbItem.tsx @@ -1,26 +1,29 @@ -import type { ExtractPropTypes } from 'vue'; +import type { ExtractPropTypes, PropType } from 'vue'; import { defineComponent } from 'vue'; import PropTypes from '../_util/vue-types'; import { getPropsSlot } from '../_util/props-util'; import DropDown from '../dropdown/dropdown'; import DownOutlined from '@ant-design/icons-vue/DownOutlined'; import useConfigInject from '../_util/hooks/useConfigInject'; +import type { MouseEventHandler } from '../_util/EventInterface'; -export const breadcrumbItemProps = { +export const breadcrumbItemProps = () => ({ prefixCls: String, href: String, separator: PropTypes.any, overlay: PropTypes.any, -}; + onClick: Function as PropType, +}); -export type BreadcrumbItemProps = Partial>; +export type BreadcrumbItemProps = Partial>>; export default defineComponent({ name: 'ABreadcrumbItem', + inheritAttrs: false, __ANT_BREADCRUMB_ITEM: true, - props: breadcrumbItemProps, - emits: ['click'], + props: breadcrumbItemProps(), + // emits: ['click'], slots: ['separator', 'overlay'], - setup(props, { slots, emit }) { + setup(props, { slots, attrs }) { const { prefixCls } = useConfigInject('breadcrumb', props); /** * if overlay is have @@ -41,24 +44,29 @@ export default defineComponent({ return breadcrumbItem; }; - const handleClick = (e: MouseEvent) => { - emit('click', e); - }; - return () => { const separator = getPropsSlot(slots, props, 'separator') ?? '/'; const children = getPropsSlot(slots, props); + const { class: cls, style, ...restAttrs } = attrs; let link: JSX.Element; if (props.href !== undefined) { - link = {children}; + link = ( + + {children} + + ); } else { - link = {children}; + link = ( + + {children} + + ); } // wrap to dropDown link = renderBreadcrumbNode(link, prefixCls.value); if (children) { return ( - + {link} {separator && {separator}} diff --git a/components/breadcrumb/BreadcrumbSeparator.tsx b/components/breadcrumb/BreadcrumbSeparator.tsx index e15b26d24..f0b4f2cab 100644 --- a/components/breadcrumb/BreadcrumbSeparator.tsx +++ b/components/breadcrumb/BreadcrumbSeparator.tsx @@ -1,19 +1,20 @@ import type { ExtractPropTypes } from 'vue'; import { defineComponent } from 'vue'; -import PropTypes from '../_util/vue-types'; import { flattenChildren } from '../_util/props-util'; import useConfigInject from '../_util/hooks/useConfigInject'; -export const breadcrumbSeparatorProps = { +export const breadcrumbSeparatorProps = () => ({ prefixCls: String, -}; -export type BreadcrumbSeparatorProps = Partial>; +}); +export type BreadcrumbSeparatorProps = Partial< + ExtractPropTypes> +>; export default defineComponent({ name: 'ABreadcrumbSeparator', __ANT_BREADCRUMB_SEPARATOR: true, inheritAttrs: false, - props: breadcrumbSeparatorProps, + props: breadcrumbSeparatorProps(), setup(props, { slots, attrs }) { const { prefixCls } = useConfigInject('breadcrumb', props); diff --git a/components/button/button-group.tsx b/components/button/button-group.tsx index b1ee9f4e9..fd543d9ff 100644 --- a/components/button/button-group.tsx +++ b/components/button/button-group.tsx @@ -1,25 +1,23 @@ import { computed, defineComponent } from 'vue'; import { flattenChildren } from '../_util/props-util'; -import PropTypes from '../_util/vue-types'; import useConfigInject from '../_util/hooks/useConfigInject'; import type { ExtractPropTypes, PropType } from 'vue'; import type { SizeType } from '../config-provider'; import UnreachableException from '../_util/unreachableException'; -const buttonGroupProps = { +export const buttonGroupProps = () => ({ prefixCls: String, size: { type: String as PropType, }, -}; -export { buttonGroupProps }; +}); -export type ButtonGroupProps = Partial>; +export type ButtonGroupProps = Partial>>; export default defineComponent({ name: 'AButtonGroup', - props: buttonGroupProps, + props: buttonGroupProps(), setup(props, { slots }) { const { prefixCls, direction } = useConfigInject('btn-group', props); const classes = computed(() => { diff --git a/components/button/button.tsx b/components/button/button.tsx index e83697546..d5a1a3960 100644 --- a/components/button/button.tsx +++ b/components/button/button.tsx @@ -10,7 +10,7 @@ import { watchEffect, } from 'vue'; import Wave from '../_util/wave'; -import buttonTypes from './buttonTypes'; +import buttonProps from './buttonTypes'; import { flattenChildren, initDefaultProps } from '../_util/props-util'; import useConfigInject from '../_util/hooks/useConfigInject'; import devWarning from '../vc-util/devWarning'; @@ -27,14 +27,14 @@ const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar); function isUnborderedButtonType(type: ButtonType | undefined) { return type === 'text' || type === 'link'; } - +export { buttonProps }; export default defineComponent({ name: 'AButton', inheritAttrs: false, __ANT_BUTTON: true, - props: initDefaultProps(buttonTypes(), { type: 'default' }), + props: initDefaultProps(buttonProps(), { type: 'default' }), slots: ['icon'], - emits: ['click', 'mousedown'], + // emits: ['click', 'mousedown'], setup(props, { slots, attrs, emit }) { const { prefixCls, autoInsertSpaceInButton, direction, size } = useConfigInject('btn', props); @@ -151,7 +151,7 @@ export default defineComponent({ isNeedInserted = children.length === 1 && !icon && !isUnborderedButtonType(props.type); - const { type, htmlType, disabled, href, title, target } = props; + const { type, htmlType, disabled, href, title, target, onMousedown } = props; const iconType = innerLoading.value ? 'loading' : icon; const buttonProps = { @@ -164,6 +164,7 @@ export default defineComponent({ { [`${prefixCls.value}-icon-only`]: children.length === 0 && !!iconType }, ], onClick: handleClick, + onMousedown, }; // https://github.com/vueComponent/ant-design-vue/issues/4930 if (!disabled) { diff --git a/components/button/buttonTypes.ts b/components/button/buttonTypes.ts index 08df01c0d..d4e49551d 100644 --- a/components/button/buttonTypes.ts +++ b/components/button/buttonTypes.ts @@ -1,16 +1,12 @@ -import { tuple } from '../_util/type'; import PropTypes from '../_util/vue-types'; import type { ExtractPropTypes, PropType } from 'vue'; import type { SizeType } from '../config-provider'; -const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'link', 'text'); -export type ButtonType = typeof ButtonTypes[number]; -const ButtonShapes = tuple('default', 'circle', 'round'); -export type ButtonShape = typeof ButtonShapes[number]; +export type ButtonType = 'link' | 'default' | 'primary' | 'ghost' | 'dashed' | 'text'; +export type ButtonShape = 'default' | 'circle' | 'round'; -const ButtonHTMLTypes = tuple('submit', 'button', 'reset'); -export type ButtonHTMLType = typeof ButtonHTMLTypes[number]; +export type ButtonHTMLType = 'submit' | 'button' | 'reset'; export type LegacyButtonType = ButtonType | 'danger'; export function convertLegacyProps(type?: LegacyButtonType): ButtonProps { @@ -22,9 +18,9 @@ export function convertLegacyProps(type?: LegacyButtonType): ButtonProps { export const buttonProps = () => ({ prefixCls: String, - type: PropTypes.oneOf(ButtonTypes), - htmlType: PropTypes.oneOf(ButtonHTMLTypes).def('button'), - shape: PropTypes.oneOf(ButtonShapes), + type: String as PropType, + htmlType: { type: String as PropType, default: 'button' }, + shape: { type: String as PropType }, size: { type: String as PropType, }, @@ -43,6 +39,9 @@ export const buttonProps = () => ({ onClick: { type: Function as PropType<(event: MouseEvent) => void>, }, + onMousedown: { + type: Function as PropType<(event: MouseEvent) => void>, + }, }); export type ButtonProps = Partial>>;