diff --git a/components/_util/transition.tsx b/components/_util/transition.tsx
index 1894aff8b..6caea7504 100644
--- a/components/_util/transition.tsx
+++ b/components/_util/transition.tsx
@@ -1,5 +1,5 @@
-import type { BaseTransitionProps, CSSProperties, Ref } from 'vue';
-import { getCurrentInstance, onUpdated } from 'vue';
+import { BaseTransitionProps, CSSProperties, onBeforeUpdate, Ref } from 'vue';
+import { getCurrentInstance } from 'vue';
import { defineComponent, nextTick, Transition as T, TransitionGroup as TG } from 'vue';
export const getTransitionProps = (transitionName: string, opt: object = {}) => {
@@ -51,7 +51,7 @@ if (process.env.NODE_ENV === 'test') {
inheritAttrs: false,
setup(_props, { slots, attrs }) {
const instance = getCurrentInstance();
- onUpdated(() => {
+ onBeforeUpdate(() => {
const child = instance.subTree.children[0];
if (child && child.dirs && child.dirs[0]) {
const value = child.dirs[0].value;
diff --git a/components/auto-complete/InputElement.tsx b/components/auto-complete/InputElement.tsx
deleted file mode 100644
index c3623cfec..000000000
--- a/components/auto-complete/InputElement.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { cloneElement } from '../_util/vnode';
-import { flattenChildren } from '../_util/props-util';
-
-const InputElement = (_: any, { attrs, slots }) => {
- const children = flattenChildren(slots.default?.())[0];
- return cloneElement(children, { ...attrs });
-};
-InputElement.inheritAttrs = false;
-export default InputElement;
diff --git a/components/auto-complete/index.tsx b/components/auto-complete/index.tsx
index dac4d43db..d9e43f753 100644
--- a/components/auto-complete/index.tsx
+++ b/components/auto-complete/index.tsx
@@ -2,7 +2,6 @@ import type { App, Plugin, VNode, ExtractPropTypes } from 'vue';
import { defineComponent, inject, provide } from 'vue';
import Select, { SelectProps } from '../select';
import Input from '../input';
-import InputElement from './InputElement';
import PropTypes from '../_util/vue-types';
import { defaultConfigProvider } from '../config-provider';
import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util';
@@ -72,7 +71,7 @@ const AutoComplete = defineComponent({
getInputElement() {
const children = getSlot(this);
const element = children.length ? children[0] : ;
- return {element};
+ return element;
},
focus() {
diff --git a/components/cascader/__tests__/__snapshots__/index.test.js.snap b/components/cascader/__tests__/__snapshots__/index.test.js.snap
index 708351c16..c2a63580d 100644
--- a/components/cascader/__tests__/__snapshots__/index.test.js.snap
+++ b/components/cascader/__tests__/__snapshots__/index.test.js.snap
@@ -113,4 +113,33 @@ exports[`Cascader popup correctly with defaultValue 1`] = `
`;
-exports[`Cascader support controlled mode 1`] = `Zhejiang / Hangzhou / West Lake`;
+exports[`Cascader popup correctly with defaultValue 2`] = `
+
+
+
+
+`;
+
+exports[`Cascader support controlled mode 1`] = `Zhejiang / Hangzhou / West Lake`;
diff --git a/components/drawer/index.tsx b/components/drawer/index.tsx
index cd4ababc7..bb53f4dab 100644
--- a/components/drawer/index.tsx
+++ b/components/drawer/index.tsx
@@ -123,7 +123,7 @@ const Drawer = defineComponent({
}
if (!this.visible) {
this.destroyClose = true;
- this.$forceUpdate();
+ (this as any).$forceUpdate();
}
},
diff --git a/components/input/Input.tsx b/components/input/Input.tsx
index df07a8bf1..46cb7ce0e 100644
--- a/components/input/Input.tsx
+++ b/components/input/Input.tsx
@@ -128,7 +128,7 @@ export default defineComponent({
if (!hasProp(this, 'value')) {
this.stateValue = value;
} else {
- this.$forceUpdate();
+ (this as any).$forceUpdate();
}
nextTick(() => {
callback && callback();
diff --git a/components/input/TextArea.tsx b/components/input/TextArea.tsx
index 1fb195432..f654bc56d 100644
--- a/components/input/TextArea.tsx
+++ b/components/input/TextArea.tsx
@@ -55,7 +55,7 @@ export default defineComponent({
if (!hasProp(this, 'value')) {
this.stateValue = value;
} else {
- this.$forceUpdate();
+ (this as any).$forceUpdate();
}
nextTick(() => {
callback && callback();
diff --git a/components/menu/src/MenuItem.tsx b/components/menu/src/MenuItem.tsx
index 49f7f7405..df483b93d 100644
--- a/components/menu/src/MenuItem.tsx
+++ b/components/menu/src/MenuItem.tsx
@@ -10,6 +10,7 @@ import type { MenuInfo } from './interface';
import KeyCode from '../../_util/KeyCode';
import useDirectionStyle from './hooks/useDirectionStyle';
import Overflow from '../../vc-overflow';
+import devWarning from '../../vc-util/devWarning';
let indexGuid = 0;
const menuItemProps = {
@@ -30,7 +31,15 @@ export default defineComponent({
slots: ['icon', 'title'],
setup(props, { slots, emit, attrs }) {
const instance = getCurrentInstance();
- const key = instance.vnode.key;
+
+ const key =
+ typeof instance.vnode.key === 'symbol' ? String(instance.vnode.key) : instance.vnode.key;
+ devWarning(
+ typeof instance.vnode.key !== 'symbol',
+ 'MenuItem',
+ `MenuItem \`:key="${String(key)}"\` not support Symbol type`,
+ );
+
const eventKey = `menu_item_${++indexGuid}_$$_${key}`;
const { parentEventKeys, parentKeys } = useInjectKeyPath();
const {
diff --git a/components/menu/src/SubMenu.tsx b/components/menu/src/SubMenu.tsx
index 24fde493f..57fea3003 100644
--- a/components/menu/src/SubMenu.tsx
+++ b/components/menu/src/SubMenu.tsx
@@ -12,6 +12,8 @@ import InlineSubMenuList from './InlineSubMenuList';
import Transition, { getTransitionProps } from '../../_util/transition';
import { cloneElement } from '../../_util/vnode';
import Overflow from '../../vc-overflow';
+import devWarning from '../../vc-util/devWarning';
+import isValid from '../../_util/isValid';
let indexGuid = 0;
@@ -39,14 +41,17 @@ export default defineComponent({
useProvideFirstLevel(false);
const instance = getCurrentInstance();
- const key =
- instance.vnode.key !== null ? instance.vnode.key : `sub_menu_${++indexGuid}_$$_not_set_key`;
-
+ const vnodeKey =
+ typeof instance.vnode.key === 'symbol' ? String(instance.vnode.key) : instance.vnode.key;
+ devWarning(
+ typeof instance.vnode.key !== 'symbol',
+ 'SubMenu',
+ `SubMenu \`:key="${String(vnodeKey)}"\` not support Symbol type`,
+ );
+ const key = isValid(vnodeKey) ? vnodeKey : `sub_menu_${++indexGuid}_$$_not_set_key`;
const eventKey =
props.eventKey ??
- (instance.vnode.key !== null
- ? `sub_menu_${++indexGuid}_$$_${instance.vnode.key}`
- : (key as string));
+ (isValid(vnodeKey) ? `sub_menu_${++indexGuid}_$$_${vnodeKey}` : (key as string));
const { parentEventKeys, parentInfo, parentKeys } = useInjectKeyPath();
const keysPath = computed(() => [...parentKeys.value, key]);
const eventKeysPath = computed(() => [...parentEventKeys.value, eventKey]);
diff --git a/components/table/filterDropdown.tsx b/components/table/filterDropdown.tsx
index 8f3b8ba27..12380eb11 100755
--- a/components/table/filterDropdown.tsx
+++ b/components/table/filterDropdown.tsx
@@ -98,7 +98,7 @@ export default defineComponent({
this.setVisible(false);
// Call `setSelectedKeys` & `confirm` in the same time will make filter data not up to date
// https://github.com/ant-design/ant-design/issues/12284
- this.$forceUpdate();
+ (this as any).$forceUpdate();
nextTick(this.confirmFilter2);
},
diff --git a/components/upload/UploadList.tsx b/components/upload/UploadList.tsx
index 4137f876a..05f5fdc9b 100644
--- a/components/upload/UploadList.tsx
+++ b/components/upload/UploadList.tsx
@@ -64,7 +64,7 @@ export default defineComponent({
previewFile(file.originFileObj).then(previewDataUrl => {
// Need append '' to avoid dead loop
file.thumbUrl = previewDataUrl || '';
- this.$forceUpdate();
+ (this as any).$forceUpdate();
});
}
});
diff --git a/components/vc-select/OptionList.tsx b/components/vc-select/OptionList.tsx
index fbeb9744b..a24735d76 100644
--- a/components/vc-select/OptionList.tsx
+++ b/components/vc-select/OptionList.tsx
@@ -5,7 +5,7 @@ import classNames from '../_util/classNames';
import pickAttrs from '../_util/pickAttrs';
import { isValidElement } from '../_util/props-util';
import createRef from '../_util/createRef';
-import type { VNodeChild } from 'vue';
+import type { PropType, VNodeChild } from 'vue';
import { computed, defineComponent, nextTick, reactive, watch } from 'vue';
import List from '../vc-virtual-list/List';
import type {
@@ -61,7 +61,7 @@ const OptionListProps = {
virtual: PropTypes.looseBool,
onSelect: PropTypes.func,
- onToggleOpen: PropTypes.func,
+ onToggleOpen: { type: Function as PropType<(open?: boolean) => void> },
/** Tell Select that some value is now active to make accessibility work */
onActiveValue: PropTypes.func,
onScroll: PropTypes.func,
diff --git a/components/vc-select/Selector/Input.tsx b/components/vc-select/Selector/Input.tsx
index c8f72a71d..b29c6edf0 100644
--- a/components/vc-select/Selector/Input.tsx
+++ b/components/vc-select/Selector/Input.tsx
@@ -74,7 +74,7 @@ const Input = defineComponent) as VNode, [[antInput]]);
+ let inputNode: any = inputElement || withDirectives(() as VNode, [[antInput]]);
const inputProps = inputNode.props || {};
const {
diff --git a/components/vc-select/Selector/MultipleSelector.tsx b/components/vc-select/Selector/MultipleSelector.tsx
index dc9805a97..950378854 100644
--- a/components/vc-select/Selector/MultipleSelector.tsx
+++ b/components/vc-select/Selector/MultipleSelector.tsx
@@ -7,9 +7,9 @@ import type {
DisplayLabelValueType,
} from '../interface/generator';
import type { RenderNode } from '../interface';
-import type { InnerSelectorProps } from '.';
+import type { InnerSelectorProps } from './interface';
import Input from './Input';
-import type { VNodeChild, Ref } from 'vue';
+import type { VNodeChild, Ref, PropType } from 'vue';
import { computed, defineComponent, onMounted, ref, watch } from 'vue';
import classNames from '../../_util/classNames';
import pickAttrs from '../../_util/pickAttrs';
@@ -17,24 +17,24 @@ import PropTypes from '../../_util/vue-types';
import type { VueNode } from '../../_util/type';
import Overflow from '../../vc-overflow';
-interface SelectorProps extends InnerSelectorProps {
+type SelectorProps = InnerSelectorProps & {
// Icon
removeIcon?: RenderNode;
// Tags
maxTagCount?: number | 'responsive';
maxTagTextLength?: number;
- maxTagPlaceholder?: VNodeChild;
+ maxTagPlaceholder?: VNodeChild | ((omittedValues: LabelValueType[]) => VNodeChild);
tokenSeparators?: string[];
tagRender?: (props: CustomTagProps) => VNodeChild;
- onToggleOpen: (open?: boolean) => void;
+ onToggleOpen: any;
// Motion
choiceTransitionName?: string;
// Event
onSelect: (value: RawValueType, option: { selected: boolean }) => void;
-}
+};
const props = {
id: PropTypes.string,
@@ -62,6 +62,7 @@ const props = {
),
tagRender: PropTypes.func,
+ onToggleOpen: { type: Function as PropType<(open?: boolean) => void> },
onSelect: PropTypes.func,
onInputChange: PropTypes.func,
onInputPaste: PropTypes.func,
@@ -78,6 +79,8 @@ const onPreventMouseDown = (event: MouseEvent) => {
const SelectSelector = defineComponent({
name: 'MultipleSelectSelector',
+ inheritAttrs: false,
+ props: props as any,
setup(props) {
const measureRef = ref();
const inputWidth = ref(0);
@@ -278,6 +281,5 @@ const SelectSelector = defineComponent({
};
},
});
-SelectSelector.inheritAttrs = false;
-SelectSelector.props = props;
+
export default SelectSelector;
diff --git a/components/vc-select/Selector/SingleSelector.tsx b/components/vc-select/Selector/SingleSelector.tsx
index be58e784f..fdbff431a 100644
--- a/components/vc-select/Selector/SingleSelector.tsx
+++ b/components/vc-select/Selector/SingleSelector.tsx
@@ -1,6 +1,6 @@
import pickAttrs from '../../_util/pickAttrs';
import Input from './Input';
-import type { InnerSelectorProps } from '.';
+import type { InnerSelectorProps } from './interface';
import type { VNodeChild } from 'vue';
import { computed, defineComponent, Fragment, ref, watch } from 'vue';
import PropTypes from '../../_util/vue-types';
diff --git a/components/vc-select/Selector/index.tsx b/components/vc-select/Selector/index.tsx
index d4430c35a..e6dd0f9a1 100644
--- a/components/vc-select/Selector/index.tsx
+++ b/components/vc-select/Selector/index.tsx
@@ -14,36 +14,12 @@ import SingleSelector from './SingleSelector';
import type { LabelValueType, RawValueType, CustomTagProps } from '../interface/generator';
import type { RenderNode, Mode } from '../interface';
import useLock from '../hooks/useLock';
-import type { VNodeChild } from 'vue';
+import type { VNodeChild, PropType } from 'vue';
import { defineComponent } from 'vue';
-import type { RefObject } from '../../_util/createRef';
import createRef from '../../_util/createRef';
import PropTypes from '../../_util/vue-types';
import type { VueNode } from '../../_util/type';
-export interface InnerSelectorProps {
- prefixCls: string;
- id: string;
- mode: Mode;
- inputRef: RefObject;
- placeholder?: VNodeChild;
- disabled?: boolean;
- autofocus?: boolean;
- autocomplete?: string;
- values: LabelValueType[];
- showSearch?: boolean;
- searchValue: string;
- accessibilityIndex: number;
- open: boolean;
- tabindex?: number | string;
- onInputKeyDown: EventHandlerNonNull;
- onInputMouseDown: EventHandlerNonNull;
- onInputChange: EventHandlerNonNull;
- onInputPaste: EventHandlerNonNull;
- onInputCompositionStart: EventHandlerNonNull;
- onInputCompositionEnd: EventHandlerNonNull;
-}
-
export interface SelectorProps {
id: string;
prefixCls: string;
@@ -67,7 +43,7 @@ export interface SelectorProps {
// Tags
maxTagCount?: number | 'responsive';
maxTagTextLength?: number;
- maxTagPlaceholder?: VNodeChild;
+ maxTagPlaceholder?: VNodeChild | ((omittedValues: LabelValueType[]) => VNodeChild);
tagRender?: (props: CustomTagProps) => VNodeChild;
/** Check if `tokenSeparators` contains `\n` or `\r\n` */
@@ -92,6 +68,52 @@ export interface SelectorProps {
const Selector = defineComponent({
name: 'Selector',
+ inheritAttrs: false,
+ props: {
+ id: PropTypes.string,
+ prefixCls: PropTypes.string,
+ showSearch: PropTypes.looseBool,
+ open: PropTypes.looseBool,
+ /** Display in the Selector value, it's not same as `value` prop */
+ values: PropTypes.array,
+ multiple: PropTypes.looseBool,
+ mode: PropTypes.string,
+ searchValue: PropTypes.string,
+ activeValue: PropTypes.string,
+ inputElement: PropTypes.any,
+
+ autofocus: PropTypes.looseBool,
+ accessibilityIndex: PropTypes.number,
+ tabindex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
+ disabled: PropTypes.looseBool,
+ placeholder: PropTypes.any,
+ removeIcon: PropTypes.any,
+
+ // Tags
+ maxTagCount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
+ maxTagTextLength: PropTypes.number,
+ maxTagPlaceholder: PropTypes.any,
+ tagRender: PropTypes.func,
+
+ /** Check if `tokenSeparators` contains `\n` or `\r\n` */
+ tokenWithEnter: PropTypes.looseBool,
+
+ // Motion
+ choiceTransitionName: PropTypes.string,
+
+ onToggleOpen: { type: Function as PropType<(open?: boolean) => void> },
+ /** `onSearch` returns go next step boolean to check if need do toggle open */
+ onSearch: PropTypes.func,
+ onSearchSubmit: PropTypes.func,
+ onSelect: PropTypes.func,
+ onInputKeyDown: PropTypes.func,
+
+ /**
+ * @private get real dom for trigger align.
+ * This may be removed after React provides replacement of `findDOMNode`
+ */
+ domRef: PropTypes.func,
+ } as any,
setup(props) {
const inputRef = createRef();
let compositionStatus = false;
@@ -258,51 +280,4 @@ const Selector = defineComponent({
},
});
-Selector.inheritAttrs = false;
-Selector.props = {
- id: PropTypes.string,
- prefixCls: PropTypes.string,
- showSearch: PropTypes.looseBool,
- open: PropTypes.looseBool,
- /** Display in the Selector value, it's not same as `value` prop */
- values: PropTypes.array,
- multiple: PropTypes.looseBool,
- mode: PropTypes.string,
- searchValue: PropTypes.string,
- activeValue: PropTypes.string,
- inputElement: PropTypes.any,
-
- autofocus: PropTypes.looseBool,
- accessibilityIndex: PropTypes.number,
- tabindex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
- disabled: PropTypes.looseBool,
- placeholder: PropTypes.any,
- removeIcon: PropTypes.any,
-
- // Tags
- maxTagCount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
- maxTagTextLength: PropTypes.number,
- maxTagPlaceholder: PropTypes.any,
- tagRender: PropTypes.func,
-
- /** Check if `tokenSeparators` contains `\n` or `\r\n` */
- tokenWithEnter: PropTypes.looseBool,
-
- // Motion
- choiceTransitionName: PropTypes.string,
-
- onToggleOpen: PropTypes.func,
- /** `onSearch` returns go next step boolean to check if need do toggle open */
- onSearch: PropTypes.func,
- onSearchSubmit: PropTypes.func,
- onSelect: PropTypes.func,
- onInputKeyDown: PropTypes.func,
-
- /**
- * @private get real dom for trigger align.
- * This may be removed after React provides replacement of `findDOMNode`
- */
- domRef: PropTypes.func,
-};
-
export default Selector;
diff --git a/components/vc-select/Selector/interface.ts b/components/vc-select/Selector/interface.ts
new file mode 100644
index 000000000..2aa8b1e2c
--- /dev/null
+++ b/components/vc-select/Selector/interface.ts
@@ -0,0 +1,27 @@
+import type { RefObject } from '../../_util/createRef';
+import type { VNodeChild } from 'vue';
+import type { Mode } from '../interface';
+import type { LabelValueType } from '../interface/generator';
+
+export interface InnerSelectorProps {
+ prefixCls: string;
+ id: string;
+ mode: Mode;
+ inputRef: RefObject;
+ placeholder?: VNodeChild;
+ disabled?: boolean;
+ autofocus?: boolean;
+ autocomplete?: string;
+ values: LabelValueType[];
+ showSearch?: boolean;
+ searchValue: string;
+ accessibilityIndex: number;
+ open: boolean;
+ tabindex?: number | string;
+ onInputKeyDown: EventHandlerNonNull;
+ onInputMouseDown: EventHandlerNonNull;
+ onInputChange: EventHandlerNonNull;
+ onInputPaste: EventHandlerNonNull;
+ onInputCompositionStart: EventHandlerNonNull;
+ onInputCompositionEnd: EventHandlerNonNull;
+}
diff --git a/components/vc-select/generate.tsx b/components/vc-select/generate.tsx
index 09b2591ce..eb6571923 100644
--- a/components/vc-select/generate.tsx
+++ b/components/vc-select/generate.tsx
@@ -1057,7 +1057,7 @@ export default function generateSelector<
methods: {
// We need force update here since popup dom is render async
onPopupMouseEnter() {
- this.$forceUpdate();
+ (this as any).$forceUpdate();
},
},
render() {
diff --git a/v2-doc b/v2-doc
index 157cce105..6b53258cc 160000
--- a/v2-doc
+++ b/v2-doc
@@ -1 +1 @@
-Subproject commit 157cce105e1f0a369658dfb29cc802ebc09d0d93
+Subproject commit 6b53258cc2b3709e070d340714e992760e660e67