diff --git a/packages/Skeleton/Skeleton.css b/packages/Skeleton/Skeleton.css new file mode 100644 index 0000000..0533236 --- /dev/null +++ b/packages/Skeleton/Skeleton.css @@ -0,0 +1,49 @@ +.van-skeleton { + display: flex; + box-sizing: border-box; + width: 100%; + padding: 0 16px; + padding: var(--skeleton-padding, 0 16px); +} +.van-skeleton__avatar { + flex-shrink: 0; + margin-right: 16px; + margin-right: var(--padding-md, 16px); + background-color: #f2f3f5; + background-color: var(--skeleton-avatar-background-color, #f2f3f5); +} +.van-skeleton__avatar--round { + border-radius: 100%; +} +.van-skeleton__content { + flex: 1; +} +.van-skeleton__avatar + .van-skeleton__content { + padding-top: 8px; + padding-top: var(--padding-xs, 8px); +} +.van-skeleton__row, +.van-skeleton__title { + height: 16px; + height: var(--skeleton-row-height, 16px); + background-color: #f2f3f5; + background-color: var(--skeleton-row-background-color, #f2f3f5); +} +.van-skeleton__title { + margin: 0; +} +.van-skeleton__row:not(:first-child) { + margin-top: 12px; + margin-top: var(--skeleton-row-margin-top, 12px); +} +.van-skeleton__title + .van-skeleton__row { + margin-top: 20px; +} +.van-skeleton--animate { + animation: van-skeleton-blink 1.2s ease-in-out infinite; +} +@keyframes van-skeleton-blink { + 50% { + opacity: 0.6; + } +} diff --git a/packages/Skeleton/Skeleton.tsx b/packages/Skeleton/Skeleton.tsx new file mode 100644 index 0000000..7b7e9b8 --- /dev/null +++ b/packages/Skeleton/Skeleton.tsx @@ -0,0 +1,115 @@ +// packages +import React, { FunctionComponent, CSSProperties } from 'react'; +import clsx from 'clsx'; +import { View } from 'remax/wechat'; +// internal +import { Switch, Case, Select } from '../tools/Switch'; +import withDefaultProps from '../tools/with-default-props-advance'; +import './Skeleton.css'; + +// 默认值填充属性 +interface NeutralSkeletonProps { + row: number; + rowWidth: string | string[]; + title: boolean; + titleWidth: string; + avatar: boolean; + avatarSize: string; + avatarShape: 'round' | 'square'; + loading: boolean; + animate: boolean; +} + +interface ExogenousSkeletonProps { + // 容器类名,用以覆盖内部 + className?: string; +} + +type SkeletonProps = NeutralSkeletonProps & ExogenousSkeletonProps; + +const DefaultSkeletonProps: NeutralSkeletonProps = { + row: 0, + rowWidth: '100%', + title: false, + titleWidth: '40%', + avatar: false, + avatarSize: '32px', + avatarShape: 'round', + loading: true, + animate: true, +}; + +const Skeleton: FunctionComponent = (props) => { + const { + className, + loading, + animate, + avatar, + avatarSize, + avatarShape, + title, + titleWidth, + row, + rowWidth, + children, + } = props; + const classnames = { + container: clsx(className, 'van-skeleton', { + 'van-skeleton--animate': animate, + }), + avatar: clsx( + 'van-skeleton__avatar', + `van-skeleton__avatar--${avatarShape}` + ), + }; + const stylesheets: Record = { + avatar: { + width: avatarSize, + height: avatarSize, + }, + title: { + width: titleWidth, + }, + }; + + // 占位符计算 + const elements = Array.from({ length: row }).map((_, index) => ({ + className: 'van-skeleton__row', + style: { + width: Array.isArray(rowWidth) ? rowWidth[index] : rowWidth, + }, + })); + + return ( + + + + + + + + {elements.map((element, index) => ( + // eslint-disable-next-line react/no-array-index-key + + ))} + + + + + {children} + + + ); +}; + +export default withDefaultProps( + DefaultSkeletonProps +)(Skeleton); diff --git a/packages/Skeleton/index.ts b/packages/Skeleton/index.ts new file mode 100644 index 0000000..26e889c --- /dev/null +++ b/packages/Skeleton/index.ts @@ -0,0 +1,4 @@ +/** + * @description - nothing but export component + */ +export { default } from './Skeleton'; diff --git a/public/pages/skeleton/index.tsx b/public/pages/skeleton/index.tsx new file mode 100644 index 0000000..8f034ca --- /dev/null +++ b/public/pages/skeleton/index.tsx @@ -0,0 +1,22 @@ +// packages +import * as React from 'react'; +import { View, Text } from 'remax/wechat'; + +// internal +import Skeleton from '../../../packages/Skeleton'; + +export default () => { + return ( + + 基础用法 + + + + + 显示头像 + + + + + ); +};