1
This commit is contained in:
+7
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import type { SkeletonElementProps } from './Element';
|
||||
export interface AvatarProps extends Omit<SkeletonElementProps, 'shape'> {
|
||||
shape?: 'circle' | 'square';
|
||||
}
|
||||
declare const SkeletonAvatar: React.FC<AvatarProps>;
|
||||
export default SkeletonAvatar;
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import useSize from '../config-provider/hooks/useSize';
|
||||
import Element from './Element';
|
||||
import useStyle from './style';
|
||||
const SkeletonAvatar = props => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
classNames,
|
||||
rootClassName,
|
||||
active,
|
||||
style,
|
||||
styles,
|
||||
shape = 'circle',
|
||||
size: customSize,
|
||||
...rest
|
||||
} = props;
|
||||
const {
|
||||
getPrefixCls
|
||||
} = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const [hashId, cssVarCls] = useStyle(prefixCls);
|
||||
const mergedSize = useSize(ctx => customSize ?? ctx);
|
||||
const cls = clsx(prefixCls, `${prefixCls}-element`, {
|
||||
[`${prefixCls}-active`]: active
|
||||
}, classNames?.root, className, rootClassName, hashId, cssVarCls);
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
className: cls,
|
||||
style: styles?.root
|
||||
}, /*#__PURE__*/React.createElement(Element, {
|
||||
prefixCls: `${prefixCls}-avatar`,
|
||||
className: classNames?.content,
|
||||
style: {
|
||||
...styles?.content,
|
||||
...style
|
||||
},
|
||||
shape: shape,
|
||||
size: mergedSize,
|
||||
...rest
|
||||
}));
|
||||
};
|
||||
export default SkeletonAvatar;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import type { SizeType } from '../config-provider/SizeContext';
|
||||
import type { SkeletonElementProps } from './Element';
|
||||
export interface SkeletonButtonProps extends Omit<SkeletonElementProps, 'size'> {
|
||||
/**
|
||||
* Note: `default` is deprecated and will be removed in v7, please use `medium` instead.
|
||||
*/
|
||||
size?: SizeType | 'default';
|
||||
block?: boolean;
|
||||
}
|
||||
declare const SkeletonButton: React.FC<SkeletonButtonProps>;
|
||||
export default SkeletonButton;
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import useSize from '../config-provider/hooks/useSize';
|
||||
import Element from './Element';
|
||||
import useStyle from './style';
|
||||
const SkeletonButton = props => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
rootClassName,
|
||||
classNames,
|
||||
active,
|
||||
style,
|
||||
styles,
|
||||
block = false,
|
||||
size: customSize,
|
||||
...rest
|
||||
} = props;
|
||||
const {
|
||||
getPrefixCls
|
||||
} = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const [hashId, cssVarCls] = useStyle(prefixCls);
|
||||
const mergedSize = useSize(ctx => customSize ?? ctx);
|
||||
const cls = clsx(prefixCls, `${prefixCls}-element`, {
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-block`]: block
|
||||
}, classNames?.root, className, rootClassName, hashId, cssVarCls);
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
className: cls,
|
||||
style: styles?.root
|
||||
}, /*#__PURE__*/React.createElement(Element, {
|
||||
prefixCls: `${prefixCls}-button`,
|
||||
className: classNames?.content,
|
||||
style: {
|
||||
...styles?.content,
|
||||
...style
|
||||
},
|
||||
size: mergedSize,
|
||||
...rest
|
||||
}));
|
||||
};
|
||||
export default SkeletonButton;
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import * as React from 'react';
|
||||
import type { SizeType } from '../config-provider/SizeContext';
|
||||
export type ElementSemanticName = keyof ElementSemanticClassNames & keyof ElementSemanticStyles;
|
||||
export type ElementSemanticClassNames = {
|
||||
root?: string;
|
||||
content?: string;
|
||||
};
|
||||
export type ElementSemanticStyles = {
|
||||
root?: React.CSSProperties;
|
||||
content?: React.CSSProperties;
|
||||
};
|
||||
export interface SkeletonElementProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
rootClassName?: string;
|
||||
style?: React.CSSProperties;
|
||||
/**
|
||||
* Note: `default` is deprecated and will be removed in v7, please use `medium` instead.
|
||||
*/
|
||||
size?: SizeType | number | 'default';
|
||||
shape?: 'circle' | 'square' | 'round' | 'default';
|
||||
active?: boolean;
|
||||
classNames?: ElementSemanticClassNames;
|
||||
styles?: ElementSemanticStyles;
|
||||
}
|
||||
declare const Element: React.FC<SkeletonElementProps>;
|
||||
export default Element;
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { isNumber } from '../_util/is';
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
const Element = props => {
|
||||
const {
|
||||
prefixCls,
|
||||
className,
|
||||
style,
|
||||
size,
|
||||
shape
|
||||
} = props;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const warning = devUseWarning('Skeleton');
|
||||
warning.deprecated(size !== 'default', 'size="default"', 'size="medium"');
|
||||
}
|
||||
const sizeCls = clsx({
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
[`${prefixCls}-sm`]: size === 'small'
|
||||
});
|
||||
const shapeCls = clsx({
|
||||
[`${prefixCls}-circle`]: shape === 'circle',
|
||||
[`${prefixCls}-square`]: shape === 'square',
|
||||
[`${prefixCls}-round`]: shape === 'round'
|
||||
});
|
||||
const sizeStyle = React.useMemo(() => isNumber(size) ? {
|
||||
width: size,
|
||||
height: size,
|
||||
lineHeight: `${size}px`
|
||||
} : {}, [size]);
|
||||
return /*#__PURE__*/React.createElement("span", {
|
||||
className: clsx(prefixCls, sizeCls, shapeCls, className),
|
||||
style: {
|
||||
...sizeStyle,
|
||||
...style
|
||||
}
|
||||
});
|
||||
};
|
||||
export default Element;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import type { SkeletonNodeProps } from './Node';
|
||||
export interface SkeletonImageProps extends Omit<SkeletonNodeProps, 'children' | 'internalClassName'> {
|
||||
}
|
||||
declare const SkeletonImage: React.FC<SkeletonImageProps>;
|
||||
export default SkeletonImage;
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import SkeletonNode from './Node';
|
||||
const SkeletonImage = props => {
|
||||
const {
|
||||
getPrefixCls
|
||||
} = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', props.prefixCls);
|
||||
return /*#__PURE__*/React.createElement(SkeletonNode, {
|
||||
...props,
|
||||
internalClassName: `${prefixCls}-image`
|
||||
}, /*#__PURE__*/React.createElement("svg", {
|
||||
viewBox: "0 0 1098 1024",
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
className: `${prefixCls}-image-svg`
|
||||
}, /*#__PURE__*/React.createElement("title", null, "Image placeholder"), /*#__PURE__*/React.createElement("path", {
|
||||
d: "M365.7 329.1q0 45.8-32 77.7t-77.7 32-77.7-32-32-77.7 32-77.6 77.7-32 77.7 32 32 77.6M951 548.6v256H146.3V694.9L329 512l91.5 91.4L713 311zm54.8-402.3H91.4q-7.4 0-12.8 5.4T73 164.6v694.8q0 7.5 5.5 12.9t12.8 5.4h914.3q7.5 0 12.9-5.4t5.4-12.9V164.6q0-7.5-5.4-12.9t-12.9-5.4m91.4 18.3v694.8q0 37.8-26.8 64.6t-64.6 26.9H91.4q-37.7 0-64.6-26.9T0 859.4V164.6q0-37.8 26.8-64.6T91.4 73h914.3q37.8 0 64.6 26.9t26.8 64.6",
|
||||
className: `${prefixCls}-image-path`
|
||||
})));
|
||||
};
|
||||
export default SkeletonImage;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import type { SizeType } from '../config-provider/SizeContext';
|
||||
import type { SkeletonElementProps } from './Element';
|
||||
export interface SkeletonInputProps extends Omit<SkeletonElementProps, 'size' | 'shape'> {
|
||||
/**
|
||||
* Note: `default` is deprecated and will be removed in v7, please use `medium` instead.
|
||||
*/
|
||||
size?: SizeType | 'default';
|
||||
block?: boolean;
|
||||
}
|
||||
declare const SkeletonInput: React.FC<SkeletonInputProps>;
|
||||
export default SkeletonInput;
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import useSize from '../config-provider/hooks/useSize';
|
||||
import Element from './Element';
|
||||
import useStyle from './style';
|
||||
const SkeletonInput = props => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
classNames,
|
||||
rootClassName,
|
||||
active,
|
||||
block,
|
||||
style,
|
||||
styles,
|
||||
size: customSize,
|
||||
...rest
|
||||
} = props;
|
||||
const {
|
||||
getPrefixCls
|
||||
} = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const [hashId, cssVarCls] = useStyle(prefixCls);
|
||||
const mergedSize = useSize(ctx => customSize ?? ctx);
|
||||
const cls = clsx(prefixCls, `${prefixCls}-element`, {
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-block`]: block
|
||||
}, classNames?.root, className, rootClassName, hashId, cssVarCls);
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
className: cls,
|
||||
style: styles?.root
|
||||
}, /*#__PURE__*/React.createElement(Element, {
|
||||
prefixCls: `${prefixCls}-input`,
|
||||
className: classNames?.content,
|
||||
style: {
|
||||
...styles?.content,
|
||||
...style
|
||||
},
|
||||
size: mergedSize,
|
||||
...rest
|
||||
}));
|
||||
};
|
||||
export default SkeletonInput;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import type { SkeletonElementProps } from './Element';
|
||||
export interface SkeletonNodeProps extends Omit<SkeletonElementProps, 'size' | 'shape'> {
|
||||
children?: React.ReactNode;
|
||||
internalClassName?: string;
|
||||
}
|
||||
declare const SkeletonNode: React.FC<SkeletonNodeProps>;
|
||||
export default SkeletonNode;
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import useStyle from './style';
|
||||
const SkeletonNode = props => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
classNames,
|
||||
rootClassName,
|
||||
internalClassName,
|
||||
style,
|
||||
styles,
|
||||
active,
|
||||
children
|
||||
} = props;
|
||||
const {
|
||||
getPrefixCls
|
||||
} = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const [hashId, cssVarCls] = useStyle(prefixCls);
|
||||
const cls = clsx(prefixCls, `${prefixCls}-element`, {
|
||||
[`${prefixCls}-active`]: active
|
||||
}, hashId, classNames?.root, className, rootClassName, cssVarCls);
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
className: cls,
|
||||
style: styles?.root
|
||||
}, /*#__PURE__*/React.createElement("div", {
|
||||
className: clsx(classNames?.content, internalClassName || `${prefixCls}-node`),
|
||||
style: {
|
||||
...styles?.content,
|
||||
...style
|
||||
}
|
||||
}, children));
|
||||
};
|
||||
export default SkeletonNode;
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import * as React from 'react';
|
||||
type widthUnit = number | string;
|
||||
export interface SkeletonParagraphProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
width?: widthUnit | Array<widthUnit>;
|
||||
rows?: number;
|
||||
}
|
||||
declare const Paragraph: React.FC<SkeletonParagraphProps>;
|
||||
export default Paragraph;
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
const getWidth = (index, props) => {
|
||||
const {
|
||||
width,
|
||||
rows = 2
|
||||
} = props;
|
||||
if (Array.isArray(width)) {
|
||||
return width[index];
|
||||
}
|
||||
// last paragraph
|
||||
if (rows - 1 === index) {
|
||||
return width;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
const Paragraph = props => {
|
||||
const {
|
||||
prefixCls,
|
||||
className,
|
||||
style,
|
||||
rows = 0
|
||||
} = props;
|
||||
const rowList = Array.from({
|
||||
length: rows
|
||||
}).map((_, index) => (/*#__PURE__*/React.createElement("li", {
|
||||
key: index,
|
||||
style: {
|
||||
width: getWidth(index, props)
|
||||
}
|
||||
})));
|
||||
return /*#__PURE__*/React.createElement("ul", {
|
||||
className: clsx(prefixCls, className),
|
||||
style: style
|
||||
}, rowList);
|
||||
};
|
||||
export default Paragraph;
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import * as React from 'react';
|
||||
import type { SemanticClassNamesType, SemanticStylesType } from '../_util/hooks';
|
||||
import type { AvatarProps } from './Avatar';
|
||||
import SkeletonAvatar from './Avatar';
|
||||
import SkeletonButton from './Button';
|
||||
import SkeletonImage from './Image';
|
||||
import SkeletonInput from './Input';
|
||||
import SkeletonNode from './Node';
|
||||
import type { SkeletonParagraphProps } from './Paragraph';
|
||||
import type { SkeletonTitleProps } from './Title';
|
||||
type SkeletonAvatarProps = Omit<AvatarProps, 'active'>;
|
||||
export type SkeletonSemanticName = keyof SkeletonSemanticClassNames & keyof SkeletonSemanticStyles;
|
||||
export type SkeletonSemanticClassNames = {
|
||||
root?: string;
|
||||
header?: string;
|
||||
section?: string;
|
||||
avatar?: string;
|
||||
title?: string;
|
||||
paragraph?: string;
|
||||
};
|
||||
export type SkeletonSemanticStyles = {
|
||||
root?: React.CSSProperties;
|
||||
header?: React.CSSProperties;
|
||||
section?: React.CSSProperties;
|
||||
avatar?: React.CSSProperties;
|
||||
title?: React.CSSProperties;
|
||||
paragraph?: React.CSSProperties;
|
||||
};
|
||||
export type SkeletonClassNamesType = SemanticClassNamesType<SkeletonProps, SkeletonSemanticClassNames>;
|
||||
export type SkeletonStylesType = SemanticStylesType<SkeletonProps, SkeletonSemanticStyles>;
|
||||
export interface SkeletonProps {
|
||||
active?: boolean;
|
||||
loading?: boolean;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
rootClassName?: string;
|
||||
style?: React.CSSProperties;
|
||||
avatar?: SkeletonAvatarProps | boolean;
|
||||
title?: SkeletonTitleProps | boolean;
|
||||
paragraph?: SkeletonParagraphProps | boolean;
|
||||
round?: boolean;
|
||||
classNames?: SkeletonClassNamesType;
|
||||
styles?: SkeletonStylesType;
|
||||
}
|
||||
type CompoundedComponent = {
|
||||
Button: typeof SkeletonButton;
|
||||
Avatar: typeof SkeletonAvatar;
|
||||
Input: typeof SkeletonInput;
|
||||
Image: typeof SkeletonImage;
|
||||
Node: typeof SkeletonNode;
|
||||
};
|
||||
declare const Skeleton: React.FC<React.PropsWithChildren<SkeletonProps>> & CompoundedComponent;
|
||||
export default Skeleton;
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
"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;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
export interface SkeletonTitleProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
width?: number | string;
|
||||
}
|
||||
declare const Title: React.FC<SkeletonTitleProps>;
|
||||
export default Title;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
"use client";
|
||||
|
||||
/* eslint-disable jsx-a11y/heading-has-content */
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
const Title = ({
|
||||
prefixCls,
|
||||
className,
|
||||
width,
|
||||
style
|
||||
}) => (/*#__PURE__*/React.createElement("h3", {
|
||||
className: clsx(prefixCls, className),
|
||||
style: {
|
||||
width,
|
||||
...style
|
||||
}
|
||||
}));
|
||||
export default Title;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import Skeleton from './Skeleton';
|
||||
export type { SkeletonProps, SkeletonSemanticClassNames, SkeletonSemanticName, SkeletonSemanticStyles, } from './Skeleton';
|
||||
export default Skeleton;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import Skeleton from './Skeleton';
|
||||
export default Skeleton;
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import type { GetDefaultToken } from '../../theme/internal';
|
||||
export interface ComponentToken {
|
||||
/** @deprecated use gradientFromColor instead. */
|
||||
color: string;
|
||||
/** @deprecated use gradientToColor instead. */
|
||||
colorGradientEnd: string;
|
||||
/**
|
||||
* @desc 渐变色起点颜色
|
||||
* @descEN Start color of gradient
|
||||
*/
|
||||
gradientFromColor: string;
|
||||
/**
|
||||
* @desc 渐变色终点颜色
|
||||
* @descEN End color of gradient
|
||||
*/
|
||||
gradientToColor: string;
|
||||
/**
|
||||
* @desc 标题骨架屏高度
|
||||
* @descEN Height of title skeleton
|
||||
*/
|
||||
titleHeight: number | string;
|
||||
/**
|
||||
* @desc 骨架屏圆角
|
||||
* @descEN Border radius of skeleton
|
||||
*/
|
||||
blockRadius: number;
|
||||
/**
|
||||
* @desc 段落骨架屏上间距
|
||||
* @descEN Margin top of paragraph skeleton
|
||||
*/
|
||||
paragraphMarginTop: number;
|
||||
/**
|
||||
* @desc 段落骨架屏单行高度
|
||||
* @descEN Line height of paragraph skeleton
|
||||
*/
|
||||
paragraphLiHeight: number;
|
||||
}
|
||||
export declare const prepareComponentToken: GetDefaultToken<'Skeleton'>;
|
||||
declare const _default: (prefixCls: string, rootCls?: string) => readonly [string, string];
|
||||
export default _default;
|
||||
+358
@@ -0,0 +1,358 @@
|
||||
import { Keyframes, unit } from '@ant-design/cssinjs';
|
||||
import { genStyleHooks, mergeToken } from '../../theme/internal';
|
||||
const skeletonClsLoading = new Keyframes(`ant-skeleton-loading`, {
|
||||
'0%': {
|
||||
backgroundPosition: '100% 50%'
|
||||
},
|
||||
'100%': {
|
||||
backgroundPosition: '0 50%'
|
||||
}
|
||||
});
|
||||
const genSkeletonElementCommonSize = size => ({
|
||||
height: size,
|
||||
lineHeight: unit(size)
|
||||
});
|
||||
const genSkeletonElementSize = size => ({
|
||||
width: size,
|
||||
...genSkeletonElementCommonSize(size)
|
||||
});
|
||||
const genSkeletonColor = token => ({
|
||||
background: token.skeletonLoadingBackground,
|
||||
backgroundSize: '400% 100%',
|
||||
animationName: skeletonClsLoading,
|
||||
animationDuration: token.skeletonLoadingMotionDuration,
|
||||
animationTimingFunction: 'ease',
|
||||
animationIterationCount: 'infinite'
|
||||
});
|
||||
const genSkeletonElementInputSize = (size, calc) => ({
|
||||
width: calc(size).mul(5).equal(),
|
||||
minWidth: calc(size).mul(5).equal(),
|
||||
...genSkeletonElementCommonSize(size)
|
||||
});
|
||||
const genSkeletonElementAvatar = token => {
|
||||
const {
|
||||
skeletonAvatarCls,
|
||||
gradientFromColor,
|
||||
controlHeight,
|
||||
controlHeightLG,
|
||||
controlHeightSM
|
||||
} = token;
|
||||
return {
|
||||
[skeletonAvatarCls]: {
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
background: gradientFromColor,
|
||||
...genSkeletonElementSize(controlHeight)
|
||||
},
|
||||
[`${skeletonAvatarCls}${skeletonAvatarCls}-circle`]: {
|
||||
borderRadius: '50%'
|
||||
},
|
||||
[`${skeletonAvatarCls}${skeletonAvatarCls}-lg`]: {
|
||||
...genSkeletonElementSize(controlHeightLG)
|
||||
},
|
||||
[`${skeletonAvatarCls}${skeletonAvatarCls}-sm`]: {
|
||||
...genSkeletonElementSize(controlHeightSM)
|
||||
}
|
||||
};
|
||||
};
|
||||
const genSkeletonElementInput = token => {
|
||||
const {
|
||||
controlHeight,
|
||||
borderRadiusSM,
|
||||
skeletonInputCls,
|
||||
controlHeightLG,
|
||||
controlHeightSM,
|
||||
gradientFromColor,
|
||||
calc
|
||||
} = token;
|
||||
return {
|
||||
[skeletonInputCls]: {
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
background: gradientFromColor,
|
||||
borderRadius: borderRadiusSM,
|
||||
...genSkeletonElementInputSize(controlHeight, calc)
|
||||
},
|
||||
[`${skeletonInputCls}-lg`]: {
|
||||
...genSkeletonElementInputSize(controlHeightLG, calc)
|
||||
},
|
||||
[`${skeletonInputCls}-sm`]: {
|
||||
...genSkeletonElementInputSize(controlHeightSM, calc)
|
||||
}
|
||||
};
|
||||
};
|
||||
const genSkeletonElementShape = token => {
|
||||
const {
|
||||
gradientFromColor,
|
||||
borderRadiusSM,
|
||||
imageSizeBase,
|
||||
calc
|
||||
} = token;
|
||||
return {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
verticalAlign: 'middle',
|
||||
background: gradientFromColor,
|
||||
borderRadius: borderRadiusSM,
|
||||
...genSkeletonElementSize(calc(imageSizeBase).mul(2).equal())
|
||||
};
|
||||
};
|
||||
const genSkeletonElementNode = token => {
|
||||
return {
|
||||
[token.skeletonNodeCls]: {
|
||||
...genSkeletonElementShape(token)
|
||||
}
|
||||
};
|
||||
};
|
||||
const genSkeletonElementImage = token => {
|
||||
const {
|
||||
skeletonImageCls,
|
||||
imageSizeBase,
|
||||
calc
|
||||
} = token;
|
||||
return {
|
||||
[skeletonImageCls]: {
|
||||
...genSkeletonElementShape(token),
|
||||
[`${skeletonImageCls}-path`]: {
|
||||
fill: '#bfbfbf'
|
||||
},
|
||||
[`${skeletonImageCls}-svg`]: {
|
||||
...genSkeletonElementSize(imageSizeBase),
|
||||
maxWidth: calc(imageSizeBase).mul(4).equal(),
|
||||
maxHeight: calc(imageSizeBase).mul(4).equal()
|
||||
},
|
||||
[`${skeletonImageCls}-svg${skeletonImageCls}-svg-circle`]: {
|
||||
borderRadius: '50%'
|
||||
}
|
||||
},
|
||||
[`${skeletonImageCls}${skeletonImageCls}-circle`]: {
|
||||
borderRadius: '50%'
|
||||
}
|
||||
};
|
||||
};
|
||||
const genSkeletonElementButtonShape = (token, size, buttonCls) => {
|
||||
const {
|
||||
skeletonButtonCls
|
||||
} = token;
|
||||
return {
|
||||
[`${buttonCls}${skeletonButtonCls}-circle`]: {
|
||||
width: size,
|
||||
minWidth: size,
|
||||
borderRadius: '50%'
|
||||
},
|
||||
[`${buttonCls}${skeletonButtonCls}-round`]: {
|
||||
borderRadius: size
|
||||
}
|
||||
};
|
||||
};
|
||||
const genSkeletonElementButtonSize = (size, calc) => ({
|
||||
width: calc(size).mul(2).equal(),
|
||||
minWidth: calc(size).mul(2).equal(),
|
||||
...genSkeletonElementCommonSize(size)
|
||||
});
|
||||
const genSkeletonElementButton = token => {
|
||||
const {
|
||||
borderRadiusSM,
|
||||
skeletonButtonCls,
|
||||
controlHeight,
|
||||
controlHeightLG,
|
||||
controlHeightSM,
|
||||
gradientFromColor,
|
||||
calc
|
||||
} = token;
|
||||
return {
|
||||
[skeletonButtonCls]: {
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
background: gradientFromColor,
|
||||
borderRadius: borderRadiusSM,
|
||||
width: calc(controlHeight).mul(2).equal(),
|
||||
minWidth: calc(controlHeight).mul(2).equal(),
|
||||
...genSkeletonElementButtonSize(controlHeight, calc)
|
||||
},
|
||||
...genSkeletonElementButtonShape(token, controlHeight, skeletonButtonCls),
|
||||
[`${skeletonButtonCls}-lg`]: {
|
||||
...genSkeletonElementButtonSize(controlHeightLG, calc)
|
||||
},
|
||||
...genSkeletonElementButtonShape(token, controlHeightLG, `${skeletonButtonCls}-lg`),
|
||||
[`${skeletonButtonCls}-sm`]: {
|
||||
...genSkeletonElementButtonSize(controlHeightSM, calc)
|
||||
},
|
||||
...genSkeletonElementButtonShape(token, controlHeightSM, `${skeletonButtonCls}-sm`)
|
||||
};
|
||||
};
|
||||
// =============================== Base ===============================
|
||||
const genBaseStyle = token => {
|
||||
const {
|
||||
componentCls,
|
||||
skeletonAvatarCls,
|
||||
skeletonTitleCls,
|
||||
skeletonParagraphCls,
|
||||
skeletonButtonCls,
|
||||
skeletonInputCls,
|
||||
skeletonNodeCls,
|
||||
skeletonImageCls,
|
||||
controlHeight,
|
||||
controlHeightLG,
|
||||
controlHeightSM,
|
||||
gradientFromColor,
|
||||
padding,
|
||||
marginSM,
|
||||
borderRadius,
|
||||
titleHeight,
|
||||
blockRadius,
|
||||
paragraphLiHeight,
|
||||
controlHeightXS,
|
||||
paragraphMarginTop
|
||||
} = token;
|
||||
return {
|
||||
[componentCls]: {
|
||||
display: 'table',
|
||||
width: '100%',
|
||||
[`${componentCls}-header`]: {
|
||||
display: 'table-cell',
|
||||
paddingInlineEnd: padding,
|
||||
verticalAlign: 'top',
|
||||
// Avatar
|
||||
[skeletonAvatarCls]: {
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
background: gradientFromColor,
|
||||
...genSkeletonElementSize(controlHeight)
|
||||
},
|
||||
[`${skeletonAvatarCls}-circle`]: {
|
||||
borderRadius: '50%'
|
||||
},
|
||||
[`${skeletonAvatarCls}-lg`]: {
|
||||
...genSkeletonElementSize(controlHeightLG)
|
||||
},
|
||||
[`${skeletonAvatarCls}-sm`]: {
|
||||
...genSkeletonElementSize(controlHeightSM)
|
||||
}
|
||||
},
|
||||
[`${componentCls}-section`]: {
|
||||
display: 'table-cell',
|
||||
width: '100%',
|
||||
verticalAlign: 'top',
|
||||
// Title
|
||||
[skeletonTitleCls]: {
|
||||
width: '100%',
|
||||
height: titleHeight,
|
||||
background: gradientFromColor,
|
||||
borderRadius: blockRadius,
|
||||
[`+ ${skeletonParagraphCls}`]: {
|
||||
marginBlockStart: controlHeightSM
|
||||
}
|
||||
},
|
||||
// paragraph
|
||||
[skeletonParagraphCls]: {
|
||||
padding: 0,
|
||||
'> li': {
|
||||
width: '100%',
|
||||
height: paragraphLiHeight,
|
||||
listStyle: 'none',
|
||||
background: gradientFromColor,
|
||||
borderRadius: blockRadius,
|
||||
'+ li': {
|
||||
marginBlockStart: controlHeightXS
|
||||
}
|
||||
}
|
||||
},
|
||||
[`${skeletonParagraphCls}> li:last-child:not(:first-child):not(:nth-child(2))`]: {
|
||||
width: '61%'
|
||||
}
|
||||
},
|
||||
[`&-round ${componentCls}-section`]: {
|
||||
[`${skeletonTitleCls}, ${skeletonParagraphCls} > li`]: {
|
||||
borderRadius
|
||||
}
|
||||
}
|
||||
},
|
||||
[`${componentCls}-with-avatar ${componentCls}-section`]: {
|
||||
// Title
|
||||
[skeletonTitleCls]: {
|
||||
marginBlockStart: marginSM,
|
||||
[`+ ${skeletonParagraphCls}`]: {
|
||||
marginBlockStart: paragraphMarginTop
|
||||
}
|
||||
}
|
||||
},
|
||||
// Skeleton with element
|
||||
[`${componentCls}${componentCls}-element`]: {
|
||||
display: 'inline-block',
|
||||
width: 'auto',
|
||||
...genSkeletonElementButton(token),
|
||||
...genSkeletonElementAvatar(token),
|
||||
...genSkeletonElementInput(token),
|
||||
...genSkeletonElementNode(token),
|
||||
...genSkeletonElementImage(token)
|
||||
},
|
||||
// Skeleton Block Button, Input
|
||||
[`${componentCls}${componentCls}-block`]: {
|
||||
width: '100%',
|
||||
[skeletonButtonCls]: {
|
||||
width: '100%'
|
||||
},
|
||||
[skeletonInputCls]: {
|
||||
width: '100%'
|
||||
}
|
||||
},
|
||||
// With active animation
|
||||
[`${componentCls}${componentCls}-active`]: {
|
||||
[`
|
||||
${skeletonTitleCls},
|
||||
${skeletonParagraphCls} > li,
|
||||
${skeletonAvatarCls},
|
||||
${skeletonButtonCls},
|
||||
${skeletonInputCls},
|
||||
${skeletonNodeCls},
|
||||
${skeletonImageCls}
|
||||
`]: {
|
||||
...genSkeletonColor(token)
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
// ============================== Export ==============================
|
||||
export const prepareComponentToken = token => {
|
||||
const {
|
||||
colorFillContent,
|
||||
colorFill
|
||||
} = token;
|
||||
const gradientFromColor = colorFillContent;
|
||||
const gradientToColor = colorFill;
|
||||
return {
|
||||
color: gradientFromColor,
|
||||
colorGradientEnd: gradientToColor,
|
||||
gradientFromColor,
|
||||
gradientToColor,
|
||||
titleHeight: token.controlHeight / 2,
|
||||
blockRadius: token.borderRadiusSM,
|
||||
paragraphMarginTop: token.marginLG + token.marginXXS,
|
||||
paragraphLiHeight: token.controlHeight / 2
|
||||
};
|
||||
};
|
||||
export default genStyleHooks('Skeleton', token => {
|
||||
const {
|
||||
componentCls,
|
||||
calc
|
||||
} = token;
|
||||
const skeletonToken = mergeToken(token, {
|
||||
skeletonAvatarCls: `${componentCls}-avatar`,
|
||||
skeletonTitleCls: `${componentCls}-title`,
|
||||
skeletonParagraphCls: `${componentCls}-paragraph`,
|
||||
skeletonButtonCls: `${componentCls}-button`,
|
||||
skeletonInputCls: `${componentCls}-input`,
|
||||
skeletonNodeCls: `${componentCls}-node`,
|
||||
skeletonImageCls: `${componentCls}-image`,
|
||||
imageSizeBase: calc(token.controlHeight).mul(1.5).equal(),
|
||||
borderRadius: 100,
|
||||
// Large number to make capsule shape
|
||||
skeletonLoadingBackground: `linear-gradient(90deg, ${token.gradientFromColor} 25%, ${token.gradientToColor} 37%, ${token.gradientFromColor} 63%)`,
|
||||
skeletonLoadingMotionDuration: '1.4s'
|
||||
});
|
||||
return genBaseStyle(skeletonToken);
|
||||
}, prepareComponentToken, {
|
||||
deprecatedTokens: [['color', 'gradientFromColor'], ['colorGradientEnd', 'gradientToColor']]
|
||||
});
|
||||
Reference in New Issue
Block a user