Просмотр исходного кода

AvatarList: add attribute maxLength (#2984)

* AvatarList: add attribute `maxLength` that determine the number of avatar
items to show.

* fix markdown lint

* fix markdown lint
Rayron Victor 7 лет назад
Родитель
Сommit
12f4797194

+ 24 - 0
src/components/AvatarList/demo/maxLength.md

@@ -0,0 +1,24 @@
+---
+order: 0
+title: 
+  zh-CN: 要显示的最大项目 
+  en-US: Max Items to Show
+---
+
+`maxLength` attribute specifies the maximum number of items to show while `excessItemsStyle` style the excess
+item component.
+
+````jsx
+import AvatarList from 'ant-design-pro/lib/AvatarList';
+
+ReactDOM.render(
+  <AvatarList size="mini" maxLength={3} excessItemsStyle={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>
+    <AvatarList.Item tips="Jake" src="https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png" />
+    <AvatarList.Item tips="Andy" src="https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png" />
+    <AvatarList.Item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
+    <AvatarList.Item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
+    <AvatarList.Item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
+    <AvatarList.Item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
+  </AvatarList>
+, mountNode);
+````

+ 2 - 0
src/components/AvatarList/index.d.ts

@@ -3,6 +3,8 @@ import AvatarItem from './AvatarItem';
 
 export interface IAvatarListProps {
   size?: 'large' | 'small' | 'mini' | 'default';
+  maxLength?: number;
+  excessItemsStyle?: React.CSSProperties;
   style?: React.CSSProperties;
   children: React.ReactElement<AvatarItem> | Array<React.ReactElement<AvatarItem>>;
 }

+ 9 - 7
src/components/AvatarList/index.en-US.md

@@ -10,13 +10,15 @@ A list of user's avatar for project or group member list frequently. If a large
 
 ### AvatarList
 
-| Property | Description | Type | Default |
-|----------|------------------------------------------|-------------|-------|
-| size | size of list | `large`、`small` 、`mini`, `default` | `default` |
+| Property         | Description           | Type                               | Default   |
+| ---------------- | --------------------- | ---------------------------------- | --------- |
+| size             | size of list          | `large`、`small` 、`mini`, `default` | `default` |
+| maxLength        | max items to show     | number                             | -         |
+| excessItemsStyle | the excess item style | CSSProperties                      | -         |
 
 ### AvatarList.Item
 
-| Property | Description | Type | Default |
-|----------|------------------------------------------|-------------|-------|
-| tips | title tips for avatar item | ReactNode | - |
-| src | the address of the image for an image avatar | string | - |
+| Property | Description                                  | Type      | Default |
+| -------- | -------------------------------------------- | --------- | ------- |
+| tips     | title tips for avatar item                   | ReactNode | -       |
+| src      | the address of the image for an image avatar | string    | -       |

+ 29 - 11
src/components/AvatarList/index.js

@@ -4,12 +4,34 @@ import classNames from 'classnames';
 
 import styles from './index.less';
 
-const AvatarList = ({ children, size, ...other }) => {
-  const childrenWithProps = React.Children.map(children, child =>
-    React.cloneElement(child, {
-      size,
-    })
-  );
+const avatarSizeToClassName = size =>
+  classNames(styles.avatarItem, {
+    [styles.avatarItemLarge]: size === 'large',
+    [styles.avatarItemSmall]: size === 'small',
+    [styles.avatarItemMini]: size === 'mini',
+  });
+
+const AvatarList = ({ children, size, maxLength, excessItemsStyle, ...other }) => {
+  const numOfChildren = React.Children.count(children);
+  const numToShow = maxLength >= numOfChildren ? numOfChildren : maxLength;
+
+  const childrenWithProps = React.Children.toArray(children)
+    .slice(0, numToShow)
+    .map(child =>
+      React.cloneElement(child, {
+        size,
+      })
+    );
+
+  if (numToShow < numOfChildren) {
+    const cls = avatarSizeToClassName(size);
+
+    childrenWithProps.push(
+      <li key="exceed" className={cls}>
+        <Avatar size={size} style={excessItemsStyle}>{`+${numOfChildren - maxLength}`}</Avatar>
+      </li>
+    );
+  }
 
   return (
     <div {...other} className={styles.avatarList}>
@@ -19,11 +41,7 @@ const AvatarList = ({ children, size, ...other }) => {
 };
 
 const Item = ({ src, size, tips, onClick = () => {} }) => {
-  const cls = classNames(styles.avatarItem, {
-    [styles.avatarItemLarge]: size === 'large',
-    [styles.avatarItemSmall]: size === 'small',
-    [styles.avatarItemMini]: size === 'mini',
-  });
+  const cls = avatarSizeToClassName(size);
 
   return (
     <li className={cls} onClick={onClick}>

+ 5 - 0
src/components/AvatarList/index.less

@@ -40,6 +40,11 @@
       width: 20px;
       height: 20px;
       line-height: 20px;
+
+      .ant-avatar-string {
+        font-size: 12px;
+        line-height: 18px;
+      }
     }
   }
 }

+ 29 - 0
src/components/AvatarList/index.test.js

@@ -0,0 +1,29 @@
+import React from 'react';
+import range from 'lodash/range';
+import { mount } from 'enzyme';
+import AvatarList from './index';
+
+const renderItems = numItems =>
+  range(numItems).map(i => (
+    <AvatarList.Item
+      key={i}
+      tips="Jake"
+      src="https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png"
+    />
+  ));
+
+describe('AvatarList', () => {
+  it('renders all items', () => {
+    const wrapper = mount(<AvatarList>{renderItems(4)}</AvatarList>);
+    expect(wrapper.find('AvatarList').length).toBe(1);
+    expect(wrapper.find('Item').length).toBe(4);
+    expect(wrapper.findWhere(node => node.key() === 'exceed').length).toBe(0);
+  });
+
+  it('renders max of 3 items', () => {
+    const wrapper = mount(<AvatarList maxLength={3}>{renderItems(4)}</AvatarList>);
+    expect(wrapper.find('AvatarList').length).toBe(1);
+    expect(wrapper.find('Item').length).toBe(3);
+    expect(wrapper.findWhere(node => node.key() === 'exceed').length).toBe(1);
+  });
+});

+ 9 - 7
src/components/AvatarList/index.zh-CN.md

@@ -11,13 +11,15 @@ cols: 1
 
 ### AvatarList
 
-| 参数      | 说明                                      | 类型         | 默认值 |
-|----------|------------------------------------------|-------------|-------|
-| size | 头像大小 | `large`、`small` 、`mini`, `default` | `default` |
+| 参数               | 说明       | 类型                                 | 默认值       |
+| ---------------- | -------- | ---------------------------------- | --------- |
+| size             | 头像大小     | `large`、`small` 、`mini`, `default` | `default` |
+| maxLength        | 要显示的最大项目 | number                             | -         |
+| excessItemsStyle | 多余的项目风格  | CSSProperties                      | -         |
 
 ### AvatarList.Item
 
-| 参数      | 说明                                      | 类型         | 默认值 |
-|----------|------------------------------------------|-------------|-------|
-| tips | 头像展示文案 | ReactNode | - |
-| src | 头像图片连接 | string | - |
+| 参数   | 说明     | 类型        | 默认值 |
+| ---- | ------ | --------- | --- |
+| tips | 头像展示文案 | ReactNode | -   |
+| src  | 头像图片连接 | string    | -   |