1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//! Paginator component for offset/limit paginated tables.
//!
//! Bridges `orbital_paging`'s `offset`/`limit`/`total_count` convention to the
//! 1-indexed `page`/`page_count` model used by [`Pagination`], so every
//! paginated table in the platform gets consistent controls out of the box.
use *;
use SignalModel;
use ;
use component_doc;
use inline_style_sheet_values;
/// Table footer control for offset/limit queries.
///
/// Bind `offset` and `limit` to your fetch `Resource`, set `total_count` from `Page::total_count`, and page clicks update `offset` automatically. When `total_count` is unknown, navigation collapses to a single page. Renders core [`Pagination`] for the page-button UX.
///
/// # When to use
///
/// - Table and list views with explicit page controls and a known (or eventually known) total
/// - Platform paging convention: `offset` + `limit` rather than page index in your query layer
///
/// Prefer [`crate::components::OrbitalInfiniteScroll`] when load-more-on-scroll fits better — social feeds, activity logs, and long catalogs where scrolling is the primary navigation. Use [`crate::components::EmptyState`] when the first page returns no items.
///
/// # Usage
///
/// 1. Create an `offset` signal (starts at `0`). 2. Pass `limit` matching your query page size. 3. Set `total_count` from the first page response (`Page::total_count`). 4. Bind the table `Resource` to `offset` so page clicks trigger a refetch.
///
/// Renders native [`Pagination`] from `orbital-core-components`.
///
/// Minimal wiring (docs snippet — not a live preview):
///
/// ```rust
/// let offset = RwSignal::new(0u32);
/// let rows = Resource::new(move || offset.get(), |o| fetch_page(o, 25));
/// ```
///
/// # Best Practices
///
/// ## Do's
///
/// * Reset `offset` to `0` when filters or search change. * Keep **limit** stable for a given view. * When `total_count` is unknown, pass `None`.
///
/// ## Don'ts
///
/// * Do not fetch on every render — bind the table `Resource` to `offset`. * Do not use paginator UX when infinite scroll fits better ([`crate::components::OrbitalInfiniteScroll`]).
///
/// # Examples
///
/// ## Default pagination
/// Table footer with 25 rows per page and a known total.
/// <!-- default -->
/// <!-- preview -->
/// ```rust
/// let offset = RwSignal::new(0u32);
/// let total_count = RwSignal::new(Some(250u64));
///
/// view! {
/// <div data-testid="paginator-preview" style="display: flex; justify-content: center; width: 100%;">
/// <Paginator offset=offset limit=25 total_count=total_count />
/// </div>
/// }
/// ```
///
/// ## Small dataset (3 pages)
/// Compact footer with ten rows per page and thirty total items, yielding three page buttons. Use to verify pagination layout and behavior on short lists without many controls.
/// <!-- preview -->
/// ```rust
/// let offset = RwSignal::new(0u32);
/// let total = RwSignal::new(Some(30u64));
///
/// view! {
/// <div data-testid="paginator-small">
/// <Paginator offset=offset limit=10 total_count=total />
/// </div>
/// }
/// ```
///
/// ## Unknown total
/// Single-page fallback when the server has not returned a total yet.
/// <!-- preview -->
/// ```rust
/// let offset = RwSignal::new(0u32);
/// let total = Signal::derive(|| None::<u64>);
///
/// view! {
/// <div data-testid="paginator-unknown">
/// <Paginator offset=offset limit=25 total_count=total />
/// </div>
/// }
/// ```
///
/// ## Click page 2 updates offset
/// Paginator bound to an offset signal with a live readout of the current offset value. Use to confirm page clicks write back to the parent offset for Resource refetches.
/// <!-- preview -->
/// ```rust
/// let offset = RwSignal::new(0u32);
/// let total = RwSignal::new(Some(50u64));
///
/// view! {
/// <div data-testid="paginator-offset">
/// <Paginator offset=offset limit=25 total_count=total />
/// <span data-testid="paginator-offset-value">{move || offset.get()}</span>
/// </div>
/// }
/// ```
///
/// ## Theme surfaces
/// Active page button resolves theme tokens.
/// <!-- preview -->
/// ```rust
/// let offset = RwSignal::new(25u32);
/// let total = RwSignal::new(Some(100u64));
///
/// view! {
/// <div data-testid="paginator-theme">
/// <Paginator offset=offset limit=25 total_count=total />
/// </div>
/// }
/// ```
///
/// ## Wiring with a Resource
/// Docs-only — not rendered live.
/// ```rust,ignore
/// let offset = RwSignal::new(0u32);
/// let rows = Resource::new(move || (offset.get(),), |(o,)| fetch_page(o, 25));
/// ```