dioxus_bootstrap_css/
pagination.rs1use dioxus::prelude::*;
2
3use crate::types::Size;
4
5#[derive(Clone, PartialEq, Props)]
14pub struct PaginationProps {
15 pub current: Signal<usize>,
17 pub total: usize,
19 #[props(default = 2)]
21 pub window: usize,
22 #[props(default)]
24 pub size: Size,
25 #[props(default = true)]
27 pub show_prev_next: bool,
28 #[props(default)]
30 pub class: String,
31}
32
33#[component]
34pub fn Pagination(props: PaginationProps) -> Element {
35 let current = *props.current.read();
36 let mut page_signal = props.current;
37 let total = props.total;
38
39 if total == 0 {
40 return rsx! {};
41 }
42
43 let size_class = match props.size {
44 Size::Md => String::new(),
45 s => format!(" pagination-{s}"),
46 };
47
48 let full_class = if props.class.is_empty() {
49 format!("pagination{size_class}")
50 } else {
51 format!("pagination{size_class} {}", props.class)
52 };
53
54 let start = if current > props.window {
56 current - props.window
57 } else {
58 1
59 };
60 let end = if current + props.window <= total {
61 current + props.window
62 } else {
63 total
64 };
65
66 rsx! {
67 nav { "aria-label": "Page navigation",
68 ul { class: "{full_class}",
69 if props.show_prev_next {
71 li { class: if current <= 1 { "page-item disabled" } else { "page-item" },
72 button {
73 class: "page-link",
74 disabled: current <= 1,
75 onclick: move |_| {
76 if current > 1 {
77 page_signal.set(current - 1);
78 }
79 },
80 "aria-label": "Previous",
81 span { "aria-hidden": "true", "\u{2039}" }
82 }
83 }
84 }
85
86 if start > 1 {
88 li { class: "page-item",
89 button {
90 class: "page-link",
91 onclick: move |_| page_signal.set(1),
92 "1"
93 }
94 }
95 if start > 2 {
96 li { class: "page-item disabled",
97 span { class: "page-link", "\u{2026}" }
98 }
99 }
100 }
101
102 for p in start..=end {
104 li {
105 class: if p == current { "page-item active" } else { "page-item" },
106 button {
107 class: "page-link",
108 "aria-current": if p == current { "page" } else { "" },
109 onclick: move |_| page_signal.set(p),
110 "{p}"
111 }
112 }
113 }
114
115 if end < total {
117 if end < total - 1 {
118 li { class: "page-item disabled",
119 span { class: "page-link", "\u{2026}" }
120 }
121 }
122 li { class: "page-item",
123 button {
124 class: "page-link",
125 onclick: move |_| page_signal.set(total),
126 "{total}"
127 }
128 }
129 }
130
131 if props.show_prev_next {
133 li { class: if current >= total { "page-item disabled" } else { "page-item" },
134 button {
135 class: "page-link",
136 disabled: current >= total,
137 onclick: move |_| {
138 if current < total {
139 page_signal.set(current + 1);
140 }
141 },
142 "aria-label": "Next",
143 span { "aria-hidden": "true", "\u{203A}" }
144 }
145 }
146 }
147 }
148 }
149 }
150}