0.7.3 • Published 3 years ago

chakra-paginator v0.7.3

Weekly downloads
208
License
MIT
Repository
github
Last release
3 years ago

Chakra paginator

Deprecation notice: this package has been moved to @ajna/pagination

Table of Contents

Version

npm version

Installation

npm

npm i chakra-paginator

Yarn

yarn add chakra-paginator

Demo with all options applied

Check it out in this Sandbox

Components API

Paginator

PropDescriptionTypeDefaultRequired
pagesQuantityThe total number of pages, calculated based on Backend datanumber0yes
onPageChangeOn change handler which returns the last selected page(nextPage: number) => voidyes
isDisabledDisables all of the pagination components. You can always disable each individual component via the isDisabled prop, as the components render HTML buttonsbooleanfalseno
activeStylesThe styles of the active page buttonButtonProps{}no
normalStylesThe styles of the inactive page buttonsButtonProps{}no
separatorStylesThe styles of the separator wrapperButtonProps{}no
outerLimitThe amount of pages to show at the start and at the endnumber0no
innerLimitThe amount of pages to show from the currentPage backwards and forwardnumber0no
currentPageManually set the currentPage of the paginationnumber1no

usePaginator

Options

PropDescriptionTypeDefaultRequired
totalThe total amount of items obtained from a Backend callnumber0no
initialStateInitial states for pagination valuesInitialStateyes

Returned values

PropDescriptionTypeDefaultRequired
offsetGeneric offset value generated if pageSize is providednumber0no
pagesQuantityAutomatically calculated based on total and pageSize. Keep in mind that you can pass this directly to Paginator. This is a commodity if you know the totalnumber0no
currentPageThe current page numbernumberyes
pageSizeThe amount of items per pagenumber10no
isDisabledDisabled or enables all the pagination componentsbooleanfalseno
setPageSizeA setter for the pageSize valueDispatch<SetStateAction >no
setIsDisabledA setter for the isDisabled valueDispatch<SetStateAction >no
setCurrentPageA setter for the currentPage valueDispatch<SetStateAction >yes

Container

Container is a _Flex_ component, so any _FlexProps_ are accepted

PageGroup

PageGroup is a _Stack_ component, so any _StackProps_ are accepted

Previous

Previous is a _Button_ component, so any _ButtonProps_ are accepted

Next

Next is a _Button_ component, so any _ButtonProps_ are accepted

Usage

Minimal

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 {
  Paginator,
  Container,
  Previous,
  Next,
  PageGroup,
  usePaginator
} from "chakra-paginator";

const Demo: FC = () => {
  const pagesQuantity = 12;
  const { currentPage, setCurrentPage } = usePaginator({
    initialState: { currentPage: 1 }
  });

  return (
    <ChakraProvider>
      <Paginator
        pagesQuantity={pagesQuantity}
        currentPage={currentPage}
        onPageChange={setCurrentPage}
      >
        <Container align="center" justify="space-between" w="full" p={4}>
          <Previous>
            Previous
            {/* Or an icon from `react-icons` */}
          </Previous>
          <PageGroup isInline align="center" />
          <Next>
            Next
            {/* Or an icon from `react-icons` */}
          </Next>
        </Container>
      </Paginator>
    </ChakraProvider>
  );
};

export default Demo;
+ From here on, the examples are only partial. You can think of them as modules you can add to the previous component
+ Merge them togheter and you would be adding the given functionality

Styling

Add styles to the possible components inside PageGroup

First: the styles for the unselected and selected page buttons
Second: the styles for the separator button
const normalStyles: ButtonProps = {
  w: 7,
  bg: "red.300"
  fontSize: "sm"
  _hover: {
    bg: "green.300"
  },
};

const activeStyles: ButtonProps = {
  w: 7,
  bg: "green.300"
  fontSize: "sm"
  _hover: {
    bg: "blue.300"
  },
};

const separatorStyles: ButtonProps = {
  w: 7,
  bg: "green.200"
};

<Paginator
  activeStyles={activeStyles}
  normalStyles={normalStyles}
  separatorStyles={separatorStyles}
>

Disabling

It's provided a commodity disable prop to disable/enable all your pagination components at once
const { isDisabled, setIsDisabled } = usePaginator({
  initialState: { isDisabled: false }
});

const handleDisableClick = () => {
  return setIsDisabled((oldState) => !oldState);
};

<Paginator
  isDisabled={isDisabled}
>

Page size

It's provided a commodity page size setter and getter
const { pageSize, setPageSize } = usePaginator({
  initialState: { pageSize: 5 }
});

const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {
  const pageSize = Number(event.target.value);

  setPageSize(pageSize);
};

<Paginator
  pageSize={pageSize}
>

Limits

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 outerLimit = 2;
const innerLimit = 2;

<Paginator
  outerLimit={outerLimit}
  innerLimit={innerLimit}
