1
- use std:: cmp:: { max, min} ;
2
-
1
+ use crate :: { Button , ButtonSize , ButtonVariant } ;
3
2
use leptos:: * ;
4
- use thaw_utils:: { class_list, mount_style, OptionalProp } ;
5
-
6
- use crate :: { Button , ButtonColor , ButtonSize , ButtonVariant } ;
3
+ use std:: cmp:: min;
4
+ use thaw_utils:: { class_list, mount_style, Model , OptionalProp , StoredMaybeSignal } ;
7
5
8
- fn range ( start : i64 , end : i64 ) -> Vec < PaginationItem > {
6
+ fn range ( start : usize , end : usize ) -> Vec < PaginationItem > {
9
7
let mut ret = vec ! [ ] ;
10
8
for idx in start..=end {
11
9
ret. push ( PaginationItem :: Number ( idx) ) ;
@@ -16,10 +14,10 @@ fn range(start: i64, end: i64) -> Vec<PaginationItem> {
16
14
enum PaginationItem {
17
15
DotLeft ,
18
16
DotRight ,
19
- Number ( i64 ) ,
17
+ Number ( usize ) ,
20
18
}
21
19
22
- fn use_pagination ( page : i64 , count : i64 , sibling_count : i64 ) -> Vec < PaginationItem > {
20
+ fn use_pagination ( page : usize , count : usize , sibling_count : usize ) -> Vec < PaginationItem > {
23
21
// Pages count is determined as siblingCount + firstPage + lastPage + currentPage + 2*DOTS
24
22
let total_page_numbers = sibling_count + 5 ;
25
23
// Case 1:
@@ -30,7 +28,11 @@ fn use_pagination(page: i64, count: i64, sibling_count: i64) -> Vec<PaginationIt
30
28
}
31
29
let current_page = page;
32
30
// Calculate left and right sibling index and make sure they are within range 1 and totalPageCount
33
- let left_sibling_index = max ( current_page - sibling_count, 1 ) ;
31
+ let left_sibling_index = if current_page > sibling_count + 1 {
32
+ current_page - sibling_count
33
+ } else {
34
+ 1
35
+ } ;
34
36
let right_sibling_index = min ( current_page + sibling_count, count) ;
35
37
// We do not show dots just when there is just one page number to be inserted between the extremes of sibling and the page limits i.e 1 and totalPageCount.
36
38
// Hence we are using leftSiblingIndex > 2 and rightSiblingIndex < totalPageCount - 2
@@ -75,85 +77,101 @@ fn use_pagination(page: i64, count: i64, sibling_count: i64) -> Vec<PaginationIt
75
77
76
78
#[ component]
77
79
pub fn Pagination (
78
- #[ prop( default = MaybeSignal :: Static ( 1 ) , into) ] page : MaybeSignal < i64 > ,
79
- #[ prop( into) ] count : MaybeSignal < i64 > ,
80
- #[ prop( default = MaybeSignal :: Static ( 1 ) , into) ] sibling_count : MaybeSignal < i64 > ,
81
- #[ prop( optional, into) ] on_change : Option < Callback < i64 > > ,
80
+ #[ prop( default = 1 . into ( ) , into) ] page : Model < usize > ,
81
+ #[ prop( into) ] count : MaybeSignal < usize > ,
82
+ #[ prop( default = 1 . into ( ) , into) ] sibling_count : MaybeSignal < usize > ,
83
+ #[ prop( optional, into) ] on_change : Option < Callback < usize > > ,
82
84
#[ prop( optional, into) ] class : OptionalProp < MaybeSignal < String > > ,
83
- #[ prop( optional, into) ] color : MaybeSignal < ButtonColor > ,
84
85
#[ prop( optional, into) ] size : MaybeSignal < ButtonSize > ,
85
86
) -> impl IntoView {
86
- let ( page_signal, set_page_signal) = create_signal ( 1 ) ;
87
- let no_next = MaybeSignal :: derive ( move || page_signal. get ( ) == count. get ( ) ) ;
88
- let no_previous = MaybeSignal :: derive ( move || page_signal. get ( ) == 1 ) ;
87
+ mount_style ( "pagination" , include_str ! ( "./pagination.css" ) ) ;
88
+
89
+ let size: StoredMaybeSignal < _ > = size. into ( ) ;
90
+ let no_next = Memo :: new ( move |_| page. get ( ) == count. get ( ) ) ;
91
+ let no_previous = Memo :: new ( move |_| page. get ( ) == 1 ) ;
89
92
90
93
let on_click_previous = move |_| {
91
- set_page_signal . update ( |val| * val -= 1 ) ;
94
+ page . update ( |val| * val -= 1 ) ;
92
95
if let Some ( callback) = on_change. as_ref ( ) {
93
- callback. call ( page_signal . get ( ) )
96
+ callback. call ( page . get ( ) )
94
97
}
95
98
} ;
96
99
97
100
let on_click_next = move |_| {
98
- set_page_signal . update ( |val| * val += 1 ) ;
101
+ page . update ( |val| * val += 1 ) ;
99
102
if let Some ( callback) = on_change. as_ref ( ) {
100
- callback. call ( page_signal . get ( ) )
103
+ callback. call ( page . get ( ) )
101
104
}
102
105
} ;
103
106
104
- create_effect ( move |_| {
105
- set_page_signal. update ( |val| {
106
- let default = page. get ( ) ;
107
- if * val != default {
108
- * val = default
109
- }
110
- } ) ;
111
- } ) ;
112
-
113
- mount_style ( "pagination" , include_str ! ( "./pagination.css" ) ) ;
114
-
115
107
view ! {
116
108
<nav class=class_list![ "thaw-pagination" , class. map( | c | move || c. get( ) ) ] >
117
109
<ul>
118
110
<li>
119
111
<Button
120
- color=color . clone ( ) size=size. clone( )
112
+ size=size. clone( )
121
113
on_click=on_click_previous
122
114
variant=ButtonVariant :: Text
123
- icon=icondata_ai:: AiLeftOutlined disabled=no_previous circle=true />
115
+ icon=icondata_ai:: AiLeftOutlined
116
+ disabled=no_previous
117
+ circle=true
118
+ />
124
119
</li>
125
- {
126
- let cloned_color = color. clone( ) ;
127
- let cloned_size = size. clone( ) ;
128
- view! {
129
- <For each=move || use_pagination( page_signal. get( ) , count. get( ) , sibling_count. get( ) ) key=|item| match item {
130
- PaginationItem :: DotLeft => -2 ,
131
- PaginationItem :: DotRight => -1 ,
132
- PaginationItem :: Number ( nb) => nb. clone( )
133
- }
134
- children=move |item| match item {
135
- PaginationItem :: Number ( nb) => view! { <li>
136
- <Button
137
- color=cloned_color. clone( ) size=cloned_size. clone( )
138
- variant=MaybeSignal :: derive( move || if page_signal. get( ) == nb { ButtonVariant :: Primary } else { ButtonVariant :: Text } )
139
- on_click = move |_| {
140
- if page_signal. get( ) != nb { set_page_signal. set( nb) }
141
- if let Some ( callback) = on_change. as_ref( ) {
142
- callback. call( page_signal. get( ) )
120
+
121
+ <For
122
+ each=move || use_pagination( page. get( ) , count. get( ) , sibling_count. get( ) )
123
+ key=|item| match item {
124
+ PaginationItem :: DotLeft => -2 ,
125
+ PaginationItem :: DotRight => -1 ,
126
+ PaginationItem :: Number ( nb) => nb. clone( ) as i64
127
+ }
128
+ let : item
129
+ >
130
+ {
131
+ if let PaginationItem :: Number ( nb) = item {
132
+ view! {
133
+ <li>
134
+ <Button
135
+ size=size. clone( )
136
+ style=Memo :: new( move |_| if page. get( ) == nb {
137
+ "color: var(--thaw-font-color-hover); border-color: var(--thaw-border-color-hover);" . to_string( )
138
+ } else {
139
+ "" . to_string( )
140
+ } )
141
+ variant=Memo :: new( move |_| if page. get( ) == nb {
142
+ ButtonVariant :: Outlined
143
+ } else {
144
+ ButtonVariant :: Text
145
+ } )
146
+ on_click = move |_| {
147
+ if page. get( ) != nb {
148
+ page. set( nb)
149
+ }
150
+ if let Some ( callback) = on_change. as_ref( ) {
151
+ callback. call( page. get( ) )
152
+ }
143
153
}
144
- }
145
- round=true >{ nb} </Button >
146
- </li>} ,
147
- _ => view! { <li>"..." </li>} ,
148
- } />
154
+ round=true
155
+ >
156
+ { nb}
157
+ </Button >
158
+ </li>
159
+ }
160
+ } else {
161
+ view! {
162
+ <li>"..." </li>
163
+ }
164
+ }
149
165
}
150
- }
166
+ </ For >
151
167
<li>
152
168
<Button
153
- color size
169
+ size
154
170
on_click=on_click_next
155
171
variant=ButtonVariant :: Text
156
- icon=icondata_ai:: AiRightOutlined disabled=no_next circle=true />
172
+ icon=icondata_ai:: AiRightOutlined disabled=no_next
173
+ circle=true
174
+ />
157
175
</li>
158
176
</ul>
159
177
</nav>
0 commit comments