Files
SSA-Admin-Panel/src/components/ui/pagination.tsx
2025-02-04 13:56:43 +05:30

238 lines
6.2 KiB
TypeScript

"use client";
import type { ButtonProps, TextProps } from "@chakra-ui/react";
import {
Button,
Pagination as ChakraPagination,
HStack,
IconButton,
Text,
createContext,
usePaginationContext,
} from "@chakra-ui/react";
import * as React from "react";
import { HiChevronLeft, HiChevronRight } from "react-icons/hi2";
import { LinkButton } from "./link-button";
interface ButtonVariantMap {
current: ButtonProps["variant"];
default: ButtonProps["variant"];
ellipsis: ButtonProps["variant"];
}
type PaginationVariant = "outline" | "solid" | "subtle";
interface ButtonVariantContext {
size: ButtonProps["size"];
variantMap: ButtonVariantMap;
getHref?: (page: number) => string;
}
const [RootPropsProvider, useRootProps] = createContext<ButtonVariantContext>({
name: "RootPropsProvider",
});
export interface PaginationRootProps
extends Omit<ChakraPagination.RootProps, "type"> {
size?: ButtonProps["size"];
variant?: PaginationVariant;
getHref?: (page: number) => string;
}
const variantMap: Record<PaginationVariant, ButtonVariantMap> = {
outline: { default: "ghost", ellipsis: "plain", current: "solid" },
solid: { default: "outline", ellipsis: "outline", current: "solid" },
subtle: { default: "ghost", ellipsis: "plain", current: "subtle" },
};
export const PaginationRoot = React.forwardRef<
HTMLDivElement,
PaginationRootProps
>(function PaginationRoot(props, ref) {
const { size = "sm", variant = "outline", getHref, ...rest } = props;
return (
<RootPropsProvider
value={{ size, variantMap: variantMap[variant], getHref }}
>
<ChakraPagination.Root
ref={ref}
type={getHref ? "link" : "button"}
{...rest}
/>
</RootPropsProvider>
);
});
export const PaginationEllipsis = React.forwardRef<
HTMLDivElement,
ChakraPagination.EllipsisProps
>(function PaginationEllipsis(props, ref) {
const { size, variantMap } = useRootProps();
return (
<ChakraPagination.Ellipsis ref={ref} {...props} asChild>
<Button as="span" variant={variantMap.ellipsis} size={size}>
...
</Button>
</ChakraPagination.Ellipsis>
);
});
export const PaginationItem = React.forwardRef<
HTMLButtonElement,
ChakraPagination.ItemProps
>(function PaginationItem(props, ref) {
const { page } = usePaginationContext();
const { size, variantMap, getHref } = useRootProps();
const current = page === props.value;
const variant = current ? variantMap.current : variantMap.default;
if (getHref) {
return (
<LinkButton
href={getHref(props.value)}
variant={variant}
size={size}
bg={current ? "#02A0A0" : "white"}
color={current ? "black" : "black"}
_hover={{ bg: "#02A0A0", color: "black" }}
>
{props.value}
</LinkButton>
);
}
return (
<ChakraPagination.Item ref={ref} {...props} asChild>
<Button
bg={current ? "#F5F8FB" : "white"}
color={current ? "black" : "black"}
variant={variant}
size={size}
_hover={{ bg: "#F5F8FB", color: "black" }}
border="none"
>
{props.value}
</Button>
</ChakraPagination.Item>
);
});
export const PaginationPrevTrigger = React.forwardRef<
HTMLButtonElement,
ChakraPagination.PrevTriggerProps
>(function PaginationPrevTrigger(props, ref) {
const { size, variantMap, getHref } = useRootProps();
const { previousPage } = usePaginationContext();
if (getHref) {
return (
<LinkButton
href={previousPage != null ? getHref(previousPage) : undefined}
variant={variantMap.default}
size={size}
_hover={{ bg: "#F5F8FB", color: "black" }}
>
<HiChevronLeft />
</LinkButton>
);
}
return (
<ChakraPagination.PrevTrigger ref={ref} asChild {...props}>
<IconButton variant={variantMap.default} size={size}>
<HiChevronLeft />
</IconButton>
</ChakraPagination.PrevTrigger>
);
});
export const PaginationNextTrigger = React.forwardRef<
HTMLButtonElement,
ChakraPagination.NextTriggerProps
>(function PaginationNextTrigger(props, ref) {
const { size, variantMap, getHref } = useRootProps();
const { nextPage } = usePaginationContext();
if (getHref) {
return (
<LinkButton
href={nextPage != null ? getHref(nextPage) : undefined}
variant={variantMap.default}
// size={size}
borderRadius="94px"
bg="#F5F8FB"
color="white"
w="136px"
fontSize="sm"
_hover={{ bg: "#026060" }}
>
Next
</LinkButton>
);
}
return (
<ChakraPagination.NextTrigger ref={ref} asChild {...props}>
<Text
w="136px"
// borderRadius="94px"
// bg="#02A0A0"
color="black"
// variant={variantMap.default}
// size={size}
cursor="pointer"
// _hover={{ bg: "#026060" }}
display="flex"
gap="12px"
alignItems="center"
fontSize="xs"
justifyContent="center"
>
Next
<HiChevronRight />
</Text>
</ChakraPagination.NextTrigger>
);
});
export const PaginationItems = (props: React.HTMLAttributes<HTMLElement>) => {
return (
<ChakraPagination.Context>
{({ pages }) =>
pages.map((page, index) => (
<PaginationItem
key={index}
type="page"
value={page.value}
{...props}
/>
))
}
</ChakraPagination.Context>
);
};
interface PageTextProps extends TextProps {
format?: "short" | "compact" | "long";
}
export const PaginationPageText = React.forwardRef<
HTMLParagraphElement,
PageTextProps
>(function PaginationPageText(props, ref) {
const { format = "compact", ...rest } = props;
const { page, totalPages, pageRange, count } = usePaginationContext();
const content = React.useMemo(() => {
if (format === "short") return `${page} / ${totalPages}`;
if (format === "compact") return `${page} of ${totalPages}`;
return `${pageRange.start + 1} - ${Math.min(pageRange.end, count)} of ${count}`;
}, [format, page, totalPages, pageRange, count]);
return (
<Text fontWeight="medium" ref={ref} {...rest}>
{content}
</Text>
);
});