-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(pagination): ✨ initiate pagination
- Loading branch information
1 parent
4826556
commit 36e4513
Showing
8 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { BoxHTMLProps, BoxOptions, useBox } from "reakit"; | ||
import { createComponent, createHook } from "reakit-system"; | ||
|
||
import { PAGINATION_KEYS } from "./__keys"; | ||
import { PaginationStateReturn } from "./PaginationState"; | ||
|
||
export type PaginationOptions = BoxOptions & PaginationStateReturn; | ||
|
||
export type PaginationHTMLProps = BoxHTMLProps; | ||
|
||
export type PaginationProps = PaginationOptions & PaginationHTMLProps; | ||
|
||
export const usePagination = createHook<PaginationOptions, PaginationHTMLProps>( | ||
{ | ||
name: "Pagination", | ||
compose: useBox, | ||
keys: PAGINATION_KEYS, | ||
|
||
useProps(_, htmlProps) { | ||
return { "aria-label": "pagination navigation", ...htmlProps }; | ||
}, | ||
}, | ||
); | ||
|
||
export const Pagination = createComponent({ | ||
as: "nav", | ||
memo: true, | ||
useHook: usePagination, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { callAllHandlers } from "@chakra-ui/utils"; | ||
import React from "react"; | ||
import { createComponent, createHook } from "reakit-system"; | ||
import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit"; | ||
|
||
import { PAGINATION_KEYS } from "./__keys"; | ||
import { PaginationStateReturn } from "./PaginationState"; | ||
|
||
export type PaginationItemOptions = ButtonOptions & | ||
PaginationStateReturn & { | ||
page: number; | ||
}; | ||
|
||
export type PaginationItemHTMLProps = ButtonHTMLProps; | ||
|
||
export type PaginationItemProps = PaginationItemOptions & | ||
PaginationItemHTMLProps; | ||
|
||
export const usePaginationItem = createHook< | ||
PaginationItemOptions, | ||
PaginationItemHTMLProps | ||
>({ | ||
name: "PaginationItem", | ||
compose: useButton, | ||
keys: PAGINATION_KEYS, | ||
|
||
useProps( | ||
{ currentPage, page, goTo }, | ||
{ onClick: htmlOnClick, ...htmlProps }, | ||
) { | ||
const isCurrent = currentPage === page; | ||
|
||
const onClick = React.useCallback(() => { | ||
if (!isCurrent) { | ||
goTo?.(page); | ||
} | ||
}, [goTo, isCurrent, page]); | ||
|
||
return { | ||
"aria-label": isCurrent ? `Page ${page}` : `Go to Page ${page}`, | ||
"aria-current": isCurrent ? true : undefined, | ||
onClick: callAllHandlers(onClick, htmlOnClick), | ||
...htmlProps, | ||
}; | ||
}, | ||
}); | ||
|
||
export const PaginationItem = createComponent({ | ||
as: "button", | ||
memo: true, | ||
useHook: usePaginationItem, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React from "react"; | ||
import { callAllHandlers } from "@chakra-ui/utils"; | ||
import { createComponent, createHook } from "reakit-system"; | ||
import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit"; | ||
|
||
import { PAGINATION_KEYS } from "./__keys"; | ||
import { PaginationStateReturn } from "./PaginationState"; | ||
|
||
export type PaginationNextOptions = ButtonOptions & PaginationStateReturn; | ||
|
||
export type PaginationNextHTMLProps = ButtonHTMLProps; | ||
|
||
export type PaginationNextProps = PaginationNextOptions & | ||
PaginationNextHTMLProps; | ||
|
||
export const usePaginationNext = createHook< | ||
PaginationNextOptions, | ||
PaginationNextHTMLProps | ||
>({ | ||
name: "PaginationNext", | ||
compose: useButton, | ||
keys: PAGINATION_KEYS, | ||
|
||
useOptions(options, htmlProps) { | ||
return { disabled: htmlProps.disabled || options.isAtMax, ...options }; | ||
}, | ||
|
||
useProps({ next }, { onClick: htmlOnClick, ...htmlProps }) { | ||
return { | ||
"aria-label": "Next Page", | ||
onClick: callAllHandlers(htmlOnClick, next), | ||
...htmlProps, | ||
}; | ||
}, | ||
}); | ||
|
||
export const PaginationNext = createComponent({ | ||
as: "button", | ||
memo: true, | ||
useHook: usePaginationNext, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { callAllHandlers } from "@chakra-ui/utils"; | ||
import React from "react"; | ||
import { createComponent, createHook } from "reakit-system"; | ||
import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit"; | ||
|
||
import { PAGINATION_KEYS } from "./__keys"; | ||
import { PaginationStateReturn } from "./PaginationState"; | ||
|
||
export type PaginationPrevOptions = ButtonOptions & PaginationStateReturn; | ||
|
||
export type PaginationPrevHTMLProps = ButtonHTMLProps; | ||
|
||
export type PaginationPrevProps = PaginationPrevOptions & | ||
PaginationPrevHTMLProps; | ||
|
||
export const usePaginationPrev = createHook< | ||
PaginationPrevOptions, | ||
PaginationPrevHTMLProps | ||
>({ | ||
name: "PaginationPrev", | ||
compose: useButton, | ||
keys: PAGINATION_KEYS, | ||
|
||
useOptions(options, htmlProps) { | ||
return { disabled: htmlProps.disabled || options.isAtMin, ...options }; | ||
}, | ||
|
||
useProps({ prev }, { onClick: htmlOnClick, ...htmlProps }) { | ||
return { | ||
"aria-label": "Previous Page", | ||
onClick: callAllHandlers(htmlOnClick, prev), | ||
...htmlProps, | ||
}; | ||
}, | ||
}); | ||
|
||
export const PaginationPrev = createComponent({ | ||
as: "button", | ||
memo: true, | ||
useHook: usePaginationPrev, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React from "react"; | ||
|
||
export interface UsePaginationProps { | ||
totalItems?: number; | ||
perPage?: number; | ||
defaultPage?: number; | ||
} | ||
|
||
export const usePaginationState = (props: UsePaginationProps = {}) => { | ||
const { | ||
totalItems = 50, | ||
perPage = 10, | ||
defaultPage: currentPageProp = 1, | ||
} = props; | ||
|
||
const totalPages = Math.ceil(totalItems / perPage); | ||
console.log("%c totalPages", "color: #aa00ff", totalPages); | ||
|
||
const [currentPage, setCurrentPage] = React.useState(currentPageProp); | ||
|
||
const pages = Array(totalPages) | ||
.fill("") | ||
.map((_, i) => i + 1); | ||
|
||
const isAtMax = currentPage >= totalPages; | ||
const isAtMin = currentPage <= 1; | ||
|
||
const next = React.useCallback(() => { | ||
setCurrentPage(prevPage => prevPage + 1); | ||
}, []); | ||
|
||
const prev = React.useCallback(() => { | ||
setCurrentPage(prevPage => prevPage - 1); | ||
}, []); | ||
|
||
const goTo = React.useCallback(page => { | ||
setCurrentPage(page); | ||
}, []); | ||
|
||
return { currentPage, isAtMax, isAtMin, next, prev, goTo, pages }; | ||
}; | ||
|
||
export type PaginationStateReturn = ReturnType<typeof usePaginationState>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const PAGINATION_STATE_KEYS = [ | ||
"currentPage", | ||
"isAtMin", | ||
"isAtMax", | ||
"next", | ||
"prev", | ||
"goTo", | ||
"id", | ||
"page", | ||
"pages", | ||
] as const; | ||
|
||
export const PAGINATION_KEYS = PAGINATION_STATE_KEYS; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import React from "react"; | ||
|
||
import { Meta } from "@storybook/react"; | ||
import { Pagination } from "../Pagination"; | ||
import { PaginationPrev } from "../PaginationPrev"; | ||
import { PaginationNext } from "../PaginationNext"; | ||
import { PaginationItem } from "../PaginationItem"; | ||
import { usePaginationState } from "../PaginationState"; | ||
|
||
export default { | ||
title: "Component/Pagination", | ||
} as Meta; | ||
|
||
// export const Default = () => { | ||
// const state = usePaginationState(); | ||
// console.log("%c state", "color: #00a3cc", state); | ||
|
||
// return ( | ||
// <Pagination {...state}> | ||
// <ul> | ||
// <li> | ||
// <PaginationPrev {...state}>{"<"}</PaginationPrev> | ||
// </li> | ||
// <li> | ||
// <PaginationItem page={1} {...state}> | ||
// 1 | ||
// </PaginationItem> | ||
// </li> | ||
// <li> | ||
// <PaginationItem page={2} {...state}> | ||
// 2 | ||
// </PaginationItem> | ||
// </li> | ||
// <li> | ||
// <PaginationItem page={3} {...state}> | ||
// 3 | ||
// </PaginationItem> | ||
// </li> | ||
// <li> | ||
// <PaginationItem page={4} {...state}> | ||
// 4 | ||
// </PaginationItem> | ||
// </li> | ||
// <li> | ||
// <PaginationItem page={5} {...state}> | ||
// 5 | ||
// </PaginationItem> | ||
// </li> | ||
// <li> | ||
// <PaginationNext {...state}>{">"}</PaginationNext> | ||
// </li> | ||
// </ul> | ||
// </Pagination> | ||
// ); | ||
// }; | ||
|
||
export const Dynamic = () => { | ||
const state = usePaginationState(); | ||
console.log("%c state", "color: #00fe600", state); | ||
|
||
return ( | ||
<Pagination {...state}> | ||
<ul> | ||
<li> | ||
<PaginationPrev {...state}>{"<"}</PaginationPrev> | ||
</li> | ||
{state.pages.map(page => ( | ||
<li> | ||
<PaginationItem | ||
page={page} | ||
style={{ | ||
fontWeight: state.currentPage === page ? "bold" : undefined, | ||
}} | ||
{...state} | ||
> | ||
{page} | ||
</PaginationItem> | ||
</li> | ||
))} | ||
<li> | ||
<PaginationNext {...state}>{">"}</PaginationNext> | ||
</li> | ||
</ul> | ||
</Pagination> | ||
); | ||
}; |