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 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 isValid from './isValid';
// function getType(fn) {
@ -40,7 +49,7 @@ const parseStyleText = (cssText = '', camel) => {
return res;
};
const hasProp = (instance, prop) => {
const hasProp = (instance: VNode, prop: string) => {
return prop in getOptionProps(instance);
};
// 重构后直接使用 hasProp 替换
@ -115,14 +124,14 @@ const getAllChildren = ele => {
const getSlotOptions = () => {
throw Error('使用 .type 直接取值');
};
const findDOMNode = instance => {
const findDOMNode = (instance: ComponentPublicInstance) => {
let node = instance && (instance.$el || instance);
while (node && !node.tagName) {
node = node.nextSibling;
}
return node;
};
const getOptionProps = instance => {
const getOptionProps = (instance: ComponentPublicInstance) => {
const res = {};
if (instance.$ && instance.$.vnode) {
const props = instance.$.vnode.props || {};
@ -149,7 +158,12 @@ const getOptionProps = instance => {
}
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;
if (instance.$) {
const temp = instance[prop];
@ -228,7 +242,7 @@ const getAllProps = ele => {
return props;
};
const getPropsData = ins => {
const getPropsData = (ins: ComponentPublicInstance) => {
const vnode = ins.$ ? ins.$ : ins;
const res = {};
const originProps = vnode.props || {};
@ -333,7 +347,7 @@ export function isFragment(c) {
return c.length === 1 && c[0].type === Fragment;
}
export function isEmptyElement(c) {
export function isEmptyElement(c: VNode) {
return (
c.type === Comment ||
(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;
}
@ -373,22 +387,6 @@ const initDefaultProps = <T>(
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) {
return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node
}

View File

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

View File

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

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 { ConfigConsumerProps } from '../config-provider';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
@ -13,81 +13,74 @@ export interface TransferLocale {
description: string;
}
const Empty = defineComponent({
name: 'AEmpty',
props: {
prefixCls: {
type: String,
},
imageStyle: {
type: Object as PropType<string | CSSProperties>,
},
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;
export interface EmptyProps {
prefixCls?: string;
class?: string;
style?: CSSProperties;
imageStyle?: CSSProperties;
image?: VNodeChild | JSX.Element;
description?: VNodeChild | JSX.Element;
children?: VNodeChild | JSX.Element;
}
return () => (
<LocaleReceiver
componentName="Empty"
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: any = null;
const Empty = (props: EmptyProps, { slots }: SetupContext) => {
const configProvider = inject('configProvider', ConfigConsumerProps);
const { getPrefixCls } = configProvider;
const {
prefixCls: customizePrefixCls,
class: className,
image = defaultEmptyImg,
description,
imageStyle,
...restProps
} = props;
if (typeof image === 'string') {
imageNode = <img alt={alt} src={image} />;
} else {
imageNode = image;
}
return () => (
<LocaleReceiver
componentName="Empty"
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 (
<div
class={classNames(
prefixCls,
{
[`${prefixCls}-normal`]: image === simpleEmptyImg,
},
className,
)}
{...restProps}
>
<div class={`${prefixCls}-image`} style={imageStyle}>
{imageNode}
</div>
{des && <p class={`${prefixCls}-description`}>{des}</p>}
{slots.default && (
<div class={`${prefixCls}-footer`}>{filterEmpty(slots.default?.())}</div>
)}
if (typeof image === 'string') {
imageNode = <img alt={alt} src={image} />;
} else {
imageNode = image;
}
return (
<div
class={classNames(
prefixCls,
{
[`${prefixCls}-normal`]: image === simpleEmptyImg,
},
className,
)}
{...restProps}
>
<div class={`${prefixCls}-image`} style={imageStyle}>
{imageNode}
</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_SIMPLE = simpleEmptyImg;
/* istanbul ignore next */
Empty.install = function(app: App) {
app.component(Empty.name, Empty);
app.component('AEmpty', 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 PropTypes from '../_util/vue-types';
import { filterEmpty } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider';
export const SpaceProps = {
prefixCls: PropTypes.string,
align: PropTypes.tuple<'start' | 'end' | 'center' | 'baseline'>(),
size: PropTypes.tuple<'small' | 'middle' | 'large'>(),
direction: PropTypes.tuple<'horizontal' | 'vertical'>(),
};
// export const SpaceProps = {
// prefixCls: PropTypes.string,
// align: PropTypes.tuple<'start' | 'end' | 'center' | 'baseline'>(),
// size: PropTypes.tuple<'small' | 'middle' | 'large'>(),
// direction: PropTypes.tuple<'horizontal' | 'vertical'>(),
// };
const spaceSize = {
small: 8,
@ -17,36 +16,39 @@ const spaceSize = {
large: 24,
};
// export const SpaceProps = {
// prefixCls: PropTypes.string,
// size: SpaceSizeType,
// direction: PropTypes.oneOf(['horizontal', 'vertical']),
// align: PropTypes.oneOf(['start', 'end', 'center', 'baseline']),
// };
export interface SpaceProps {
prefixCls?: string;
className?: string;
style?: CSSProperties;
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 { align, size, direction, prefixCls: customizePrefixCls } = props;
const { getPrefixCls } = configProvider;
const prefixCls = getPrefixCls('space', customizePrefixCls);
const items = filterEmpty(slots.default?.());
const len = items.length;
const { getPrefixCls } = configProvider;
const prefixCls = getPrefixCls('space', customizePrefixCls);
const items = filterEmpty(slots.default?.());
const len = items.length;
if (len === 0) {
return null;
}
if (len === 0) {
return null;
}
const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align;
const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align;
const someSpaceClass = {
[prefixCls]: true,
[`${prefixCls}-${direction}`]: true,
[`${prefixCls}-align-${mergedAlign}`]: mergedAlign,
};
const someSpaceClass = {
[prefixCls]: true,
[`${prefixCls}-${direction}`]: true,
[`${prefixCls}-align-${mergedAlign}`]: mergedAlign,
};
const itemClassName = `${prefixCls}-item`;
const marginDirection = 'marginRight'; // directionConfig === 'rtl' ? 'marginLeft' : 'marginRight';
const itemClassName = `${prefixCls}-item`;
const marginDirection = 'marginRight'; // directionConfig === 'rtl' ? 'marginLeft' : 'marginRight';
return (
<div class={someSpaceClass}>
@ -75,7 +77,8 @@ Space.props = initDefaultProps(SpaceProps, {
});
/* istanbul ignore next */
Space.install = function(app) {
Space.install = function(app: App) {
app.component('ASpace', Space);
};
export default Space;