Merge remote-tracking branch 'origin/next' into v2.3

pull/4671/head
tangjinzhou 2021-09-12 08:54:07 +08:00
commit a6f37debb1
16 changed files with 118 additions and 64 deletions

View File

@ -10,6 +10,21 @@
--- ---
## 2.2.7
`2021-09-08`
- ๐ŸŒŸ Menu supports overflowedIndicator slot [#4515](https://github.com/vueComponent/ant-design-vue/issues/4515)
- ๐ŸŒŸ useForm supports dynamic rule [#4498](https://github.com/vueComponent/ant-design-vue/issues/4498)
- ๐ŸŒŸ Select supports Number type [#4570](https://github.com/vueComponent/ant-design-vue/issues/4570)
- ๐Ÿž Fix the warning problem caused by css zoom [#4554](https://github.com/vueComponent/ant-design-vue/issues/4554)
- ๐Ÿž Fix Mentions input Chinese error report [#4524](https://github.com/vueComponent/ant-design-vue/issues/4524)
- ๐Ÿž Fix the issue that AutoComplete does not support global prefixCls [#4566](https://github.com/vueComponent/ant-design-vue/issues/4566)
- ๐Ÿž Fix Table nested table error report [#4600](https://github.com/vueComponent/ant-design-vue/issues/4600)
- ๐Ÿž Fix MenuItem danger property under Dropdown has no style problem [#4618](https://github.com/vueComponent/ant-design-vue/issues/4618)
- ๐Ÿž Fix Modal.xxx and other methods passing appContext invalid problem [#4627](https://github.com/vueComponent/ant-design-vue/issues/4627)
- ๐Ÿž Fix some TS type errors
## 2.2.6 ## 2.2.6
`2021-08-12` `2021-08-12`

View File

@ -10,6 +10,21 @@
--- ---
## 2.2.7
`2021-09-08`
- ๐ŸŒŸ Menu ๆ”ฏๆŒ overflowedIndicator ๆ’ๆงฝ [#4515](https://github.com/vueComponent/ant-design-vue/issues/4515)
- ๐ŸŒŸ useForm ๆ”ฏๆŒๅŠจๆ€ rule [#4498](https://github.com/vueComponent/ant-design-vue/issues/4498)
- ๐ŸŒŸ Select ๆ”ฏๆŒ Number ็ฑปๅž‹ [#4570](https://github.com/vueComponent/ant-design-vue/issues/4570)
- ๐Ÿž ไฟฎๅค css zoom ๅผ•่ตท็š„ warning ้—ฎ้ข˜ [#4554](https://github.com/vueComponent/ant-design-vue/issues/4554)
- ๐Ÿž ไฟฎๅค Mentions ่พ“ๅ…ฅไธญๆ–‡ๆŠฅ้”™้—ฎ้ข˜ [#4524](https://github.com/vueComponent/ant-design-vue/issues/4524)
- ๐Ÿž ไฟฎๅค AutoComplete ไธๆ”ฏๆŒๅ…จๅฑ€ prefixCls ้—ฎ้ข˜ [#4566](https://github.com/vueComponent/ant-design-vue/issues/4566)
- ๐Ÿž ไฟฎๅค Table ๅตŒๅฅ—่กจๆ ผๆŠฅ้”™้—ฎ้ข˜ [#4600](https://github.com/vueComponent/ant-design-vue/issues/4600)
- ๐Ÿž ไฟฎๅค Dropdown ไธ‹็š„ MenuItem danger ๅฑžๆ€งๆ— ๆ ทๅผ้—ฎ้ข˜ [#4618](https://github.com/vueComponent/ant-design-vue/issues/4618)
- ๐Ÿž ไฟฎๅค Modal.xxx ็ญ‰ๆ–นๆณ•ไผ ้€’ appContext ๅคฑๆ•ˆ้—ฎ้ข˜ [#4627](https://github.com/vueComponent/ant-design-vue/issues/4627)
- ๐Ÿž ไฟฎๅคไธ€ไบ› TS ็ฑปๅž‹้”™่ฏฏ
## 2.2.6 ## 2.2.6
`2021-08-12` `2021-08-12`

View File

@ -13,7 +13,7 @@ const initDefaultProps = <T>(
: any; : any;
}, },
): T => { ): T => {
const propTypes: T = { ...types } as T; const propTypes: T = { ...types };
Object.keys(defaultProps).forEach(k => { Object.keys(defaultProps).forEach(k => {
const prop = propTypes[k] as VueTypeValidableDef; const prop = propTypes[k] as VueTypeValidableDef;
if (prop) { if (prop) {

View File

@ -29,7 +29,7 @@ const buttonProps = () => ({
type: String as PropType<SizeType>, type: String as PropType<SizeType>,
}, },
loading: { loading: {
type: [Boolean, Object], type: [Boolean, Object] as PropType<boolean | { delay?: number }>,
default: (): boolean | { delay?: number } => false, default: (): boolean | { delay?: number } => false,
}, },
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,

View File

@ -122,7 +122,7 @@ function useForm(
const validateInfos = reactive<validateInfos>({}); const validateInfos = reactive<validateInfos>({});
const rulesKeys = computed(() => { const rulesKeys = computed(() => {
return Object.keys(unref(rulesRef)); return rulesRef ? Object.keys(unref(rulesRef)) : [];
}); });
watch( watch(

View File

@ -24,7 +24,7 @@ export type { ListItemMetaProps } from './ItemMeta';
export type ColumnType = 'gutter' | 'column' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; export type ColumnType = 'gutter' | 'column' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
export const ListGridType = { export const ListGridType = {
gutter: PropTypes.number, gutter: PropTypes.oneOfType([PropTypes.number, PropTypes.arrayOf(Number)]),
column: PropTypes.number, column: PropTypes.number,
xs: PropTypes.number, xs: PropTypes.number,
sm: PropTypes.number, sm: PropTypes.number,

View File

@ -3,14 +3,21 @@ import type { ModalFuncProps } from './Modal';
import Dialog from './Modal'; import Dialog from './Modal';
import ActionButton from './ActionButton'; import ActionButton from './ActionButton';
import { getConfirmLocale } from './locale'; import { getConfirmLocale } from './locale';
import type { FunctionalComponent } from 'vue'; import { FunctionalComponent } from 'vue';
interface ConfirmDialogProps extends ModalFuncProps { interface ConfirmDialogProps extends ModalFuncProps {
afterClose?: () => void; afterClose?: () => void;
close: (...args: any[]) => void; close?: (...args: any[]) => void;
autoFocusButton?: null | 'ok' | 'cancel'; autoFocusButton?: null | 'ok' | 'cancel';
} }
function renderSomeContent(_name, someContent) {
if (typeof someContent === 'function') {
return someContent();
}
return someContent;
}
const ConfirmDialog: FunctionalComponent<ConfirmDialogProps> = props => { const ConfirmDialog: FunctionalComponent<ConfirmDialogProps> = props => {
const { const {
icon, icon,
@ -40,8 +47,10 @@ const ConfirmDialog: FunctionalComponent<ConfirmDialogProps> = props => {
// ้ป˜่ฎคไธบ false๏ผŒไฟๆŒๆ—ง็‰ˆ้ป˜่ฎค่กŒไธบ // ้ป˜่ฎคไธบ false๏ผŒไฟๆŒๆ—ง็‰ˆ้ป˜่ฎค่กŒไธบ
const maskClosable = props.maskClosable === undefined ? false : props.maskClosable; const maskClosable = props.maskClosable === undefined ? false : props.maskClosable;
const runtimeLocale = getConfirmLocale(); const runtimeLocale = getConfirmLocale();
const okText = props.okText || (okCancel ? runtimeLocale.okText : runtimeLocale.justOkText); const okText =
const cancelText = props.cancelText || runtimeLocale.cancelText; renderSomeContent('okText', props.okText) ||
(okCancel ? runtimeLocale.okText : runtimeLocale.justOkText);
const cancelText = renderSomeContent('cancelText', props.cancelText) || runtimeLocale.cancelText;
const autoFocusButton = props.autoFocusButton === null ? false : props.autoFocusButton || 'ok'; const autoFocusButton = props.autoFocusButton === null ? false : props.autoFocusButton || 'ok';
const transitionName = props.transitionName || 'zoom'; const transitionName = props.transitionName || 'zoom';
const maskTransitionName = props.maskTransitionName || 'fade'; const maskTransitionName = props.maskTransitionName || 'fade';
@ -89,11 +98,15 @@ const ConfirmDialog: FunctionalComponent<ConfirmDialogProps> = props => {
> >
<div class={`${contentPrefixCls}-body-wrapper`}> <div class={`${contentPrefixCls}-body-wrapper`}>
<div class={`${contentPrefixCls}-body`}> <div class={`${contentPrefixCls}-body`}>
{icon} {renderSomeContent('icon', icon)}
{props.title === undefined ? null : ( {props.title === undefined ? null : (
<span class={`${contentPrefixCls}-title`}>{props.title}</span> <span class={`${contentPrefixCls}-title`}>
{renderSomeContent('title', props.title)}
</span>
)} )}
<div class={`${contentPrefixCls}-content`}>{props.content}</div> <div class={`${contentPrefixCls}-content`}>
{renderSomeContent('content', props.content)}
</div>
</div> </div>
<div class={`${contentPrefixCls}-btns`}> <div class={`${contentPrefixCls}-btns`}>
{cancelButton} {cancelButton}

View File

@ -95,9 +95,9 @@ export interface ModalFuncProps {
prefixCls?: string; prefixCls?: string;
class?: string; class?: string;
visible?: boolean; visible?: boolean;
title?: VNodeTypes; title?: (() => VNodeTypes) | VNodeTypes;
closable?: boolean; closable?: boolean;
content?: VNodeTypes; content?: (() => VNodeTypes) | VNodeTypes;
// TODO: find out exact types // TODO: find out exact types
onOk?: (...args: any[]) => any; onOk?: (...args: any[]) => any;
onCancel?: (...args: any[]) => any; onCancel?: (...args: any[]) => any;
@ -105,10 +105,10 @@ export interface ModalFuncProps {
cancelButtonProps?: ButtonPropsType; cancelButtonProps?: ButtonPropsType;
centered?: boolean; centered?: boolean;
width?: string | number; width?: string | number;
okText?: VNodeTypes; okText?: (() => VNodeTypes) | VNodeTypes;
okType?: LegacyButtonType; okType?: LegacyButtonType;
cancelText?: VNodeTypes; cancelText?: (() => VNodeTypes) | VNodeTypes;
icon?: VNodeTypes; icon?: (() => VNodeTypes) | VNodeTypes;
/* Deprecated */ /* Deprecated */
iconType?: string; iconType?: string;
mask?: boolean; mask?: boolean;
@ -123,7 +123,10 @@ export interface ModalFuncProps {
autoFocusButton?: null | 'ok' | 'cancel'; autoFocusButton?: null | 'ok' | 'cancel';
transitionName?: string; transitionName?: string;
maskTransitionName?: string; maskTransitionName?: string;
/** @deprecated please use `appContext` instead */
parentContext?: any; parentContext?: any;
appContext?: any;
} }
type getContainerFunc = () => HTMLElement; type getContainerFunc = () => HTMLElement;

View File

@ -1,17 +1,20 @@
import { createApp } from 'vue'; import { createVNode, render as vueRender } from 'vue';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
import type { ModalFuncProps } from './Modal'; import type { ModalFuncProps } from './Modal';
import { destroyFns } from './Modal'; import { destroyFns } from './Modal';
import Omit from 'omit.js'; import Omit from 'omit.js';
export default function confirm(config: ModalFuncProps) { const confirm = (config: ModalFuncProps) => {
const div = document.createElement('div'); const div = document.createElement('div');
document.body.appendChild(div); document.body.appendChild(div);
let currentConfig = { ...Omit(config, ['parentContext']), close, visible: true } as any; let currentConfig = {
...Omit(config, ['parentContext', 'appContext']),
close,
visible: true,
} as any;
let confirmDialogInstance = null; let confirmDialogInstance = null;
let confirmDialogProps = {};
function close(this: typeof close, ...args: any[]) { function close(this: typeof close, ...args: any[]) {
currentConfig = { currentConfig = {
...currentConfig, ...currentConfig,
@ -25,12 +28,15 @@ export default function confirm(config: ModalFuncProps) {
...currentConfig, ...currentConfig,
...newConfig, ...newConfig,
}; };
confirmDialogInstance && if (confirmDialogInstance) {
Object.assign(confirmDialogInstance, { confirmDialogProps: currentConfig }); Object.assign(confirmDialogInstance.component.props, currentConfig);
confirmDialogInstance.component.update();
}
} }
function destroy(...args: any[]) { function destroy(...args: any[]) {
if (confirmDialogInstance && div.parentNode) { if (confirmDialogInstance && div.parentNode) {
confirmDialogInstance.vIf = false; // hack destroy Object.assign(confirmDialogInstance.component.props, { vIf: false }); // hack destroy
confirmDialogInstance.component.update();
confirmDialogInstance = null; confirmDialogInstance = null;
div.parentNode.removeChild(div); div.parentNode.removeChild(div);
} }
@ -46,20 +52,14 @@ export default function confirm(config: ModalFuncProps) {
} }
} }
} }
const Wrapper = p => {
return p.vIf ? <ConfirmDialog {...p}></ConfirmDialog> : null;
};
function render(props: ModalFuncProps) { function render(props: ModalFuncProps) {
confirmDialogProps = props; const vm = createVNode(Wrapper, { ...props, vIf: true });
return createApp({ vm.appContext = config.parentContext || config.appContext || vm.appContext;
parent: (config as any).parentContext, vueRender(vm, div);
data() { return vm;
return { confirmDialogProps, vIf: true };
},
render() {
// ๅ…ˆ่งฃๆž„๏ผŒ้ฟๅ…ๆŠฅ้”™๏ผŒๅŽŸๅ› ไธ่ฏฆ
const cdProps = { ...this.confirmDialogProps };
return this.vIf ? <ConfirmDialog {...cdProps} /> : null;
},
}).mount(div);
} }
confirmDialogInstance = render(currentConfig); confirmDialogInstance = render(currentConfig);
@ -68,4 +68,6 @@ export default function confirm(config: ModalFuncProps) {
destroy: close, destroy: close,
update, update,
}; };
} };
export default confirm;

View File

@ -13,7 +13,7 @@ export type { ModalProps, ModalFuncProps } from './Modal';
const info = function (props: ModalFuncProps) { const info = function (props: ModalFuncProps) {
const config = { const config = {
type: 'info', type: 'info',
icon: <InfoCircleOutlined />, icon: () => <InfoCircleOutlined />,
okCancel: false, okCancel: false,
...props, ...props,
}; };
@ -23,7 +23,7 @@ const info = function (props: ModalFuncProps) {
const success = function (props: ModalFuncProps) { const success = function (props: ModalFuncProps) {
const config = { const config = {
type: 'success', type: 'success',
icon: <CheckCircleOutlined />, icon: () => <CheckCircleOutlined />,
okCancel: false, okCancel: false,
...props, ...props,
}; };
@ -33,7 +33,7 @@ const success = function (props: ModalFuncProps) {
const error = function (props: ModalFuncProps) { const error = function (props: ModalFuncProps) {
const config = { const config = {
type: 'error', type: 'error',
icon: <CloseCircleOutlined />, icon: () => <CloseCircleOutlined />,
okCancel: false, okCancel: false,
...props, ...props,
}; };
@ -43,7 +43,7 @@ const error = function (props: ModalFuncProps) {
const warning = function (props: ModalFuncProps) { const warning = function (props: ModalFuncProps) {
const config = { const config = {
type: 'warning', type: 'warning',
icon: <ExclamationCircleOutlined />, icon: () => <ExclamationCircleOutlined />,
okCancel: false, okCancel: false,
...props, ...props,
}; };

View File

@ -70,7 +70,7 @@ export const UploadProps = {
action: PropsTypes.oneOfType([PropsTypes.string, PropsTypes.func]), action: PropsTypes.oneOfType([PropsTypes.string, PropsTypes.func]),
directory: PropsTypes.looseBool, directory: PropsTypes.looseBool,
data: PropsTypes.oneOfType([PropsTypes.object, PropsTypes.func]), data: PropsTypes.oneOfType([PropsTypes.object, PropsTypes.func]),
method: PropsTypes.oneOf(tuple('POST', 'PUT', 'post', 'put')), method: PropsTypes.oneOf(tuple('POST', 'PUT', 'PATCH', 'post', 'put', 'patch')),
headers: PropsTypes.object, headers: PropsTypes.object,
showUploadList: PropsTypes.oneOfType([PropsTypes.looseBool, ShowUploadListInterface]), showUploadList: PropsTypes.oneOfType([PropsTypes.looseBool, ShowUploadListInterface]),
multiple: PropsTypes.looseBool, multiple: PropsTypes.looseBool,

View File

@ -81,7 +81,7 @@ const Drawer = defineComponent({
} }
this.preProps.open = val; this.preProps.open = val;
if (val) { if (val) {
nextTick(() => { setTimeout(() => {
this.domFocus(); this.domFocus();
}); });
} }

View File

@ -14,7 +14,7 @@ export default defineComponent({
item: PropTypes.any, item: PropTypes.any,
renderItem: Function as PropType<(item: any) => VueNode>, renderItem: Function as PropType<(item: any) => VueNode>,
responsive: Boolean, responsive: Boolean,
itemKey: [String, Number], itemKey: { type: [String, Number] as PropType<string | number> },
registerSize: Function as PropType<(key: Key, width: number | null) => void>, registerSize: Function as PropType<(key: Key, width: number | null) => void>,
display: Boolean, display: Boolean,
order: Number, order: Number,
@ -29,7 +29,7 @@ export default defineComponent({
// ================================ Effect ================================ // ================================ Effect ================================
function internalRegisterSize(width: number | null) { function internalRegisterSize(width: number | null) {
props.registerSize(props.itemKey!, width); props.registerSize(props.itemKey, width);
} }
onUnmounted(() => { onUnmounted(() => {

View File

@ -36,7 +36,7 @@ import { getSeparatedContent } from './utils/valueUtil';
import useSelectTriggerControl from './hooks/useSelectTriggerControl'; import useSelectTriggerControl from './hooks/useSelectTriggerControl';
import useCacheDisplayValue from './hooks/useCacheDisplayValue'; import useCacheDisplayValue from './hooks/useCacheDisplayValue';
import useCacheOptions from './hooks/useCacheOptions'; import useCacheOptions from './hooks/useCacheOptions';
import type { CSSProperties, DefineComponent, PropType, VNode, VNodeChild } from 'vue'; import type { CSSProperties, PropType, VNode, VNodeChild } from 'vue';
import { getCurrentInstance } from 'vue'; import { getCurrentInstance } from 'vue';
import { import {
computed, computed,
@ -215,9 +215,13 @@ export type SelectProps<T1, T2> = FuncReturnType<T1, T2>;
export interface GenerateConfig<OptionType extends object> { export interface GenerateConfig<OptionType extends object> {
prefixCls: string; prefixCls: string;
components: { components: {
optionList: DefineComponent< // TODO
Omit<OptionListProps<OptionType>, 'options'> & { options?: OptionType[] } optionList: (
>; props: Omit<OptionListProps<OptionType>, 'options'> & { options?: OptionType[] },
) => JSX.Element;
// optionList: DefineComponent<
// Omit<OptionListProps<OptionType>, 'options'> & { options?: OptionType[] }
// >;
}; };
/** Convert jsx tree into `OptionType[]` */ /** Convert jsx tree into `OptionType[]` */
convertChildrenToData: (children: VNodeChild | JSX.Element) => OptionType[]; convertChildrenToData: (children: VNodeChild | JSX.Element) => OptionType[];
@ -245,6 +249,7 @@ export interface GenerateConfig<OptionType extends object> {
) => OptionType[]; ) => OptionType[];
omitDOMProps?: (props: object) => object; omitDOMProps?: (props: object) => object;
} }
type ValueType = DefaultValueType; type ValueType = DefaultValueType;
/** /**
* This function is in internal usage. * This function is in internal usage.
@ -330,13 +335,18 @@ export default function generateSelector<
// ============================== Ref =============================== // ============================== Ref ===============================
const selectorDomRef = createRef(); const selectorDomRef = createRef();
const mergedValue = ref(); const innerSearchValue = ref('');
const setInnerSearchValue = (val: string) => {
innerSearchValue.value = val;
};
const mergedValue = ref(props.value !== undefined ? props.value : props.defaultValue);
watch( watch(
() => props.value, () => props.value,
() => { () => {
mergedValue.value = props.value !== undefined ? props.value : props.defaultValue; mergedValue.value = props.value;
innerSearchValue.value = '';
}, },
{ immediate: true },
); );
// ============================= Value ============================== // ============================= Value ==============================
@ -358,10 +368,6 @@ export default function generateSelector<
const setActiveValue = (val: string) => { const setActiveValue = (val: string) => {
activeValue.value = val; activeValue.value = val;
}; };
const innerSearchValue = ref('');
const setInnerSearchValue = (val: string) => {
innerSearchValue.value = val;
};
const mergedSearchValue = computed(() => { const mergedSearchValue = computed(() => {
let mergedSearchValue = innerSearchValue.value; let mergedSearchValue = innerSearchValue.value;
@ -378,7 +384,7 @@ export default function generateSelector<
const mergedOptions = computed((): OptionType[] => { const mergedOptions = computed((): OptionType[] => {
let newOptions = props.options; let newOptions = props.options;
if (newOptions === undefined) { if (newOptions === undefined) {
newOptions = convertChildrenToData(props.children); newOptions = convertChildrenToData(props.children as VNodeChild);
} }
/** /**
@ -667,7 +673,7 @@ export default function generateSelector<
// Check if match the `tokenSeparators` // Check if match the `tokenSeparators`
const patchLabels: string[] = isCompositing const patchLabels: string[] = isCompositing
? null ? null
: getSeparatedContent(searchText, props.tokenSeparators); : getSeparatedContent(searchText, props.tokenSeparators as string[]);
let patchRawValues: RawValueType[] = patchLabels; let patchRawValues: RawValueType[] = patchLabels;
if (props.mode === 'combobox') { if (props.mode === 'combobox') {
@ -847,12 +853,12 @@ export default function generateSelector<
if (props.disabled) { if (props.disabled) {
return; return;
} }
const serachVal = mergedSearchValue.value; const searchVal = mergedSearchValue.value;
if (serachVal) { if (searchVal) {
// `tags` mode should move `searchValue` into values // `tags` mode should move `searchValue` into values
if (props.mode === 'tags') { if (props.mode === 'tags') {
triggerSearch('', false, false); triggerSearch('', false, false);
triggerChange(Array.from(new Set([...mergedRawValue.value, serachVal]))); triggerChange(Array.from(new Set([...mergedRawValue.value, searchVal])));
} else if (props.mode === 'multiple') { } else if (props.mode === 'multiple') {
// `multiple` mode only clean the search value but not trigger event // `multiple` mode only clean the search value but not trigger event
setInnerSearchValue(''); setInnerSearchValue('');

View File

@ -12,7 +12,7 @@ export type RawValueType = string | number | null;
export interface LabelValueType extends Record<string, any> { export interface LabelValueType extends Record<string, any> {
key?: Key; key?: Key;
value?: RawValueType; value?: RawValueType;
label?: VueNode; label?: any;
isCacheable?: boolean; isCacheable?: boolean;
} }
export type DefaultValueType = RawValueType | RawValueType[] | LabelValueType | LabelValueType[]; export type DefaultValueType = RawValueType | RawValueType[] | LabelValueType | LabelValueType[];
@ -26,7 +26,7 @@ export type SingleType<MixType> = MixType extends (infer Single)[] ? Single : Mi
export type OnClear = () => any; export type OnClear = () => any;
export type CustomTagProps = { export type CustomTagProps = {
label: VueNode; label: any;
value: DefaultValueType; value: DefaultValueType;
disabled: boolean; disabled: boolean;
onClose: (event?: MouseEvent) => void; onClose: (event?: MouseEvent) => void;

View File

@ -1,6 +1,6 @@
{ {
"name": "ant-design-vue", "name": "ant-design-vue",
"version": "2.2.6", "version": "2.2.7",
"title": "Ant Design Vue", "title": "Ant Design Vue",
"description": "An enterprise-class UI design language and Vue-based implementation", "description": "An enterprise-class UI design language and Vue-based implementation",
"keywords": [ "keywords": [