Skip to content

Commit

Permalink
feat(pagination): refactor pagination into low-level
Browse files Browse the repository at this point in the history
  • Loading branch information
bryceosterhaus committed Oct 9, 2019
1 parent bbca4da commit e14281f
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 138 deletions.
File renamed without changes.
File renamed without changes.
148 changes: 25 additions & 123 deletions packages/clay-pagination/src/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,141 +4,43 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

import ClayIcon from '@clayui/icon';
import {getEllipsisItems} from '@clayui/shared';
import classNames from 'classnames';
import React from 'react';

import PaginationEllipsis from './PaginationEllipsis';
import PaginationItem from './PaginationItem';

const ELLIPSIS_BUFFER = 2;
import Ellipsis from './Ellipsis';
import Item from './Item';

interface IProps extends React.HTMLAttributes<HTMLUListElement> {
/**
* The page that is currently active. The first page is `1`.
*/
activePage: number;

/**
* The number of pages to show on each side of the active page before
* using an ellipsis dropdown.
*/
ellipsisBuffer?: number;

/**
* The page numbers that should be disabled. For example, `[2,5,6]`.
*/
disabledPages?: Array<number>;

/**
* Function used to create the href provided for each page link.
*/
hrefConstructor?: (page?: number) => string;

/**
* Callback for when the active page changes. This is only used if
* an href is not provided.
*/
onPageChange?: (page?: number) => void;

/**
* The total number of pages in the pagination list.
*/
totalPages: number;

/**
* The size of pagination element.
*/
size?: 'lg' | 'sm';

/**
* Path to spritemap from clay-css.
*/
spritemap?: string;
}

const ClayPagination: React.FunctionComponent<IProps> = ({
activePage,
className,
disabledPages = [],
ellipsisBuffer = ELLIPSIS_BUFFER,
hrefConstructor,
onPageChange,
size,
spritemap,
totalPages,
}: IProps) => {
const previousPage = activePage - 1;
const previousHref = hrefConstructor && hrefConstructor(previousPage);

const nextPage = activePage + 1;
const nextHref = hrefConstructor && hrefConstructor(nextPage);

const pages = Array(totalPages)
.fill(0)
.map((item, index) => index + 1);

return (
<ul
className={classNames('pagination pagination-root', className, {
[`pagination-${size}`]: size,
})}
>
<PaginationItem
data-testid="prevArrow"
disabled={activePage === 1}
href={previousHref}
onClick={() => onPageChange && onPageChange(previousPage)}
>
<ClayIcon spritemap={spritemap} symbol="angle-left" />
</PaginationItem>

{(ellipsisBuffer
? getEllipsisItems(
{
EllipsisComponent: PaginationEllipsis,
ellipsisProps: {
disabledPages,
hrefConstructor,
onPageChange,
},
items: pages,
},
ellipsisBuffer,
activePage - 1
)
: pages
).map((page: number | JSX.Element | Object, index: number) =>
React.isValidElement(page) ? (
React.cloneElement(page, {key: `ellipsis${index}`})
) : (
<PaginationItem
active={page === activePage}
disabled={disabledPages.includes(page as number)}
href={
hrefConstructor && hrefConstructor(page as number)
}
key={page as number}
onClick={() =>
onPageChange && onPageChange(page as number)
}
>
{page}
</PaginationItem>
)
)}
type TPagination = React.ForwardRefExoticComponent<
IProps & React.RefAttributes<HTMLUListElement>
> & {
Ellipsis: typeof Ellipsis;
Item: typeof Item;
};

<PaginationItem
data-testid="nextArrow"
disabled={activePage === totalPages}
href={nextHref}
onClick={() => onPageChange && onPageChange(nextPage)}
const ClayPagination = React.forwardRef(
({children, className, size, ...otherProps}: IProps, ref) => {
return (
<ul
{...otherProps}
className={classNames('pagination pagination-root', className, {
[`pagination-${size}`]: size,
})}
ref={ref}
>
<ClayIcon spritemap={spritemap} symbol="angle-right" />
</PaginationItem>
</ul>
);
};
{children}
</ul>
);
}
) as TPagination;

ClayPagination.Ellipsis = Ellipsis;
ClayPagination.Item = Item;

