From 0a3e2086bafca064ce38dc12a034811fa6d25bd9 Mon Sep 17 00:00:00 2001 From: stbui Date: Wed, 16 Oct 2019 11:33:09 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat(pagination):=20=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/pagination/PropsType.tsx | 24 +- .../__snapshots__/index.test.jsx.snap | 828 +++++++++--------- .../pagination/__tests__/index.test.jsx | 94 +- components/pagination/index.tsx | 337 +++---- components/pagination/pagination.md | 267 +++--- components/pagination/style/component.scss | 141 --- components/pagination/style/index.scss | 71 +- components/pagination/style/index.tsx | 3 +- components/pagination/style/mixins.scss | 150 ++++ components/style/themes/variable.scss | 26 + 10 files changed, 1029 insertions(+), 912 deletions(-) delete mode 100644 components/pagination/style/component.scss create mode 100644 components/pagination/style/mixins.scss diff --git a/components/pagination/PropsType.tsx b/components/pagination/PropsType.tsx index bce5d9b1..c35996c8 100644 --- a/components/pagination/PropsType.tsx +++ b/components/pagination/PropsType.tsx @@ -1,22 +1,18 @@ export default interface PropsType { prefixCls?: string; + className?: string; + style?: React.CSSProperties; value?: number; defaultValue?: number; + locale?: { [propName: string]: any }; pageSize: number; - pageSizeSource?: Array; + pageSizeOptions?: Array; total: number; showTotal?: boolean; - showJumper?: boolean; - showPageSizeSelector?: boolean; - className?: string; - style?: object; - shape: 'rect' | 'radius'; - bordered?: boolean; - isBordered?: boolean; - addonBefore?: React.ReactNode; - addonAfter?: React.ReactNode; - onPageChange: (value: number) => void; - onPageSizeChange: (value: number) => void; - locale?: { [propName: string]: any }; - onChange: (pageInfo: { currentPage: number; pageSize: number }) => void; + showQuickJumper?: boolean; + showPageSizeChanger?: boolean; + simple?: boolean; + size?: 'md' | 'sm'; + onPageSizeChange: (pageSize?: number) => void; + onChange: (page?: number) => void; } diff --git a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap index 14aa7886..09bcdfee 100644 --- a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap +++ b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap @@ -1,420 +1,466 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Pagination renders Pagination with customized props correctly 1`] = ` -
-
+
  • -
    -
      -
      - addonBefore -
      -
    • - - - - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • + -
    • - 10 -
    • -
    • - - - - - -
    • -
      - addonAfter -
      -
    -
    -
  • -
    + + + +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • +
  • + 10 +
  • +
  • + + + + + +
  • + `; exports[`Pagination renders Pagination with jumper correctly 1`] = ` -
    -
    +
  • -
    -
      -
    • - - - - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • + -
    • - 10 -
    • -
    • - - - - - -
    • -
    -
    + +
  • +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • +
  • + 10 +
  • +
  • + + - 跳至 -
    - -
    - 页 -
  • + + + + +
  • +
    + 跳至 + + 页
    -
  • - + + `; exports[`Pagination renders Pagination with total info correctly 1`] = ` -
    -
    +
  • -
    +
  • + - 共有 100 条记录 第 1 / 10 页 -
  • -
    + + + + +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • +
  • + 10 +
  • +
  • + -
      -
    • - - - - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • + -
    • - 10 -
    • -
    • - - - - - -
    • -
    -
  • -
    - + + + + `; exports[`Pagination renders normal Pagination correctly 1`] = ` -
    -
    +
  • -
    -
      -
    • - - - - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • + -
    • - 10 -
    • -
    • - - - - - -
    • -
    -
    -
  • + + + +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • +
  • + 10 +
  • +
  • + + + + + +
  • + +`; + +exports[`Pagination renders size correctly 1`] = ` +
    +
      +
    • + + + + + +
    • +
    • + 1 +
    • +
    • + 2 +
    • +
    • + 3 +
    • +
    • + 4 +
    • +
    • + 5 +
    • +
    • +
    • + 10 +
    • +
    • + + + + + +
    • +
    `; diff --git a/components/pagination/__tests__/index.test.jsx b/components/pagination/__tests__/index.test.jsx index a704e22e..6d79cd48 100644 --- a/components/pagination/__tests__/index.test.jsx +++ b/components/pagination/__tests__/index.test.jsx @@ -5,60 +5,37 @@ import Pagination from '../index'; describe('Pagination', () => { it('renders normal Pagination correctly', () => { - const wrapper = render( -
    - -
    , - ); + const wrapper = render(); expect(toJson(wrapper)).toMatchSnapshot(); }); it('renders Pagination with total info correctly', () => { - const wrapper = render( -
    - -
    , - ); + const wrapper = render(); expect(toJson(wrapper)).toMatchSnapshot(); }); it('renders Pagination with jumper correctly', () => { - const wrapper = render( -
    - -
    , - ); + const wrapper = render(); expect(toJson(wrapper)).toMatchSnapshot(); }); it('renders Pagination with customized props correctly', () => { - const wrapper = render( -
    - -
    , - ); + const wrapper = render(); expect(toJson(wrapper)).toMatchSnapshot(); }); it('behaves correctly when changing page', () => { const onChange = jest.fn(); - const wrapper = mount( -
    - -
    , - ); + const wrapper = mount(); - wrapper.find('.ui-pagination-item').at(2).simulate('click'); + wrapper + .find('.zw-pagination__item') + .at(2) + .simulate('click'); expect(onChange).toHaveBeenCalledWith(2); }); @@ -67,11 +44,11 @@ describe('Pagination', () => { const onChange = jest.fn(); const wrapper = mount(
    - +
    , ); - wrapper.find('.ui-pagination-item-prev').simulate('click'); + wrapper.find('.zw-pagination__prev').simulate('click'); expect(onChange).toHaveBeenCalledWith(5); }); @@ -79,12 +56,10 @@ describe('Pagination', () => { it('behaves correctly when click next button', () => { const onChange = jest.fn(); const wrapper = mount( -
    - -
    , + , ); - wrapper.find('.ui-pagination-item-next').simulate('click'); + wrapper.find('.zw-pagination__next').simulate('click'); expect(onChange).toHaveBeenCalledWith(6); }); @@ -92,38 +67,32 @@ describe('Pagination', () => { it('behaves correctly when click prev 5 button', () => { const onChange = jest.fn(); const wrapper = mount( -
    - -
    , + , ); - wrapper.find('.ui-pagination-item-jump-prev').simulate('click'); + wrapper.find('.zw-pagination__prev').simulate('click'); - expect(onChange).toHaveBeenCalledWith(1); + expect(onChange).toHaveBeenCalledWith(5); }); it('behaves correctly when click next 5 button', () => { const onChange = jest.fn(); const wrapper = mount( -
    - -
    , + , ); - wrapper.find('.ui-pagination-item-jump-next').simulate('click'); + wrapper.find('.zw-pagination__next').simulate('click'); - expect(onChange).toHaveBeenCalledWith(6); + expect(onChange).toHaveBeenCalledWith(2); }); it('behaves correctly when change page with jumper', () => { const onChange = jest.fn(); const wrapper = mount( -
    - -
    , + , ); - wrapper.find('.ui-pagination-jumper input').simulate('keydown', { + wrapper.find('.zw-pagination__options--jumper input').simulate('keydown', { keyCode: 13, target: { value: 6, @@ -133,11 +102,24 @@ describe('Pagination', () => { }); it('behaves correctly when receiving new value', () => { - const wrapper = mount( - , - ); + const wrapper = mount(); wrapper.setProps({ value: 1 }); - expect(wrapper.find('.ui-pagination-item').at(1).hasClass('ui-pagination-item-active')).toBeTruthy(); + expect( + wrapper + .find('.zw-pagination__item') + .at(1) + .hasClass('zw-pagination__item--active'), + ).toBeTruthy(); + }); + + it('renders size correctly', () => { + const wrapper = render( +
    + +
    , + ); + expect(wrapper.find('.zw-pagination--sm').length).toEqual(1); + expect(toJson(wrapper)).toMatchSnapshot(); }); }); diff --git a/components/pagination/index.tsx b/components/pagination/index.tsx index e797a46e..9dabd83f 100644 --- a/components/pagination/index.tsx +++ b/components/pagination/index.tsx @@ -1,26 +1,23 @@ import React, { Component } from 'react'; import classnames from 'classnames'; import Select from '../select'; -import Input from '../input'; import Icon from '../icon'; import PropsType from './PropsType'; import format from '../locale-provider/format'; import LocaleReceiver from '../locale-provider/LocaleReceiver'; -const noop = () => { }; +const noop = () => {}; + class Pagination extends Component { static defaultProps = { - prefixCls: 'ui-pagination', + prefixCls: 'zw-pagination', defaultValue: 1, - isBordered: false, - isRadius: false, total: 0, pageSize: 10, - pageSizeSource: [10, 20, 30, 40, 50], + pageSizeOptions: [10, 20, 30, 40, 50], showTotal: false, - showJumper: false, - showPageSizeSelector: false, - onPageChange: noop, + showQuickJumper: false, + showPageSizeChanger: false, onPageSizeChange: noop, onChange: noop, }; @@ -29,26 +26,26 @@ class Pagination extends Component { super(props); this.state = { value: props.value || props.defaultValue, + currentInputValue: props.value || props.defaultValue, }; } - componentWillReceiveProps(nextProps) { + static getDerivedStateFromProps(nextProps) { if ('value' in nextProps) { - this.setState({ + return { value: nextProps.value, - }); + }; } + return null; } - getPagerList = () => { - const { - total, - addonBefore, - addonAfter, - pageSize, - } = this.props; + getPageSize = () => { + const { total, pageSize } = this.props; + return Math.ceil(total / pageSize); + }; - const pageCount = Math.ceil(total / pageSize); + getPagerList = () => { + const pageCount = this.getPageSize(); const pagerList: JSX.Element[] = []; let { value } = this.state; value = value < 1 ? 1 : value; @@ -87,13 +84,37 @@ class Pagination extends Component { pagerList.push(this.nextPager(value, pageCount)); } - if (addonBefore) { - pagerList.unshift(this.renderAddonBefore(addonBefore)); - } - if (addonAfter) { - pagerList.push(this.renderAddonAfter(addonAfter)); - } + return pagerList; + }; + renderSimple = () => { + const { prefixCls } = this.props; + const pagerList: JSX.Element[] = []; + const pageCount = this.getPageSize(); + const { currentInputValue } = this.state; + let { value } = this.state; + value = value > pageCount ? pageCount : value; + + pagerList.push( +
  • + + + {pageCount} +
  • , + ); + + pagerList.unshift(this.prevPager(value)); + pagerList.push(this.nextPager(value, pageCount)); return pagerList; }; @@ -103,7 +124,7 @@ class Pagination extends Component {
  • this._onPagerClick(1)} > 1 @@ -111,109 +132,150 @@ class Pagination extends Component { ); }; - lastPager = (pageCount) => { + lastPager = (pageSize: number) => { const { prefixCls, locale } = this.props; return (
  • this._onPagerClick(pageCount)} + className={`${prefixCls}__item`} + onClick={() => this._onPagerClick(pageSize)} > - {pageCount} + {pageSize}
  • ); }; - prevPager = (current) => { + prevPager = (page: number) => { const { prefixCls, locale } = this.props; + const cls = classnames({ + [`${prefixCls}__item`]: true, + [`${prefixCls}__prev`]: true, + [`${prefixCls}--disabled`]: Number(page) === 1, + }); + return (
  • current > 1 && this._onPagerClick(current - 1)} + className={classnames(cls)} + onClick={() => page > 1 && this._onPagerClick(page - 1)} > - +
  • ); }; - nextPager = (current, pageCount) => { + nextPager = (page: number, pageSize: number) => { const { prefixCls, locale } = this.props; + const cls = classnames({ + [`${prefixCls}__item`]: true, + [`${prefixCls}__next`]: true, + [`${prefixCls}--disabled`]: Number(page) === pageSize, + }); + return (
  • current < pageCount && this._onPagerClick(current + 1)} + className={cls} + onClick={() => page < pageSize && this._onPagerClick(page + 1)} > - +
  • ); }; - jumpPrev = (current) => { + jumpPrev = (page: number) => { const { prefixCls, locale } = this.props; + const cls = classnames({ + [`${prefixCls}__item`]: true, + [`${prefixCls}__item--ellipsis`]: true, + }); + return (
  • this._onPagerClick(current - 5)} + className={cls} + onClick={() => this._onPagerClick(page - 5)} /> ); }; - jumpNext = (current) => { + jumpNext = (page: number) => { const { prefixCls, locale } = this.props; + const cls = classnames({ + [`${prefixCls}__item`]: true, + [`${prefixCls}__item--ellipsis`]: true, + }); + return (
  • this._onPagerClick(current + 5)} + className={cls} + onClick={() => this._onPagerClick(page + 5)} /> ); }; - _onPagerClick(value) { - const { onPageChange, onChange, pageSize } = this.props; + handleJumpChange = ({ target: { value } }) => { + const sValue = parseInt(value, 10); + if (typeof sValue !== 'number') { + this.setState({ currentInputValue: '' }); + return; + } + + this.setState({ currentInputValue: value }); + }; + + /** + * 按下回车键,改变分页 + */ + handleJumpKeyDown = ({ keyCode, target: { value } }: any) => { + if (keyCode === 13) { + let sValue = parseInt(value, 10); + if (typeof sValue !== 'number') { + return; + } + + const pageCount = this.getPageSize(); + if (sValue < 1) { + sValue = 1; + } + + if (sValue > pageCount) { + sValue = pageCount; + } + + this._onPagerClick(sValue); + } + }; + + _onPagerClick(value: number) { + const { onChange } = this.props; this.setState({ value, + currentInputValue: value, }); - if (onPageChange !== noop) { - onPageChange(value); - return; - } - onChange({ - pageSize, - currentPage: value, - }); + + onChange(value); } - renderPager = (i, current) => { + renderPager = (i: number, page: number) => { const { prefixCls } = this.props; + const cls = classnames({ + [`${prefixCls}__item`]: true, + [`${prefixCls}--active`]: page === i, + }); + return (
  • this._onPagerClick(i)} > {i} @@ -221,144 +283,109 @@ class Pagination extends Component { ); }; - renderAddonBefore = (addonBefore) => { - const { prefixCls } = this.props; - return ( -
    - {addonBefore} -
    - ); - }; - - renderAddonAfter = (addonAfter) => { - const { prefixCls } = this.props; - return ( -
    - {addonAfter} -
    - ); - }; - renderTotal = () => { const { total, prefixCls, locale, pageSize } = this.props; + const cls = classnames({ + [`${prefixCls}__total`]: true, + }); const { value } = this.state; return ( -
    +
  • {format(locale!.total, { total, })} {format(locale!.current, { current: `${value} / ${Math.ceil(total / pageSize)}`, })} -
  • + ); }; renderPageSizeSelector = () => { - const { prefixCls, onPageSizeChange, onChange, locale, pageSize } = this.props; - let { pageSizeSource } = this.props; - let defaultPageSize = pageSizeSource && pageSizeSource.length > 0 && pageSizeSource[0]; + const { + prefixCls, + onPageSizeChange, + onChange, + locale, + pageSize, + } = this.props; + let { pageSizeOptions } = this.props; + let defaultPageSize = pageSizeOptions && pageSizeOptions.length > 0 && pageSizeOptions[0]; - if (!pageSizeSource) { - pageSizeSource = [10, 20, 30, 40, 50]; + if (!pageSizeOptions) { + pageSizeOptions = [10, 20, 30, 40, 50]; defaultPageSize = 10; } return ( -
    +
  • -
  • + ); }; renderJumper = () => { - const { shape, total, prefixCls, locale, pageSize } = this.props; + const { prefixCls, locale } = this.props; return ( -
    - {locale!.goto} - ) => { - const { value } = e.target as HTMLInputElement; - if (e.keyCode === 13) { - let sValue = parseInt(value, 10); - // eslint-disable-next-line - if (!sValue || isNaN(sValue)) { return; } - - if (sValue < 1) { sValue = 1; } - const pageCount = Math.ceil(total / pageSize); - if (sValue > pageCount) { sValue = pageCount; } - - this._onPagerClick(sValue); - } - }} - /> - {locale!.pageClassifier} -
    +
  • +
    + {locale!.goto} + + {locale!.pageClassifier} +
    +
  • ); }; render() { const { prefixCls, - isBordered, - shape, className, showTotal, - showJumper, - showPageSizeSelector, + showQuickJumper, + showPageSizeChanger, + simple, + size, style, } = this.props; const cls = classnames({ [prefixCls!]: true, - bordered: 'bordered' in this.props || isBordered, - [`shape-${shape}`]: !!shape, + [`${prefixCls}--${size}`]: !!size, + [`${prefixCls}--simple`]: simple, [className!]: !!className, }); return ( -
    +
      {showTotal && this.renderTotal()} -
      -
        - {this.getPagerList()} -
      - {showPageSizeSelector && this.renderPageSizeSelector()} - {showJumper && this.renderJumper()} -
      -
    + {simple ? this.renderSimple() : this.getPagerList()} + {showPageSizeChanger && this.renderPageSizeSelector()} + {showQuickJumper && this.renderJumper()} + ); } } diff --git a/components/pagination/pagination.md b/components/pagination/pagination.md index e144028a..2ab41bf9 100644 --- a/components/pagination/pagination.md +++ b/components/pagination/pagination.md @@ -1,209 +1,174 @@ -## Pagination 分页 -一般配合Table组件做分页展示。 +# Pagination 分页 -### 基础用法 +采用分页的形式分隔长列表,每次只加载一个页面。 + +## 基础用法 最简单的分页。 -:::demo 只需要设置`total`,`pageSize`默认为10。 +```jsx +import { Pagination } from 'zarm-web'; -```js +class Demo extends React.Component { render() { - return ( -
    - -
    - ) + return ; } +} + +ReactDOM.render(, mountNode); ``` -::: -### 显示总数 +## 显示总数 -添加`showToal`属性即可。 +通过设置 showTotal 展示总共有多少数据。 -:::demo +```jsx +import { Pagination } from 'zarm-web'; -```js +class Demo extends React.Component { render() { - return ( -
    - -
    - ) + return ; } +} + +ReactDOM.render(, mountNode); ``` -::: -### 显示跳转 +## 显示跳转 -添加`showJumper`属性即可。 +添加`showQuickJumper`属性即可。 -:::demo +```jsx +import { Pagination } from 'zarm-web'; -```js +class Demo extends React.Component { render() { - return ( -
    - -
    - ) + return ; } +} + +ReactDOM.render(, mountNode); ``` -::: -### 显示每页条数选择器 +## 显示每页条数选择器 -添加`showPageSizeSelector`属性即可。 +添加`showPageSizeChanger`属性即可。 -:::demo +```jsx +import { Pagination } from 'zarm-web'; -```js +class Demo extends React.Component { render() { - return ( -
    - -
    - ) + return ; } +} + +ReactDOM.render(, mountNode); ``` -::: -### 设置页面下拉框的数据源 +## 指定每页可以显示多少条 -添加`pageSizeSource`属性即可。 +添加`pageSizeOptions`属性即可。 -:::demo +```jsx +import { Pagination } from 'zarm-web'; -```js +class Demo extends React.Component { render() { return ( -
    - -
    - ) + + ); } +} + +ReactDOM.render(, mountNode); ``` -::: -### 事件回调 +## 小型分页 -通过`onPageChange`监听翻页和跳转,通过`onPageSizeChange`监听每页条数变更事件。 +占用更小位置的分页 -:::demo +```jsx +import { Pagination } from 'zarm-web'; -```js - constructor(props) { - super(props); - this.state = { - pageSize: 10 - } - } +class Demo extends React.Component { render() { - const { pageSize } = this.state; - return ( -
    - { - alert('翻页到:' + page); - }} - onPageSizeChange={(pageSize) => { - alert('每页展示:' + pageSize); - this.setState({ - pageSize - }); - }} - /> -
    - ) + return ; } -``` -::: - -### 事件回调 +} -通过`onChange`兼容`onPageSizeChange`与`onPageChange`,监听翻页和跳转以及每页条数变更事件。 +ReactDOM.render(, mountNode); +``` +## 迷你 -:::demo +```jsx +import { Pagination } from 'zarm-web'; -```js - constructor(props) { - super(props); - this.state = { - pageSize: 10, - currentPage: 1, - } - } +class Demo extends React.Component { render() { - const { pageSize, currentPage } = this.state; - return ( -
    - { - alert('每页展示:' + pageSize + ',且当前页是' + currentPage); - this.setState({ - pageSize, - currentPage, - }); - }} - /> -
    - ) + return ; } +} + +ReactDOM.render(, mountNode); ``` -::: -### 更多设置 +## 事件回调 -通过`radius`,`bordered`设置样式。 +通过`onChange`监听翻页和跳转,通过`onPageSizeChange`监听每页条数变更事件。 -:::demo +```jsx +import { Pagination } from 'zarm-web'; -```js +class Demo extends React.Component { + constructor(props) { + super(props); + this.state = { + pageSize: 10 + }; + } render() { + const { pageSize } = this.state; return ( -
    - -
    - ) + { + alert('翻页到:' + page); + }} + onPageSizeChange={pageSize => { + alert('每页展示:' + pageSize); + this.setState({ + pageSize + }); + }} + /> + ); } +} + +ReactDOM.render(, mountNode); ``` -::: - -### Attributes -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -|---------- |-------- |---------- |------------- |-------- | -| value | 当前页 | number | - | - | -| defaultValue | 默认页 | number | - | 1 | -| total | 总数 | number | — | 0 | -| pageSize | 每页条数 | number | — | 10 | -| pageSizeSource |页数下拉框的数据源 | number[] | - | [10,20,30,40,50] -| showTotal | 是否展示总数 | boolean | — | false | -| showJumper | 是否展示跳转 | boolean | — | false | -| showPageSizeSelector | 是否展示每页条数选择器 | boolean | — | false | -| radius | 是否圆角 | boolean | — | false | -| bordered | 是否有边框 | boolean | — | false | - - -### Events -| 事件名称 | 说明 | 回调参数 | -|---------- |-------- |---------- | -| onPageChange | 翻页或跳转触发的事件 | page | -| onPageSizeChange | 每页展示条数变更触发的事件 | pageSize | -| onChange |监听翻页和跳转以及每页条数变更事件。 | {pageSize, currentPage} | + +## API + +| 属性 | 类型 | 默认值 | 说明 | +| ------------------- | --------------------------- | ---------------- | -------------------------- | +| value | number | - | 当前页 | +| defaultValue | number | 1 | 默认页 | +| simple | boolean | false | 是否简洁分页 | +| size | 'md' or 'sm' | md | 分页器尺寸 | +| total | number | 0 | 数据总数 | +| pageSize | number | 10 | 每页条数 | +| pageSizeOptions | number[] | [10,20,30,40,50] | 每页条数下拉框的选项 | +| showTotal | boolean | false | 是否展示总数 | +| showQuickJumper | boolean | false | 是否展示跳转 | +| showPageSizeChanger | boolean | false | 是否展示每页条数选择器 | +| onPageSizeChange | (pageSize?: number) => void | - | 每页展示条数变更触发的事件 | +| onChange | (page?: number) => void | - | 页面切换和跳转时触发的事件 | diff --git a/components/pagination/style/component.scss b/components/pagination/style/component.scss deleted file mode 100644 index c06db2ee..00000000 --- a/components/pagination/style/component.scss +++ /dev/null @@ -1,141 +0,0 @@ -.ui-pagination { - &:after { - content: " "; - display: block; - height: 0; - clear: both; - overflow: hidden; - visibility: hidden; - } - - &.bordered { - .ui-pagination-item { - border: 1px solid #d9d9d9; - margin-right: 8px; - - &:hover { - border-color: #2db7f5; - } - - &.ui-pagination-item-jump-prev, - &.ui-pagination-item-jump-next { - border-width: 0; - } - - &.ui-pagination-item-active { - border-color: #2db7f5; - } - - &.ui-pagination-item-disabled { - &:hover { - border-color: #d9d9d9; - } - } - } - } - - &.shape-radius { - .ui-pagination-item { - border-radius: $base-radius; - } - } - - &-total { - float: left; - line-height: 28px; - padding-right: 4px; - color: #999; - } - - &-pagers { - float: right; - - & > ul { - float: left; - margin: 0; - padding: 0; - } - } - - &-size, - &-jumper { - float: left; - margin-left: 6px; - line-height: 28px; - - .ui-selectm, - .ui-dropdown-trigger-box { - vertical-align: inherit; - } - } -} - -.ui-pagination-item { - float: left; - // display: inline-block; - border: 1px solid transparent; - min-width: 28px; - padding: 0 6px; - height: 28px; - line-height: 26px; - text-align: center; - list-style: none; - background-color: #fff; - margin-right: 4px; - font-family: Arial; - user-select: none; - cursor: pointer; - - &.ui-pagination-item-prev, - &.ui-pagination-item-next { - color: #ccc; - } - - &.ui-pagination-item-jump-prev, - &.ui-pagination-item-jump-next { - &:after { - content: "\2022\2022\2022"; - display: block; - letter-spacing: 2px; - color: #ccc; - text-align: center; - } - } - - &:hover { - color: #2db7f5; - - &.ui-pagination-jump-prev, - &.ui-pagination-jump-next { - &:after { - color: #2db7f5; - } - } - } - - &.ui-pagination-item-disabled { - cursor: not-allowed; - opacity: 0.7; - - &:hover { - color: #ccc; - } - } - - &.ui-pagination-item-active { - background-color: #2db7f5; - color: #fff; - } -} - -.ui-pagination-addon-before { - float: left; - margin-right: 15px; - line-height: 28px; -} - -.ui-pagination-addon-after { - float: left; - margin-left: 15px; - line-height: 28px; -} diff --git a/components/pagination/style/index.scss b/components/pagination/style/index.scss index 87ed5f3d..e2bd1809 100644 --- a/components/pagination/style/index.scss +++ b/components/pagination/style/index.scss @@ -1,2 +1,69 @@ -@import '../../style/themes/default'; -@import './component'; +@import '../../style/core/index'; +@import 'mixins'; + +@include b(pagination) { + margin: 0; + padding: 0; + @include clearfix(); + + @include e(item) { + @include pagination-item( + var(--pagination-color), + var(--pagination-default-bg-color), + var(--pagination-default-hover-color), + var(--pagination-default-active-background), + var(--pagination-font-size-md), + var(--pagination-opacity), + var(--pagination-height-md), + var(--radius-md) + ); + } + + @include e(total) { + @include pagination-total(var(--pagination-font-size-md)); + } + + @include e(options) { + @include pagination-options( + var(--pagination-default-bg-color), + var(--pagination-font-size-sm), + var(--radius-md) + ); + } + + @include m(sm) { + @include pagination-size( + var(--pagination-default-active-background), + var(--pagination-font-size-sm), + var(--pagination-height-sm) + ); + } + + @include m(simple) { + @include pagination-simple( + var(--pagination-default-bg-color), + var(--pagination-height-md), + var(--pagination-font-size-md) + ); + } + + @include m(disabled) { + &, + &:active, + &:hover, + &:focus, + &:visited { + color: var(--color-text-disabled); + cursor: not-allowed; + } + } + + @include m(active) { + background-color: var(--pagination-default-active-background); + + &, + &:hover { + color: #fff; + } + } +} diff --git a/components/pagination/style/index.tsx b/components/pagination/style/index.tsx index 6054c0b4..8a3ccd84 100644 --- a/components/pagination/style/index.tsx +++ b/components/pagination/style/index.tsx @@ -1,5 +1,4 @@ import '../../style'; -import '../../input/style'; import '../../select/style'; -import '../../button/style'; +import '../../icon/style'; import './index.scss'; diff --git a/components/pagination/style/mixins.scss b/components/pagination/style/mixins.scss new file mode 100644 index 00000000..27622e01 --- /dev/null +++ b/components/pagination/style/mixins.scss @@ -0,0 +1,150 @@ +@mixin pagination-item( + $color, + $background, + $hover-color, + $active-background, + $font-size, + $disabled-opacity, + $height, + $radius +) { + min-width: $height; + height: $height; + line-height: $height; + padding: 0 6px; + margin-right: 8px; + display: inline-block; + text-align: center; + list-style: none; + user-select: none; + cursor: pointer; + vertical-align: middle; + border: 1px solid transparent; + background-color: $background; + border-radius: $radius; + font-size: $font-size; + + &:hover { + color: $hover-color; + } + + @include m(ellipsis) { + background-color: transparent; + + &:after { + content: '\2022\2022\2022'; + display: block; + letter-spacing: 2px; + color: #ccc; + text-align: center; + font-size: 12px; + } + } + + @include m(icon) { + font-size: 14px; + } +} + +@mixin pagination-total($font-size) { + display: inline-block; + vertical-align: middle; + padding-right: 8px; + color: #999; + font-size: $font-size; +} + +@mixin pagination-options($background, $font-size, $radius) { + display: inline-block; + margin-left: 8px; + vertical-align: middle; + + @include m(changer) { + font-size: $font-size; + } + + @include m(jumper) { + display: inline-block; + vertical-align: top; + + > input { + position: relative; + display: inline-block; + width: 48px; + height: 32px; + margin: 0 8px; + text-align: center; + border-radius: $radius; + font-size: $font-size; + border: 1px solid $background; + background-color: $background; + } + } + + @include m(slash) { + margin: 0 10px 0 5px; + } +} + +@mixin pagination-size($active-background, $font-size, $height) { + @include e(item) { + background-color: transparent; + min-width: $height; + height: $height; + line-height: $height; + margin: 0; + } + + @include e(item--icon) { + font-size: $font-size; + } + + @include b(pagination--active) { + background-color: var(--pagination-default-active-background); + + &, + &:hover { + color: #fff; + } + } + + @include e(total) { + height: $height; + line-height: $height; + font-size: $font-size; + } +} + +@mixin pagination-simple($background, $height, $font-size) { + @include e(item) { + background-color: transparent; + min-width: $height; + height: $height; + line-height: $height; + margin: 0; + font-size: $font-size; + vertical-align: top; + } + + @include e(item--icon) { + font-size: $font-size; + } + + @include e(pager) { + display: inline-block; + height: 24px; + + > input { + box-sizing: border-box; + height: 100%; + margin-right: 8px; + padding: 0 6px; + border-radius: 4px; + outline: none; + transition: border-color 0.3s; + text-align: center; + border: 1px solid $background; + background-color: $background; + } + } +} diff --git a/components/style/themes/variable.scss b/components/style/themes/variable.scss index 3c1e8471..c2e00230 100644 --- a/components/style/themes/variable.scss +++ b/components/style/themes/variable.scss @@ -244,4 +244,30 @@ --steps-status-error: var(--theme-danger); --steps-icon-size: 28px; --steps-content-width: 140px; + // Avatar + --avatar-border-radius: 50%; + --avatar-fontSize: 14px; + --avatar-width-md: 40px; + --avatar-height-md: 40px; + --avatar-width-xl: 72px; + --avatar-height-xl: 72px; + --avatar-width-lg: 48px; + --avatar-height-lg: 48px; + --avatar-width-sm: 32px; + --avatar-height-sm: 32px; + --avatar-width-xs: 24px; + --avatar-height-xs: 24px; + --avatar-default-color: #fff; + --avatar-default-bg-color: #ccc; + + // pagination + --pagination-color: #343434; + --pagination-default-hover-color: var(--theme-primary); + --pagination-default-bg-color: #fafafa; + --pagination-default-active-background: var(--theme-primary); + --pagination-font-size-md: 14px; + --pagination-font-size-sm: 12px; + --pagination-height-md: 32px; + --pagination-height-sm: 24px; + --pagination-opacity: var(--opacity-disabled); } From d2c1eafd300bd028f89b2eaa890b54f42faa7efb Mon Sep 17 00:00:00 2001 From: stbui Date: Fri, 13 Dec 2019 11:10:51 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix(pagination):=20=E8=B8=A2=E5=87=BA?= =?UTF-8?q?=E6=97=A0=E6=95=88=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/index.test.jsx.snap | 20 +++++++++---------- components/pagination/style/mixins.scss | 17 ++++++++-------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap index 09bcdfee..68d1ca8a 100644 --- a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap +++ b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap @@ -5,7 +5,7 @@ exports[`Pagination renders Pagination with customized props correctly 1`] = ` class="zw-pagination" >
  • 1 @@ -94,7 +94,7 @@ exports[`Pagination renders Pagination with jumper correctly 1`] = ` class="zw-pagination" >
  • 1 @@ -201,7 +201,7 @@ exports[`Pagination renders Pagination with total info correctly 1`] = ` 共有 100 条记录 第 1 / 10 页
  • 1 @@ -290,7 +290,7 @@ exports[`Pagination renders normal Pagination correctly 1`] = ` class="zw-pagination" >
  • 1 @@ -380,7 +380,7 @@ exports[`Pagination renders size correctly 1`] = ` class="zw-pagination zw-pagination--sm" >
  • 1 diff --git a/components/pagination/style/mixins.scss b/components/pagination/style/mixins.scss index 27622e01..4ff44103 100644 --- a/components/pagination/style/mixins.scss +++ b/components/pagination/style/mixins.scss @@ -32,7 +32,7 @@ background-color: transparent; &:after { - content: '\2022\2022\2022'; + content: "\2022\2022\2022"; display: block; letter-spacing: 2px; color: #ccc; @@ -65,13 +65,12 @@ @include m(jumper) { display: inline-block; - vertical-align: top; > input { position: relative; display: inline-block; width: 48px; - height: 32px; + height: 24px; margin: 0 8px; text-align: center; border-radius: $radius; @@ -93,6 +92,8 @@ height: $height; line-height: $height; margin: 0; + display: inline-flex; + align-items: center; } @include e(item--icon) { @@ -131,14 +132,14 @@ } @include e(pager) { - display: inline-block; - height: 24px; + &:hover { + color: inherit; + cursor: inherit; + } > input { - box-sizing: border-box; - height: 100%; margin-right: 8px; - padding: 0 6px; + padding: 4px 6px; border-radius: 4px; outline: none; transition: border-color 0.3s; From dba929dc9fc89772471996311ce9b9a183fb1156 Mon Sep 17 00:00:00 2001 From: stbui Date: Thu, 26 Dec 2019 19:20:51 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20disable=E6=A0=B7=E5=BC=8F=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/pagination/PropsType.tsx | 18 + .../__snapshots__/index.test.jsx.snap | 2561 ++++++++++++++--- .../pagination/__tests__/index.test.jsx | 207 +- components/pagination/index.tsx | 39 +- components/pagination/style/index.scss | 28 +- components/pagination/style/mixins.scss | 22 +- 6 files changed, 2366 insertions(+), 509 deletions(-) diff --git a/components/pagination/PropsType.tsx b/components/pagination/PropsType.tsx index c35996c8..2f45f076 100644 --- a/components/pagination/PropsType.tsx +++ b/components/pagination/PropsType.tsx @@ -1,18 +1,36 @@ export default interface PropsType { + // 样式前缀 prefixCls?: string; + // 样式名 className?: string; + // 内联样式 style?: React.CSSProperties; + // 当前页 value?: number; + // 默认页 defaultValue?: number; + // 禁用 + disabled?: boolean; + // 本地化 locale?: { [propName: string]: any }; + // 每页条数 pageSize: number; + // 每页条数下拉框的选项 pageSizeOptions?: Array; + // 数据总数 total: number; + // 是否展示总数 showTotal?: boolean; + // 是否展示跳转 showQuickJumper?: boolean; + // 是否展示每页条数选择器 showPageSizeChanger?: boolean; + // 是否简洁分页 simple?: boolean; + // 分页器尺寸 size?: 'md' | 'sm'; + // 每页展示条数变更触发的事件 onPageSizeChange: (pageSize?: number) => void; + // 页面切换和跳转时触发的事件 onChange: (page?: number) => void; } diff --git a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap index 68d1ca8a..6f8648f5 100644 --- a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap +++ b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap @@ -1,466 +1,2189 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Pagination renders Pagination with customized props correctly 1`] = ` -
      -
    • - - - - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • -
    • - 10 -
    • -
    • - - - + + + + + + + + + + + +
    • +
    • + 1 +
    • +
    • + 2 +
    • +
    • + 3 +
    • +
    • + 4 +
    • +
    • + 5 +
    • +
    • - - -
    • -
    +
  • + 10 +
  • +
  • + + + + + + + + + + + +
  • +
  • +
    + 跳至 + + 页 +
    +
  • + +
    + + `; -exports[`Pagination renders Pagination with jumper correctly 1`] = ` -
      -
    • - - - + + + + + + + + + + + +
    • +
    • + 1 +
    • +
    • + 2 +
    • +
    • + 3 +
    • +
    • + 4 +
    • +
    • + 5 +
    • +
    • - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • -
    • - 10 -
    • -
    • + 10 +
    • +
    • + + + + + + + + + + + +
    • +
    +
    + + +`; + +exports[`Pagination renders Pagination with pageSize info correctly 1`] = ` + + - - - + + + + + + + + + + + + +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • - - -
  • -
  • -
    - 跳至 - - 页 -
    -
  • - +
  • + 10 +
  • +
  • + + + + + + + + + + + +
  • + +
    + + `; -exports[`Pagination renders Pagination with total info correctly 1`] = ` -
      -
    • - 共有 100 条记录 第 1 / 10 页 -
    • -
    • - - - + + + + + + + + + + + +
    • +
    • + 1 +
    • +
    • + 2 +
    • +
    • + 3 +
    • +
    • + 4 +
    • +
    • + 5 +
    • +
    • - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • -
    • - 10 -
    • -
    • + 10 +
    • +
    • + + + + + + + + + + + +
    • +
    +
    + + +`; + +exports[`Pagination renders Pagination with showPageSizeChanger info correctly 1`] = ` + + - - - + + + + + + + + + + + + +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • - - -
  • - +
  • + 10 +
  • +
  • + + + + + + + + + + + +
  • +
  • + + + + + +
  • + +
    + + `; -exports[`Pagination renders normal Pagination correctly 1`] = ` -
      -
    • - - - + 共有 100 条记录 + 第 1 / 10 页 +
    • +
    • + + + + + + + + + + + +
    • +
    • + 1 +
    • +
    • + 2 +
    • +
    • + 3 +
    • +
    • + 4 +
    • +
    • + 5 +
    • +
    • - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • -
    • - 10 -
    • -
    • + 10 +
    • +
    • + + + + + + + + + + + +
    • +
    +
    + + +`; + +exports[`Pagination renders Pagination with simple info correctly 1`] = ` + + - - - - - - - +
  • + + + + + + + + + + + +
  • +
  • + + + / + + 10 +
  • +
  • + + + + + + + + + + + +
  • + +
    + + `; exports[`Pagination renders size correctly 1`] = ` -
    -
      + -
    • - - - - - -
    • -
    • - 1 -
    • -
    • - 2 -
    • -
    • - 3 -
    • -
    • - 4 -
    • -
    • - 5 -
    • -
    • -
    • - 10 -
    • -
    • + + + +`; + +exports[`Pagination should render page total number 1`] = ` + + + - - - - - -
    • -
    -
    +
  • + + + + + + + + + + + +
  • +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • +
  • + 50 +
  • +
  • + + + + + + + + + + + +
  • + +
    + + `; diff --git a/components/pagination/__tests__/index.test.jsx b/components/pagination/__tests__/index.test.jsx index 6d79cd48..abdbace3 100644 --- a/components/pagination/__tests__/index.test.jsx +++ b/components/pagination/__tests__/index.test.jsx @@ -4,93 +4,129 @@ import toJson from 'enzyme-to-json'; import Pagination from '../index'; describe('Pagination', () => { - it('renders normal Pagination correctly', () => { - const wrapper = render(); + let wrapper; - expect(toJson(wrapper)).toMatchSnapshot(); + beforeEach(() => { + wrapper = mount(); }); - it('renders Pagination with total info correctly', () => { - const wrapper = render(); + afterEach(() => { + wrapper && wrapper.unmount(); + wrapper = null; + }); - expect(toJson(wrapper)).toMatchSnapshot(); + it('should receive className prop', () => { + wrapper.setProps({ + className: 'custom', + }); + expect(wrapper.find('.zw-pagination').hasClass('custom')); }); - it('renders Pagination with jumper correctly', () => { - const wrapper = render(); + it('should receive style prop', () => { + wrapper.setProps({ + style: { + color: 'red', + }, + }); + expect(wrapper.find('.zw-pagination').prop('style').color === 'red'); + }); + it('renders size correctly', () => { + wrapper.setProps({ + size: 'sm', + }); + + expect(wrapper.find('.zw-pagination--sm').length).toEqual(1); expect(toJson(wrapper)).toMatchSnapshot(); }); - it('renders Pagination with customized props correctly', () => { - const wrapper = render(); - + it('should render page total number', () => { + wrapper.setProps({ + total: 500, + }); expect(toJson(wrapper)).toMatchSnapshot(); }); - it('behaves correctly when changing page', () => { - const onChange = jest.fn(); - const wrapper = mount(); + it('should render by total', () => { + wrapper.setProps({ + total: 0, + }); + expect(wrapper.find('.zw-pagination__item').hostNodes().length === 0); - wrapper - .find('.zw-pagination__item') - .at(2) - .simulate('click'); + wrapper.setProps({ + total: 10, + }); + expect(wrapper.find('.zw-pagination__item zw-pagination__item--prev').hostNodes().length === 0); + expect(wrapper.find('.zw-pagination__item zw-pagination__item--next').hostNodes().length === 0); - expect(onChange).toHaveBeenCalledWith(2); + wrapper.setProps({ + total: 100, + }); + expect(wrapper.find('.zw-pagination__item').hostNodes().length === 9); }); - it('behaves correctly when click prev button', () => { - const onChange = jest.fn(); - const wrapper = mount( -
    - -
    , - ); - - wrapper.find('.zw-pagination__prev').simulate('click'); - - expect(onChange).toHaveBeenCalledWith(5); + it('should disable the previous button when current is the first page ', () => { + wrapper.setProps({ + current: 1, + }); + expect(wrapper.find('.zw-pagination__item zw-pagination__item--prev zw-pagination__item--disabled')); }); - it('behaves correctly when click next button', () => { - const onChange = jest.fn(); - const wrapper = mount( - , + it('should disable the next button when current is the last page', () => { + wrapper.setProps({ + current: 10, + total: 100, + }); + expect( + wrapper.find('.zw-pagination__item zw-pagination__item--next zw-pagination__item--disabled'), ); - - wrapper.find('.zw-pagination__next').simulate('click'); - - expect(onChange).toHaveBeenCalledWith(6); }); - it('behaves correctly when click prev 5 button', () => { + it('should not trigger onChange callback when input some text that can not conver to positive integer or current page', () => { const onChange = jest.fn(); - const wrapper = mount( - , - ); + wrapper.setProps({ + total: 100, + onChange, + }); - wrapper.find('.zw-pagination__prev').simulate('click'); + wrapper.find('.zw-pagination__item--prev').simulate('click'); + }); - expect(onChange).toHaveBeenCalledWith(5); + it('should disable the previous button when current is the first page ', () => { + wrapper.setProps({ current: 1 }); + expect(wrapper.find('.zw-pagination__item--prev')); }); - it('behaves correctly when click next 5 button', () => { + it('should not trigger onChange callback when click current page button', () => { const onChange = jest.fn(); - const wrapper = mount( - , - ); + wrapper.setProps({ + total: 100, + onChange, + }); + + wrapper + .find('.zw-pagination__item') + .hostNodes() + .at(0) + .simulate('click'); + }); - wrapper.find('.zw-pagination__next').simulate('click'); + it('renders Pagination with jumper correctly', () => { + wrapper.setProps({ + total: 100, + showQuickJumper: true, + }); - expect(onChange).toHaveBeenCalledWith(2); + expect(toJson(wrapper)).toMatchSnapshot(); }); it('behaves correctly when change page with jumper', () => { const onChange = jest.fn(); - const wrapper = mount( - , - ); + wrapper.setProps({ + total: 100, + showQuickJumper: true, + onChange, + }); wrapper.find('.zw-pagination__options--jumper input').simulate('keydown', { keyCode: 13, @@ -101,25 +137,58 @@ describe('Pagination', () => { expect(onChange).toHaveBeenCalledWith(6); }); - it('behaves correctly when receiving new value', () => { - const wrapper = mount(); + it('renders Pagination with pageSize info correctly', () => { + wrapper.setProps({ + total: 100, + pageSize: 10, + }); - wrapper.setProps({ value: 1 }); - expect( - wrapper - .find('.zw-pagination__item') - .at(1) - .hasClass('zw-pagination__item--active'), - ).toBeTruthy(); + expect(toJson(wrapper)).toMatchSnapshot(); }); - it('renders size correctly', () => { - const wrapper = render( -
    - -
    , - ); - expect(wrapper.find('.zw-pagination--sm').length).toEqual(1); + it('renders Pagination with simple info correctly', () => { + wrapper.setProps({ + total: 100, + simple: true, + }); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); + + it('renders Pagination with pageSizeOptions info correctly', () => { + wrapper.setProps({ + total: 100, + pageSizeOptions: [10, 20, 30, 40, 50], + }); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); + + it('renders Pagination with showTotal info correctly', () => { + wrapper.setProps({ + total: 100, + showTotal: true, + }); + expect(toJson(wrapper)).toMatchSnapshot(); }); + + it('renders Pagination with showPageSizeChanger info correctly', () => { + wrapper.setProps({ + total: 100, + showPageSizeChanger: true, + }); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); + + it('renders Pagination with onPageSizeChange info correctly', () => { + wrapper.setProps({ + total: 100, + onPageSizeChange: jest.fn(), + }); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); + }); diff --git a/components/pagination/index.tsx b/components/pagination/index.tsx index 9dabd83f..1795d3ad 100644 --- a/components/pagination/index.tsx +++ b/components/pagination/index.tsx @@ -10,15 +10,25 @@ const noop = () => {}; class Pagination extends Component { static defaultProps = { + // 样式前缀 prefixCls: 'zw-pagination', + // 默认页 defaultValue: 1, + // 数据总数 total: 0, + // 每页条数 pageSize: 10, + // 每页条数下拉框的选项 pageSizeOptions: [10, 20, 30, 40, 50], + // 是否展示总数 showTotal: false, + // 是否展示跳转 showQuickJumper: false, + // 是否展示每页条数选择器 showPageSizeChanger: false, + // 每页展示条数变更触发的事件 onPageSizeChange: noop, + // 页面切换和跳转时触发的事件 onChange: noop, }; @@ -39,6 +49,10 @@ class Pagination extends Component { return null; } + /** + * 根据总数计算分页数 + * @return {number} 返回分页数 + */ getPageSize = () => { const { total, pageSize } = this.props; return Math.ceil(total / pageSize); @@ -88,7 +102,7 @@ class Pagination extends Component { }; renderSimple = () => { - const { prefixCls } = this.props; + const { prefixCls, disabled } = this.props; const pagerList: JSX.Element[] = []; const pageCount = this.getPageSize(); const { currentInputValue } = this.state; @@ -107,6 +121,7 @@ class Pagination extends Component { value={currentInputValue} onChange={this.handleJumpChange} onKeyDown={this.handleJumpKeyDown} + disabled={disabled} /> {pageCount} @@ -150,8 +165,8 @@ class Pagination extends Component { const { prefixCls, locale } = this.props; const cls = classnames({ [`${prefixCls}__item`]: true, - [`${prefixCls}__prev`]: true, - [`${prefixCls}--disabled`]: Number(page) === 1, + [`${prefixCls}__item--prev`]: true, + [`${prefixCls}__item--disabled`]: Number(page) === 1, }); return ( @@ -170,8 +185,8 @@ class Pagination extends Component { const { prefixCls, locale } = this.props; const cls = classnames({ [`${prefixCls}__item`]: true, - [`${prefixCls}__next`]: true, - [`${prefixCls}--disabled`]: Number(page) === pageSize, + [`${prefixCls}__item--next`]: true, + [`${prefixCls}__item--disabled`]: Number(page) === pageSize, }); return ( @@ -220,6 +235,9 @@ class Pagination extends Component { ); }; + /** + * 指定跳转页码 + */ handleJumpChange = ({ target: { value } }) => { const sValue = parseInt(value, 10); if (typeof sValue !== 'number') { @@ -254,7 +272,10 @@ class Pagination extends Component { }; _onPagerClick(value: number) { - const { onChange } = this.props; + const { onChange, disabled } = this.props; + if (disabled) { + return false; + } this.setState({ value, @@ -268,7 +289,7 @@ class Pagination extends Component { const { prefixCls } = this.props; const cls = classnames({ [`${prefixCls}__item`]: true, - [`${prefixCls}--active`]: page === i, + [`${prefixCls}__item--active`]: page === i, }); return ( @@ -309,6 +330,7 @@ class Pagination extends Component { onChange, locale, pageSize, + disabled, } = this.props; let { pageSizeOptions } = this.props; let defaultPageSize = pageSizeOptions && pageSizeOptions.length > 0 && pageSizeOptions[0]; @@ -323,6 +345,7 @@ class Pagination extends Component { className={`${prefixCls}__options--changer`} defaultValue={defaultPageSize} value={pageSize === 10 ? defaultPageSize : pageSize} + disabled={disabled} onChange={({ value }: any) => { if (value === pageSize) { return; @@ -369,11 +392,13 @@ class Pagination extends Component { showPageSizeChanger, simple, size, + disabled, style, } = this.props; const cls = classnames({ [prefixCls!]: true, + [`${prefixCls}--disabled`]: !!disabled, [`${prefixCls}--${size}`]: !!size, [`${prefixCls}--simple`]: simple, [className!]: !!className, diff --git a/components/pagination/style/index.scss b/components/pagination/style/index.scss index e2bd1809..c79dd86b 100644 --- a/components/pagination/style/index.scss +++ b/components/pagination/style/index.scss @@ -1,5 +1,5 @@ -@import '../../style/core/index'; -@import 'mixins'; +@import "../../style/core/index"; +@import "mixins"; @include b(pagination) { margin: 0; @@ -48,22 +48,24 @@ } @include m(disabled) { - &, + background-color: var(--opacity-disabled); + color: var(--color-text); + opacity: var(--opacity-disabled); + cursor: not-allowed; + &:active, - &:hover, &:focus, + &:hover, &:visited { - color: var(--color-text-disabled); - cursor: not-allowed; + background-color: var(--opacity-disabled); + color: var(--color-text); } - } - - @include m(active) { - background-color: var(--pagination-default-active-background); - &, - &:hover { - color: #fff; + @include e(item) { + cursor: not-allowed; + &:hover { + color: inherit; + } } } } diff --git a/components/pagination/style/mixins.scss b/components/pagination/style/mixins.scss index 4ff44103..1013339a 100644 --- a/components/pagination/style/mixins.scss +++ b/components/pagination/style/mixins.scss @@ -28,6 +28,26 @@ color: $hover-color; } + @include m(disabled) { + &, + &:active, + &:hover, + &:focus, + &:visited { + color: var(--color-text-disabled); + cursor: not-allowed; + } + } + + @include m(active) { + background-color: var(--pagination-default-active-background); + + &, + &:hover { + color: #fff; + } + } + @include m(ellipsis) { background-color: transparent; @@ -100,7 +120,7 @@ font-size: $font-size; } - @include b(pagination--active) { + @include e(item--active) { background-color: var(--pagination-default-active-background); &, From f94acc37944b7ff21173092f6c5ae61c583366f2 Mon Sep 17 00:00:00 2001 From: stbui Date: Wed, 22 Jan 2020 14:01:28 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix(pagination):=20css=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/pagination/index.tsx | 7 ++- components/pagination/style/index.scss | 21 ++++--- components/pagination/style/mixins.scss | 73 ++++++++++--------------- 3 files changed, 46 insertions(+), 55 deletions(-) diff --git a/components/pagination/index.tsx b/components/pagination/index.tsx index 1795d3ad..9185651c 100644 --- a/components/pagination/index.tsx +++ b/components/pagination/index.tsx @@ -116,6 +116,7 @@ class Pagination extends Component { className={`${prefixCls}__item ${prefixCls}__pager`} > { } renderPager = (i: number, page: number) => { - const { prefixCls } = this.props; + const { prefixCls, disabled } = this.props; const cls = classnames({ [`${prefixCls}__item`]: true, - [`${prefixCls}__item--active`]: page === i, + [`${prefixCls}__item--active`]: page === i && !disabled, }); return ( @@ -376,7 +377,7 @@ class Pagination extends Component {
  • {locale!.goto} - + {locale!.pageClassifier}
  • diff --git a/components/pagination/style/index.scss b/components/pagination/style/index.scss index c79dd86b..36cb60e0 100644 --- a/components/pagination/style/index.scss +++ b/components/pagination/style/index.scss @@ -19,15 +19,24 @@ ); } + @include e(input) { + @include pagination-input( + var(--pagination-height-md), + var(--pagination-height-md), + var(--radius-md), + var(--pagination-default-bg-color) + ); + } + @include e(total) { - @include pagination-total(var(--pagination-font-size-md)); + @include pagination-total(); } @include e(options) { @include pagination-options( var(--pagination-default-bg-color), - var(--pagination-font-size-sm), - var(--radius-md) + var(--radius-md), + var(--pagination-height-md) ); } @@ -40,11 +49,7 @@ } @include m(simple) { - @include pagination-simple( - var(--pagination-default-bg-color), - var(--pagination-height-md), - var(--pagination-font-size-md) - ); + @include pagination-simple(var(--pagination-height-sm)); } @include m(disabled) { diff --git a/components/pagination/style/mixins.scss b/components/pagination/style/mixins.scss index 1013339a..42733a30 100644 --- a/components/pagination/style/mixins.scss +++ b/components/pagination/style/mixins.scss @@ -66,42 +66,27 @@ } } -@mixin pagination-total($font-size) { +@mixin pagination-total() { display: inline-block; vertical-align: middle; padding-right: 8px; - color: #999; - font-size: $font-size; } -@mixin pagination-options($background, $font-size, $radius) { +@mixin pagination-options($background, $radius, $height) { display: inline-block; margin-left: 8px; vertical-align: middle; - @include m(changer) { - font-size: $font-size; - } + // select + // @include m(changer) { + // } @include m(jumper) { display: inline-block; - - > input { - position: relative; - display: inline-block; - width: 48px; - height: 24px; - margin: 0 8px; - text-align: center; - border-radius: $radius; - font-size: $font-size; - border: 1px solid $background; - background-color: $background; - } } @include m(slash) { - margin: 0 10px 0 5px; + margin: 0 16px 0 16px; } } @@ -111,7 +96,7 @@ min-width: $height; height: $height; line-height: $height; - margin: 0; + margin-right: 6px; display: inline-flex; align-items: center; } @@ -132,23 +117,17 @@ @include e(total) { height: $height; line-height: $height; - font-size: $font-size; } -} -@mixin pagination-simple($background, $height, $font-size) { - @include e(item) { - background-color: transparent; - min-width: $height; + @include e(input) { height: $height; - line-height: $height; - margin: 0; - font-size: $font-size; - vertical-align: top; } +} - @include e(item--icon) { - font-size: $font-size; +@mixin pagination-simple($height) { + @include e(item) { + margin: 0; + background-color: transparent; } @include e(pager) { @@ -156,16 +135,22 @@ color: inherit; cursor: inherit; } + } - > input { - margin-right: 8px; - padding: 4px 6px; - border-radius: 4px; - outline: none; - transition: border-color 0.3s; - text-align: center; - border: 1px solid $background; - background-color: $background; - } + @include e(input) { + height: $height; + margin: 0; } } + +@mixin pagination-input($width, $height, $radius, $background) { + position: relative; + display: inline-block; + width: 48px; + height: $height; + margin: 0 8px; + text-align: center; + border-radius: $radius; + border: 1px solid $background; + background-color: $background; +} From 8f41b9ca60b68984e8ae96d9606a7591a6551da7 Mon Sep 17 00:00:00 2001 From: stbui Date: Wed, 22 Jan 2020 14:13:16 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(pagination):=20css=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pagination/__tests__/__snapshots__/index.test.jsx.snap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap index 6f8648f5..e0d36dc4 100644 --- a/components/pagination/__tests__/__snapshots__/index.test.jsx.snap +++ b/components/pagination/__tests__/__snapshots__/index.test.jsx.snap @@ -209,6 +209,7 @@ exports[`Pagination renders Pagination with jumper correctly 1`] = ` > 跳至 @@ -1862,6 +1863,7 @@ exports[`Pagination renders Pagination with simple info correctly 1`] = ` title="1/10" >