Merge branch 'next' into feat-dayjs

feat-dayjs
tangjinzhou 2020-10-20 21:29:15 +08:00
commit 91b4a1c0e4
51 changed files with 582 additions and 453 deletions

View File

@ -3,18 +3,18 @@ const getTransitionGroupProps = (transitionName, opt = {}) => {
if (process.env.NODE_ENV === 'test') { if (process.env.NODE_ENV === 'test') {
return { css: false, ...opt }; return { css: false, ...opt };
} }
const transitionProps = { const transitionProps = transitionName ? {
appear: true, appear: true,
appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`, appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
appearActiveClass: `${transitionName}`, appearActiveClass: `${transitionName}`,
appearToClass: `${transitionName}-appear-active`, appearToClass: `${transitionName}-appear ${transitionName}-appear-active`,
enterFromClass: `${transitionName}-appear ${transitionName}-enter ${transitionName}-appear-prepare ${transitionName}-enter-prepare`, enterFromClass: `${transitionName}-appear ${transitionName}-enter ${transitionName}-appear-prepare ${transitionName}-enter-prepare`,
enterActiveClass: `${transitionName}`, enterActiveClass: `${transitionName}`,
enterToClass: `${transitionName}-appear-active ${transitionName}-enter-active`, enterToClass: `${transitionName}-enter ${transitionName}-appear ${transitionName}-appear-active ${transitionName}-enter-active`,
leaveActiveClass: `${transitionName} ${transitionName}-leave`, leaveActiveClass: `${transitionName} ${transitionName}-leave`,
leaveToClass: `${transitionName}-leave-active`, leaveToClass: `${transitionName}-leave-active`,
...opt, ...opt,
}; } : { css: false, ...opt };
return transitionProps; return transitionProps;
}; };

View File

@ -2,7 +2,7 @@ const getTransitionProps = (transitionName, opt = {}) => {
if (process.env.NODE_ENV === 'test') { if (process.env.NODE_ENV === 'test') {
return { css: false, ...opt }; return { css: false, ...opt };
} }
const transitionProps = { const transitionProps = transitionName ? {
appear: true, appear: true,
appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`, appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
// appearActiveClass: `antdv-base-transtion`, // appearActiveClass: `antdv-base-transtion`,
@ -14,7 +14,7 @@ const getTransitionProps = (transitionName, opt = {}) => {
leaveActiveClass: `${transitionName}-leave ${transitionName}-leave-active`, leaveActiveClass: `${transitionName}-leave ${transitionName}-leave-active`,
leaveToClass: `${transitionName}-leave ${transitionName}-leave-active`, leaveToClass: `${transitionName}-leave ${transitionName}-leave-active`,
...opt, ...opt,
}; }: { css: false, ...opt };
return transitionProps; return transitionProps;
}; };

View File

