@bramus/pagination-sequence
Advanced tools
Comparing version 1.0.2 to 1.0.3
{ | ||
"name": "@bramus/pagination-sequence", | ||
"version": "1.0.2", | ||
"description": "Pagination Sequence Generator", | ||
"version": "1.0.3", | ||
"description": "Generate a sequence of numbers for use in a Pagination Component, the clever way.", | ||
"type": "module", | ||
@@ -6,0 +6,0 @@ "source": "src/index.js", |
@@ -0,4 +1,6 @@ | ||
![JavaScript Pagination Sequence Generator](./screenshots/js-pagination-sequence.png) | ||
# JavaScript Pagination Sequence Generator | ||
Generate a sequence of numbers for use in a pagination system, the clever way. | ||
Generate a sequence of numbers for use in a Pagination Component, the clever way. | ||
@@ -13,9 +15,15 @@ ## Installation | ||
This library contains an algorithm to generate an array of pagination entries. | ||
```js | ||
import { generate } from '@bramus/pagination-sequence'; | ||
// [1, 2, '…', 65, 66, 67, 68, 69, '…', 73, 74] | ||
const sequence = generate(67, 74); | ||
// ~> [1, 2, '…', 65, 66, 67, 68, 69, '…', 73, 74] | ||
``` | ||
The generated array is not rendered in any way but, instead, must be fed into your own Pagination Component for rendering. | ||
💡 Looking for some Pagination Component inspiration? See [Integration Examples](#integration-examples) below to see how to use this with your Favorite JavaScript Framework Du Jour™. | ||
## API | ||
@@ -37,11 +45,35 @@ | ||
## Limitations | ||
## Principles | ||
To be clear: this package will only generate an array with values that needs to be shown. You will need to process the array yourself for use within your the JavaScript Framework Du Jour™, as demonstrated in the Integration Example below. You might consider this a limitation. | ||
The algorithm is opinionated and follows these principles: | ||
## Integration Example (React) | ||
- **Quantitative Stability** | ||
When generating a sequence, it will always generate the same amount of entries, for any `curPage` value. When viewing a page at the edge of a series, this can result in `numberOfPagesAtEdges` being ignored. | ||
For example: Instead of having `generate(2, 12, 1, 1)` return `01-[02]-03-..-12` _(5 entries)_, it will return `01-[02]-03-04-05-..-12` _(7 entries)_. This is a deliberate choice because `01-[02]-03-04-05-..-12` contains the same amount of entries as the output for `generate(7, 12, 1, 1)`, which will also return 7 entries: `01-..-06-[07]-08-..-12`. | ||
With a stable amount of entries being generated, the output will also be visually stable when rendered on screen. | ||
- **Always include links to the edges** | ||
The algorithm will always include links to the first and last page. | ||
For Example: when looking at page 25 of 50, the algorithm will include a link to page 1 and page 50. | ||
- **No unnecessary gaps** | ||
When the algorithm detects a gap that's only “1 item wide”, it will replace that gap with the actual number. | ||
For Example: A foolish take on `generate(4, 9, 1, 1)`, would generate `01-..-03-[04]-05-..-09`. The algorithm corrects the first gap to `02` and will return `01-02-03-[04]-05-..-09` instead. | ||
## Integration Examples | ||
### React | ||
🔗 Try it online: [https://codepen.io/bramus/pen/NWaxNKQ](https://codepen.io/bramus/pen/NWaxNKQ) | ||
```js | ||
```jsx | ||
import React from "react"; | ||
import ReactDOM from "react-dom"; | ||
import { generate } from "@bramus/pagination-sequence"; | ||
@@ -51,18 +83,26 @@ | ||
const PaginationEntry = ({ value, isCurrent = false }) => { | ||
const PaginationEntry = ({ value, onEntryClick = null, label = null, title = null, isCurrent = false, isDisabled = false, ...props }) => { | ||
label ??= value; | ||
title ??= `Go to page ${value}`; | ||
onEntryClick ??= (e) => {}; | ||
if (value == '…') { | ||
return ( | ||
<li data-pagination-ellipsis><span>…</span></li> | ||
<li data-pagination-ellipsis {...props}><span>{label}</span></li> | ||
); | ||
} | ||
if (isCurrent) { | ||
if (isDisabled) { | ||
return ( | ||
<li data-pagination-current><span>{value}</span></li> | ||
<li data-pagination-disabled {...props}><span>{label}</span></li> | ||
); | ||
} | ||
if (isCurrent) { | ||
props['data-pagination-current'] = true; | ||
} | ||
return ( | ||
<li> | ||
<a href={`${BASE_URL}/page/${value}`} title={`Go to page ${value}`}>{value}</a> | ||
<li {...props}> | ||
<a href={`${BASE_URL}/page/${value}`} title={title} onClick={onEntryClick}>{label}</a> | ||
</li> | ||
@@ -72,15 +112,15 @@ ); | ||
const Pagination = ({ curr, max }) => { | ||
const sequence = generate(curr, max); | ||
const Pagination = ({ curPage, numPages, numPagesAtEdges = 2, numPagesAroundCurrent = 2, onEntryClick = null }) => { | ||
const sequence = generate(curPage, numPages, numPagesAtEdges, numPagesAroundCurrent); | ||
// console.log(sequence); | ||
// @TODO: Conditionally make the first/prev/next/last links active or inactive, but you get the idea … | ||
return ( | ||
<ul className="pagination"> | ||
<li data-pagination-first><a href={`${BASE_URL}/page/${1}`} title="First Page">«</a></li> | ||
<li data-pagination-prev><a href={`${BASE_URL}/page/${curr-1}`} title="Previous Page">‹</a></li> | ||
{sequence.map(number => | ||
<PaginationEntry key={number} value={number} isCurrent={number == curr} /> | ||
<PaginationEntry data-pagination-first onEntryClick={onEntryClick} value={1} title="Go to First Page" label="«" isDisabled={curPage === 1} /> | ||
<PaginationEntry data-pagination-prev onEntryClick={onEntryClick} value={curPage-1} title="Go to Previous Page" label="‹" isDisabled={curPage === 1} /> | ||
{sequence.map((val, idx) => | ||
<PaginationEntry key={`page-${(val == '…') ? `…-${idx}` : val}`} onEntryClick={onEntryClick} value={val} isCurrent={val == curPage} /> | ||
)} | ||
<li data-pagination-next><a href={`${BASE_URL}/page/${curr+1}`} title="Next Page">›</a></li> | ||
<li data-pagination-last><a href={`${BASE_URL}/page/${max}`} title="Last Page">»</a></li> | ||
<PaginationEntry data-pagination-next onEntryClick={onEntryClick} value={curPage+1} title="Go to Next Page" label="›" isDisabled={curPage === numPages} /> | ||
<PaginationEntry data-pagination-next onEntryClick={onEntryClick} value={numPages} title="Go to Last Page" label="»" isDisabled={curPage === numPages} /> | ||
</ul> | ||
@@ -91,3 +131,3 @@ ); | ||
ReactDOM.render( | ||
<Pagination curr="25" max="50" />, | ||
<Pagination curPage="25" numPages="50" />, | ||
document.getElementById('root') | ||
@@ -99,1 +139,8 @@ ); | ||
`@bramus/pagination-sequence` is released under the MIT public license. See the enclosed `LICENSE` for details. | ||
## Other Language Implementations | ||
Looking for an implementation in another programming language? | ||
- PHP: [https://gist.github.com/bramus/5d8f2e0269e57dff5136](https://gist.github.com/bramus/5d8f2e0269e57dff5136) _(The original, from 2014)_ | ||
- _(submit a PR to add your own)_ |
19223
141