Files
react/components/pagination/pagination.tsx
witt 6da0509316 release 2.1.0 (#451)
* feat: optimize fonts rendering on windows (#385)

* feat(styles): set Inter to highest font

* docs(fonts): add guide for fonts rendering on windows

* test: udpate snapshots

* chore: release v2.1.0-canary.0

* feat(table): add update row action to Table (#378)

* feat: add update to Table's actions. add test and doc

fix(table): fix comments

* feat(table): improve type for table actions

chore: update docs

chore: remove unused types

chore(table): improve docs

Co-authored-by: William Castandet <williamcastandet@williams-air.home>
Co-authored-by: unix <unix.bio@gmail.com>

* refactor(use-theme): move use-theme to the top directory (#397)

* refactor(use-theme): move use-theme to the top directory

* chore(jest): ignore use-theme of forwarding

* chore: release v2.1.0-canary.1

* feat(select): add clearable option to select multiple with test and english doc (#396)

* docs: add clearable option to select multiple with test and english doc

* fix: fix types for onClear

* fix: fix import path for use-theme

add more test for coverage

* docs(select): add chinese document

Co-authored-by: unix <unix.bio@gmail.com>

* chore: release v2.1.0-canary.2

* fix(tabs): scrollable (#404)

docs(tabs): scroll behavior

* feat(textarea): resize prop (#416)

* feat: add resize prop to textarea

* docs: add resize prop for textarea

* docs(textarea): improve docs and attributes for cn

* test(textarea): update snapshots

Co-authored-by: unix <unix.bio@gmail.com>

* fix(types): replace path aliases in type files (#432)

* fix(types): replace path aliases in type files

* chore(lint): upgrade eslint and optimize code style

* chore: fix type error for context handler

* test: update snapshots

* fix: use ttsc to identify aliases in type paths

* feat(hooks): add a tool hooks for react context (#439)

* feat(hooks): add a tool hooks for react context

* chore: move use-context-state to internal tools

style: fix lint warning

* chore: simplify the structure of the catalog

* refactor(themes): refactor theme module to keep multiple themes (#440)

* refactor(themes): refactor theme module to keep multiple themes

* chore: migrate APIs to be compatible with new theme system

* test: update snapshots

* chore: migrate the path of the theme module

* feat(themes): append static methods of themes

* chore: hide custom theme when no custom content in the context

* chore: manually add flush to preload styles in html

* docs(themes): update to fit the new theme system

* chore: release v2.1.0-canary.3 (#450)

* docs: add link to GH discussions

* chore: upgrade deps

* chore: update code style for prettier

* chore: release v2.1.0-canary.3

* chore(deps): upgrade babel

* chore: replace enzyme adapter with community repo to fit react.17

* test: updatee snapshots for auto typesetting

* test(config): ignore unexported parts of the tools

Co-authored-by: William <wcastand@gmail.com>
Co-authored-by: William Castandet <williamcastandet@williams-air.home>
Co-authored-by: Vaibhav Acharya <vaibhavacharya111@gmail.com>
Co-authored-by: Paul van Dyk <39598117+PaulPCIO@users.noreply.github.com>
2021-02-14 15:58:52 +08:00

147 lines
3.6 KiB
TypeScript

import React, { useEffect, useMemo } from 'react'
import PaginationPrevious from './pagination-previous'
import PaginationNext from './pagination-next'
import PaginationPages from './pagination-pages'
import {
PaginationContext,
PaginationConfig,
PaginationUpdateType,
} from './pagination-context'
import useCurrentState from '../utils/use-current-state'
import { pickChild } from '../utils/collections'
import { NormalSizes } from '../utils/prop-types'
interface Props {
size?: NormalSizes
page?: number
initialPage?: number
count?: number
limit?: number
onChange?: (val: number) => void
}
const defaultProps = {
size: 'medium' as NormalSizes,
initialPage: 1,
count: 1,
limit: 7,
}
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
export type PaginationProps = Props & typeof defaultProps & NativeAttrs
type PaginationSize = {
font: string
width: string
}
const getPaginationSizes = (size: NormalSizes) => {
const sizes: { [key in NormalSizes]: PaginationSize } = {
mini: {
font: '.75rem',
width: '1.25rem',
},
small: {
font: '.75rem',
width: '1.65rem',
},
medium: {
font: '.875rem',
width: '2rem',
},
large: {
font: '1rem',
width: '2.4rem',
},
}
return sizes[size]
}
const Pagination: React.FC<React.PropsWithChildren<PaginationProps>> = ({
page: customPage,
initialPage,
count,
limit,
size,
children,
onChange,
}) => {
const [page, setPage, pageRef] = useCurrentState(initialPage)
const [, prevChildren] = pickChild(children, PaginationPrevious)
const [, nextChildren] = pickChild(children, PaginationNext)
const [prevItem, nextItem] = useMemo(() => {
const hasChildren = (c: any) => React.Children.count(c) > 0
const prevDefault = <PaginationPrevious>prev</PaginationPrevious>
const nextDefault = <PaginationNext>next</PaginationNext>
return [
hasChildren(prevChildren) ? prevChildren : prevDefault,
hasChildren(nextChildren) ? nextChildren : nextDefault,
]
}, [prevChildren, nextChildren])
const { font, width } = useMemo(() => getPaginationSizes(size), [size])
const update = (type: PaginationUpdateType) => {
if (type === 'prev' && pageRef.current > 1) {
setPage(last => last - 1)
}
if (type === 'next' && pageRef.current < count) {
setPage(last => last + 1)
}
}
const values = useMemo<PaginationConfig>(
() => ({
isFirst: page <= 1,
isLast: page >= count,
update,
}),
[page],
)
useEffect(() => {
onChange && onChange(page)
}, [page])
useEffect(() => {
if (customPage !== undefined) {
setPage(customPage)
}
}, [customPage])
return (
<PaginationContext.Provider value={values}>
<nav>
{prevItem}
<PaginationPages count={count} current={page} limit={limit} setPage={setPage} />
{nextItem}
</nav>
<style jsx>{`
nav {
margin: 0;
padding: 0;
font-variant: tabular-nums;
font-feature-settings: 'tnum';
font-size: ${font};
--pagination-size: ${width};
}
nav :global(button:last-of-type) {
margin-right: 0;
}
`}</style>
</PaginationContext.Provider>
)
}
type MemoPaginationComponent<P = {}> = React.NamedExoticComponent<P> & {
Previous: typeof PaginationPrevious
Next: typeof PaginationNext
}
type ComponentProps = Partial<typeof defaultProps> &
Omit<Props, keyof typeof defaultProps> &
NativeAttrs
Pagination.defaultProps = defaultProps
export default React.memo(Pagination) as MemoPaginationComponent<ComponentProps>