Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@ajna/pagination
Advanced tools
npm i @ajna/pagination
yarn add @ajna/pagination
Prop | Description | Type | Default | Required |
---|---|---|---|---|
pagesCount | The total number of pages | number | yes | |
currentPage | The page which is currently being selected | number | yes | |
onPageChange | On change handler which returns the last selected page | (currentPage: number) => void | yes | |
isDisabled | Denotates if all items on the pagination are disabled or not | boolean | false | no |
It's a Flex component, so any FlexProps are accepted
It's a Stack component, so any StackProps are accepted
It's a Button component, so any ButtonProps are accepted
It's a Button component, so any ButtonProps are accepted
It's a Button component, so any ButtonProps are accepted
It's a Button component, so any ButtonProps are accepted
Prop | Description | Type | Default | Required |
---|---|---|---|---|
initialState | Initial states for pagination values | InitialState | yes | |
total | The total amount of items from the endpoint you are consuming | number | undefined | no |
limits | The limits cut the amount of pages to show | Limits | undefined | no |
pagesCount | If the amount of pages is manually set, it will take precedence | number | undefined | no |
Prop | Description | Type | Default |
---|---|---|---|
offset | Offset value generated | number | 0 |
pages | The array of pages to render | number[] | [] |
pagesCount | The total amount of pages | number | 0 |
currentPage | The page which is currently being selected | number | |
pageSize | The amount of items per page | number | undefined |
isDisabled | Denotates if all items on the pagination are disabled or not | boolean | false |
setPageSize | A setter for the isDisabled value | Dispatch<SetStateAction> | |
setIsDisabled | A setter for the isDisabled value | Dispatch<SetStateAction> | |
setCurrentPage | A setter for the currentPage value | Dispatch<SetStateAction> |
This is the bare minimum set up you need to get it up and working
import React, { FC, ChangeEvent, useEffect, useState } from "react";
import { ChakraProvider } from "@chakra-ui/react";
import {
Pagination,
usePagination,
PaginationNext,
PaginationPage,
PaginationPrevious,
PaginationContainer,
PaginationPageGroup,
} from "@ajna/pagination";
const Minimal: FC = () => {
const {
currentPage,
setCurrentPage,
pagesCount,
pages
} = usePagination({
pagesCount: 12,
initialState: { currentPage: 1 },
});
return (
<ChakraProvider>
<Pagination
pagesCount={pagesCount}
currentPage={currentPage}
onPageChange={setCurrentPage}
>
<PaginationContainer>
<PaginationPrevious>Previous</PaginationPrevious>
<PaginationPageGroup>
{pages.map((page: number) => (
<PaginationPage
key={`pagination_page_${page}`}
page={page}
/>
))}
</PaginationPageGroup>
<PaginationNext>Next</PaginationNext>
</PaginationContainer>
</Pagination>
</ChakraProvider>
);
};
export default Demo;
The _curent prop will contain the props for the page which is currently selected All other props will apply to every other page
<PaginationPage
w={7}
bg="red.300"
fontSize="sm"
_hover={{
bg: "green.300"
}}
_current={{
w: 7,
bg: "green.300"
fontSize: "sm"
_hover: {
bg: "blue.300"
},
}}
>
<PaginationPrevious
bg="blue.500"
w="20rem"
//...any button prop
>
Previous
</PaginationPrevious>
<PaginationNext
w={7}
bg="red.300"
fontSize="sm"
//...any button prop
>
Next
</PaginationNext>
<PaginationContainer
bg="blue.500"
w="full"
//...any flex prop
>
...
</PaginationContainer>
<PaginationPageGroup
bg="blue.500"
w="full"
//...any stack prop
>
...
</PaginationPageGroup>
It's provided a commodity disable prop to disable/enable all your pagination components at once
const { isDisabled, setIsDisabled } = usePagination({
initialState: { isDisabled: false }
});
const handleDisableClick = () => {
return setIsDisabled((oldState) => !oldState);
};
<Pagination
isDisabled={isDisabled}
>
It's provided a commodity page size setter and getter
const { pageSize, setPageSize } = usePagination({
initialState: { pageSize: 5 },
});
const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {
const pageSize = Number(event.target.value);
setPageSize(pageSize);
};
You can trim the ammount of pages you show by passing both limits at the same time You need to pass them both, otherwise no limits will be applied
const { pages } = usePagination({
limits: {
outer: outerLimit,
inner: innerLimit,
},
});
Additionaly, you can customize the separator component used when limits are defined
<PaginationPageGroup separator={<PaginationSeparator _hover={{ bg: 'purple.500' }} bg='teal.500'>}>
{pages.map((page: number) => (
<PaginationPage key={`pagination_page_${page}`} page={page} />
))}
</PaginationPageGroup>
It's possible that the API for the pagination you are consuming works with an offset One it's calculated and provided for you using the pageSize and currentPage values
This is calculated with the next formula:
[currentPage * pageSize - pageSize]
currentPage === 1 && pageSize === 5 // offset = 0;
currentPage === 2 && pageSize === 5 // offset = 5;
currentPage === 3 && pageSize === 5 // offset = 10;
const { offset, pageSize } = usePagination({
initialState: { pageSize: 5 },
});
fetchUsingOffset(pageSize, offset).then((data) => {
// use data
});
Keep in mind that if you know the total amount of items of the requested endpoint, which is not a strange thing to be returned, you can use that to generate the pages for you
const { pages, pagesCount } = usePaginator({
total: 4021,
initialState: { pageSize: 5 }
});
<Pagination
pagesCount={pagesCount}
>
<PaginationPageGroup>
{pages.map((page: number) => (
<PaginationPage key={`pagination_page_${page}`} page={page} />
))}
</PaginationPageGroup>
In this example you can see all the possible features provided by the library being applied to show 10 pokemons names, with the ability to play with the page size and disable state
import React, { FC, ChangeEvent, useEffect, useState } from "react";
import { Grid, Center, Select, Text, Button, Stack } from "@chakra-ui/react";
import {
Pagination,
usePagination,
PaginationPage,
PaginationNext,
PaginationPrevious,
PaginationPageGroup,
PaginationContainer,
PaginationSeparator,
} from "@ajna/pagination";
const fetchPokemons = async (
pageSize: number,
offset: number
): Promise<any> => {
return await fetch(
`https://pokeapi.co/api/v2/pokemon?limit=${pageSize}&offset=${offset}`
).then(async (res) => await res.json());
};
const Full: FC = () => {
// states
const [pokemonsTotal, setPokemonsTotal] = useState<number | undefined>(
undefined
);
const [pokemons, setPokemons] = useState<any[]>([]);
// constants
const outerLimit = 2;
const innerLimit = 2;
// pagination hook
const {
pages,
pagesCount,
offset,
currentPage,
setCurrentPage,
setIsDisabled,
isDisabled,
pageSize,
setPageSize,
} = usePagination({
total: pokemonsTotal,
limits: {
outer: outerLimit,
inner: innerLimit,
},
initialState: {
pageSize: 5,
isDisabled: false,
currentPage: 1,
},
});
// effects
useEffect(() => {
fetchPokemons(pageSize, offset)
.then((pokemons) => {
setPokemonsTotal(pokemons.count);
setPokemons(pokemons.results);
})
.catch((error) => console.error("App =>", error));
}, [currentPage, pageSize, offset]);
// handlers
const handlePageChange = (nextPage: number): void => {
// -> request new data using the page number
setCurrentPage(nextPage);
console.log("request new data with ->", nextPage);
};
const handlePageSizeChange = (
event: ChangeEvent<HTMLSelectElement>
): void => {
const pageSize = Number(event.target.value);
setPageSize(pageSize);
};
const handleDisableClick = (): void => {
setIsDisabled((oldState) => !oldState);
};
return (
<Stack>
<Pagination
pagesCount={pagesCount}
currentPage={currentPage}
isDisabled={isDisabled}
onPageChange={handlePageChange}
>
<PaginationContainer
align="center"
justify="space-between"
p={4}
w="full"
>
<PaginationPrevious
_hover={{
bg: "yellow.400",
}}
bg="yellow.300"
isDisabled
onClick={() => console.warn("I'm clicking the previous")}
>
<Text>Previous</Text>
</PaginationPrevious>
<PaginationPageGroup
isInline
align="center"
separator={
<PaginationSeparator
isDisabled
onClick={() => console.warn("I'm clicking the separator")}
bg="blue.300"
fontSize="sm"
w={7}
jumpSize={11}
/>
}
>
{pages.map((page: number) => (
<PaginationPage
w={7}
bg="red.300"
key={`pagination_page_${page}`}
page={page}
onClick={() => console.warn("Im clicking the page")}
fontSize="sm"
_hover={{
bg: "green.300",
}}
_current={{
bg: "green.300",
fontSize: "sm",
w: 7,
}}
/>
))}
</PaginationPageGroup>
<PaginationNext
_hover={{
bg: "yellow.400",
}}
bg="yellow.300"
onClick={() => console.warn("I'm clicking the next")}
>
<Text>Next</Text>
</PaginationNext>
</PaginationContainer>
</Pagination>
<Center w="full">
<Button
_hover={{
bg: "purple.400",
}}
bg="purple.300"
onClick={handleDisableClick}
>
Disable ON / OFF
</Button>
<Select ml={3} onChange={handlePageSizeChange} w={40}>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
</Select>
</Center>
<Grid
gap={3}
mt={20}
px={20}
templateColumns="repeat(5, 1fr)"
templateRows="repeat(2, 1fr)"
>
{pokemons?.map(({ name }) => (
<Center key={name} bg="green.100" p={4}>
<Text>{name}</Text>
</Center>
))}
</Grid>
</Stack>
);
};
export default Full;
FAQs
## Table of Contents
We found that @ajna/pagination demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.