UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

123 lines (122 loc) • 4.54 kB
"use client"; import Select from "../Select/Select.mjs"; import { useEventCallback } from "../../hooks/useEventCallback.mjs"; import { clampPage, getPageCount, getPaginationItems } from "./helpers.mjs"; import { buttonVariants, ellipsisVariants, styles } from "./style.mjs"; import { memo, useEffect, useRef, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import { cx } from "antd-style"; import useMergeState from "use-merge-value"; import { ChevronLeft, ChevronRight } from "lucide-react"; //#region src/base-ui/Pagination/Pagination.tsx const Pagination = memo(({ className, current, defaultCurrent = 1, defaultPageSize = 10, disabled, hideOnSinglePage, onChange, onPageSizeChange, pageSize, pageSizeOptions = [ 10, 20, 50, 100 ], ref, showSizeChanger = false, showTotal, size = "middle", style, total, ...rest }) => { const [mergedPageSize, setMergedPageSize] = useMergeState(defaultPageSize, { value: pageSize }); const pageCount = getPageCount(total, mergedPageSize); const [mergedCurrent, setMergedCurrent] = useMergeState(defaultCurrent, { value: current }); const onChangeStable = useEventCallback((nextCurrent, nextPageSize) => { onChange?.(nextCurrent, nextPageSize); }); const pendingNotifyRef = useRef(null); const [prevPageCount, setPrevPageCount] = useState(pageCount); if (pageCount !== prevPageCount) { setPrevPageCount(pageCount); if (mergedCurrent > pageCount && pageCount >= 1) { setMergedCurrent(pageCount); pendingNotifyRef.current = { current: pageCount, pageSize: mergedPageSize }; } } useEffect(() => { if (!pendingNotifyRef.current) return; const { current: nextCurrent, pageSize: nextPageSize } = pendingNotifyRef.current; pendingNotifyRef.current = null; onChangeStable(nextCurrent, nextPageSize); }); const displayCurrent = clampPage(mergedCurrent, pageCount); if (hideOnSinglePage && pageCount <= 1) return null; const commitCurrent = (nextCurrent, nextPageSize) => { setMergedCurrent(nextCurrent); onChange?.(nextCurrent, nextPageSize); }; const goTo = (page) => { commitCurrent(clampPage(page, pageCount), mergedPageSize); }; const handlePageSizeChange = (value) => { const nextSize = Number(value); const nextPageCount = getPageCount(total, nextSize); const nextCurrent = clampPage(displayCurrent, nextPageCount); setMergedPageSize(nextSize); commitCurrent(nextCurrent, nextSize); onPageSizeChange?.(nextCurrent, nextSize); }; const items = getPaginationItems(displayCurrent, pageCount); const rangeStart = total === 0 ? 0 : (displayCurrent - 1) * mergedPageSize + 1; const rangeEnd = Math.min(displayCurrent * mergedPageSize, total); return /* @__PURE__ */ jsxs("nav", { "aria-label": "Pagination", className: cx(styles.root, className), ref, role: "navigation", style, ...rest, children: [ showTotal && /* @__PURE__ */ jsx("span", { className: styles.total, children: showTotal(total, [rangeStart, rangeEnd]) }), /* @__PURE__ */ jsx("button", { "aria-label": "Previous page", className: buttonVariants({ size }), disabled: disabled || displayCurrent <= 1, type: "button", onClick: () => goTo(displayCurrent - 1), children: /* @__PURE__ */ jsx(ChevronLeft, { size: size === "small" ? 14 : 16 }) }), items.map((item) => typeof item === "number" ? /* @__PURE__ */ jsx("button", { "aria-current": item === displayCurrent ? "page" : void 0, className: buttonVariants({ size }), disabled, type: "button", onClick: () => goTo(item), children: item }, item) : /* @__PURE__ */ jsx("span", { className: ellipsisVariants({ size }), children: "···" }, item)), /* @__PURE__ */ jsx("button", { "aria-label": "Next page", className: buttonVariants({ size }), disabled: disabled || displayCurrent >= pageCount, type: "button", onClick: () => goTo(displayCurrent + 1), children: /* @__PURE__ */ jsx(ChevronRight, { size: size === "small" ? 14 : 16 }) }), showSizeChanger && /* @__PURE__ */ jsx(Select, { disabled, size: size === "small" ? "small" : "middle", style: { flex: "none", marginInlineStart: 8, width: "auto" }, value: String(mergedPageSize), options: pageSizeOptions.map((option) => ({ label: `${option} / page`, value: String(option) })), onChange: handlePageSizeChange }) ] }); }); Pagination.displayName = "Pagination"; //#endregion export { Pagination as default }; //# sourceMappingURL=Pagination.mjs.map