>

Offset

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 } = usePaginator({
  initialState: { pageSize: 5 }
});

fetchUsingOffset(pageSize, offset).then((data) => {
  // use data
});

Pages quantity

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 quantity value for you
const { pagesQuantity } = usePaginator({
  total: 4021,
  initialState: { pageSize: 5 }
});

<Paginator
  pagesQuantity={pagesQuantity}
>

Full usage example

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,
  ButtonProps,
  Text,
  Button,
  ChakraProvider
} from "@chakra-ui/react";
import {
  Paginator,
  Container,
  Previous,
  usePaginator,
  Next,
  PageGroup
} from "chakra-paginator";

const fetchPokemons = (pageSize: number, offset: number) => {
  return fetch(
    `https://pokeapi.co/api/v2/pokemon?limit=${pageSize}&offset=${offset}`
  ).then((res) => res.json());
};

const Demo: FC = () => {
  // states
  const [pokemonsTotal, setPokemonsTotal] = useState<number | undefined>(
    undefined
  );
  const [pokemons, setPokemons] = useState<any[]>([]);

  // constants
  const outerLimit = 2;
  const innerLimit = 2;

  const {
    pagesQuantity,
    offset, 
    currentPage,
    setCurrentPage,
    setIsDisabled,
    isDisabled,
    pageSize,
    setPageSize
  } = usePaginator({
    total: pokemonsTotal,
    initialState: {
      pageSize: 5,
      isDisabled: false,
      currentPage: 1
    }
  });

  // effects
  useEffect(() => {
    fetchPokemons(pageSize, offset).then((pokemons) => {
      setPokemonsTotal(pokemons.count);
      setPokemons(pokemons.results);
    });
  }, [currentPage, pageSize, offset]);

  // styles
  const baseStyles: ButtonProps = {
    w: 7,
    fontSize: "sm"
  };

  const normalStyles: ButtonProps = {
    ...baseStyles,
    _hover: {
      bg: "green.300"
    },
    bg: "red.300"
  };

  const activeStyles: ButtonProps = {
    ...baseStyles,
    _hover: {
      bg: "blue.300"
    },
    bg: "green.300"
  };

  const separatorStyles: ButtonProps = {
    w: 7,
    bg: "green.200"
  };

  // handlers
  const handlePageChange = (nextPage: number) => {
    // -> request new data using the page number
    setCurrentPage(nextPage);
    console.log("request new data with ->", nextPage);
  };

  const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {
    const pageSize = Number(event.target.value);

    setPageSize(pageSize);
  };

  const handleDisableClick = () => {
    return setIsDisabled((oldState) => !oldState);
  };

  return (
    <ChakraProvider>
      <Paginator
        isDisabled={isDisabled}
        activeStyles={activeStyles}
        innerLimit={innerLimit}
        currentPage={currentPage}
        outerLimit={outerLimit}
        normalStyles={normalStyles}
        separatorStyles={separatorStyles}
        pagesQuantity={pagesQuantity}
        onPageChange={handlePageChange}
      >
        <Container align="center" justify="space-between" w="full" p={4}>
          <Previous>
            Previous
            {/* Or an icon from `react-icons` */}
          </Previous>
          <PageGroup isInline align="center" />
          <Next>
            Next
            {/* Or an icon from `react-icons` */}
          </Next>
        </Container>
      </Paginator>
      <Center w="full">
        <Button onClick={handleDisableClick}>Disable ON / OFF</Button>
        <Select w={40} ml={3} onChange={handlePageSizeChange}>
          <option value="10">10</option>
          <option value="25">25</option>
          <option value="50">50</option>
        </Select>
      </Center>
      <Grid
        templateRows="repeat(2, 1fr)"
        templateColumns="repeat(5, 1fr)"
        gap={3}
        px={20}
        mt={20}
      >
        {pokemons?.map(({ name }) => (
          <Center p={4} bg="green.100" key={name}>
            <Text>{name}</Text>
          </Center>
        ))}
      </Grid>
    </ChakraProvider>
  );
};

export default Demo;
0.7.3

3 years ago

0.7.2

3 years ago

0.7.1

3 years ago

0.6.5

3 years ago

0.6.4

3 years ago

0.7.0

3 years ago

0.6.3

3 years ago

0.6.2

3 years ago

0.6.1

3 years ago

0.5.3

3 years ago

0.5.2

3 years ago

0.5.1

3 years ago

0.5.0

3 years ago

0.4.1

3 years ago

0.4.0

3 years ago

0.3.1

3 years ago

0.3.0

3 years ago

0.2.1

3 years ago

0.2.0

4 years ago

0.1.8

4 years ago

0.1.6-0

4 years ago

0.1.7

4 years ago

0.1.6

4 years ago

0.1.5-0

4 years ago

0.1.4-0

4 years ago

0.1.3-0

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago