181 lines
4.9 KiB
JavaScript
181 lines
4.9 KiB
JavaScript
"use client";
|
|
|
|
import * as React from 'react';
|
|
import { clsx } from 'clsx';
|
|
import { useMergeSemantic } from '../_util/hooks';
|
|
import { isPlainObject } from '../_util/is';
|
|
import { useComponentConfig } from '../config-provider/context';
|
|
import SkeletonAvatar from './Avatar';
|
|
import SkeletonButton from './Button';
|
|
import Element from './Element';
|
|
import SkeletonImage from './Image';
|
|
import SkeletonInput from './Input';
|
|
import SkeletonNode from './Node';
|
|
import Paragraph from './Paragraph';
|
|
import useStyle from './style';
|
|
import Title from './Title';
|
|
function getComponentProps(prop) {
|
|
if (isPlainObject(prop)) {
|
|
return prop;
|
|
}
|
|
return {};
|
|
}
|
|
function getAvatarBasicProps(hasTitle, hasParagraph) {
|
|
if (hasTitle && !hasParagraph) {
|
|
// Square avatar
|
|
return {
|
|
size: 'large',
|
|
shape: 'square'
|
|
};
|
|
}
|
|
return {
|
|
size: 'large',
|
|
shape: 'circle'
|
|
};
|
|
}
|
|
function getTitleBasicProps(hasAvatar, hasParagraph) {
|
|
if (!hasAvatar && hasParagraph) {
|
|
return {
|
|
width: '38%'
|
|
};
|
|
}
|
|
if (hasAvatar && hasParagraph) {
|
|
return {
|
|
width: '50%'
|
|
};
|
|
}
|
|
return {};
|
|
}
|
|
function getParagraphBasicProps(hasAvatar, hasTitle) {
|
|
const basicProps = {};
|
|
// Width
|
|
if (!hasAvatar || !hasTitle) {
|
|
basicProps.width = '61%';
|
|
}
|
|
// Rows
|
|
if (!hasAvatar && hasTitle) {
|
|
basicProps.rows = 3;
|
|
} else {
|
|
basicProps.rows = 2;
|
|
}
|
|
return basicProps;
|
|
}
|
|
// Tips: ctx.classNames.root < ctx.className < cpns.classNames.root < cpns.className < rootClassName
|
|
const Skeleton = props => {
|
|
const {
|
|
prefixCls: customizePrefixCls,
|
|
loading,
|
|
className,
|
|
rootClassName,
|
|
classNames,
|
|
style,
|
|
styles,
|
|
children,
|
|
avatar = false,
|
|
title = true,
|
|
paragraph = true,
|
|
active,
|
|
round
|
|
} = props;
|
|
const {
|
|
getPrefixCls,
|
|
direction,
|
|
className: contextClassName,
|
|
style: contextStyle,
|
|
classNames: contextClassNames,
|
|
styles: contextStyles
|
|
} = useComponentConfig('skeleton');
|
|
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
|
const [hashId, cssVarCls] = useStyle(prefixCls);
|
|
const mergedProps = {
|
|
...props,
|
|
avatar,
|
|
title,
|
|
paragraph
|
|
};
|
|
const [mergedClassNames, mergedStyles] = useMergeSemantic([contextClassNames, classNames], [contextStyles, styles], {
|
|
props: mergedProps
|
|
});
|
|
if (loading || !('loading' in props)) {
|
|
const hasAvatar = !!avatar;
|
|
const hasTitle = !!title;
|
|
const hasParagraph = !!paragraph;
|
|
// Avatar
|
|
let avatarNode;
|
|
if (hasAvatar) {
|
|
const avatarProps = {
|
|
className: mergedClassNames.avatar,
|
|
prefixCls: `${prefixCls}-avatar`,
|
|
...getAvatarBasicProps(hasTitle, hasParagraph),
|
|
...getComponentProps(avatar),
|
|
style: mergedStyles.avatar
|
|
};
|
|
// We direct use SkeletonElement as avatar in skeleton internal.
|
|
avatarNode = /*#__PURE__*/React.createElement("div", {
|
|
className: clsx(mergedClassNames.header, `${prefixCls}-header`),
|
|
style: mergedStyles.header
|
|
}, /*#__PURE__*/React.createElement(Element, {
|
|
...avatarProps
|
|
}));
|
|
}
|
|
let contentNode;
|
|
if (hasTitle || hasParagraph) {
|
|
// Title
|
|
let $title;
|
|
if (hasTitle) {
|
|
const titleProps = {
|
|
className: mergedClassNames.title,
|
|
prefixCls: `${prefixCls}-title`,
|
|
...getTitleBasicProps(hasAvatar, hasParagraph),
|
|
...getComponentProps(title),
|
|
style: mergedStyles.title
|
|
};
|
|
$title = /*#__PURE__*/React.createElement(Title, {
|
|
...titleProps
|
|
});
|
|
}
|
|
// Paragraph
|
|
let paragraphNode;
|
|
if (hasParagraph) {
|
|
const paragraphProps = {
|
|
className: mergedClassNames.paragraph,
|
|
prefixCls: `${prefixCls}-paragraph`,
|
|
...getParagraphBasicProps(hasAvatar, hasTitle),
|
|
...getComponentProps(paragraph),
|
|
style: mergedStyles.paragraph
|
|
};
|
|
paragraphNode = /*#__PURE__*/React.createElement(Paragraph, {
|
|
...paragraphProps
|
|
});
|
|
}
|
|
contentNode = /*#__PURE__*/React.createElement("div", {
|
|
className: clsx(mergedClassNames.section, `${prefixCls}-section`),
|
|
style: mergedStyles.section
|
|
}, $title, paragraphNode);
|
|
}
|
|
const cls = clsx(prefixCls, {
|
|
[`${prefixCls}-with-avatar`]: hasAvatar,
|
|
[`${prefixCls}-active`]: active,
|
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
|
[`${prefixCls}-round`]: round
|
|
}, mergedClassNames.root, contextClassName, className, rootClassName, hashId, cssVarCls);
|
|
return /*#__PURE__*/React.createElement("div", {
|
|
className: cls,
|
|
style: {
|
|
...mergedStyles.root,
|
|
...contextStyle,
|
|
...style
|
|
}
|
|
}, avatarNode, contentNode);
|
|
}
|
|
return children ?? null;
|
|
};
|
|
Skeleton.Button = SkeletonButton;
|
|
Skeleton.Avatar = SkeletonAvatar;
|
|
Skeleton.Input = SkeletonInput;
|
|
Skeleton.Image = SkeletonImage;
|
|
Skeleton.Node = SkeletonNode;
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
Skeleton.displayName = 'Skeleton';
|
|
}
|
|
export default Skeleton; |