export default ClayPagination;
4 changes: 2 additions & 2 deletions packages/clay-pagination/src/PaginationWithBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {sub} from '@clayui/shared';
import classNames from 'classnames';
import React from 'react';

import ClayPagination from './Pagination';
import {ClayPaginationWithBasicItems} from './PaginationWithBasicItems';

const defaultDeltas = [
{
Expand Down Expand Up @@ -196,7 +196,7 @@ export const ClayPaginationWithBar: React.FunctionComponent<IProps> = ({
])}
</div>

<ClayPagination
<ClayPaginationWithBasicItems
activePage={activePage}
disabledPages={disabledPages}
ellipsisBuffer={ellipsisBuffer}
Expand Down
139 changes: 139 additions & 0 deletions packages/clay-pagination/src/PaginationWithBasicItems.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* © 2019 Liferay, Inc. <https://liferay.com>
*
* SPDX-License-Identifier: BSD-3-Clause
*/

import ClayIcon from '@clayui/icon';
import {getEllipsisItems} from '@clayui/shared';
import React from 'react';

import Pagination from './Pagination';

const ELLIPSIS_BUFFER = 2;

interface IProps extends React.ComponentProps<typeof Pagination> {
/**
* The page that is currently active. The first page is `1`.
*/
activePage: number;

/**
* The number of pages to show on each side of the active page before
* using an ellipsis dropdown.
*/
ellipsisBuffer?: number;

/**
* The page numbers that should be disabled. For example, `[2,5,6]`.
*/
disabledPages?: Array<number>;

/**
* Function used to create the href provided for each page link.
*/
hrefConstructor?: (page?: number) => string;

/**
* Callback for when the active page changes. This is only used if
* an href is not provided.
*/
onPageChange?: (page?: number) => void;

/**
* The total number of pages in the pagination list.
*/
totalPages: number;

/**
* Path to spritemap from clay-css.
*/
spritemap?: string;
}

export const ClayPaginationWithBasicItems = React.forwardRef<
HTMLUListElement,
IProps
>(
(
{
activePage,
disabledPages = [],
ellipsisBuffer = ELLIPSIS_BUFFER,
hrefConstructor,
onPageChange,
spritemap,
totalPages,
...otherProps
},
ref
) => {
const previousPage = activePage - 1;
const previousHref = hrefConstructor && hrefConstructor(previousPage);

const nextPage = activePage + 1;
const nextHref = hrefConstructor && hrefConstructor(nextPage);

const pages = Array(totalPages)
.fill(0)
.map((item, index) => index + 1);

return (
<Pagination {...otherProps} ref={ref}>
<Pagination.Item
data-testid="prevArrow"
disabled={activePage === 1}
href={previousHref}
onClick={() => onPageChange && onPageChange(previousPage)}
>
<ClayIcon spritemap={spritemap} symbol="angle-left" />
</Pagination.Item>

{(ellipsisBuffer
? getEllipsisItems(
{
EllipsisComponent: Pagination.Ellipsis,
ellipsisProps: {
disabledPages,
hrefConstructor,
onPageChange,
},
items: pages,
},
ellipsisBuffer,
activePage - 1
)
: pages
).map((page: number | JSX.Element | Object, index: number) =>
React.isValidElement(page) ? (
React.cloneElement(page, {key: `ellipsis${index}`})
) : (
<Pagination.Item
active={page === activePage}
disabled={disabledPages.includes(page as number)}
href={
hrefConstructor &&
hrefConstructor(page as number)
}
key={page as number}
onClick={() =>
onPageChange && onPageChange(page as number)
}
>
{page}
</Pagination.Item>
)
)}

<Pagination.Item
data-testid="nextArrow"
disabled={activePage === totalPages}
href={nextHref}
onClick={() => onPageChange && onPageChange(nextPage)}
>
<ClayIcon spritemap={spritemap} symbol="angle-right" />
</Pagination.Item>
</Pagination>
);
}
);
3 changes: 2 additions & 1 deletion packages/clay-pagination/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

import ClayPagination from './Pagination';
import {ClayPaginationWithBar} from './PaginationWithBar';
import {ClayPaginationWithBasicItems} from './PaginationWithBasicItems';

export {ClayPaginationWithBar};
export {ClayPaginationWithBar, ClayPaginationWithBasicItems};

export default ClayPagination;
Loading

0 comments on commit e14281f

Please sign in to comment.