add additional list pagination helpers and components

This commit is contained in:
jeffvli
2025-09-29 00:33:32 -07:00
parent 90e7541bc1
commit 3efa54b68a
7 changed files with 188 additions and 35 deletions
@@ -1,14 +1,18 @@
.root {
justify-content: center;
}
.control {
color: var(--theme-btn-default-fg);
background-color: var(--theme-btn-default-bg);
color: var(--theme-colors-foreground);
background-color: var(--theme-colors-surface);
border: none;
transition:
background 0.2s ease-in-out,
color 0.2s ease-in-out;
&[data-active] {
color: var(--theme-btn-primary-fg);
background-color: var(--theme-btn-primary-bg);
color: var(--theme-colors-primary-contrast);
background-color: var(--theme-colors-primary-filled);
}
&[data-dots] {
@@ -16,12 +20,10 @@
}
&:hover {
color: var(--theme-btn-default-fg-hover);
background-color: var(--theme-btn-default-bg-hover);
background-color: lighten(var(--theme-colors-surface), 10%);
&[data-active] {
color: var(--theme-btn-primary-fg-hover);
background-color: var(--theme-btn-primary-bg-hover);
background-color: darken(var(--theme-colors-primary-filled), 10%);
}
&[data-dots] {
@@ -29,3 +31,9 @@
}
}
}
.container {
display: flex;
align-items: center;
justify-content: space-between;
}
+61 -13
View File
@@ -2,23 +2,71 @@ import {
Pagination as MantinePagination,
PaginationProps as MantinePaginationProps,
} from '@mantine/core';
import clsx from 'clsx';
import { useRef } from 'react';
import styles from './pagination.module.css';
interface PaginationProps extends MantinePaginationProps {}
import { Icon } from '/@/shared/components/icon/icon';
import { Text } from '/@/shared/components/text/text';
import { useContainerQuery } from '/@/shared/hooks/use-container-query';
interface PaginationProps extends MantinePaginationProps {
containerClassName?: string;
itemsPerPage: number;
totalItemCount: number;
}
export const Pagination = ({
classNames,
containerClassName,
itemsPerPage,
style,
totalItemCount,
...props
}: PaginationProps) => {
const { ref: containerRef, ...containerQuery } = useContainerQuery();
const paginationRef = useRef<HTMLDivElement>(null);
// !IMPORTANT: Mantine Pagination is 1-indexed
const currentPageIndex = props.value || 0;
const currentPageValue = currentPageIndex + 1;
const handleChange = (e: number) => {
props.onChange?.(e - 1);
};
const currentPageStartIndex = itemsPerPage * currentPageIndex + 1;
const currentPageEndIndex = Math.min(currentPageValue * itemsPerPage, totalItemCount);
export const Pagination = ({ classNames, style, ...props }: PaginationProps) => {
return (
<MantinePagination
classNames={{
control: styles.control,
...classNames,
}}
radius="xl"
style={{
...style,
}}
{...props}
/>
<div className={clsx(styles.container, containerClassName)} ref={containerRef}>
<MantinePagination
boundaries={1}
classNames={{
control: styles.control,
root: styles.root,
...classNames,
}}
nextIcon={() => <Icon icon="arrowRightS" />}
previousIcon={() => <Icon icon="arrowLeftS" />}
radius="md"
ref={paginationRef}
siblings={containerQuery.isXl ? 3 : containerQuery.isMd ? 2 : 1}
size="md"
style={{
...style,
}}
{...props}
onChange={handleChange}
value={currentPageValue}
/>
{containerQuery.isSm && totalItemCount && (
<Text isNoSelect weight={500}>
{currentPageStartIndex} - {currentPageEndIndex} of {totalItemCount}
</Text>
)}
</div>
);
};