code: nextjs,frontends,tsx (7 files)

This commit is contained in:
Richard Ward
2025-12-30 18:33:23 +00:00
parent 4fccef6616
commit fa82944ecb
7 changed files with 181 additions and 100 deletions

View File

@@ -1,8 +1,10 @@
'use client'
import { Box } from '@mui/material'
import { Box } from '@/fakemui'
import { forwardRef, ReactNode } from 'react'
import styles from './pagination.module.scss'
interface PaginationContentProps {
children: ReactNode
}
@@ -17,14 +19,7 @@ const PaginationContent = forwardRef<HTMLUListElement, PaginationContentProps>(
<Box
ref={ref}
component="ul"
sx={{
display: 'flex',
alignItems: 'center',
gap: 0.5,
listStyle: 'none',
p: 0,
m: 0,
}}
className={styles.paginationContent}
{...props}
>
{children}

View File

@@ -1,21 +1,16 @@
'use client'
import { Box } from '@mui/material'
import { Box } from '@/fakemui'
import { forwardRef } from 'react'
import styles from './pagination.module.scss'
const PaginationEllipsis = forwardRef<HTMLSpanElement, Record<string, never>>((props, ref) => {
return (
<Box
ref={ref}
component="span"
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 36,
height: 36,
color: 'text.secondary',
}}
className={styles.paginationEllipsis}
{...props}
>
...

View File

@@ -1,29 +1,22 @@
'use client'
import { IconButton } from '@mui/material'
import { IconButton } from '@/fakemui'
import { forwardRef } from 'react'
import { type PaginationLinkProps, paginationSizeMap } from './paginationTypes'
import styles from './pagination.module.scss'
import { type PaginationLinkProps } from './paginationTypes'
const PaginationLink = forwardRef<HTMLButtonElement, PaginationLinkProps>(
({ children, onClick, isActive = false, disabled = false, size = 'medium', ...props }, ref) => {
const sizeClass = size === 'small' ? styles.paginationLinkSmall : size === 'large' ? styles.paginationLinkLarge : ''
const activeClass = isActive ? styles.paginationLinkActive : ''
return (
<IconButton
ref={ref}
onClick={onClick}
disabled={disabled}
sx={{
...paginationSizeMap[size],
borderRadius: 1,
bgcolor: isActive ? 'primary.main' : 'transparent',
color: isActive ? 'primary.contrastText' : 'text.primary',
'&:hover': {
bgcolor: isActive ? 'primary.dark' : 'action.hover',
},
'&.Mui-disabled': {
opacity: 0.5,
},
}}
className={`${styles.paginationLink} ${sizeClass} ${activeClass}`}
{...props}
>
{children}

View File

@@ -1,6 +1,6 @@
'use client'
import { Pagination as MuiPagination } from '@mui/material'
import { Pagination as FakeMuiPagination } from '@/fakemui'
import { forwardRef } from 'react'
interface PaginationProps {
@@ -38,11 +38,11 @@ const Pagination = forwardRef<HTMLElement, PaginationProps>(
ref
) => {
return (
<MuiPagination
ref={ref}
<FakeMuiPagination
ref={ref as React.Ref<HTMLElement>}
count={count}
page={page}
onChange={(_, newPage) => onChange(newPage)}
onChange={onChange}
siblingCount={siblingCount}
boundaryCount={boundaryCount}
showFirstButton={showFirstButton}

View File

@@ -1,8 +1,9 @@
'use client'
import { Box, IconButton, Typography } from '@mui/material'
import { Box, IconButton, Typography } from '@/fakemui'
import { forwardRef } from 'react'
import styles from './pagination.module.scss'
import { NextIcon, PreviousIcon } from './paginationIcons'
interface SimplePaginationProps {
@@ -32,50 +33,27 @@ const SimplePagination = forwardRef<HTMLDivElement, SimplePaginationProps>(
return (
<Box
ref={ref}
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 2,
}}
className={styles.simplePagination}
{...props}
>
<IconButton
onClick={onPrevious}
disabled={disabled || !hasPrevious}
size="small"
sx={{
border: 1,
borderColor: 'divider',
borderRadius: 1,
px: 2,
py: 1,
'&:hover': {
bgcolor: 'action.hover',
},
}}
sm
className={styles.simplePaginationButton}
>
<PreviousIcon />
<Typography variant="body2" sx={{ ml: 0.5 }}>
<Typography variant="body2" className={styles.simplePaginationLabel}>
{previousLabel}
</Typography>
</IconButton>
<IconButton
onClick={onNext}
disabled={disabled || !hasNext}
size="small"
sx={{
border: 1,
borderColor: 'divider',
borderRadius: 1,
px: 2,
py: 1,
'&:hover': {
bgcolor: 'action.hover',
},
}}
sm
className={styles.simplePaginationButton}
>
<Typography variant="body2" sx={{ mr: 0.5 }}>
<Typography variant="body2" className={styles.simplePaginationLabel}>
{nextLabel}
</Typography>
<NextIcon />

View File

@@ -1,17 +1,10 @@
'use client'
import { Box, FormControl, IconButton, Select, Typography } from '@/fakemui'
import { FirstPage as FirstPageIcon, LastPage as LastPageIcon } from '@/fakemui/icons'
import {
Box,
FormControl,
IconButton,
MenuItem,
Select,
SelectChangeEvent,
Typography,
} from '@mui/material'
import { forwardRef } from 'react'
import { forwardRef, ChangeEvent } from 'react'
import styles from './pagination.module.scss'
import { NextIcon, PreviousIcon } from './paginationIcons'
interface TablePaginationProps {
@@ -44,57 +37,56 @@ const TablePagination = forwardRef<HTMLDivElement, TablePaginationProps>(
const startItem = (page - 1) * pageSize + 1
const endItem = Math.min(page * pageSize, count)
const handlePageSizeChange = (event: SelectChangeEvent<number>) => {
const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {
onPageSizeChange(Number(event.target.value))
}
return (
<Box
ref={ref}
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
flexWrap: 'wrap',
gap: 2,
py: 1,
}}
className={styles.tablePagination}
{...props}
>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Typography variant="body2" color="text.secondary">
<Box className={styles.tablePaginationRowsPerPage}>
<Typography variant="body2" className={styles.tablePaginationLabel}>
Rows per page:
</Typography>
<FormControl size="small" disabled={disabled}>
<Select value={pageSize} onChange={handlePageSizeChange} sx={{ minWidth: 70 }}>
<FormControl sm>
<Select
value={pageSize}
onChange={handlePageSizeChange}
disabled={disabled}
sm
className={styles.tablePaginationSelect}
>
{pageSizeOptions.map(option => (
<MenuItem key={option} value={option}>
<option key={option} value={option}>
{option}
</MenuItem>
</option>
))}
</Select>
</FormControl>
</Box>
<Typography variant="body2" color="text.secondary">
<Typography variant="body2" className={styles.tablePaginationLabel}>
{count === 0 ? '0' : `${startItem}-${endItem}`} of {count}
</Typography>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
<Box className={styles.tablePaginationActions}>
{showFirstLastButtons && (
<IconButton
onClick={() => onPageChange(1)}
disabled={disabled || page === 1}
size="small"
sm
aria-label="Go to first page"
>
<FirstPageIcon fontSize="small" />
<FirstPageIcon size={16} />
</IconButton>
)}
<IconButton
onClick={() => onPageChange(page - 1)}
disabled={disabled || page === 1}
size="small"
sm
aria-label="Go to previous page"
>
<PreviousIcon />
@@ -102,7 +94,7 @@ const TablePagination = forwardRef<HTMLDivElement, TablePaginationProps>(
<IconButton
onClick={() => onPageChange(page + 1)}
disabled={disabled || page === totalPages}
size="small"
sm
aria-label="Go to next page"
>
<NextIcon />
@@ -111,10 +103,10 @@ const TablePagination = forwardRef<HTMLDivElement, TablePaginationProps>(
<IconButton
onClick={() => onPageChange(totalPages)}
disabled={disabled || page === totalPages}
size="small"
sm
aria-label="Go to last page"
>
<LastPageIcon fontSize="small" />
<LastPageIcon size={16} />
</IconButton>
)}
</Box>

View File

@@ -0,0 +1,128 @@
// Pagination component styles
// Migrated from @mui/material sx props to SCSS modules
// PaginationContent
.paginationContent {
display: flex;
align-items: center;
gap: 0.25rem;
list-style: none;
padding: 0;
margin: 0;
}
// PaginationEllipsis
.paginationEllipsis {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
color: var(--text-secondary, #666);
}
// PaginationLink
.paginationLink {
min-width: 36px;
height: 36px;
border-radius: 4px;
background-color: transparent;
color: var(--text-primary, #333);
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.2s ease, color 0.2s ease;
&:hover:not(:disabled) {
background-color: var(--action-hover, rgba(0, 0, 0, 0.04));
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
.paginationLinkSmall {
min-width: 28px;
height: 28px;
}
.paginationLinkLarge {
min-width: 44px;
height: 44px;
}
.paginationLinkActive {
background-color: var(--primary-main, #1976d2);
color: var(--primary-contrast-text, #fff);
&:hover:not(:disabled) {
background-color: var(--primary-dark, #1565c0);
}
}
// SimplePagination
.simplePagination {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.simplePaginationButton {
border: 1px solid var(--divider, rgba(0, 0, 0, 0.12));
border-radius: 4px;
padding: 0.5rem 1rem;
display: flex;
align-items: center;
gap: 0.25rem;
background-color: transparent;
cursor: pointer;
transition: background-color 0.2s ease;
&:hover:not(:disabled) {
background-color: var(--action-hover, rgba(0, 0, 0, 0.04));
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
.simplePaginationLabel {
margin: 0 0.25rem;
}
// TablePagination
.tablePagination {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 1rem;
padding: 0.5rem 0;
}
.tablePaginationRowsPerPage {
display: flex;
align-items: center;
gap: 0.5rem;
}
.tablePaginationLabel {
color: var(--text-secondary, #666);
}
.tablePaginationSelect {
min-width: 70px;
}
.tablePaginationActions {
display: flex;
align-items: center;
gap: 0.25rem;
}