chore: update empty and space

pull/2926/head
Amour1688 2020-08-23 16:45:55 +08:00
parent 2397fb931c
commit 91fe27d12c
5 changed files with 141 additions and 149 deletions

View File

@ -1,6 +1,15 @@
import isPlainObject from 'lodash/isPlainObject'; import isPlainObject from 'lodash/isPlainObject';
import classNames from 'classnames'; import classNames from 'classnames';
import { isVNode, Fragment, Comment, Text, h, VNode, Prop, PropOptions } from 'vue'; import {
isVNode,
Fragment,
Comment,
Text,
h,
VNode,
ComponentPublicInstance,
PropOptions,
} from 'vue';
import { camelize, hyphenate, isOn, resolvePropValue } from './util'; import { camelize, hyphenate, isOn, resolvePropValue } from './util';
import isValid from './isValid'; import isValid from './isValid';
// function getType(fn) { // function getType(fn) {
@ -40,7 +49,7 @@ const parseStyleText = (cssText = '', camel) => {
return res; return res;
}; };
const hasProp = (instance, prop) => { const hasProp = (instance: VNode, prop: string) => {
return prop in getOptionProps(instance); return prop in getOptionProps(instance);
}; };
// 重构后直接使用 hasProp 替换 // 重构后直接使用 hasProp 替换
@ -115,14 +124,14 @@ const getAllChildren = ele => {
const getSlotOptions = () => { const getSlotOptions = () => {
throw Error('使用 .type 直接取值'); throw Error('使用 .type 直接取值');
}; };
const findDOMNode = instance => { const findDOMNode = (instance: ComponentPublicInstance) => {
let node = instance && (instance.$el || instance); let node = instance && (instance.$el || instance);
while (node && !node.tagName) { while (node && !node.tagName) {
node = node.nextSibling; node = node.nextSibling;
} }
return node; return node;
}; };
const getOptionProps = instance => { const getOptionProps = (instance: ComponentPublicInstance) => {
const res = {}; const res = {};
if (instance.$ && instance.$.vnode) { if (instance.$ && instance.$.vnode) {
const props = instance.$.vnode.props || {}; const props = instance.$.vnode.props || {};
@ -149,7 +158,12 @@ const getOptionProps = instance => {
} }
return res; return res;
}; };
const getComponent = (instance, prop = 'default', options = instance, execute = true) => { const getComponent = (
instance: ComponentPublicInstance,
prop: string = 'default',
options = instance,
execute: boolean = true,
) => {
let com = undefined; let com = undefined;
if (instance.$) { if (instance.$) {
const temp = instance[prop]; const temp = instance[prop];
@ -228,7 +242,7 @@ const getAllProps = ele => {
return props; return props;
}; };
const getPropsData = ins => { const getPropsData = (ins: ComponentPublicInstance) => {
const vnode = ins.$ ? ins.$ : ins; const vnode = ins.$ ? ins.$ : ins;
const res = {}; const res = {};
const originProps = vnode.props || {}; const originProps = vnode.props || {};
@ -333,7 +347,7 @@ export function isFragment(c) {
return c.length === 1 && c[0].type === Fragment; return c.length === 1 && c[0].type === Fragment;
} }
export function isEmptyElement(c) { export function isEmptyElement(c: VNode) {
return ( return (
c.type === Comment || c.type === Comment ||
(c.type === Fragment && c.children.length === 0) || (c.type === Fragment && c.children.length === 0) ||
@ -341,7 +355,7 @@ export function isEmptyElement(c) {
); );
} }
export function isStringElement(c) { export function isStringElement(c: VNode): boolean {
return c && c.type === Text; return c && c.type === Text;
} }
@ -373,22 +387,6 @@ const initDefaultProps = <T>(
return propTypes; return propTypes;
}; };
export function mergeProps() {
const args = [].slice.call(arguments, 0);
const props = {};
args.forEach((p = {}) => {
for (const [k, v] of Object.entries(p)) {
props[k] = props[k] || {};
if (isPlainObject(v)) {
Object.assign(props[k], v);
} else {
props[k] = v;
}
}
});
return props;
}
function isValidElement(element) { function isValidElement(element) {
return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node
} }

View File

@ -70,7 +70,7 @@ const ConfigProvider = {
}; };
export const ConfigConsumerProps = { export const ConfigConsumerProps = {
getPrefixCls: (suffixCls, customizePrefixCls) => { getPrefixCls: (suffixCls: string, customizePrefixCls?: string) => {
if (customizePrefixCls) return customizePrefixCls; if (customizePrefixCls) return customizePrefixCls;
return `ant-${suffixCls}`; return `ant-${suffixCls}`;
}, },

View File

@ -1,38 +1,36 @@
import { inject } from 'vue'; import { inject } from 'vue';
import PropTypes from '../_util/vue-types';
import Empty from '../empty'; import Empty from '../empty';
import { ConfigConsumerProps } from './'; import { ConfigConsumerProps } from '.';
const RenderEmpty = { export interface RenderEmptyProps {
props: { componentName?: string;
componentName: PropTypes.string, }
},
setup(props) {
const configProvider = inject('configProvider', ConfigConsumerProps);
function renderHtml(componentName: string) {
const getPrefixCls = configProvider.getPrefixCls;
const prefix = getPrefixCls('empty');
switch (componentName) {
case 'Table':
case 'List':
return <Empty image={<Empty.PRESENTED_IMAGE_SIMPLE />} />;
case 'Select': const RenderEmpty = (props: RenderEmptyProps) => {
case 'TreeSelect': const configProvider = inject('configProvider', ConfigConsumerProps);
case 'Cascader': const renderHtml = (componentName?: string) => {
case 'Transfer': const { getPrefixCls } = configProvider;
case 'Mentions': const prefix = getPrefixCls('empty');
return <Empty image={<Empty.PRESENTED_IMAGE_SIMPLE />} class={`${prefix}-small`} />; switch (componentName) {
case 'Table':
case 'List':
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
default: case 'Select':
return <Empty />; case 'TreeSelect':
} case 'Cascader':
case 'Transfer':
case 'Mentions':
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} class={`${prefix}-small`} />;
default:
return <Empty />;
} }
return () => renderHtml(props.componentName); };
}, return () => renderHtml(props.componentName);
}; };
function renderEmpty(componentName) { function renderEmpty(componentName?: string) {
return <RenderEmpty componentName={componentName} />; return <RenderEmpty componentName={componentName} />;
} }

View File

@ -1,4 +1,4 @@
import { defineComponent, CSSProperties, VNodeChild, inject, App, PropType, VNode } from 'vue'; import { CSSProperties, VNodeChild, inject, App, SetupContext } from 'vue';
import classNames from 'classnames'; import classNames from 'classnames';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
@ -13,81 +13,74 @@ export interface TransferLocale {
description: string; description: string;
} }
const Empty = defineComponent({ export interface EmptyProps {
name: 'AEmpty', prefixCls?: string;
props: { class?: string;
prefixCls: { style?: CSSProperties;
type: String, imageStyle?: CSSProperties;
}, image?: VNodeChild | JSX.Element;
imageStyle: { description?: VNodeChild | JSX.Element;
type: Object as PropType<string | CSSProperties>, children?: VNodeChild | JSX.Element;
}, }
image: {
type: Object as PropType<VNode>,
},
description: {
type: String,
},
},
setup(props, { slots }) {
const configProvider = inject('configProvider', ConfigConsumerProps);
const { getPrefixCls } = configProvider;
const {
class: className,
prefixCls: customizePrefixCls,
image = defaultEmptyImg,
description,
imageStyle,
...restProps
} = props;
return () => ( const Empty = (props: EmptyProps, { slots }: SetupContext) => {
<LocaleReceiver const configProvider = inject('configProvider', ConfigConsumerProps);
componentName="Empty" const { getPrefixCls } = configProvider;
children={(locale: TransferLocale) => { const {
const prefixCls = getPrefixCls('empty', customizePrefixCls); prefixCls: customizePrefixCls,
const des = typeof description !== 'undefined' ? description : locale.description; class: className,
const alt = typeof des === 'string' ? des : 'empty'; image = defaultEmptyImg,
let imageNode: any = null; description,
imageStyle,
...restProps
} = props;
if (typeof image === 'string') { return () => (
imageNode = <img alt={alt} src={image} />; <LocaleReceiver
} else { componentName="Empty"
imageNode = image; children={(locale: TransferLocale) => {
} const prefixCls = getPrefixCls('empty', customizePrefixCls);
const des = typeof description !== 'undefined' ? description : locale.description;
const alt = typeof des === 'string' ? des : 'empty';
let imageNode: EmptyProps['image'] = null;
return ( if (typeof image === 'string') {
<div imageNode = <img alt={alt} src={image} />;
class={classNames( } else {
prefixCls, imageNode = image;
{ }
[`${prefixCls}-normal`]: image === simpleEmptyImg,
}, return (
className, <div
)} class={classNames(
{...restProps} prefixCls,
> {
<div class={`${prefixCls}-image`} style={imageStyle}> [`${prefixCls}-normal`]: image === simpleEmptyImg,
{imageNode} },
</div> className,
{des && <p class={`${prefixCls}-description`}>{des}</p>} )}
{slots.default && ( {...restProps}
<div class={`${prefixCls}-footer`}>{filterEmpty(slots.default?.())}</div> >
)} <div class={`${prefixCls}-image`} style={imageStyle}>
{imageNode}
</div> </div>
) as VNodeChild; {des && <p class={`${prefixCls}-description`}>{des}</p>}
}} {slots.default && (
/> <div class={`${prefixCls}-footer`}>{filterEmpty(slots.default())}</div>
); )}
}, </div>
}); ) as VNodeChild;
}}
/>
);
};
Empty.PRESENTED_IMAGE_DEFAULT = defaultEmptyImg; Empty.PRESENTED_IMAGE_DEFAULT = defaultEmptyImg;
Empty.PRESENTED_IMAGE_SIMPLE = simpleEmptyImg; Empty.PRESENTED_IMAGE_SIMPLE = simpleEmptyImg;
/* istanbul ignore next */ /* istanbul ignore next */
Empty.install = function(app: App) { Empty.install = function(app: App) {
app.component(Empty.name, Empty); app.component('AEmpty', Empty);
}; };
export default Empty; export default Empty;

View File

@ -1,15 +1,14 @@
import { inject, defineComponent, App } from 'vue'; import { inject, App, CSSProperties, SetupContext } from 'vue';
import { initDefaultProps } from '../_util/props-util'; import { initDefaultProps } from '../_util/props-util';
import PropTypes from '../_util/vue-types';
import { filterEmpty } from '../_util/props-util'; import { filterEmpty } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
export const SpaceProps = { // export const SpaceProps = {
prefixCls: PropTypes.string, // prefixCls: PropTypes.string,
align: PropTypes.tuple<'start' | 'end' | 'center' | 'baseline'>(), // align: PropTypes.tuple<'start' | 'end' | 'center' | 'baseline'>(),
size: PropTypes.tuple<'small' | 'middle' | 'large'>(), // size: PropTypes.tuple<'small' | 'middle' | 'large'>(),
direction: PropTypes.tuple<'horizontal' | 'vertical'>(), // direction: PropTypes.tuple<'horizontal' | 'vertical'>(),
}; // };
const spaceSize = { const spaceSize = {
small: 8, small: 8,
@ -17,36 +16,39 @@ const spaceSize = {
large: 24, large: 24,
}; };
// export const SpaceProps = { export interface SpaceProps {
// prefixCls: PropTypes.string, prefixCls?: string;
// size: SpaceSizeType, className?: string;
// direction: PropTypes.oneOf(['horizontal', 'vertical']), style?: CSSProperties;
// align: PropTypes.oneOf(['start', 'end', 'center', 'baseline']), size?: SizeType | number;
// }; direction?: 'horizontal' | 'vertical';
// No `stretch` since many components do not support that.
align?: 'start' | 'end' | 'center' | 'baseline';
}
const Space = (props, { slots }) => { const Space = (props: SpaceProps, { slots }: SetupContext) => {
const configProvider = inject('configProvider', ConfigConsumerProps); const configProvider = inject('configProvider', ConfigConsumerProps);
const { align, size, direction, prefixCls: customizePrefixCls } = props; const { align, size, direction, prefixCls: customizePrefixCls } = props;
const { getPrefixCls } = configProvider; const { getPrefixCls } = configProvider;
const prefixCls = getPrefixCls('space', customizePrefixCls); const prefixCls = getPrefixCls('space', customizePrefixCls);
const items = filterEmpty(slots.default?.()); const items = filterEmpty(slots.default?.());
const len = items.length; const len = items.length;
if (len === 0) { if (len === 0) {
return null; return null;
} }
const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align; const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align;
const someSpaceClass = { const someSpaceClass = {
[prefixCls]: true, [prefixCls]: true,
[`${prefixCls}-${direction}`]: true, [`${prefixCls}-${direction}`]: true,
[`${prefixCls}-align-${mergedAlign}`]: mergedAlign, [`${prefixCls}-align-${mergedAlign}`]: mergedAlign,
}; };
const itemClassName = `${prefixCls}-item`; const itemClassName = `${prefixCls}-item`;
const marginDirection = 'marginRight'; // directionConfig === 'rtl' ? 'marginLeft' : 'marginRight'; const marginDirection = 'marginRight'; // directionConfig === 'rtl' ? 'marginLeft' : 'marginRight';
return ( return (
<div class={someSpaceClass}> <div class={someSpaceClass}>
@ -75,7 +77,8 @@ Space.props = initDefaultProps(SpaceProps, {
}); });
/* istanbul ignore next */ /* istanbul ignore next */
Space.install = function(app) { Space.install = function(app: App) {
app.component('ASpace', Space); app.component('ASpace', Space);
}; };
export default Space; export default Space;