koval-ui
Version:
React components collection with minimalistic design. Supports theming, layout, and input validation.
1 lines • 12.9 kB
Source Map (JSON)
{"version":3,"file":"Pagination.cjs","sources":["../../../../src/lib/Pagination/Pagination.tsx"],"sourcesContent":["import type {ReactNode, ChangeEvent, KeyboardEvent} from 'react';\nimport {useMemo} from 'react';\nimport {useCallback, useEffect, useState, Fragment, forwardRef} from 'react';\nimport classNames from 'classnames';\nimport {useLocalTheme} from 'css-vars-hook';\n\nimport type {DataAttributes, LibraryProps} from '@/internal/LibraryAPI';\nimport {createArray} from '@/internal/utils/createArray.ts';\nimport {IconForward, IconBackward, IconEnter} from '@/internal/Icons';\n\nimport {PageButton} from './PageButton.tsx';\nimport {usePagePaginationState} from './usePagePaginationState.ts';\nimport classes from './Pagination.module.css';\n\nexport type Props = DataAttributes &\n LibraryProps & {\n children?: ReactNode;\n /** Set the total number of pages */\n totalPages: number;\n /** Callback to run on page change */\n onPageSelect: (pageNumber: number) => void;\n /** Set the selected page externally */\n selectedPage: number;\n /** Show the navigation block on the right */\n showNavigation?: boolean;\n /** Show page number buttons on the left */\n showPageButtons?: boolean;\n };\n\nexport const Pagination = forwardRef<HTMLDivElement, Props>(\n (\n {\n children,\n className,\n totalPages,\n onPageSelect,\n selectedPage: selectedPageProp,\n showNavigation = true,\n showPageButtons = true,\n ...nativeProps\n },\n ref\n ) => {\n const {\n visible,\n first,\n last,\n selectedPage,\n setSelectedPage,\n nextPage,\n previousPage,\n isLong,\n maxDigits,\n checkValidity,\n } = usePagePaginationState(totalPages, selectedPageProp);\n\n useEffect(() => {\n setSelectedPage(selectedPageProp);\n }, [selectedPageProp, setSelectedPage]);\n\n const [inputPage, setInputPage] = useState<number>(selectedPage);\n\n useEffect(() => {\n setInputPage(selectedPage);\n }, [selectedPage]);\n\n const handlePageSelect = useCallback(\n (pageNumber: number) => {\n setSelectedPage(pageNumber);\n setInputPage(pageNumber);\n onPageSelect(pageNumber);\n },\n [onPageSelect, setSelectedPage]\n );\n\n const handleIncrement = useCallback(() => {\n setSelectedPage(nextPage);\n onPageSelect(nextPage);\n }, [nextPage, onPageSelect, setSelectedPage]);\n\n const handleDecrement = useCallback(() => {\n setSelectedPage(previousPage);\n onPageSelect(previousPage);\n }, [onPageSelect, previousPage, setSelectedPage]);\n\n const handleInputChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const nextValue = parseInt(event.target.value);\n event.target.value !== '' && setInputPage(nextValue);\n },\n [setInputPage]\n );\n\n const handleSubmitClick = useCallback(() => {\n checkValidity(inputPage) && inputPage !== null && handlePageSelect(inputPage);\n }, [checkValidity, handlePageSelect, inputPage]);\n\n const handleInputEnter = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n checkValidity(inputPage) && inputPage !== null && handlePageSelect(inputPage);\n }\n },\n [checkValidity, handlePageSelect, inputPage]\n );\n\n const {LocalRoot} = useLocalTheme();\n\n const theme = useMemo(\n () => ({\n digits: maxDigits,\n }),\n [maxDigits]\n );\n\n return (\n <div {...nativeProps} className={classNames(classes.pagination, className)} ref={ref}>\n {showPageButtons && (\n <div className={classNames(classes.buttons, {[classes.short]: !isLong})}>\n {!isLong &&\n createArray(totalPages).map((_, i) => {\n const pageNumber = i + 1;\n const isActive = pageNumber === selectedPage;\n return (\n <PageButton\n key={i}\n isActive={isActive}\n onClick={handlePageSelect}\n pageNumber={i + 1}\n />\n );\n })}\n {isLong && (\n <Fragment>\n <PageButton\n isActive={first === selectedPage}\n onClick={handlePageSelect}\n pageNumber={first}\n />\n <div className={classes.ellipsis}>…</div>\n {visible.map((pageNumber, i) => {\n const isActive = pageNumber === selectedPage;\n return (\n <PageButton\n className={classNames({\n [classes.centerButton]: i !== 1,\n })}\n key={pageNumber}\n isActive={isActive}\n onClick={handlePageSelect}\n pageNumber={pageNumber}\n />\n );\n })}\n <div className={classes.ellipsis}>…</div>\n <PageButton\n isActive={last === selectedPage}\n onClick={handlePageSelect}\n pageNumber={last}\n />\n </Fragment>\n )}\n </div>\n )}\n\n {showNavigation && (\n <LocalRoot className={classes.navigation} theme={theme}>\n <div className={classes.navigationBlock}>\n <button\n disabled={totalPages === 1}\n onClick={handleDecrement}\n className={classes.navigationButton}>\n <IconBackward className={classes.icon} />\n </button>\n <button\n disabled={totalPages === 1}\n onClick={handleIncrement}\n className={classes.navigationButton}>\n <IconForward className={classes.icon} />\n </button>\n </div>\n <div className={classes.navigationBlock}>\n <input\n className={classNames(classes.input, {\n [classes.error]: !checkValidity(inputPage),\n })}\n min={first}\n max={last}\n pattern=\"[0-9]{10}\"\n step=\"1\"\n size={maxDigits}\n type=\"number\"\n value={inputPage}\n onChange={handleInputChange}\n onKeyUp={handleInputEnter}\n />\n <button\n disabled={!checkValidity(inputPage) || inputPage === null}\n className={classes.navigationButton}\n onClick={handleSubmitClick}>\n <IconEnter className={classes.icon} />\n </button>\n </div>\n </LocalRoot>\n )}\n </div>\n );\n }\n);\n\nPagination.displayName = 'Pagination';\n"],"names":["Pagination","forwardRef","children","className","totalPages","onPageSelect","selectedPageProp","showNavigation","showPageButtons","nativeProps","ref","visible","first","last","selectedPage","setSelectedPage","nextPage","previousPage","isLong","maxDigits","checkValidity","usePagePaginationState","useEffect","inputPage","setInputPage","useState","handlePageSelect","useCallback","pageNumber","handleIncrement","handleDecrement","handleInputChange","event","nextValue","handleSubmitClick","handleInputEnter","LocalRoot","useLocalTheme","theme","useMemo","jsxs","classNames","classes","createArray","_","i","isActive","jsx","PageButton","Fragment","IconBackward","IconForward","IconEnter"],"mappings":"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"}