1
- import {
2
- For ,
3
- Show ,
4
- batch ,
5
- createEffect ,
6
- createSignal ,
7
- untrack ,
8
- } from "solid-js" ;
1
+ import { For , Show , createMemo } from "solid-js" ;
9
2
10
3
import { usePaginationContext } from "./pagination-context" ;
11
4
@@ -14,86 +7,112 @@ export interface PaginationItemsProps {}
14
7
export function PaginationItems ( props : PaginationItemsProps ) {
15
8
const context = usePaginationContext ( ) ;
16
9
17
- const [ showFirst , setShowFirst ] = createSignal ( false ) ;
18
- const [ showLast , setShowLast ] = createSignal ( false ) ;
19
-
20
- const [ showFirstEllipsis , setShowFirstEllipsis ] = createSignal ( false ) ;
21
- const [ showLastEllipsis , setShowLastEllipsis ] = createSignal ( false ) ;
22
-
23
- const [ previousSiblingCount , setPreviousSiblingCount ] = createSignal ( 0 ) ;
24
- const [ nextSiblingCount , setNextSiblingCount ] = createSignal ( 0 ) ;
25
-
26
- createEffect ( ( ) => {
27
- batch ( ( ) => {
28
- setShowFirst (
29
- context . showFirst ( ) && context . page ( ) - 1 > context . siblingCount ( ) ,
30
- ) ;
31
- setShowLast (
32
- context . showLast ( ) &&
33
- context . count ( ) - context . page ( ) > context . siblingCount ( ) ,
34
- ) ;
35
-
36
- setShowFirstEllipsis (
37
- context . page ( ) - ( context . showFirst ( ) ? 2 : 1 ) > context . siblingCount ( ) ,
38
- ) ;
39
- setShowLastEllipsis (
40
- context . count ( ) - context . page ( ) - ( context . showLast ( ) ? 1 : 0 ) >
41
- context . siblingCount ( ) ,
42
- ) ;
43
-
44
- setPreviousSiblingCount (
45
- Math . min ( context . page ( ) - 1 , context . siblingCount ( ) ) ,
46
- ) ;
47
- setNextSiblingCount (
48
- Math . min ( context . count ( ) - context . page ( ) , context . siblingCount ( ) ) ,
49
- ) ;
50
-
51
- if ( context . fixedItems ( ) !== false ) {
52
- // Untrack to avoid recursion
53
- untrack ( ( ) => {
54
- // Add back the difference between the opposite side and the sibling count
55
- setPreviousSiblingCount (
56
- ( prev ) =>
57
- prev + Math . max ( context . siblingCount ( ) - nextSiblingCount ( ) , 0 ) ,
58
- ) ;
59
- setNextSiblingCount (
60
- ( prev ) =>
61
- prev +
62
- Math . max ( context . siblingCount ( ) - previousSiblingCount ( ) , 0 ) ,
63
- ) ;
64
- } ) ;
65
-
66
- if ( ! showFirst ( ) ) setNextSiblingCount ( ( prev ) => prev + 1 ) ;
67
- if ( ! showLast ( ) ) setPreviousSiblingCount ( ( prev ) => prev + 1 ) ;
68
-
69
- // Check specifically if true and not "no-ellipsis"
70
- if ( context . fixedItems ( ) === true ) {
71
- if ( ! showFirstEllipsis ( ) ) setNextSiblingCount ( ( prev ) => prev + 1 ) ;
72
- if ( ! showLastEllipsis ( ) ) setPreviousSiblingCount ( ( prev ) => prev + 1 ) ;
73
- }
10
+ const items = createMemo ( ( ) => {
11
+ const { count, siblingCount, page, fixedItems, showFirst, showLast } =
12
+ context ;
13
+ // render directly if count is so small that it does not make sense to render an ellipsis
14
+ // this is the case for if count is lower than 2x siblings + 6 for fixedItems and +4 if not fixed items
15
+ const renderItemsDirectly =
16
+ count ( ) < 2 * siblingCount ( ) + ( fixedItems ( ) ? 6 : 4 ) ;
17
+
18
+ //skip the rest of the computation if we can render directly
19
+ if ( renderItemsDirectly )
20
+ return {
21
+ renderItemsDirectly,
22
+ } ;
23
+
24
+ const _showFirst = showFirst ( ) && page ( ) - 1 > siblingCount ( ) ;
25
+ const _showLast = showLast ( ) && count ( ) - page ( ) > siblingCount ( ) ;
26
+
27
+ let showFirstEllipsis = page ( ) - ( showFirst ( ) ? 2 : 1 ) > siblingCount ( ) ;
28
+ let showLastEllipsis =
29
+ count ( ) - page ( ) - ( showLast ( ) ? 1 : 0 ) > siblingCount ( ) ;
30
+
31
+ let previousSiblingCount = Math . min ( page ( ) - 1 , siblingCount ( ) ) ;
32
+ let nextSiblingCount = Math . min ( count ( ) - page ( ) , siblingCount ( ) ) ;
33
+
34
+ if ( fixedItems ( ) !== false ) {
35
+ // ref to avoid wrong corretions
36
+ const previousSiblingCountRef = previousSiblingCount ;
37
+ const nextSiblingCountRef = nextSiblingCount ;
38
+
39
+ // Add back the difference between the opposite side and the sibling count
40
+ previousSiblingCount += Math . max ( siblingCount ( ) - nextSiblingCountRef , 0 ) ;
41
+ nextSiblingCount += Math . max ( siblingCount ( ) - previousSiblingCountRef , 0 ) ;
42
+
43
+ if ( ! _showFirst ) nextSiblingCount ++ ;
44
+ if ( ! _showLast ) previousSiblingCount ++ ;
45
+
46
+ // Check specifically if true and not "no-ellipsis"
47
+ if ( fixedItems ( ) === true ) {
48
+ if ( ! showFirstEllipsis ) nextSiblingCount ++ ;
49
+ if ( ! showLastEllipsis ) previousSiblingCount ++ ;
50
+ }
51
+
52
+ //replace ellipsis if it would replace only one item
53
+ if ( page ( ) - previousSiblingCount - ( showFirst ( ) ? 2 : 1 ) === 1 ) {
54
+ showFirstEllipsis = false ;
55
+ previousSiblingCount ++ ;
74
56
}
75
- } ) ;
57
+ if ( count ( ) - page ( ) - nextSiblingCount - ( showLast ( ) ? 1 : 0 ) === 1 ) {
58
+ showLastEllipsis = false ;
59
+ nextSiblingCount ++ ;
60
+ }
61
+ }
62
+
63
+ return {
64
+ showFirst : _showFirst ,
65
+ showLast : _showLast ,
66
+ showFirstEllipsis,
67
+ showLastEllipsis,
68
+ previousSiblingCount,
69
+ nextSiblingCount,
70
+ renderItemsDirectly,
71
+ } ;
76
72
} ) ;
77
73
78
74
return (
79
75
< >
80
- < Show when = { showFirst ( ) } > { context . renderItem ( 1 ) } </ Show >
81
-
82
- < Show when = { showFirstEllipsis ( ) } > { context . renderEllipsis ( ) } </ Show >
83
-
84
- < For each = { [ ...Array ( previousSiblingCount ( ) ) . keys ( ) ] . reverse ( ) } >
85
- { ( offset ) => < > { context . renderItem ( context . page ( ) - ( offset + 1 ) ) } </ > }
86
- </ For >
87
-
88
- { context . renderItem ( context . page ( ) ) }
89
-
90
- < For each = { [ ...Array ( nextSiblingCount ( ) ) . keys ( ) ] } >
91
- { ( offset ) => < > { context . renderItem ( context . page ( ) + ( offset + 1 ) ) } </ > }
92
- </ For >
93
-
94
- < Show when = { showLastEllipsis ( ) } > { context . renderEllipsis ( ) } </ Show >
95
-
96
- < Show when = { showLast ( ) } > { context . renderItem ( context . count ( ) ) } </ Show >
76
+ < Show
77
+ when = { items ( ) . renderItemsDirectly }
78
+ fallback = {
79
+ < >
80
+ < Show when = { items ( ) . showFirst } > { context . renderItem ( 1 ) } </ Show >
81
+
82
+ < Show when = { items ( ) . showFirstEllipsis } >
83
+ { context . renderEllipsis ( ) }
84
+ </ Show >
85
+
86
+ < For
87
+ each = { [ ...Array ( items ( ) . previousSiblingCount ) . keys ( ) ] . reverse ( ) }
88
+ >
89
+ { ( offset ) => (
90
+ < > { context . renderItem ( context . page ( ) - ( offset + 1 ) ) } </ >
91
+ ) }
92
+ </ For >
93
+
94
+ { context . renderItem ( context . page ( ) ) }
95
+
96
+ < For each = { [ ...Array ( items ( ) . nextSiblingCount ) . keys ( ) ] } >
97
+ { ( offset ) => (
98
+ < > { context . renderItem ( context . page ( ) + ( offset + 1 ) ) } </ >
99
+ ) }
100
+ </ For >
101
+
102
+ < Show when = { items ( ) . showLastEllipsis } >
103
+ { context . renderEllipsis ( ) }
104
+ </ Show >
105
+
106
+ < Show when = { items ( ) . showLast } >
107
+ { context . renderItem ( context . count ( ) ) }
108
+ </ Show >
109
+ </ >
110
+ }
111
+ >
112
+ < For each = { [ ...Array ( context . count ( ) ) . keys ( ) ] } >
113
+ { ( page ) => < > { context . renderItem ( page + 1 ) } </ > }
114
+ </ For >
115
+ </ Show >
97
116
</ >
98
117
) ;
99
118
}
0 commit comments