@ -1,3 +1,4 @@
import { ExtractPropTypes } from 'vue';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
import PropTypes, { withUndefined } from '../_util/vue-types'; import PropTypes, { withUndefined } from '../_util/vue-types';
@ -10,7 +11,7 @@ export type ButtonSize = typeof ButtonSizes[number];
const ButtonHTMLTypes = tuple('submit', 'button', 'reset'); const ButtonHTMLTypes = tuple('submit', 'button', 'reset');
export type ButtonHTMLType = typeof ButtonHTMLTypes[number]; export type ButtonHTMLType = typeof ButtonHTMLTypes[number];
export default () => ({ const buttonProps = () => ({
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
type: PropTypes.oneOf(ButtonTypes), type: PropTypes.oneOf(ButtonTypes),
htmlType: PropTypes.oneOf(ButtonHTMLTypes).def('button'), htmlType: PropTypes.oneOf(ButtonHTMLTypes).def('button'),
@ -26,3 +27,7 @@ export default () => ({
title: PropTypes.string, title: PropTypes.string,
onClick: PropTypes.func, onClick: PropTypes.func,
}); });
export type ButtonProps = ExtractPropTypes<ExtractPropTypes<ReturnType<typeof buttonProps>>>;
export default buttonProps;

View File

@ -11,6 +11,8 @@ export interface CSPConfig {
nonce?: string; nonce?: string;
} }
export { RenderEmptyHandler };
export interface ConfigConsumerProps { export interface ConfigConsumerProps {
getTargetContainer?: () => HTMLElement; getTargetContainer?: () => HTMLElement;
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement; getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;

View File

@ -26,7 +26,7 @@ export default defineComponent({
}, },
children: { children: {
type: Function as PropType< type: Function as PropType<
(locale: object, localeCode?: string, fullLocale?: object) => VNodeTypes (locale: any, localeCode?: string, fullLocale?: object) => VNodeTypes
>, >,
}, },
}, },

View File

@ -1,9 +1,11 @@
import { defineComponent, ExtractPropTypes } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import Button from '../button'; import Button from '../button';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import buttonTypes from '../button/buttonTypes'; import buttonTypes from '../button/buttonTypes';
import { getSlot, findDOMNode } from '../_util/props-util'; import { getSlot, findDOMNode } from '../_util/props-util';
const ButtonType = buttonTypes().type; const ButtonType = buttonTypes().type;
const ActionButtonProps = { const ActionButtonProps = {
type: ButtonType, type: ButtonType,
actionFn: PropTypes.func, actionFn: PropTypes.func,
@ -12,7 +14,9 @@ const ActionButtonProps = {
buttonProps: PropTypes.object, buttonProps: PropTypes.object,
}; };
export default { export type IActionButtonProps = ExtractPropTypes<typeof ActionButtonProps>;
export default defineComponent({
mixins: [BaseMixin], mixins: [BaseMixin],
props: ActionButtonProps, props: ActionButtonProps,
data() { data() {
@ -20,6 +24,11 @@ export default {
loading: false, loading: false,
}; };
}, },
setup() {
return {
timeoutId: undefined,
};
},
mounted() { mounted() {
if (this.autofocus) { if (this.autofocus) {
this.timeoutId = setTimeout(() => findDOMNode(this).focus()); this.timeoutId = setTimeout(() => findDOMNode(this).focus());
@ -74,4 +83,4 @@ export default {
}; };
return <Button {...props}>{getSlot(this)}</Button>; return <Button {...props}>{getSlot(this)}</Button>;
}, },
}; });

View File

@ -1,9 +1,16 @@
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import Dialog from './Modal'; import Dialog, { ModalFuncProps } from './Modal';
import ActionButton from './ActionButton'; import ActionButton from './ActionButton';
import { getConfirmLocale } from './locale'; import { getConfirmLocale } from './locale';
import { FunctionalComponent } from 'vue';
const ConfirmDialog = (_, { attrs }) => { interface ConfirmDialogProps extends ModalFuncProps {
afterClose?: () => void;
close: (...args: any[]) => void;
autoFocusButton?: null | 'ok' | 'cancel';
}
const ConfirmDialog: FunctionalComponent<ConfirmDialogProps> = props => {
const { const {
icon, icon,
onCancel, onCancel,
@ -18,30 +25,30 @@ const ConfirmDialog = (_, { attrs }) => {
maskStyle, maskStyle,
okButtonProps, okButtonProps,
cancelButtonProps, cancelButtonProps,
closable = false, // closable = false,
} = attrs; } = props;
const okType = attrs.okType || 'primary'; const okType = props.okType || 'primary';
const prefixCls = attrs.prefixCls || 'ant-modal'; const prefixCls = props.prefixCls || 'ant-modal';
const contentPrefixCls = `${prefixCls}-confirm`; const contentPrefixCls = `${prefixCls}-confirm`;
// 默认为 true保持向下兼容 // 默认为 true保持向下兼容
const okCancel = 'okCancel' in attrs ? attrs.okCancel : true; const okCancel = 'okCancel' in props ? props.okCancel : true;
const width = attrs.width || 416; const width = props.width || 416;
const style = attrs.style || {}; const style = props.style || {};
const mask = attrs.mask === undefined ? true : attrs.mask; const mask = props.mask === undefined ? true : props.mask;
// 默认为 false保持旧版默认行为 // 默认为 false保持旧版默认行为
const maskClosable = attrs.maskClosable === undefined ? false : attrs.maskClosable; const maskClosable = props.maskClosable === undefined ? false : props.maskClosable;
const runtimeLocale = getConfirmLocale(); const runtimeLocale = getConfirmLocale();
const okText = attrs.okText || (okCancel ? runtimeLocale.okText : runtimeLocale.justOkText); const okText = props.okText || (okCancel ? runtimeLocale.okText : runtimeLocale.justOkText);
const cancelText = attrs.cancelText || runtimeLocale.cancelText; const cancelText = props.cancelText || runtimeLocale.cancelText;
const autoFocusButton = attrs.autoFocusButton === null ? false : attrs.autoFocusButton || 'ok'; const autoFocusButton = props.autoFocusButton === null ? false : props.autoFocusButton || 'ok';
const transitionName = attrs.transitionName || 'zoom'; const transitionName = props.transitionName || 'zoom';
const maskTransitionName = attrs.maskTransitionName || 'fade'; const maskTransitionName = props.maskTransitionName || 'fade';
const classString = classNames( const classString = classNames(
contentPrefixCls, contentPrefixCls,
`${contentPrefixCls}-${attrs.type}`, `${contentPrefixCls}-${props.type}`,
`${prefixCls}-${attrs.type}`, `${prefixCls}-${props.type}`,
attrs.class, props.class,
); );
const cancelButton = okCancel && ( const cancelButton = okCancel && (
@ -62,7 +69,6 @@ const ConfirmDialog = (_, { attrs }) => {
wrapClassName={classNames({ [`${contentPrefixCls}-centered`]: !!centered })} wrapClassName={classNames({ [`${contentPrefixCls}-centered`]: !!centered })}
onCancel={e => close({ triggerCancel: true }, e)} onCancel={e => close({ triggerCancel: true }, e)}
visible={visible} visible={visible}
closable={closable}
title="" title=""
transitionName={transitionName} transitionName={transitionName}
footer="" footer=""
@ -80,13 +86,11 @@ const ConfirmDialog = (_, { attrs }) => {
> >
<div class={`${contentPrefixCls}-body-wrapper`}> <div class={`${contentPrefixCls}-body-wrapper`}>
<div class={`${contentPrefixCls}-body`}> <div class={`${contentPrefixCls}-body`}>
{typeof icon === 'function' ? icon() : icon} {icon}
{attrs.title === undefined ? null : ( {props.title === undefined ? null : (
<span class={`${contentPrefixCls}-title`}>{attrs.title}</span> <span class={`${contentPrefixCls}-title`}>{props.title}</span>
)} )}
<div class={`${contentPrefixCls}-content`}> <div class={`${contentPrefixCls}-content`}>{props.content}</div>
{typeof attrs.content === 'function' ? attrs.content() : attrs.content}
</div>
</div> </div>
<div class={`${contentPrefixCls}-btns`}> <div class={`${contentPrefixCls}-btns`}>
{cancelButton} {cancelButton}
@ -104,5 +108,7 @@ const ConfirmDialog = (_, { attrs }) => {
</Dialog> </Dialog>
); );
}; };
ConfirmDialog.inheritAttrs = false; ConfirmDialog.inheritAttrs = false;
export default ConfirmDialog; export default ConfirmDialog;

View File

@ -1,4 +1,11 @@
import { inject } from 'vue'; import {
defineComponent,
ExtractPropTypes,
inject,
VNodeTypes,
CSSProperties,
PropType,
} from 'vue';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import Dialog from '../vc-dialog'; import Dialog from '../vc-dialog';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
@ -6,15 +13,18 @@ import addEventListener from '../vc-util/Dom/addEventListener';
import { getConfirmLocale } from './locale'; import { getConfirmLocale } from './locale';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined'; import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import Button from '../button'; import Button from '../button';
import buttonTypes from '../button/buttonTypes'; import buttonTypes, { ButtonType, ButtonProps } from '../button/buttonTypes';
const ButtonType = buttonTypes().type;
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { initDefaultProps, getComponent, getSlot } from '../_util/props-util'; import { getComponent, getSlot } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
let mousePosition = null; const ButtonProps = buttonTypes();
const ButtonType = ButtonProps.type;
let mousePosition: { x: number; y: number } | null = null;
// ref: https://github.com/ant-design/ant-design/issues/15795 // ref: https://github.com/ant-design/ant-design/issues/15795
const getClickPosition = e => { const getClickPosition = (e: MouseEvent) => {
mousePosition = { mousePosition = {
x: e.pageX, x: e.pageX,
y: e.pageY, y: e.pageY,
@ -31,68 +41,121 @@ if (typeof window !== 'undefined' && window.document && window.document.document
} }
function noop() {} function noop() {}
const modalProps = (defaultProps = {}) => {
const props = { const modalProps = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
/** 对话框是否可见*/ /** 对话框是否可见*/
visible: PropTypes.looseBool, visible: PropTypes.looseBool,
/** 确定按钮 loading*/ /** 确定按钮 loading*/
confirmLoading: PropTypes.looseBool, confirmLoading: PropTypes.looseBool,
/** 标题*/ /** 标题*/
title: PropTypes.any, title: PropTypes.any,
/** 是否显示右上角的关闭按钮*/ /** 是否显示右上角的关闭按钮*/
closable: PropTypes.looseBool, closable: PropTypes.looseBool,
closeIcon: PropTypes.any, closeIcon: PropTypes.any,
/** 点击确定回调*/ /** 点击确定回调*/
// onOk: (e: React.MouseEvent<any>) => void, onOk: {
/** 点击模态框右上角叉、取消按钮、Props.maskClosable 值为 true 时的遮罩层或键盘按下 Esc 时的回调*/ type: Function as PropType<(e: MouseEvent) => void>,
// onCancel: (e: React.MouseEvent<any>) => void, },
afterClose: PropTypes.func.def(noop), /** 点击模态框右上角叉、取消按钮、Props.maskClosable 值为 true 时的遮罩层或键盘按下 Esc 时的回调*/
/** 垂直居中 */ onCancel: {
centered: PropTypes.looseBool, type: Function as PropType<(e: MouseEvent) => void>,
/** 宽度*/ },
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), afterClose: PropTypes.func.def(noop),
/** 底部内容*/ /** 垂直居中 */
footer: PropTypes.any, centered: PropTypes.looseBool,
/** 确认按钮文字*/ /** 宽度*/
okText: PropTypes.any, width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/** 确认按钮类型*/ /** 底部内容*/
okType: ButtonType, footer: PropTypes.any,
/** 取消按钮文字*/ /** 确认按钮文字*/
cancelText: PropTypes.any, okText: PropTypes.any,
icon: PropTypes.any, /** 确认按钮类型*/
/** 点击蒙层是否允许关闭*/ okType: ButtonType,
maskClosable: PropTypes.looseBool, /** 取消按钮文字*/
/** 强制渲染 Modal*/ cancelText: PropTypes.any,
forceRender: PropTypes.looseBool, icon: PropTypes.any,
okButtonProps: PropTypes.object, /** 点击蒙层是否允许关闭*/
cancelButtonProps: PropTypes.object, maskClosable: PropTypes.looseBool,
destroyOnClose: PropTypes.looseBool, /** 强制渲染 Modal*/
wrapClassName: PropTypes.string, forceRender: PropTypes.looseBool,
maskTransitionName: PropTypes.string, okButtonProps: PropTypes.shape(ButtonProps),
transitionName: PropTypes.string, cancelButtonProps: PropTypes.shape(ButtonProps),
getContainer: PropTypes.func, destroyOnClose: PropTypes.looseBool,
zIndex: PropTypes.number, wrapClassName: PropTypes.string,
bodyStyle: PropTypes.object, maskTransitionName: PropTypes.string,
maskStyle: PropTypes.object, transitionName: PropTypes.string,
mask: PropTypes.looseBool, getContainer: PropTypes.func,
keyboard: PropTypes.looseBool, zIndex: PropTypes.number,
wrapProps: PropTypes.object, bodyStyle: PropTypes.style,
focusTriggerAfterClose: PropTypes.looseBool, maskStyle: PropTypes.style,
}; mask: PropTypes.looseBool,
return initDefaultProps(props, defaultProps); keyboard: PropTypes.looseBool,
wrapProps: PropTypes.object,
focusTriggerAfterClose: PropTypes.looseBool,
}; };
export type ModalProps = ExtractPropTypes<typeof modalProps>;
export interface ModalFuncProps {
prefixCls?: string;
class?: string;
visible?: boolean;
title?: VNodeTypes;
content?: VNodeTypes;
// TODO: find out exact types
onOk?: (...args: any[]) => any;
onCancel?: (...args: any[]) => any;
okButtonProps?: ButtonProps;
cancelButtonProps?: ButtonProps;
centered?: boolean;
width?: string | number;
okText?: VNodeTypes;
okType?: ButtonType;
cancelText?: VNodeTypes;
icon?: VNodeTypes;
/* Deprecated */
iconType?: string;
mask?: boolean;
maskClosable?: boolean;
zIndex?: number;
okCancel?: boolean;
style?: CSSProperties | string;
maskStyle?: CSSProperties;
type?: string;
keyboard?: boolean;
getContainer?: getContainerFunc;
autoFocusButton?: null | 'ok' | 'cancel';
transitionName?: string;
maskTransitionName?: string;
}
type getContainerFunc = () => HTMLElement;
export type ModalFunc = (
props: ModalFuncProps,
) => {
destroy: () => void;
update: (newConfig: ModalFuncProps) => void;
};
export interface ModalLocale {
okText: string;
cancelText: string;
justOkText: string;
}
export const destroyFns = []; export const destroyFns = [];
export default { export default defineComponent({
name: 'AModal', name: 'AModal',
inheritAttrs: false, inheritAttrs: false,
model: { model: {
prop: 'visible', prop: 'visible',
event: 'change', event: 'change',
}, },
props: modalProps({ emits: ['update:visible', 'cancel', 'change', 'ok'],
props: initDefaultProps(modalProps, {
width: 520, width: 520,
transitionName: 'zoom', transitionName: 'zoom',
maskTransitionName: 'fade', maskTransitionName: 'fade',
@ -115,23 +178,17 @@ export default {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
}; };
}, },
// static info: ModalFunc;
// static success: ModalFunc;
// static error: ModalFunc;
// static warn: ModalFunc;
// static warning: ModalFunc;
// static confirm: ModalFunc;
methods: { methods: {
handleCancel(e) { handleCancel(e: MouseEvent) {
this.$emit('update:visible', false); this.$emit('update:visible', false);
this.$emit('cancel', e); this.$emit('cancel', e);
this.$emit('change', false); this.$emit('change', false);
}, },
handleOk(e) { handleOk(e: MouseEvent) {
this.$emit('ok', e); this.$emit('ok', e);
}, },
renderFooter(locale) { renderFooter(locale: ModalLocale) {
const { okType, confirmLoading } = this; const { okType, confirmLoading } = this;
const cancelBtnProps = { onClick: this.handleCancel, ...(this.cancelButtonProps || {}) }; const cancelBtnProps = { onClick: this.handleCancel, ...(this.cancelButtonProps || {}) };
const okBtnProps = { const okBtnProps = {
@ -194,4 +251,4 @@ export default {
}; };
return <Dialog {...dialogProps}>{children}</Dialog>; return <Dialog {...dialogProps}>{children}</Dialog>;
}, },
}; });

View File

@ -1,17 +1,17 @@
import { createApp } from 'vue'; import { createApp } from 'vue';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
import { destroyFns } from './Modal'; import { destroyFns, ModalFuncProps } from './Modal';
import Omit from 'omit.js'; import Omit from 'omit.js';
export default function confirm(config) { export default function 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 }; let currentConfig = { ...Omit(config, ['parentContext']), close, visible: true };
let confirmDialogInstance = null; let confirmDialogInstance = null;
let confirmDialogProps = {}; let confirmDialogProps = {};
function close(...args) { function close(this: typeof close, ...args: any[]) {
currentConfig = { currentConfig = {
...currentConfig, ...currentConfig,
visible: false, visible: false,
@ -19,7 +19,7 @@ export default function confirm(config) {
}; };
update(currentConfig); update(currentConfig);
} }
function update(newConfig) { function update(newConfig: ModalFuncProps) {
currentConfig = { currentConfig = {
...currentConfig, ...currentConfig,
...newConfig, ...newConfig,
@ -27,7 +27,7 @@ export default function confirm(config) {
confirmDialogInstance && confirmDialogInstance &&
Object.assign(confirmDialogInstance, { confirmDialogProps: currentConfig }); Object.assign(confirmDialogInstance, { confirmDialogProps: currentConfig });
} }
function destroy(...args) { function destroy(...args: any[]) {
if (confirmDialogInstance && div.parentNode) { if (confirmDialogInstance && div.parentNode) {
confirmDialogInstance.vIf = false; // hack destroy confirmDialogInstance.vIf = false; // hack destroy
confirmDialogInstance = null; confirmDialogInstance = null;
@ -46,10 +46,10 @@ export default function confirm(config) {
} }
} }
function render(props) { function render(props: ModalFuncProps) {
confirmDialogProps = props; confirmDialogProps = props;
return createApp({ return createApp({
parent: config.parentContext, parent: (config as any).parentContext,
data() { data() {
return { confirmDialogProps, vIf: true }; return { confirmDialogProps, vIf: true };
}, },

View File

@ -1,14 +1,15 @@
import Modal, { destroyFns } from './Modal'; import { App } from 'vue';
import Modal, { destroyFns, ModalFuncProps } from './Modal';
import modalConfirm from './confirm'; import modalConfirm from './confirm';
import InfoCircleOutlined from '@ant-design/icons-vue/InfoCircleOutlined'; import InfoCircleOutlined from '@ant-design/icons-vue/InfoCircleOutlined';
import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined'; import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined';
import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined'; import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined';
import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined'; import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined';
// export { ActionButtonProps } from './ActionButton' export { IActionButtonProps as ActionButtonProps } from './ActionButton';
// export { ModalProps, ModalFuncProps } from './Modal' export { ModalProps, ModalFuncProps } from './Modal';
const info = function(props) { const info = function(props: ModalFuncProps) {
const config = { const config = {
type: 'info', type: 'info',
icon: <InfoCircleOutlined />, icon: <InfoCircleOutlined />,
@ -18,7 +19,7 @@ const info = function(props) {
return modalConfirm(config); return modalConfirm(config);
}; };
const success = function(props) { const success = function(props: ModalFuncProps) {
const config = { const config = {
type: 'success', type: 'success',
icon: <CheckCircleOutlined />, icon: <CheckCircleOutlined />,
@ -28,7 +29,7 @@ const success = function(props) {
return modalConfirm(config); return modalConfirm(config);
}; };
const error = function(props) { const error = function(props: ModalFuncProps) {
const config = { const config = {
type: 'error', type: 'error',
icon: <CloseCircleOutlined />, icon: <CloseCircleOutlined />,
@ -38,7 +39,7 @@ const error = function(props) {
return modalConfirm(config); return modalConfirm(config);
}; };
const warning = function(props) { const warning = function(props: ModalFuncProps) {
const config = { const config = {
type: 'warning', type: 'warning',
icon: <ExclamationCircleOutlined />, icon: <ExclamationCircleOutlined />,
@ -49,7 +50,7 @@ const warning = function(props) {
}; };
const warn = warning; const warn = warning;
const confirm = function confirmFn(props) { const confirm = function confirmFn(props: ModalFuncProps) {
const config = { const config = {
type: 'confirm', type: 'confirm',
okCancel: true, okCancel: true,
@ -74,7 +75,7 @@ Modal.destroyAll = function destroyAllFn() {
}; };
/* istanbul ignore next */ /* istanbul ignore next */
Modal.install = function(app) { Modal.install = function(app: App) {
app.component(Modal.name, Modal); app.component(Modal.name, Modal);
return app; return app;
}; };

View File

@ -10,7 +10,7 @@ let runtimeLocale = {
...defaultLocale.Modal, ...defaultLocale.Modal,
}; };
export function changeConfirmLocale(newLocale?: any) { export function changeConfirmLocale(newLocale?: ModalLocale) {
if (newLocale) { if (newLocale) {
runtimeLocale = { runtimeLocale = {
...runtimeLocale, ...runtimeLocale,

View File

@ -1,5 +1,5 @@
import omit from 'omit.js'; import omit from 'omit.js';
import { inject } from 'vue'; import { App, defineComponent, inject } from 'vue';
import Tooltip from '../tooltip'; import Tooltip from '../tooltip';
import abstractTooltipProps from '../tooltip/abstractTooltipProps'; import abstractTooltipProps from '../tooltip/abstractTooltipProps';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
@ -14,7 +14,8 @@ import { defaultConfigProvider } from '../config-provider';
const tooltipProps = abstractTooltipProps(); const tooltipProps = abstractTooltipProps();
const btnProps = buttonTypes(); const btnProps = buttonTypes();
const Popconfirm = {
const Popconfirm = defineComponent({
name: 'APopconfirm', name: 'APopconfirm',
props: { props: {
...tooltipProps, ...tooltipProps,
@ -33,9 +34,9 @@ const Popconfirm = {
onConfirm: PropTypes.func, onConfirm: PropTypes.func,
onCancel: PropTypes.func, onCancel: PropTypes.func,
onVisibleChange: PropTypes.func, onVisibleChange: PropTypes.func,
'onUpdate:visible': PropTypes.func,
}, },
mixins: [BaseMixin], mixins: [BaseMixin],
emits: ['update:visible', 'confirm', 'cancel', 'visibleChange'],
watch: { watch: {
visible(val) { visible(val) {
this.sVisible = val; this.sVisible = val;
@ -47,7 +48,7 @@ const Popconfirm = {
}; };
}, },
data() { data() {
const props = getOptionProps(this); const props = getOptionProps(this) as any;
const state = { sVisible: false }; const state = { sVisible: false };
if ('visible' in props) { if ('visible' in props) {
state.sVisible = props.visible; state.sVisible = props.visible;
@ -76,7 +77,7 @@ const Popconfirm = {
this.setVisible(sVisible); this.setVisible(sVisible);
}, },
setVisible(sVisible, e) { setVisible(sVisible: boolean, e?: Event) {
if (!hasProp(this, 'visible')) { if (!hasProp(this, 'visible')) {
this.setState({ sVisible }); this.setState({ sVisible });
} }
@ -84,9 +85,9 @@ const Popconfirm = {
this.$emit('visibleChange', sVisible, e); this.$emit('visibleChange', sVisible, e);
}, },
getPopupDomNode() { getPopupDomNode() {
return this.$refs.tooltip.getPopupDomNode(); return (this.$refs.tooltip as any).getPopupDomNode();
}, },
renderOverlay(prefixCls, popconfirmLocale) { renderOverlay(prefixCls: string, popconfirmLocale) {
const { okType, okButtonProps, cancelButtonProps } = this; const { okType, okButtonProps, cancelButtonProps } = this;
const icon = getComponent(this, 'icon') || <ExclamationCircleFilled />; const icon = getComponent(this, 'icon') || <ExclamationCircleFilled />;
const cancelBtnProps = mergeProps({ const cancelBtnProps = mergeProps({
@ -121,7 +122,7 @@ const Popconfirm = {
render() { render() {
const props = getOptionProps(this); const props = getOptionProps(this);
const { prefixCls: customizePrefixCls } = props; const { prefixCls: customizePrefixCls } = props;
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('popover', customizePrefixCls); const prefixCls = getPrefixCls('popover', customizePrefixCls);
const otherProps = omit(props, [ const otherProps = omit(props, [
@ -148,10 +149,10 @@ const Popconfirm = {
}; };
return <Tooltip {...tooltipProps}>{this.$slots?.default()}</Tooltip>; return <Tooltip {...tooltipProps}>{this.$slots?.default()}</Tooltip>;
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
Popconfirm.install = function(app) { Popconfirm.install = function(app: App) {
app.component(Popconfirm.name, Popconfirm); app.component(Popconfirm.name, Popconfirm);
return app; return app;
}; };

View File

@ -1,4 +1,4 @@
import { inject } from 'vue'; import { App, defineComponent, inject } from 'vue';
import Tooltip from '../tooltip'; import Tooltip from '../tooltip';
import abstractTooltipProps from '../tooltip/abstractTooltipProps'; import abstractTooltipProps from '../tooltip/abstractTooltipProps';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
@ -6,7 +6,7 @@ import { getOptionProps, getComponent, getSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
const props = abstractTooltipProps(); const props = abstractTooltipProps();
const Popover = { const Popover = defineComponent({
name: 'APopover', name: 'APopover',
props: { props: {
...props, ...props,
@ -22,13 +22,13 @@ const Popover = {
}, },
methods: { methods: {
getPopupDomNode() { getPopupDomNode() {
return this.$refs.tooltip.getPopupDomNode(); return (this.$refs.tooltip as any).getPopupDomNode();
}, },
}, },
render() { render() {
const { title, prefixCls: customizePrefixCls, $slots } = this; const { title, prefixCls: customizePrefixCls, $slots } = this;
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('popover', customizePrefixCls); const prefixCls = getPrefixCls('popover', customizePrefixCls);
const props = getOptionProps(this); const props = getOptionProps(this);
@ -49,10 +49,10 @@ const Popover = {
}; };
return <Tooltip {...tooltipProps}>{getSlot(this)}</Tooltip>; return <Tooltip {...tooltipProps}>{getSlot(this)}</Tooltip>;
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
Popover.install = function(app) { Popover.install = function(app: App) {
app.component(Popover.name, Popover); app.component(Popover.name, Popover);
return app; return app;
}; };

View File

@ -4,6 +4,8 @@ import PropTypes from '../_util/vue-types';
import Radio from './Radio'; import Radio from './Radio';
import { getOptionProps, filterEmpty, hasProp, getSlot } from '../_util/props-util'; import { getOptionProps, filterEmpty, hasProp, getSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { tuple } from '../_util/type';
import { RadioChangeEvent } from './interface';
export default defineComponent({ export default defineComponent({
name: 'ARadioGroup', name: 'ARadioGroup',
@ -11,43 +13,39 @@ export default defineComponent({
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
defaultValue: PropTypes.any, defaultValue: PropTypes.any,
value: PropTypes.any, value: PropTypes.any,
size: { size: PropTypes.oneOf(tuple('large', 'default', 'small')).def('default'),
default: 'default', options: PropTypes.array,
validator(value) {
return ['large', 'default', 'small'].includes(value);
},
},
options: {
default: () => [],
type: Array,
},
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,
name: String, name: PropTypes.string,
buttonStyle: PropTypes.string.def('outline'), buttonStyle: PropTypes.string.def('outline'),
onChange: PropTypes.func, onChange: PropTypes.func,
'onUpdate:value': PropTypes.func,
}, },
emits: ['update:value', 'change'],
data() { data() {
const { value, defaultValue } = this; const { value, defaultValue } = this;
this.updatingValue = false;
return { return {
stateValue: value === undefined ? defaultValue : value, stateValue: value === undefined ? defaultValue : value,
}; };
}, },
setup() { setup() {
return { return {
updatingValue: false,
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
radioGroupContext: null,
}; };
}, },
computed: { // computed: {
radioOptions() { // radioOptions() {
const { disabled } = this; // const { disabled } = this;
return this.options.map(option => { // return this.options.map(option => {
return typeof option === 'string' // return typeof option === 'string'
? { label: option, value: option } // ? { label: option, value: option }
: { ...option, disabled: option.disabled === undefined ? disabled : option.disabled }; // : { ...option, disabled: option.disabled === undefined ? disabled : option.disabled };
}); // });
}, // },
// },
created() {
this.radioGroupContext = provide('radioGroupContext', this);
}, },
watch: { watch: {
value(val) { value(val) {
@ -55,11 +53,8 @@ export default defineComponent({
this.stateValue = val; this.stateValue = val;
}, },
}, },
created() {
this.radioGroupContext = provide('radioGroupContext', this);
},
methods: { methods: {
onRadioChange(ev) { onRadioChange(ev: RadioChangeEvent) {
const lastValue = this.stateValue; const lastValue = this.stateValue;
const { value } = ev.target; const { value } = ev.target;
if (!hasProp(this, 'value')) { if (!hasProp(this, 'value')) {
@ -79,7 +74,7 @@ export default defineComponent({
render() { render() {
const props = getOptionProps(this); const props = getOptionProps(this);
const { prefixCls: customizePrefixCls, options, buttonStyle } = props; const { prefixCls: customizePrefixCls, options, buttonStyle } = props;
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('radio', customizePrefixCls); const prefixCls = getPrefixCls('radio', customizePrefixCls);
const groupPrefixCls = `${prefixCls}-group`; const groupPrefixCls = `${prefixCls}-group`;

View File

@ -1,32 +1,36 @@
import { inject } from 'vue'; import { defineComponent, ExtractPropTypes, inject } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import VcCheckbox from '../vc-checkbox'; import VcCheckbox from '../vc-checkbox';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import { getOptionProps } from '../_util/props-util'; import { getOptionProps } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { RadioChangeEvent } from './interface';
export default { export const radioProps = {
prefixCls: PropTypes.string,
defaultChecked: PropTypes.looseBool,
checked: PropTypes.looseBool,
disabled: PropTypes.looseBool,
isGroup: PropTypes.looseBool,
value: PropTypes.any,
name: PropTypes.string,
id: PropTypes.string,
autofocus: PropTypes.looseBool,
type: PropTypes.string.def('radio'),
onChange: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
};
export type RadioProps = Partial<ExtractPropTypes<typeof radioProps>>;
export default defineComponent({
name: 'ARadio', name: 'ARadio',
model: { model: {
prop: 'checked', prop: 'checked',
}, },
props: { props: radioProps,
prefixCls: PropTypes.string, emits: ['update:checked', 'update:value', 'change', 'blur', 'focus'],
defaultChecked: PropTypes.looseBool,
checked: PropTypes.looseBool,
disabled: PropTypes.looseBool,
isGroup: PropTypes.looseBool,
value: PropTypes.any,
name: String,
id: String,
autofocus: PropTypes.looseBool,
type: PropTypes.string.def('radio'),
onChange: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
'onUpdate:checked': PropTypes.func,
'onUpdate:value': PropTypes.func,
},
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
@ -35,18 +39,18 @@ export default {
}, },
methods: { methods: {
focus() { focus() {
this.$refs.vcCheckbox.focus(); (this.$refs.vcCheckbox as any).focus();
}, },
blur() { blur() {
this.$refs.vcCheckbox.blur(); (this.$refs.vcCheckbox as any).blur();
}, },
handleChange(event) { handleChange(event: RadioChangeEvent) {
const targetChecked = event.target.checked; const targetChecked = event.target.checked;
this.$emit('update:checked', targetChecked); this.$emit('update:checked', targetChecked);
this.$emit('update:value', targetChecked); this.$emit('update:value', targetChecked);
this.$emit('change', event); this.$emit('change', event);
}, },
onChange2(e) { onChange2(e: RadioChangeEvent) {
this.$emit('change', e); this.$emit('change', e);
if (this.radioGroupContext && this.radioGroupContext.onRadioChange) { if (this.radioGroupContext && this.radioGroupContext.onRadioChange) {
this.radioGroupContext.onRadioChange(e); this.radioGroupContext.onRadioChange(e);
@ -58,33 +62,33 @@ export default {
const { $slots, radioGroupContext: radioGroup } = this; const { $slots, radioGroupContext: radioGroup } = this;
const props = getOptionProps(this); const props = getOptionProps(this);
const { prefixCls: customizePrefixCls, ...restProps } = props; const { prefixCls: customizePrefixCls, ...restProps } = props;
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('radio', customizePrefixCls); const prefixCls = getPrefixCls('radio', customizePrefixCls);
const radioProps = { const rProps: RadioProps = {
prefixCls, prefixCls,
...restProps, ...restProps,
}; };
if (radioGroup) { if (radioGroup) {
radioProps.name = radioGroup.name; rProps.name = radioGroup.name;
radioProps.onChange = this.onChange2; rProps.onChange = this.onChange2;
radioProps.checked = props.value === radioGroup.stateValue; rProps.checked = props.value === radioGroup.stateValue;
radioProps.disabled = props.disabled || radioGroup.disabled; rProps.disabled = props.disabled || radioGroup.disabled;
} else { } else {
radioProps.onChange = this.handleChange; rProps.onChange = this.handleChange;
} }
const wrapperClassString = classNames({ const wrapperClassString = classNames({
[`${prefixCls}-wrapper`]: true, [`${prefixCls}-wrapper`]: true,
[`${prefixCls}-wrapper-checked`]: radioProps.checked, [`${prefixCls}-wrapper-checked`]: rProps.checked,
[`${prefixCls}-wrapper-disabled`]: radioProps.disabled, [`${prefixCls}-wrapper-disabled`]: rProps.disabled,
}); });
return ( return (
<label class={wrapperClassString}> <label class={wrapperClassString}>
<VcCheckbox {...radioProps} ref="vcCheckbox" /> <VcCheckbox {...rProps} ref="vcCheckbox" />
{$slots.default && <span>{$slots.default()}</span>} {$slots.default && <span>{$slots.default()}</span>}
</label> </label>
); );
}, },
}; });

View File

@ -1,34 +1,34 @@
import { defineComponent, inject } from 'vue'; import { defineComponent, inject } from 'vue';
import Radio from './Radio'; import Radio, { radioProps, RadioProps } from './Radio';
import { getOptionProps, getSlot } from '../_util/props-util'; import { getOptionProps, getSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
export default defineComponent({ export default defineComponent({
name: 'ARadioButton', name: 'ARadioButton',
props: { props: {
...Radio.props, ...radioProps,
}, },
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
radioGroupContext: inject('radioGroupContext', {}), radioGroupContext: inject<any>('radioGroupContext', {}),
}; };
}, },
render() { render() {
const props = getOptionProps(this); const props = getOptionProps(this) as RadioProps;
const { prefixCls: customizePrefixCls, ...otherProps } = props; const { prefixCls: customizePrefixCls, ...otherProps } = props;
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('radio-button', customizePrefixCls); const prefixCls = getPrefixCls('radio-button', customizePrefixCls);
const radioProps = { const rProps: RadioProps = {
prefixCls, prefixCls,
...otherProps, ...otherProps,
}; };
if (this.radioGroupContext) { if (this.radioGroupContext) {
radioProps.onChange = this.radioGroupContext.onRadioChange; rProps.onChange = this.radioGroupContext.onRadioChange;
radioProps.checked = props.value === this.radioGroupContext.stateValue; rProps.checked = props.value === this.radioGroupContext.stateValue;
radioProps.disabled = props.disabled || this.radioGroupContext.disabled; rProps.disabled = props.disabled || this.radioGroupContext.disabled;
} }
return <Radio {...radioProps}>{getSlot(this)}</Radio>; return <Radio {...rProps}>{getSlot(this)}</Radio>;
}, },
}); });

View File

@ -1,3 +1,4 @@
import { App } from 'vue';
import Radio from './Radio'; import Radio from './Radio';
import Group from './Group'; import Group from './Group';
import Button from './RadioButton'; import Button from './RadioButton';
@ -6,7 +7,7 @@ Radio.Group = Group;
Radio.Button = Button; Radio.Button = Button;
/* istanbul ignore next */ /* istanbul ignore next */
Radio.install = function(app) { Radio.install = function(app: App) {
app.component(Radio.name, Radio); app.component(Radio.name, Radio);
app.component(Radio.Group.name, Radio.Group); app.component(Radio.Group.name, Radio.Group);
app.component(Radio.Button.name, Radio.Button); app.component(Radio.Button.name, Radio.Button);

View File

@ -0,0 +1,12 @@
import { RadioProps } from './Radio';
export interface RadioChangeEventTarget extends RadioProps {
checked: boolean;
}
export interface RadioChangeEvent {
target: RadioChangeEventTarget;
stopPropagation: () => void;
preventDefault: () => void;
nativeEvent: MouseEvent;
}

View File

@ -1,4 +1,4 @@
import { inject } from 'vue'; import { inject, defineComponent } from 'vue';
import omit from 'omit.js'; import omit from 'omit.js';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { getOptionProps, getComponent } from '../_util/props-util'; import { getOptionProps, getComponent } from '../_util/props-util';
@ -10,8 +10,8 @@ import Tooltip from '../tooltip';
export const RateProps = { export const RateProps = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
count: PropTypes.number, count: PropTypes.number,
value: PropTypes.value, value: PropTypes.number,
defaultValue: PropTypes.value, defaultValue: PropTypes.number,
allowHalf: PropTypes.looseBool, allowHalf: PropTypes.looseBool,
allowClear: PropTypes.looseBool, allowClear: PropTypes.looseBool,
tooltips: PropTypes.arrayOf(PropTypes.string), tooltips: PropTypes.arrayOf(PropTypes.string),
@ -20,7 +20,7 @@ export const RateProps = {
autofocus: PropTypes.looseBool, autofocus: PropTypes.looseBool,
}; };
const Rate = { const Rate = defineComponent({
name: 'ARate', name: 'ARate',
props: RateProps, props: RateProps,
setup() { setup() {
@ -35,15 +35,15 @@ const Rate = {
return <Tooltip title={tooltips[index]}>{node}</Tooltip>; return <Tooltip title={tooltips[index]}>{node}</Tooltip>;
}, },
focus() { focus() {
this.$refs.refRate.focus(); (this.$refs.refRate as any).focus();
}, },
blur() { blur() {
this.$refs.refRate.blur(); (this.$refs.refRate as any).blur();
}, },
}, },
render() { render() {
const { prefixCls: customizePrefixCls, ...restProps } = getOptionProps(this); const { prefixCls: customizePrefixCls, ...restProps } = getOptionProps(this);
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('rate', customizePrefixCls); const prefixCls = getPrefixCls('rate', customizePrefixCls);
const character = getComponent(this, 'character') || <StarFilled />; const character = getComponent(this, 'character') || <StarFilled />;
@ -57,7 +57,7 @@ const Rate = {
}; };
return <VcRate {...rateProps} />; return <VcRate {...rateProps} />;
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
Rate.install = function(app) { Rate.install = function(app) {

View File

@ -1,35 +1,36 @@
import { inject } from 'vue'; import { App, defineComponent, ExtractPropTypes, inject } from 'vue';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined'; import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import CheckOutlined from '@ant-design/icons-vue/CheckOutlined'; import CheckOutlined from '@ant-design/icons-vue/CheckOutlined';
import PropTypes, { withUndefined } from '../_util/vue-types'; import PropTypes, { withUndefined } from '../_util/vue-types';
import { initDefaultProps, getOptionProps, getComponent, getSlot } from '../_util/props-util'; import { getOptionProps, getComponent, getSlot } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import VcSteps from '../vc-steps'; import VcSteps from '../vc-steps';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { tuple } from '../_util/type';
const getStepsProps = (defaultProps = {}) => { const stepsProps = {
const props = { prefixCls: PropTypes.string,
prefixCls: PropTypes.string, iconPrefix: PropTypes.string,
iconPrefix: PropTypes.string, current: PropTypes.number,
current: PropTypes.number, initial: PropTypes.number,
initial: PropTypes.number, labelPlacement: PropTypes.oneOf(tuple('horizontal', 'vertical')).def('horizontal'),
labelPlacement: PropTypes.oneOf(['horizontal', 'vertical']).def('horizontal'), status: PropTypes.oneOf(tuple('wait', 'process', 'finish', 'error')),
status: PropTypes.oneOf(['wait', 'process', 'finish', 'error']), size: PropTypes.oneOf(tuple('default', 'small')),
size: PropTypes.oneOf(['default', 'small']), direction: PropTypes.oneOf(tuple('horizontal', 'vertical')),
direction: PropTypes.oneOf(['horizontal', 'vertical']), progressDot: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func])),
progressDot: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func])), type: PropTypes.oneOf(tuple('default', 'navigation')),
type: PropTypes.oneOf(['default', 'navigation']), onChange: PropTypes.func,
onChange: PropTypes.func,
'onUpdate:current': PropTypes.func,
};
return initDefaultProps(props, defaultProps);
}; };
const Steps = { export type StepsProps = Partial<ExtractPropTypes<typeof stepsProps>>;
const Steps = defineComponent({
name: 'ASteps', name: 'ASteps',
inheritAttrs: false, inheritAttrs: false,
props: getStepsProps({ props: initDefaultProps(stepsProps, {
current: 0, current: 0,
}), }),
emits: ['update:current', 'change'],
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
@ -43,7 +44,7 @@ const Steps = {
}, },
}, },
render() { render() {
const props = { ...getOptionProps(this), ...this.$attrs }; const props: StepsProps = { ...getOptionProps(this), ...this.$attrs };
const { prefixCls: customizePrefixCls, iconPrefix: customizeIconPrefixCls } = props; const { prefixCls: customizePrefixCls, iconPrefix: customizeIconPrefixCls } = props;
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('steps', customizePrefixCls); const prefixCls = getPrefixCls('steps', customizePrefixCls);
@ -65,10 +66,10 @@ const Steps = {
}; };
return <VcSteps {...stepsProps}>{getSlot(this)}</VcSteps>; return <VcSteps {...stepsProps}>{getSlot(this)}</VcSteps>;
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
Steps.install = function(app) { Steps.install = function(app: App) {
app.component(Steps.name, Steps); app.component(Steps.name, Steps);
app.component(Steps.Step.name, Steps.Step); app.component(Steps.Step.name, Steps.Step);
return app; return app;

View File

@ -1,4 +1,4 @@
import { inject } from 'vue'; import { defineComponent, inject, App } from 'vue';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import hasProp, { getOptionProps, getComponent } from '../_util/props-util'; import hasProp, { getOptionProps, getComponent } from '../_util/props-util';
@ -6,15 +6,16 @@ import VcSwitch from '../vc-switch';
import Wave from '../_util/wave'; import Wave from '../_util/wave';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import warning from '../_util/warning'; import warning from '../_util/warning';
import { tuple } from '../_util/type';
const Switch = { const Switch = defineComponent({
name: 'ASwitch', name: 'ASwitch',
__ANT_SWITCH: true, __ANT_SWITCH: true,
inheritAttrs: false, inheritAttrs: false,
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
// size=default and size=large are the same // size=default and size=large are the same
size: PropTypes.oneOf(['small', 'default', 'large']), size: PropTypes.oneOf(tuple('small', 'default', 'large')),
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,
checkedChildren: PropTypes.any, checkedChildren: PropTypes.any,
unCheckedChildren: PropTypes.any, unCheckedChildren: PropTypes.any,
@ -26,6 +27,7 @@ const Switch = {
}, },
setup() { setup() {
return { return {
refSwitchNode: undefined,
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
}; };
}, },
@ -52,12 +54,12 @@ const Switch = {
const { prefixCls: customizePrefixCls, size, loading, disabled, ...restProps } = getOptionProps( const { prefixCls: customizePrefixCls, size, loading, disabled, ...restProps } = getOptionProps(
this, this,
); );
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('switch', customizePrefixCls); const prefixCls = getPrefixCls('switch', customizePrefixCls);
const { $attrs } = this; const { $attrs } = this;
const classes = { const classes = {
[$attrs.class]: $attrs.class, [$attrs.class as string]: $attrs.class,
[`${prefixCls}-small`]: size === 'small', [`${prefixCls}-small`]: size === 'small',
[`${prefixCls}-loading`]: loading, [`${prefixCls}-loading`]: loading,
}; };
@ -73,13 +75,16 @@ const Switch = {
class: classes, class: classes,
ref: this.saveRef, ref: this.saveRef,
}; };
const comp = <VcSwitch {...switchProps} />; return (
return <Wave insertExtraNode>{comp}</Wave>; <Wave insertExtraNode>
<VcSwitch {...switchProps} />
</Wave>
);
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
Switch.install = function(app) { Switch.install = function(app: App) {
app.component(Switch.name, Switch); app.component(Switch.name, Switch);
return app; return app;
}; };

View File

@ -1,5 +1,5 @@
import omit from 'omit.js'; import omit from 'omit.js';
import { inject, provide } from 'vue'; import { App, defineComponent, inject, provide } from 'vue';
import VcTimePicker from '../vc-time-picker'; import VcTimePicker from '../vc-time-picker';
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
@ -8,13 +8,8 @@ import warning from '../_util/warning';
import ClockCircleOutlined from '@ant-design/icons-vue/ClockCircleOutlined'; import ClockCircleOutlined from '@ant-design/icons-vue/ClockCircleOutlined';
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled'; import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import enUS from './locale/en_US'; import enUS from './locale/en_US';
import { import { hasProp, getOptionProps, getComponent, isValidElement } from '../_util/props-util';
initDefaultProps, import initDefaultProps from '../_util/props-util/initDefaultProps';
hasProp,
getOptionProps,
getComponent,
isValidElement,
} from '../_util/props-util';
import { cloneElement } from '../_util/vnode'; import { cloneElement } from '../_util/vnode';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { import {
@ -23,8 +18,9 @@ import {
momentToString, momentToString,
TimeOrTimesType, TimeOrTimesType,
} from '../_util/moment-util'; } from '../_util/moment-util';
import { tuple } from '../_util/type';
export function generateShowHourMinuteSecond(format) { export function generateShowHourMinuteSecond(format: string) {
// Ref: http://momentjs.com/docs/#/parsing/string-format/ // Ref: http://momentjs.com/docs/#/parsing/string-format/
return { return {
showHour: format.indexOf('H') > -1 || format.indexOf('h') > -1 || format.indexOf('k') > -1, showHour: format.indexOf('H') > -1 || format.indexOf('h') > -1 || format.indexOf('k') > -1,
@ -34,7 +30,7 @@ export function generateShowHourMinuteSecond(format) {
} }
export const TimePickerProps = () => ({ export const TimePickerProps = () => ({
size: PropTypes.oneOf(['large', 'default', 'small']), size: PropTypes.oneOf(tuple('large', 'default', 'small')),
value: TimeOrTimesType, value: TimeOrTimesType,
defaultValue: TimeOrTimesType, defaultValue: TimeOrTimesType,
open: PropTypes.looseBool, open: PropTypes.looseBool,
@ -58,7 +54,7 @@ export const TimePickerProps = () => ({
clearText: PropTypes.string, clearText: PropTypes.string,
defaultOpenValue: PropTypes.object, defaultOpenValue: PropTypes.object,
popupClassName: PropTypes.string, popupClassName: PropTypes.string,
popupStyle: PropTypes.object, popupStyle: PropTypes.style,
suffixIcon: PropTypes.any, suffixIcon: PropTypes.any,
align: PropTypes.object, align: PropTypes.object,
placement: PropTypes.any, placement: PropTypes.any,
@ -76,14 +72,13 @@ export const TimePickerProps = () => ({
onBlur: PropTypes.func, onBlur: PropTypes.func,
onKeydown: PropTypes.func, onKeydown: PropTypes.func,
onOpenChange: PropTypes.func, onOpenChange: PropTypes.func,
'onUpdate:value': PropTypes.func,
'onUpdate:open': PropTypes.func,
}); });
const TimePicker = { const TimePicker = defineComponent({
name: 'ATimePicker', name: 'ATimePicker',
inheritAttrs: false, inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
emits: ['update:value', 'update:open', 'change', 'openChange', 'focus', 'blur', 'keydown'],
props: initDefaultProps(TimePickerProps(), { props: initDefaultProps(TimePickerProps(), {
align: { align: {
offset: [0, -2], offset: [0, -2],
@ -103,6 +98,8 @@ const TimePicker = {
}, },
setup() { setup() {
return { return {
popupRef: null,
timePickerRef: null,
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
}; };
}, },
@ -174,14 +171,14 @@ const TimePicker = {
}, },
focus() { focus() {
this.timePickerRef.focus(); (this.timePickerRef as any).focus();
}, },
blur() { blur() {
this.timePickerRef.blur(); (this.timePickerRef as any).blur();
}, },
renderInputIcon(prefixCls) { renderInputIcon(prefixCls: string) {
let suffixIcon = getComponent(this, 'suffixIcon'); let suffixIcon = getComponent(this, 'suffixIcon');
suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon; suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon;
const clockIcon = (suffixIcon && const clockIcon = (suffixIcon &&
@ -193,7 +190,7 @@ const TimePicker = {
return <span class={`${prefixCls}-icon`}>{clockIcon}</span>; return <span class={`${prefixCls}-icon`}>{clockIcon}</span>;
}, },
renderClearIcon(prefixCls) { renderClearIcon(prefixCls: string) {
const clearIcon = getComponent(this, 'clearIcon'); const clearIcon = getComponent(this, 'clearIcon');
const clearIconPrefixCls = `${prefixCls}-clear`; const clearIconPrefixCls = `${prefixCls}-clear`;
@ -216,7 +213,7 @@ const TimePicker = {
const format = this.getDefaultFormat(); const format = this.getDefaultFormat();
const pickerClassName = { const pickerClassName = {
[className]: className, [className as string]: className,
[`${prefixCls}-${size}`]: !!size, [`${prefixCls}-${size}`]: !!size,
}; };
const tempAddon = getComponent(this, 'addon', {}, false); const tempAddon = getComponent(this, 'addon', {}, false);
@ -262,10 +259,10 @@ const TimePicker = {
/> />
); );
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
TimePicker.install = function(app) { TimePicker.install = function(app: App) {
app.component(TimePicker.name, TimePicker); app.component(TimePicker.name, TimePicker);
return app; return app;
}; };

View File

@ -1,41 +1,38 @@
import { inject, cloneVNode } from 'vue'; import { inject, cloneVNode, defineComponent, ExtractPropTypes } from 'vue';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { import { getOptionProps, getPropsData, filterEmpty, getComponent } from '../_util/props-util';
getOptionProps, import initDefaultProps from '../_util/props-util/initDefaultProps';
getPropsData, import TimelineItem, { TimeLineItemProps } from './TimelineItem';
initDefaultProps,
filterEmpty,
getComponent,
} from '../_util/props-util';
import TimelineItem from './TimelineItem';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { tuple } from '../_util/type';
export const TimelineProps = { export const timelineProps = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
/** 指定最后一个幽灵节点是否存在或内容 */ /** 指定最后一个幽灵节点是否存在或内容 */
pending: PropTypes.any, pending: PropTypes.any,
pendingDot: PropTypes.string, pendingDot: PropTypes.string,
reverse: PropTypes.looseBool, reverse: PropTypes.looseBool,
mode: PropTypes.oneOf(['left', 'alternate', 'right', '']), mode: PropTypes.oneOf(tuple('left', 'alternate', 'right', '')),
}; };
export default { export type TimelineProps = Partial<ExtractPropTypes<typeof timelineProps>>;
export default defineComponent({
name: 'ATimeline', name: 'ATimeline',
props: initDefaultProps(TimelineProps, { props: initDefaultProps(timelineProps, {
reverse: false, reverse: false,
mode: '', mode: '',
}), }),
setup() { setup() {
const configProvider = inject('configProvider', defaultConfigProvider);
return { return {
configProvider, configProvider: inject('configProvider', defaultConfigProvider),
}; };
}, },
render() { render() {
const { prefixCls: customizePrefixCls, reverse, mode } = getOptionProps(this); const { prefixCls: customizePrefixCls, reverse, mode } = getOptionProps(this);
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('timeline', customizePrefixCls); const prefixCls = getPrefixCls('timeline', customizePrefixCls);
const pendingDot = getComponent(this, 'pendingDot'); const pendingDot = getComponent(this, 'pendingDot');
@ -66,8 +63,8 @@ export default {
? [pendingItem, ...children.reverse()] ? [pendingItem, ...children.reverse()]
: [...children, pendingItem]; : [...children, pendingItem];
const getPositionCls = (ele, idx) => { const getPositionCls = (ele, idx: number) => {
const eleProps = getPropsData(ele); const eleProps = getPropsData(ele) as TimeLineItemProps;
if (mode === 'alternate') { if (mode === 'alternate') {
if (eleProps.position === 'right') return `${prefixCls}-item-right`; if (eleProps.position === 'right') return `${prefixCls}-item-right`;
if (eleProps.position === 'left') return `${prefixCls}-item-left`; if (eleProps.position === 'left') return `${prefixCls}-item-left`;
@ -94,9 +91,6 @@ export default {
}); });
}); });
const timelineProps = { return <ul class={classString}>{items}</ul>;
class: classString,
};
return <ul {...timelineProps}>{items}</ul>;
}, },
}; });

View File

@ -1,32 +1,35 @@
import { inject } from 'vue'; import { defineComponent, ExtractPropTypes, inject } from 'vue';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { getOptionProps, initDefaultProps, getComponent } from '../_util/props-util'; import { getOptionProps, getComponent } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { tuple } from '../_util/type';
export const TimeLineItemProps = { export const timeLineItemProps = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
color: PropTypes.string, color: PropTypes.string,
dot: PropTypes.any, dot: PropTypes.any,
pending: PropTypes.looseBool, pending: PropTypes.looseBool,
position: PropTypes.oneOf(['left', 'right', '']).def(''), position: PropTypes.oneOf(tuple('left', 'right', '')).def(''),
}; };
export default { export type TimeLineItemProps = Partial<ExtractPropTypes<typeof timeLineItemProps>>;
export default defineComponent({
name: 'ATimelineItem', name: 'ATimelineItem',
props: initDefaultProps(TimeLineItemProps, { props: initDefaultProps(timeLineItemProps, {
color: 'blue', color: 'blue',
pending: false, pending: false,
}), }),
setup() { setup() {
const configProvider = inject('configProvider', defaultConfigProvider);
return { return {
configProvider, configProvider: inject('configProvider', defaultConfigProvider),
}; };
}, },
render() { render() {
const { prefixCls: customizePrefixCls, color = '', pending } = getOptionProps(this); const { prefixCls: customizePrefixCls, color = '', pending } = getOptionProps(this);
const getPrefixCls = this.configProvider.getPrefixCls; const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('timeline', customizePrefixCls); const prefixCls = getPrefixCls('timeline', customizePrefixCls);
const dot = getComponent(this, 'dot'); const dot = getComponent(this, 'dot');
@ -55,4 +58,4 @@ export default {
</li> </li>
); );
}, },
}; });

View File

@ -1,3 +1,4 @@
import { App } from 'vue';
import Timeline from './Timeline'; import Timeline from './Timeline';
import TimelineItem from './TimelineItem'; import TimelineItem from './TimelineItem';
@ -7,10 +8,12 @@ export { TimeLineItemProps } from './TimelineItem';
Timeline.Item = TimelineItem; Timeline.Item = TimelineItem;
/* istanbul ignore next */ /* istanbul ignore next */
Timeline.install = function(app) { Timeline.install = function(app: App) {
app.component(Timeline.name, Timeline); app.component(Timeline.name, Timeline);
app.component(TimelineItem.name, TimelineItem); app.component(TimelineItem.name, TimelineItem);
return app; return app;
}; };
export default Timeline; export default Timeline as typeof Timeline & {
readonly Item: typeof TimelineItem;
};

View File

@ -2,10 +2,11 @@ import PropTypes, { withUndefined } from '../_util/vue-types';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import Lazyload from '../vc-lazy-load'; import Lazyload from '../vc-lazy-load';
import Checkbox from '../checkbox'; import Checkbox from '../checkbox';
import { defineComponent } from 'vue';
function noop() {} function noop() {}
export default { export default defineComponent({
name: 'ListItem', name: 'ListItem',
inheritAttrs: false, inheritAttrs: false,
props: { props: {
@ -54,7 +55,7 @@ export default {
offset: 500, offset: 500,
throttle: 0, throttle: 0,
debounce: false, debounce: false,
...lazy, ...(lazy as any),
}; };
children = <Lazyload {...lazyProps}>{listItem}</Lazyload>; children = <Lazyload {...lazyProps}>{listItem}</Lazyload>;
} else { } else {
@ -62,4 +63,4 @@ export default {
} }
return children; return children;
}, },
}; });

View File

@ -1,15 +1,16 @@
import { inject } from 'vue'; import { App, defineComponent, inject } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { hasProp, initDefaultProps, getOptionProps, getComponent } from '../_util/props-util'; import { hasProp, getOptionProps, getComponent } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import List from './list'; import List from './list';
import Operation from './operation'; import Operation from './operation';
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
import defaultLocale from '../locale-provider/default'; import defaultLocale from '../locale-provider/default';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider, RenderEmptyHandler } from '../config-provider';
export const TransferDirection = 'left' | 'right'; export type TransferDirection = 'left' | 'right';
export const TransferItem = { export const TransferItem = {
key: PropTypes.string.isRequired, key: PropTypes.string.isRequired,
@ -45,14 +46,15 @@ export const TransferProps = {
onScroll: PropTypes.func, onScroll: PropTypes.func,
}; };
export const TransferLocale = { export interface TransferLocale {
titles: PropTypes.arrayOf(PropTypes.string), titles: string[];
notFoundContent: PropTypes.string, notFoundContent: string;
itemUnit: PropTypes.string, searchPlaceholder: string;
itemsUnit: PropTypes.string, itemUnit: string;
}; itemsUnit: string;
}
const Transfer = { const Transfer = defineComponent({
name: 'ATransfer', name: 'ATransfer',
inheritAttrs: false, inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
@ -64,6 +66,9 @@ const Transfer = {
}), }),
setup() { setup() {
return { return {
selectedKeys: [],
targetKeys: [],
separatedDataSource: null,
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
}; };
}, },
@ -114,16 +119,16 @@ const Transfer = {
return direction === 'left' ? 'sourceSelectedKeys' : 'targetSelectedKeys'; return direction === 'left' ? 'sourceSelectedKeys' : 'targetSelectedKeys';
}, },
getTitles(transferLocale) { getTitles(transferLocale: TransferLocale) {
if (this.titles) { if (this.titles) {
return this.titles; return this.titles;
} }
return transferLocale.titles || ['', '']; return transferLocale.titles || ['', ''];
}, },
getLocale(transferLocale, renderEmpty) { getLocale(transferLocale: TransferLocale, renderEmpty: RenderEmptyHandler) {
// Keep old locale props still working. // Keep old locale props still working.
const oldLocale = { const oldLocale: { notFoundContent?: any; searchPlaceholder?: string } = {
notFoundContent: renderEmpty('Transfer'), notFoundContent: renderEmpty('Transfer'),
}; };
const notFoundContent = getComponent(this, 'notFoundContent'); const notFoundContent = getComponent(this, 'notFoundContent');
@ -161,7 +166,7 @@ const Transfer = {
} }
}, },
moveTo(direction) { moveTo(direction: TransferDirection) {
const { targetKeys = [], dataSource = [] } = this.$props; const { targetKeys = [], dataSource = [] } = this.$props;
const { sourceSelectedKeys, targetSelectedKeys } = this; const { sourceSelectedKeys, targetSelectedKeys } = this;
const moveKeys = direction === 'right' ? sourceSelectedKeys : targetSelectedKeys; const moveKeys = direction === 'right' ? sourceSelectedKeys : targetSelectedKeys;
@ -191,7 +196,7 @@ const Transfer = {
this.moveTo('right'); this.moveTo('right');
}, },
onItemSelectAll(direction, selectedKeys, checkAll) { onItemSelectAll(direction: TransferDirection, selectedKeys: string[], checkAll: boolean) {
const originalSelectedKeys = this.$data[this.getSelectedKeysName(direction)] || []; const originalSelectedKeys = this.$data[this.getSelectedKeysName(direction)] || [];
let mergedCheckedKeys = []; let mergedCheckedKeys = [];
@ -319,7 +324,7 @@ const Transfer = {
this.handleScroll('right', e); this.handleScroll('right', e);
}, },
handleSelectChange(direction, holder) { handleSelectChange(direction: TransferDirection, holder: string[]) {
const { sourceSelectedKeys, targetSelectedKeys } = this; const { sourceSelectedKeys, targetSelectedKeys } = this;
if (direction === 'left') { if (direction === 'left') {
@ -361,7 +366,7 @@ const Transfer = {
}; };
}, },
renderTransfer(transferLocale) { renderTransfer(transferLocale: TransferLocale) {
const props = getOptionProps(this); const props = getOptionProps(this);
const { const {
prefixCls: customizePrefixCls, prefixCls: customizePrefixCls,
@ -478,10 +483,10 @@ const Transfer = {
/> />
); );
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
Transfer.install = function(app) { Transfer.install = function(app: App) {
app.component(Transfer.name, Transfer); app.component(Transfer.name, Transfer);
return app; return app;
}; };

View File

@ -1,17 +1,13 @@
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import PropTypes, { withUndefined } from '../_util/vue-types'; import PropTypes, { withUndefined } from '../_util/vue-types';
import { import { isValidElement, splitAttrs, findDOMNode, filterEmpty } from '../_util/props-util';
isValidElement, import initDefaultProps from '../_util/props-util/initDefaultProps';
initDefaultProps,
splitAttrs,
findDOMNode,
filterEmpty,
} from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import Checkbox from '../checkbox'; import Checkbox from '../checkbox';
import Search from './search'; import Search from './search';
import defaultRenderList from './renderListBody'; import defaultRenderList from './renderListBody';
import triggerEvent from '../_util/triggerEvent'; import triggerEvent from '../_util/triggerEvent';
import { defineComponent } from 'vue';
const defaultRender = () => null; const defaultRender = () => null;
@ -71,7 +67,7 @@ function renderListNode(renderList, props) {
}; };
} }
export default { export default defineComponent({
name: 'TransferList', name: 'TransferList',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false, inheritAttrs: false,
@ -81,9 +77,14 @@ export default {
showSearch: false, showSearch: false,
lazy: {}, lazy: {},
}), }),
setup() {
return {
timer: null,
triggerScrollTimer: null,
scrollEvent: null,
};
},
data() { data() {
this.timer = null;
this.triggerScrollTimer = null;
return { return {
filterValue: '', filterValue: '',
}; };
@ -345,4 +346,4 @@ export default {
</div> </div>
); );
}, },
}; });

View File

@ -1,10 +1,23 @@
import { CSSProperties, FunctionalComponent } from 'vue';
import LeftOutlined from '@ant-design/icons-vue/LeftOutlined'; import LeftOutlined from '@ant-design/icons-vue/LeftOutlined';
import RightOutlined from '@ant-design/icons-vue/RightOutlined'; import RightOutlined from '@ant-design/icons-vue/RightOutlined';
import Button from '../button'; import Button from '../button';
function noop() {} function noop() {}
const Operation = (_, { attrs }) => { export interface TransferOperationProps {
class?: any;
leftArrowText?: string;
rightArrowText?: string;
moveToLeft?: (e: MouseEvent) => void;
moveToRight?: (e: MouseEvent) => void;
leftActive?: boolean;
rightActive?: boolean;
style?: CSSProperties | string;
disabled?: boolean;
}
const Operation: FunctionalComponent<TransferOperationProps> = props => {
const { const {
disabled, disabled,
moveToLeft = noop, moveToLeft = noop,
@ -15,7 +28,7 @@ const Operation = (_, { attrs }) => {
rightActive, rightActive,
class: className, class: className,
style, style,
} = attrs; } = props;
return ( return (
<div class={className} style={style}> <div class={className} style={style}>
@ -40,6 +53,7 @@ const Operation = (_, { attrs }) => {
</div> </div>
); );
}; };
Operation.inheritAttrs = false; Operation.inheritAttrs = false;
export default Operation; export default Operation;

View File

@ -1,11 +1,11 @@
import { TransitionGroup } from 'vue'; import { defineComponent, TransitionGroup } from 'vue';
import raf from '../_util/raf'; import raf from '../_util/raf';
import ListItem from './ListItem'; import ListItem from './ListItem';
import PropTypes, { withUndefined } from '../_util/vue-types'; import PropTypes, { withUndefined } from '../_util/vue-types';
import getTransitionProps from '../_util/getTransitionProps'; import getTransitionProps from '../_util/getTransitionProps';
import { findDOMNode } from '../_util/props-util'; import { findDOMNode } from '../_util/props-util';
function noop() {} function noop() {}
const ListBody = { const ListBody = defineComponent({
name: 'ListBody', name: 'ListBody',
inheritAttrs: false, inheritAttrs: false,
props: { props: {
@ -18,13 +18,19 @@ const ListBody = {
onItemSelectAll: PropTypes.func, onItemSelectAll: PropTypes.func,
onScroll: PropTypes.func, onScroll: PropTypes.func,
}, },
setup() {
return {
mountId: null,
lazyId: null,
};
},
data() { data() {
return { return {
mounted: false, mounted: false,
}; };
}, },
computed: { computed: {
itemsLength() { itemsLength(): number {
return this.filteredRenderItems ? this.filteredRenderItems.length : 0; return this.filteredRenderItems ? this.filteredRenderItems.length : 0;
}, },
}, },
@ -74,7 +80,7 @@ const ListBody = {
selectedKeys, selectedKeys,
disabled: globalDisabled, disabled: globalDisabled,
} = this.$props; } = this.$props;
const items = filteredRenderItems.map(({ renderedEl, renderedText, item }) => { const items = filteredRenderItems.map(({ renderedEl, renderedText, item }: any) => {
const { disabled } = item; const { disabled } = item;
const checked = selectedKeys.indexOf(item.key) >= 0; const checked = selectedKeys.indexOf(item.key) >= 0;
@ -101,11 +107,11 @@ const ListBody = {
}, },
); );
return ( return (
<TransitionGroup class={`${prefixCls}-content`} {...transitionProps}> <TransitionGroup moveClass={`${prefixCls}-content`} {...transitionProps}>
{items} {items}
</TransitionGroup> </TransitionGroup>
); );
}, },
}; });
export default props => <ListBody {...props} />; export default props => <ListBody {...props} />;

View File

@ -1,8 +1,10 @@
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { initDefaultProps, getOptionProps } from '../_util/props-util'; import { getOptionProps } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled'; import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import SearchOutlined from '@ant-design/icons-vue/SearchOutlined'; import SearchOutlined from '@ant-design/icons-vue/SearchOutlined';
import Input from '../input'; import Input from '../input';
import { defineComponent } from 'vue';
export const TransferSearchProps = { export const TransferSearchProps = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
@ -13,7 +15,7 @@ export const TransferSearchProps = {
onChange: PropTypes.func, onChange: PropTypes.func,
}; };
export default { export default defineComponent({
name: 'Search', name: 'Search',
inheritAttrs: false, inheritAttrs: false,
props: initDefaultProps(TransferSearchProps, { props: initDefaultProps(TransferSearchProps, {
@ -45,7 +47,7 @@ export default {
); );
return ( return (
<div> <>
<Input <Input
placeholder={placeholder} placeholder={placeholder}
class={prefixCls} class={prefixCls}
@ -54,7 +56,7 @@ export default {
disabled={disabled} disabled={disabled}
/> />
{icon} {icon}
</div> </>
); );
}, },
}; });

View File

@ -0,0 +1,8 @@
import '../../style/index.less';
import './index.less';
// style dependencies
import '../../empty/style';
import '../../checkbox/style';
import '../../button/style';
import '../../input/style';

View File

@ -37,7 +37,7 @@ export const TreeSelectProps = () => ({
searchValue: PropTypes.string, searchValue: PropTypes.string,
showCheckedStrategy: PropTypes.oneOf(['SHOW_ALL', 'SHOW_PARENT', 'SHOW_CHILD']), showCheckedStrategy: PropTypes.oneOf(['SHOW_ALL', 'SHOW_PARENT', 'SHOW_CHILD']),
suffixIcon: PropTypes.any, suffixIcon: PropTypes.any,
treeCheckable: PropTypes.any, treeCheckable: PropTypes.looseBool,
treeCheckStrictly: PropTypes.looseBool, treeCheckStrictly: PropTypes.looseBool,
treeData: PropTypes.arrayOf(Object), treeData: PropTypes.arrayOf(Object),
treeDataSimpleMode: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, Object])), treeDataSimpleMode: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, Object])),

View File

@ -15,6 +15,7 @@ import Tooltip from '../tooltip';
import Progress from '../progress'; import Progress from '../progress';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import { UploadListProps } from './interface'; import { UploadListProps } from './interface';
import getTransitionGroupProps from '../_util/getTransitionGroupProps';
export default { export default {
name: 'AUploadList', name: 'AUploadList',
@ -265,7 +266,7 @@ export default {
[`${prefixCls}-list-${listType}`]: true, [`${prefixCls}-list-${listType}`]: true,
}); });
const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate'; const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate';
const transitionGroupProps = getTransitionProps(`${prefixCls}-${animationDirection}`); const transitionGroupProps = getTransitionGroupProps(`${prefixCls}-${animationDirection}`);
return ( return (
<TransitionGroup {...transitionGroupProps} tag="div" class={listClassNames}> <TransitionGroup {...transitionGroupProps} tag="div" class={listClassNames}>
{list} {list}

View File

@ -3,8 +3,8 @@ import PropTypes from '../_util/vue-types';
import { getComponent } from '../_util/props-util'; import { getComponent } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import createChainedFunction from '../_util/createChainedFunction'; import createChainedFunction from '../_util/createChainedFunction';
import getTransitionProps from '../_util/getTransitionProps';
import Notice from './Notice'; import Notice from './Notice';
import getTransitionGroupProps from '../_util/getTransitionGroupProps';
function noop() {} function noop() {}
@ -75,7 +75,7 @@ const Notification = defineComponent({
render() { render() {
const { prefixCls, notices, remove, getTransitionName, $attrs } = this; const { prefixCls, notices, remove, getTransitionName, $attrs } = this;
const transitionProps = getTransitionProps(getTransitionName()); const transitionProps = getTransitionGroupProps(getTransitionName());
const noticeNodes = notices.map((notice, index) => { const noticeNodes = notices.map((notice, index) => {
const update = Boolean(index === notices.length - 1 && notice.updateKey); const update = Boolean(index === notices.length - 1 && notice.updateKey);
const key = notice.updateKey ? notice.updateKey : notice.key; const key = notice.updateKey ? notice.updateKey : notice.key;

View File

@ -158,11 +158,9 @@ const SelectSelector = defineComponent<SelectorProps>({
: maxTagPlaceholder, : maxTagPlaceholder,
}); });
} }
const transitionProps = choiceTransitionName const transitionProps = getTransitionGroupProps(choiceTransitionName, {
? getTransitionGroupProps(choiceTransitionName, { appear: motionAppear,
appear: motionAppear, })
})
: { css: false };
selectionNode.value = ( selectionNode.value = (
<TransitionGroup {...transitionProps}> <TransitionGroup {...transitionProps}>
{...displayValues.map( {...displayValues.map(

View File

@ -30,10 +30,12 @@ export const selectorPropTypes = () => ({
placeholder: PropTypes.any, placeholder: PropTypes.any,
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,
focused: PropTypes.looseBool, focused: PropTypes.looseBool,
isMultiple: PropTypes.looseBool,
showSearch: PropTypes.looseBool,
}); });
function noop() {} function noop() {}
export default function(modeName) { export default function() {
const BaseSelector = { const BaseSelector = {
name: 'BaseSelector', name: 'BaseSelector',
inheritAttrs: false, inheritAttrs: false,
@ -101,7 +103,7 @@ export default function(modeName) {
} }
const clearIcon = getComponent(this, 'clearIcon'); const clearIcon = getComponent(this, 'clearIcon');
return ( return (
<span key="clear" class={`${prefixCls}-selection__clear`} onClick={onSelectorClear}> <span key="clear" unselectable="on" aria-hidden="true" style="user-select: none;" class={`${prefixCls}-clear`} onClick={onSelectorClear}>
{clearIcon} {clearIcon}
</span> </span>
); );
@ -114,7 +116,7 @@ export default function(modeName) {
} }
const inputIcon = getComponent(this, 'inputIcon'); const inputIcon = getComponent(this, 'inputIcon');
return ( return (
<span key="arrow" class={`${prefixCls}-arrow`} style={{ outline: 'none' }}> <span key="arrow" class={`${prefixCls}-arrow`} style={{ outline: 'none', userSelect: 'none' }}>
{inputIcon} {inputIcon}
</span> </span>
); );
@ -132,6 +134,9 @@ export default function(modeName) {
renderSelection, renderSelection,
renderPlaceholder, renderPlaceholder,
tabindex, tabindex,
isMultiple,
showArrow,
showSearch,
} = this.$props; } = this.$props;
const { class: className, style, onClick = noop } = this.$attrs; const { class: className, style, onClick = noop } = this.$attrs;
const { const {
@ -142,18 +147,21 @@ export default function(modeName) {
if (disabled) { if (disabled) {
myTabIndex = null; myTabIndex = null;
} }
const mergedClassName = classNames(prefixCls, className, {
[`${prefixCls}-focused`]: open || focused,
[`${prefixCls}-multiple`]: isMultiple,
[`${prefixCls}-single`]: !isMultiple,
[`${prefixCls}-allow-clear`]: allowClear,
[`${prefixCls}-show-arrow`]: showArrow,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-open`]: open,
[`${prefixCls}-show-search`]: showSearch,
});
return ( return (
<span <div
style={style} style={style}
onClick={onClick} onClick={onClick}
class={classNames(className, prefixCls, { class={mergedClassName}
[`${prefixCls}-open`]: open,
[`${prefixCls}-focused`]: open || focused,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-enabled`]: !disabled,
[`${prefixCls}-allow-clear`]: allowClear,
})}
ref={this.domRef} ref={this.domRef}
role="combobox" role="combobox"
aria-expanded={open} aria-expanded={open}
@ -166,17 +174,13 @@ export default function(modeName) {
onBlur={this.onBlur} onBlur={this.onBlur}
onKeydown={onSelectorKeyDown} onKeydown={onSelectorKeyDown}
> >
<span <span class={`${prefixCls}-selector`}>
key="selection"
class={classNames(`${prefixCls}-selection`, `${prefixCls}-selection--${modeName}`)}
>
{renderSelection()} {renderSelection()}
{this.renderClear()}
{this.renderArrow()}
{renderPlaceholder && renderPlaceholder()} {renderPlaceholder && renderPlaceholder()}
</span> </span>
</span> {this.renderArrow()}
{this.renderClear()}
</div>
); );
}, },
}; };

View File

@ -40,7 +40,7 @@ const SinglePopup = {
display: searchValue ? 'none' : 'block', display: searchValue ? 'none' : 'block',
}} }}
onClick={this.onPlaceholderClick} onClick={this.onPlaceholderClick}
class={`${prefixCls}-search__field__placeholder`} class={`${prefixCls}-selection-placeholder`}
> >
{searchPlaceholder} {searchPlaceholder}
</span> </span>

View File

@ -4,7 +4,7 @@
* - multiple: in the selector * - multiple: in the selector
* Move the code as a SearchInput for easy management. * Move the code as a SearchInput for easy management.
*/ */
import { inject, withDirectives } from 'vue'; import { inject, withDirectives, ref, onMounted, computed, watch } from 'vue';
import antInput from '../../_util/antInputDirective'; import antInput from '../../_util/antInputDirective';
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import { createRef } from './util'; import { createRef } from './util';
@ -21,8 +21,22 @@ const SearchInput = {
needAlign: PropTypes.looseBool, needAlign: PropTypes.looseBool,
ariaId: PropTypes.string, ariaId: PropTypes.string,
}, },
setup() { setup(props) {
const measureRef = ref();
const inputWidth = ref(0);
// We measure width and set to the input immediately
onMounted(() => {
watch(
computed(()=>props.searchValue),
() => {
inputWidth.value = measureRef.value.scrollWidth;
},
{ flush: 'post' },
);
});
return { return {
measureRef,
inputWidth,
vcTreeSelect: inject('vcTreeSelect', {}), vcTreeSelect: inject('vcTreeSelect', {}),
}; };
}, },
@ -38,7 +52,7 @@ const SearchInput = {
}, },
created() { created() {
this.inputRef = createRef(); this.inputRef = createRef();
this.mirrorInputRef = createRef(); // this.mirrorInputRef = createRef();
this.prevProps = { ...this.$props }; this.prevProps = { ...this.$props };
}, },
mounted() { mounted() {
@ -55,15 +69,15 @@ const SearchInput = {
}, },
updated() { updated() {
const { open, searchValue, needAlign } = this.$props; const { open } = this.$props;
const { prevProps } = this; const { prevProps } = this;
this.$nextTick(() => { this.$nextTick(() => {
if (open && prevProps.open !== open) { if (open && prevProps.open !== open) {
this.focus(); this.focus();
} }
if (needAlign && searchValue !== prevProps.searchValue) { // if (needAlign && searchValue !== prevProps.searchValue) {
this.alignInputWidth(); // this.alignInputWidth();
} // }
this.prevProps = { ...this.$props }; this.prevProps = { ...this.$props };
}); });
}, },
@ -73,10 +87,10 @@ const SearchInput = {
* ref: https://github.com/react-component/tree-select/issues/65 * ref: https://github.com/react-component/tree-select/issues/65
* clientWidth 0 when mounted in vue. why? * clientWidth 0 when mounted in vue. why?
*/ */
alignInputWidth() { // alignInputWidth() {
this.inputRef.current.style.width = `${this.mirrorInputRef.current.clientWidth || // this.inputRef.current.style.width = `${this.mirrorInputRef.current.clientWidth ||
this.mirrorInputRef.current.offsetWidth}px`; // this.mirrorInputRef.current.offsetWidth}px`;
}, // },
/** /**
* Need additional timeout for focus cause parent dom is not ready when didMount trigger * Need additional timeout for focus cause parent dom is not ready when didMount trigger
@ -116,31 +130,34 @@ const SearchInput = {
vcTreeSelect: { onSearchInputKeyDown }, vcTreeSelect: { onSearchInputKeyDown },
handleInputChange, handleInputChange,
mirrorSearchValue, mirrorSearchValue,
inputWidth,
} = this; } = this;
return ( return (
<span class={`${prefixCls}-search__field__wrap`}> <>
{withDirectives( <span class={`${prefixCls}-selection-search`} style={{ width: inputWidth + 'px' }}>
<input {withDirectives(
type="text" <input
ref={this.inputRef} type="text"
onInput={handleInputChange} ref={this.inputRef}
onChange={handleInputChange} onInput={handleInputChange}
onKeydown={onSearchInputKeyDown} onChange={handleInputChange}
value={searchValue} onKeydown={onSearchInputKeyDown}
disabled={disabled} value={searchValue}
class={`${prefixCls}-search__field`} disabled={disabled}
aria-label="filter select" class={`${prefixCls}-selection-search-input`}
aria-autocomplete="list" aria-label="filter select"
aria-controls={open ? ariaId : undefined} aria-autocomplete="list"
aria-multiline="false" aria-controls={open ? ariaId : undefined}
/>, aria-multiline="false"
[[antInput]], />,
)} [[antInput]],
<span ref={this.mirrorInputRef} class={`${prefixCls}-search__field__mirror`}> )}
{mirrorSearchValue}&nbsp; <span ref="measureRef" class={`${prefixCls}-selection-search-mirror`} aria-hidden>
{mirrorSearchValue}&nbsp;
</span>
</span> </span>
{renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null} {renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null}
</span> </>
); );
}, },
}; };

View File

@ -1096,7 +1096,7 @@ const Select = defineComponent({
const $popup = <Popup {...popupProps} __propsSymbol__={[]} />; const $popup = <Popup {...popupProps} __propsSymbol__={[]} />;
const Selector = isMultiple ? MultipleSelector : SingleSelector; const Selector = isMultiple ? MultipleSelector : SingleSelector;
const $selector = <Selector {...passProps} ref={this.selectorRef} />; const $selector = <Selector {...passProps} isMultiple={isMultiple} ref={this.selectorRef} />;
const selectTriggerProps = { const selectTriggerProps = {
...passProps, ...passProps,
popupElement: $popup, popupElement: $popup,

View File

@ -32,20 +32,20 @@ const Selection = {
} }
const { class: className, style, onRemove } = this.$attrs; const { class: className, style, onRemove } = this.$attrs;
return ( return (
<li <span
style={{ ...UNSELECTABLE_STYLE, ...style }} style={{ ...UNSELECTABLE_STYLE, ...style }}
{...UNSELECTABLE_ATTRIBUTE} {...UNSELECTABLE_ATTRIBUTE}
role="menuitem" role="menuitem"
class={classNames(`${prefixCls}-selection__choice`, className)} class={classNames(`${prefixCls}-selection-item`, className)}
title={toTitle(label)} title={toTitle(label)}
> >
<span class={`${prefixCls}-selection-item-content`}>{content}</span>
{onRemove && ( {onRemove && (
<span class={`${prefixCls}-selection__choice__remove`} onClick={this.onRemove}> <span class={`${prefixCls}-selection-item-remove`} onClick={this.onRemove}>
{getComponent(this, 'removeIcon')} {getComponent(this, 'removeIcon')}
</span> </span>
)} )}
<span class={`${prefixCls}-selection__choice__content`}>{content}</span> </span>
</li>
); );
}, },
}; };

View File

@ -1,11 +1,10 @@
import { inject, TransitionGroup } from 'vue'; import { inject } from 'vue';
import PropTypes from '../../../../_util/vue-types'; import PropTypes from '../../../../_util/vue-types';
import { createRef } from '../../util'; import { createRef } from '../../util';
import generateSelector, { selectorPropTypes } from '../../Base/BaseSelector'; import generateSelector, { selectorPropTypes } from '../../Base/BaseSelector';
import SearchInput from '../../SearchInput'; import SearchInput from '../../SearchInput';
import Selection from './Selection'; import Selection from './Selection';
import { getComponent, getSlot } from '../../../../_util/props-util'; import { getComponent, getSlot } from '../../../../_util/props-util';
import getTransitionProps from '../../../../_util/getTransitionProps';
import BaseMixin from '../../../../_util/BaseMixin'; import BaseMixin from '../../../../_util/BaseMixin';
const TREE_SELECT_EMPTY_VALUE_KEY = 'RC_TREE_SELECT_EMPTY_VALUE_KEY'; const TREE_SELECT_EMPTY_VALUE_KEY = 'RC_TREE_SELECT_EMPTY_VALUE_KEY';
@ -73,7 +72,7 @@ const MultipleSelector = {
display: hidden ? 'none' : 'block', display: hidden ? 'none' : 'block',
}} }}
onClick={this.onPlaceholderClick} onClick={this.onPlaceholderClick}
class={`${prefixCls}-search__field__placeholder`} class={`${prefixCls}-selection-placeholder`}
> >
{currentPlaceholder} {currentPlaceholder}
</span> </span>
@ -85,8 +84,6 @@ const MultipleSelector = {
renderSelection() { renderSelection() {
const { const {
selectorValueList, selectorValueList,
choiceTransitionName,
prefixCls,
labelInValue, labelInValue,
maxTagCount, maxTagCount,
} = this.$props; } = this.$props;
@ -144,7 +141,6 @@ const MultipleSelector = {
} }
selectedValueNodes.push( selectedValueNodes.push(
<li class={`${prefixCls}-search ${prefixCls}-search--inline`} key="__input">
<SearchInput <SearchInput
{...{ {...{
...this.$props, ...this.$props,
@ -154,26 +150,10 @@ const MultipleSelector = {
ref={this.inputRef} ref={this.inputRef}
> >
{children} {children}
</SearchInput> </SearchInput>,
</li>,
);
const className = `${prefixCls}-selection__rendered`;
if (choiceTransitionName) {
const transitionProps = getTransitionProps(choiceTransitionName, {
tag: 'ul',
onAfterLeave: this.onChoiceAnimationLeave,
});
return (
<TransitionGroup class={className} {...transitionProps}>
{selectedValueNodes}
</TransitionGroup>
);
}
return (
<ul class={className} role="menubar">
{selectedValueNodes}
</ul>
); );
return selectedValueNodes;
}, },
}, },

View File

@ -21,24 +21,20 @@ const SingleSelector = {
renderSelection() { renderSelection() {
const { selectorValueList, placeholder, prefixCls } = this.$props; const { selectorValueList, placeholder, prefixCls } = this.$props;
let innerNode;
if (selectorValueList.length) { if (selectorValueList.length) {
const { label, value } = selectorValueList[0]; const { label, value } = selectorValueList[0];
innerNode = ( return (
<span key="value" title={toTitle(label)} class={`${prefixCls}-selection-selected-value`}> <span key="value" title={toTitle(label)} class={`${prefixCls}-selection-item`}>
{label || value} {label || value}
</span> </span>
); );
} else { } else {
innerNode = ( return (
<span key="placeholder" class={`${prefixCls}-selection__placeholder`}> <span key="placeholder" class={`${prefixCls}-selection-placeholder`}>
{placeholder} {placeholder}
</span> </span>
); );
} }
return <span class={`${prefixCls}-selection__rendered`}>{innerNode}</span>;
}, },
}, },