@delightui/components 0.1.104 → 0.1.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -1
- package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
- package/dist/cjs/components/molecules/Popover/Popover.presenter.d.ts +26 -0
- package/dist/cjs/components/molecules/Select/Option/Option.types.d.ts +6 -0
- package/dist/cjs/components/molecules/Select/Select.Context.d.ts +1 -1
- package/dist/cjs/components/molecules/Select/Select.d.ts +5 -5
- package/dist/cjs/components/molecules/Select/Select.presenter.d.ts +1 -0
- package/dist/cjs/components/molecules/Select/Select.types.d.ts +5 -0
- package/dist/cjs/components/molecules/Select/index.d.ts +2 -9
- package/dist/cjs/components/molecules/index.d.ts +2 -0
- package/dist/cjs/components/utils/accessibilityUtils.d.ts +41 -0
- package/dist/cjs/components/utils/index.d.ts +2 -0
- package/dist/cjs/library.css +13 -0
- package/dist/cjs/library.js +2 -2
- package/dist/cjs/library.js.map +1 -1
- package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
- package/dist/esm/components/molecules/Popover/Popover.presenter.d.ts +26 -0
- package/dist/esm/components/molecules/Select/Option/Option.types.d.ts +6 -0
- package/dist/esm/components/molecules/Select/Select.Context.d.ts +1 -1
- package/dist/esm/components/molecules/Select/Select.d.ts +5 -5
- package/dist/esm/components/molecules/Select/Select.presenter.d.ts +1 -0
- package/dist/esm/components/molecules/Select/Select.types.d.ts +5 -0
- package/dist/esm/components/molecules/Select/index.d.ts +2 -9
- package/dist/esm/components/molecules/index.d.ts +2 -0
- package/dist/esm/components/utils/accessibilityUtils.d.ts +41 -0
- package/dist/esm/components/utils/index.d.ts +2 -0
- package/dist/esm/library.css +13 -0
- package/dist/esm/library.js +3 -3
- package/dist/esm/library.js.map +1 -1
- package/dist/index.d.ts +156 -12
- package/docs/README.md +264 -0
- package/docs/components/atoms/ActionImage.md +119 -0
- package/docs/components/atoms/Button.md +197 -0
- package/docs/components/atoms/Checkbox.md +299 -0
- package/docs/components/atoms/CheckboxItem.md +314 -0
- package/docs/components/atoms/Chip.md +380 -0
- package/docs/components/atoms/CustomToggle.md +270 -0
- package/docs/components/atoms/Icon.md +365 -0
- package/docs/components/atoms/IconButton.md +407 -0
- package/docs/components/atoms/Image.md +448 -0
- package/docs/components/atoms/Input.md +430 -0
- package/docs/components/atoms/ListItem.md +502 -0
- package/docs/components/atoms/Password.md +472 -0
- package/docs/components/atoms/RadioButton.md +614 -0
- package/docs/components/atoms/RadioButtonItem.md +588 -0
- package/docs/components/atoms/ResponsiveComponent.md +612 -0
- package/docs/components/atoms/SelectListItem.md +609 -0
- package/docs/components/atoms/Slider.md +605 -0
- package/docs/components/atoms/Spinner.md +605 -0
- package/docs/components/atoms/Text.md +463 -0
- package/docs/components/atoms/TextArea.md +670 -0
- package/docs/components/atoms/ToastNotification.md +668 -0
- package/docs/components/atoms/Toggle.md +737 -0
- package/docs/components/atoms/ToggleButton.md +751 -0
- package/docs/components/atoms/Tooltip.md +391 -0
- package/docs/components/molecules/Accordion.md +440 -0
- package/docs/components/molecules/AccordionGroup.md +547 -0
- package/docs/components/molecules/ActionCard.md +546 -0
- package/docs/components/molecules/Breadcrumb.md +403 -0
- package/docs/components/molecules/Breadcrumbs.md +485 -0
- package/docs/components/molecules/ButtonGroup.md +383 -0
- package/docs/components/molecules/Card.md +298 -0
- package/docs/components/molecules/ChipInput.md +646 -0
- package/docs/components/molecules/ContextMenu.md +768 -0
- package/docs/components/molecules/CustomTimeSelector.md +116 -0
- package/docs/components/molecules/DatePicker.md +516 -0
- package/docs/components/molecules/DateTimeSelector.md +166 -0
- package/docs/components/molecules/FormField.md +312 -0
- package/docs/components/molecules/Grid.md +577 -0
- package/docs/components/molecules/GridItem.md +834 -0
- package/docs/components/molecules/GridList.md +244 -0
- package/docs/components/molecules/List.md +485 -0
- package/docs/components/molecules/Modal.md +470 -0
- package/docs/components/molecules/ModalFooter.md +702 -0
- package/docs/components/molecules/ModalHeader.md +756 -0
- package/docs/components/molecules/ModalProvider.md +205 -0
- package/docs/components/molecules/Nav.md +530 -0
- package/docs/components/molecules/NavItem.md +572 -0
- package/docs/components/molecules/NavLink.md +499 -0
- package/docs/components/molecules/Option.md +521 -0
- package/docs/components/molecules/Pagination.md +592 -0
- package/docs/components/molecules/PaginationNumberField.md +722 -0
- package/docs/components/molecules/Popover.md +516 -0
- package/docs/components/molecules/ProgressBar.md +624 -0
- package/docs/components/molecules/RadioGroup.md +831 -0
- package/docs/components/molecules/RepeaterList.md +185 -0
- package/docs/components/molecules/Select.md +402 -0
- package/docs/components/molecules/SortableTrigger.md +82 -0
- package/docs/components/molecules/useModal.md +379 -0
- package/docs/components/organisms/Dropzone.md +346 -0
- package/docs/components/organisms/DropzoneClear.md +135 -0
- package/docs/components/organisms/DropzoneContent.md +216 -0
- package/docs/components/organisms/DropzoneFilename.md +191 -0
- package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
- package/docs/components/organisms/DropzoneTrigger.md +209 -0
- package/docs/components/organisms/Form.md +533 -0
- package/docs/components/organisms/SlideOutPanel.md +662 -0
- package/docs/components/organisms/TabContent.md +902 -0
- package/docs/components/organisms/TabItem.md +1091 -0
- package/docs/components/organisms/Table.md +611 -0
- package/docs/components/organisms/TableBody.md +679 -0
- package/docs/components/organisms/TableCell.md +482 -0
- package/docs/components/organisms/TableHeader.md +513 -0
- package/docs/components/organisms/TableHeaderCell.md +661 -0
- package/docs/components/organisms/TableRow.md +715 -0
- package/docs/components/organisms/Tabs.md +1330 -0
- package/docs/components/utils/ConditionalView.md +568 -0
- package/docs/components/utils/RenderStateView.md +726 -0
- package/docs/components/utils/WrapTextNodes.md +614 -0
- package/package.json +3 -2
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
# PaginationNumberField
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
A specialized number input component designed for pagination controls. Allows users to directly enter a page number for quick navigation, with built-in validation, bounds checking, and integration with pagination state management.
|
|
6
|
+
|
|
7
|
+
## Aliases
|
|
8
|
+
|
|
9
|
+
- PaginationNumberField
|
|
10
|
+
- PageNumberInput
|
|
11
|
+
- PageJumpField
|
|
12
|
+
- PageInput
|
|
13
|
+
- NavigationNumberField
|
|
14
|
+
|
|
15
|
+
## Props Breakdown
|
|
16
|
+
|
|
17
|
+
**Extends:** Standalone interface (no HTML element inheritance)
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Required | Description |
|
|
20
|
+
|------|------|---------|----------|-------------|
|
|
21
|
+
| `className` | `string` | - | No | Additional CSS class names for custom styling |
|
|
22
|
+
| `page` | `number` | - | No | Current page number value |
|
|
23
|
+
| `totalPages` | `number` | - | No | Maximum page number allowed |
|
|
24
|
+
| `onPageChanged` | `(page: number) => void` | - | No | Callback function when page number changes |
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### Basic Usage
|
|
29
|
+
```tsx
|
|
30
|
+
import { PaginationNumberField } from '@delightui/components';
|
|
31
|
+
|
|
32
|
+
function BasicExample() {
|
|
33
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
34
|
+
const totalPages = 10;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="pagination-controls">
|
|
38
|
+
<Text>Go to page:</Text>
|
|
39
|
+
<PaginationNumberField
|
|
40
|
+
page={currentPage}
|
|
41
|
+
totalPages={totalPages}
|
|
42
|
+
onPageChanged={setCurrentPage}
|
|
43
|
+
/>
|
|
44
|
+
<Text>of {totalPages}</Text>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Integrated with Pagination
|
|
51
|
+
```tsx
|
|
52
|
+
function IntegratedPaginationExample() {
|
|
53
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
54
|
+
const totalPages = 25;
|
|
55
|
+
const totalItems = 247;
|
|
56
|
+
const itemsPerPage = 10;
|
|
57
|
+
|
|
58
|
+
const startItem = (currentPage - 1) * itemsPerPage + 1;
|
|
59
|
+
const endItem = Math.min(currentPage * itemsPerPage, totalItems);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="integrated-pagination">
|
|
63
|
+
<div className="content-area">
|
|
64
|
+
<Text type="Heading4">Page {currentPage} Content</Text>
|
|
65
|
+
<Text type="BodyMedium">
|
|
66
|
+
Showing items {startItem}-{endItem} of {totalItems}
|
|
67
|
+
</Text>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div className="pagination-bar">
|
|
71
|
+
<Pagination
|
|
72
|
+
currentPage={currentPage}
|
|
73
|
+
totalPages={totalPages}
|
|
74
|
+
updateCurrentPage={setCurrentPage}
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
<div className="page-jump">
|
|
78
|
+
<Text type="BodySmall">Jump to:</Text>
|
|
79
|
+
<PaginationNumberField
|
|
80
|
+
page={currentPage}
|
|
81
|
+
totalPages={totalPages}
|
|
82
|
+
onPageChanged={setCurrentPage}
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Search Results with Page Jump
|
|
92
|
+
```tsx
|
|
93
|
+
function SearchResultsExample() {
|
|
94
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
95
|
+
const [searchTerm, setSearchTerm] = useState('React');
|
|
96
|
+
const [resultsPerPage, setResultsPerPage] = useState(10);
|
|
97
|
+
|
|
98
|
+
const totalResults = 156;
|
|
99
|
+
const totalPages = Math.ceil(totalResults / resultsPerPage);
|
|
100
|
+
|
|
101
|
+
const mockResults = Array.from({ length: resultsPerPage }, (_, index) => ({
|
|
102
|
+
id: (currentPage - 1) * resultsPerPage + index + 1,
|
|
103
|
+
title: `${searchTerm} Tutorial ${(currentPage - 1) * resultsPerPage + index + 1}`,
|
|
104
|
+
description: 'Comprehensive guide to modern development practices...',
|
|
105
|
+
category: 'Tutorial'
|
|
106
|
+
}));
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div className="search-results-example">
|
|
110
|
+
<div className="search-header">
|
|
111
|
+
<Input
|
|
112
|
+
placeholder="Search tutorials..."
|
|
113
|
+
value={searchTerm}
|
|
114
|
+
onValueChange={setSearchTerm}
|
|
115
|
+
leadingIcon={<Icon icon="Search" />}
|
|
116
|
+
/>
|
|
117
|
+
|
|
118
|
+
<div className="results-info">
|
|
119
|
+
<Text type="BodySmall">
|
|
120
|
+
{totalResults} results found
|
|
121
|
+
</Text>
|
|
122
|
+
|
|
123
|
+
<Select value={resultsPerPage} onValueChange={setResultsPerPage}>
|
|
124
|
+
<Option value={5}>5 per page</Option>
|
|
125
|
+
<Option value={10}>10 per page</Option>
|
|
126
|
+
<Option value={20}>20 per page</Option>
|
|
127
|
+
</Select>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<div className="search-results">
|
|
132
|
+
{mockResults.map(result => (
|
|
133
|
+
<Card key={result.id} className="result-card">
|
|
134
|
+
<div className="result-header">
|
|
135
|
+
<Text type="Heading6">{result.title}</Text>
|
|
136
|
+
<Chip size="Small">{result.category}</Chip>
|
|
137
|
+
</div>
|
|
138
|
+
<Text type="BodyMedium">{result.description}</Text>
|
|
139
|
+
</Card>
|
|
140
|
+
))}
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<div className="search-pagination">
|
|
144
|
+
<Pagination
|
|
145
|
+
currentPage={currentPage}
|
|
146
|
+
totalPages={totalPages}
|
|
147
|
+
updateCurrentPage={setCurrentPage}
|
|
148
|
+
/>
|
|
149
|
+
|
|
150
|
+
<div className="quick-navigation">
|
|
151
|
+
<Text type="BodySmall">Page:</Text>
|
|
152
|
+
<PaginationNumberField
|
|
153
|
+
page={currentPage}
|
|
154
|
+
totalPages={totalPages}
|
|
155
|
+
onPageChanged={setCurrentPage}
|
|
156
|
+
className="compact-field"
|
|
157
|
+
/>
|
|
158
|
+
<Text type="BodySmall">of {totalPages}</Text>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Data Table with Page Jump
|
|
167
|
+
```tsx
|
|
168
|
+
function DataTableExample() {
|
|
169
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
170
|
+
const [sortBy, setSortBy] = useState('id');
|
|
171
|
+
const [sortOrder, setSortOrder] = useState('asc');
|
|
172
|
+
|
|
173
|
+
const rowsPerPage = 15;
|
|
174
|
+
const totalRows = 342;
|
|
175
|
+
const totalPages = Math.ceil(totalRows / rowsPerPage);
|
|
176
|
+
|
|
177
|
+
const mockData = Array.from({ length: rowsPerPage }, (_, index) => {
|
|
178
|
+
const id = (currentPage - 1) * rowsPerPage + index + 1;
|
|
179
|
+
return {
|
|
180
|
+
id,
|
|
181
|
+
name: `User ${id}`,
|
|
182
|
+
email: `user${id}@example.com`,
|
|
183
|
+
status: ['Active', 'Inactive', 'Pending'][Math.floor(Math.random() * 3)],
|
|
184
|
+
lastLogin: '2024-01-15'
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<div className="data-table-example">
|
|
190
|
+
<div className="table-controls">
|
|
191
|
+
<div className="sort-controls">
|
|
192
|
+
<Select value={sortBy} onValueChange={setSortBy}>
|
|
193
|
+
<Option value="id">Sort by ID</Option>
|
|
194
|
+
<Option value="name">Sort by Name</Option>
|
|
195
|
+
<Option value="email">Sort by Email</Option>
|
|
196
|
+
<Option value="status">Sort by Status</Option>
|
|
197
|
+
</Select>
|
|
198
|
+
|
|
199
|
+
<Select value={sortOrder} onValueChange={setSortOrder}>
|
|
200
|
+
<Option value="asc">Ascending</Option>
|
|
201
|
+
<Option value="desc">Descending</Option>
|
|
202
|
+
</Select>
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
<Text type="BodySmall">
|
|
206
|
+
{totalRows} total records
|
|
207
|
+
</Text>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<Table className="data-table">
|
|
211
|
+
<TableHeader>
|
|
212
|
+
<TableHeaderCell>ID</TableHeaderCell>
|
|
213
|
+
<TableHeaderCell>Name</TableHeaderCell>
|
|
214
|
+
<TableHeaderCell>Email</TableHeaderCell>
|
|
215
|
+
<TableHeaderCell>Status</TableHeaderCell>
|
|
216
|
+
<TableHeaderCell>Last Login</TableHeaderCell>
|
|
217
|
+
</TableHeader>
|
|
218
|
+
<TableBody>
|
|
219
|
+
{mockData.map(row => (
|
|
220
|
+
<TableRow key={row.id}>
|
|
221
|
+
<TableCell>{row.id}</TableCell>
|
|
222
|
+
<TableCell>{row.name}</TableCell>
|
|
223
|
+
<TableCell>{row.email}</TableCell>
|
|
224
|
+
<TableCell>
|
|
225
|
+
<Chip
|
|
226
|
+
size="Small"
|
|
227
|
+
style={row.status === 'Active' ? 'Success' : row.status === 'Pending' ? 'Warning' : 'Default'}
|
|
228
|
+
>
|
|
229
|
+
{row.status}
|
|
230
|
+
</Chip>
|
|
231
|
+
</TableCell>
|
|
232
|
+
<TableCell>{row.lastLogin}</TableCell>
|
|
233
|
+
</TableRow>
|
|
234
|
+
))}
|
|
235
|
+
</TableBody>
|
|
236
|
+
</Table>
|
|
237
|
+
|
|
238
|
+
<div className="table-pagination">
|
|
239
|
+
<div className="pagination-info">
|
|
240
|
+
<Text type="BodySmall">
|
|
241
|
+
Showing {(currentPage - 1) * rowsPerPage + 1}-{Math.min(currentPage * rowsPerPage, totalRows)} of {totalRows}
|
|
242
|
+
</Text>
|
|
243
|
+
</div>
|
|
244
|
+
|
|
245
|
+
<div className="pagination-controls">
|
|
246
|
+
<Pagination
|
|
247
|
+
currentPage={currentPage}
|
|
248
|
+
totalPages={totalPages}
|
|
249
|
+
updateCurrentPage={setCurrentPage}
|
|
250
|
+
/>
|
|
251
|
+
|
|
252
|
+
<div className="page-jump-controls">
|
|
253
|
+
<Text type="BodySmall">Go to:</Text>
|
|
254
|
+
<PaginationNumberField
|
|
255
|
+
page={currentPage}
|
|
256
|
+
totalPages={totalPages}
|
|
257
|
+
onPageChanged={setCurrentPage}
|
|
258
|
+
/>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Advanced Navigation Controls
|
|
268
|
+
```tsx
|
|
269
|
+
function AdvancedNavigationExample() {
|
|
270
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
271
|
+
const [jumpToPage, setJumpToPage] = useState('');
|
|
272
|
+
const [pageHistory, setPageHistory] = useState([1]);
|
|
273
|
+
const totalPages = 50;
|
|
274
|
+
|
|
275
|
+
const handlePageChange = (newPage) => {
|
|
276
|
+
setCurrentPage(newPage);
|
|
277
|
+
setPageHistory(prev => [...prev.slice(-9), newPage]); // Keep last 10 pages
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const goToFirstPage = () => handlePageChange(1);
|
|
281
|
+
const goToLastPage = () => handlePageChange(totalPages);
|
|
282
|
+
|
|
283
|
+
const goToRandomPage = () => {
|
|
284
|
+
const randomPage = Math.floor(Math.random() * totalPages) + 1;
|
|
285
|
+
handlePageChange(randomPage);
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
return (
|
|
289
|
+
<div className="advanced-navigation">
|
|
290
|
+
<div className="navigation-controls">
|
|
291
|
+
<div className="quick-actions">
|
|
292
|
+
<Button onClick={goToFirstPage} size="Small">
|
|
293
|
+
First Page
|
|
294
|
+
</Button>
|
|
295
|
+
<Button onClick={goToLastPage} size="Small">
|
|
296
|
+
Last Page
|
|
297
|
+
</Button>
|
|
298
|
+
<Button onClick={goToRandomPage} size="Small" type="Outlined">
|
|
299
|
+
Random Page
|
|
300
|
+
</Button>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div className="primary-pagination">
|
|
304
|
+
<Pagination
|
|
305
|
+
currentPage={currentPage}
|
|
306
|
+
totalPages={totalPages}
|
|
307
|
+
updateCurrentPage={handlePageChange}
|
|
308
|
+
/>
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
<div className="page-jump-section">
|
|
312
|
+
<Text type="BodySmall">Jump to page:</Text>
|
|
313
|
+
<PaginationNumberField
|
|
314
|
+
page={currentPage}
|
|
315
|
+
totalPages={totalPages}
|
|
316
|
+
onPageChanged={handlePageChange}
|
|
317
|
+
className="main-page-field"
|
|
318
|
+
/>
|
|
319
|
+
<Text type="BodySmall">of {totalPages}</Text>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
<div className="page-history">
|
|
324
|
+
<Text type="BodySmall">Recently visited pages:</Text>
|
|
325
|
+
<div className="history-buttons">
|
|
326
|
+
{pageHistory.slice(-5).reverse().map((page, index) => (
|
|
327
|
+
<Button
|
|
328
|
+
key={`${page}-${index}`}
|
|
329
|
+
size="Small"
|
|
330
|
+
type={page === currentPage ? 'Filled' : 'Ghost'}
|
|
331
|
+
onClick={() => handlePageChange(page)}
|
|
332
|
+
>
|
|
333
|
+
{page}
|
|
334
|
+
</Button>
|
|
335
|
+
))}
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
<div className="current-page-info">
|
|
340
|
+
<Text type="Heading5">Page {currentPage}</Text>
|
|
341
|
+
<Text type="BodyMedium">Content for page {currentPage} would be displayed here.</Text>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Form-based Page Navigation
|
|
349
|
+
```tsx
|
|
350
|
+
function FormPageNavigationExample() {
|
|
351
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
352
|
+
const [pageInput, setPageInput] = useState('');
|
|
353
|
+
const [isValidPage, setIsValidPage] = useState(true);
|
|
354
|
+
const totalPages = 100;
|
|
355
|
+
|
|
356
|
+
const validateAndNavigate = () => {
|
|
357
|
+
const pageNumber = parseInt(pageInput);
|
|
358
|
+
|
|
359
|
+
if (isNaN(pageNumber) || pageNumber < 1 || pageNumber > totalPages) {
|
|
360
|
+
setIsValidPage(false);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
setIsValidPage(true);
|
|
365
|
+
setCurrentPage(pageNumber);
|
|
366
|
+
setPageInput('');
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const handleKeyPress = (event) => {
|
|
370
|
+
if (event.key === 'Enter') {
|
|
371
|
+
validateAndNavigate();
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const handleInputChange = (value) => {
|
|
376
|
+
setPageInput(value);
|
|
377
|
+
setIsValidPage(true); // Reset validation state when user types
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
return (
|
|
381
|
+
<div className="form-page-navigation">
|
|
382
|
+
<div className="content-section">
|
|
383
|
+
<Text type="Heading4">Page {currentPage} Content</Text>
|
|
384
|
+
<Text type="BodyMedium">
|
|
385
|
+
This is the content for page {currentPage} of {totalPages}.
|
|
386
|
+
</Text>
|
|
387
|
+
</div>
|
|
388
|
+
|
|
389
|
+
<div className="navigation-form">
|
|
390
|
+
<FormField
|
|
391
|
+
label="Navigate to Page"
|
|
392
|
+
error={!isValidPage ? `Please enter a valid page number (1-${totalPages})` : ''}
|
|
393
|
+
>
|
|
394
|
+
<div className="page-input-group">
|
|
395
|
+
<Input
|
|
396
|
+
value={pageInput}
|
|
397
|
+
onValueChange={handleInputChange}
|
|
398
|
+
onKeyPress={handleKeyPress}
|
|
399
|
+
placeholder={`1-${totalPages}`}
|
|
400
|
+
state={!isValidPage ? 'Error' : 'Default'}
|
|
401
|
+
/>
|
|
402
|
+
<Button onClick={validateAndNavigate}>
|
|
403
|
+
Go
|
|
404
|
+
</Button>
|
|
405
|
+
</div>
|
|
406
|
+
</FormField>
|
|
407
|
+
|
|
408
|
+
<div className="current-page-field">
|
|
409
|
+
<Text type="BodySmall">Current page:</Text>
|
|
410
|
+
<PaginationNumberField
|
|
411
|
+
page={currentPage}
|
|
412
|
+
totalPages={totalPages}
|
|
413
|
+
onPageChanged={setCurrentPage}
|
|
414
|
+
/>
|
|
415
|
+
</div>
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
<div className="standard-pagination">
|
|
419
|
+
<Pagination
|
|
420
|
+
currentPage={currentPage}
|
|
421
|
+
totalPages={totalPages}
|
|
422
|
+
updateCurrentPage={setCurrentPage}
|
|
423
|
+
/>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Mobile-Optimized Page Input
|
|
431
|
+
```tsx
|
|
432
|
+
function MobilePageInputExample() {
|
|
433
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
434
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
435
|
+
const totalPages = 30;
|
|
436
|
+
|
|
437
|
+
useEffect(() => {
|
|
438
|
+
const checkMobile = () => {
|
|
439
|
+
setIsMobile(window.innerWidth < 768);
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
checkMobile();
|
|
443
|
+
window.addEventListener('resize', checkMobile);
|
|
444
|
+
|
|
445
|
+
return () => window.removeEventListener('resize', checkMobile);
|
|
446
|
+
}, []);
|
|
447
|
+
|
|
448
|
+
return (
|
|
449
|
+
<div className="mobile-page-input">
|
|
450
|
+
<div className="page-content">
|
|
451
|
+
<Text type="Heading4">Page {currentPage}</Text>
|
|
452
|
+
<Text type="BodyMedium">
|
|
453
|
+
Content optimized for {isMobile ? 'mobile' : 'desktop'} viewing.
|
|
454
|
+
</Text>
|
|
455
|
+
</div>
|
|
456
|
+
|
|
457
|
+
{isMobile ? (
|
|
458
|
+
<div className="mobile-navigation">
|
|
459
|
+
<div className="mobile-page-controls">
|
|
460
|
+
<Button
|
|
461
|
+
disabled={currentPage === 1}
|
|
462
|
+
onClick={() => setCurrentPage(currentPage - 1)}
|
|
463
|
+
leadingIcon={<Icon icon="ChevronLeft" />}
|
|
464
|
+
/>
|
|
465
|
+
|
|
466
|
+
<div className="mobile-page-display">
|
|
467
|
+
<PaginationNumberField
|
|
468
|
+
page={currentPage}
|
|
469
|
+
totalPages={totalPages}
|
|
470
|
+
onPageChanged={setCurrentPage}
|
|
471
|
+
className="mobile-page-field"
|
|
472
|
+
/>
|
|
473
|
+
<Text type="BodySmall">/ {totalPages}</Text>
|
|
474
|
+
</div>
|
|
475
|
+
|
|
476
|
+
<Button
|
|
477
|
+
disabled={currentPage === totalPages}
|
|
478
|
+
onClick={() => setCurrentPage(currentPage + 1)}
|
|
479
|
+
trailingIcon={<Icon icon="ChevronRight" />}
|
|
480
|
+
/>
|
|
481
|
+
</div>
|
|
482
|
+
</div>
|
|
483
|
+
) : (
|
|
484
|
+
<div className="desktop-navigation">
|
|
485
|
+
<Pagination
|
|
486
|
+
currentPage={currentPage}
|
|
487
|
+
totalPages={totalPages}
|
|
488
|
+
updateCurrentPage={setCurrentPage}
|
|
489
|
+
/>
|
|
490
|
+
|
|
491
|
+
<div className="desktop-page-jump">
|
|
492
|
+
<Text type="BodySmall">Page:</Text>
|
|
493
|
+
<PaginationNumberField
|
|
494
|
+
page={currentPage}
|
|
495
|
+
totalPages={totalPages}
|
|
496
|
+
onPageChanged={setCurrentPage}
|
|
497
|
+
/>
|
|
498
|
+
<Text type="BodySmall">of {totalPages}</Text>
|
|
499
|
+
</div>
|
|
500
|
+
</div>
|
|
501
|
+
)}
|
|
502
|
+
</div>
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Batch Operations with Page Navigation
|
|
508
|
+
```tsx
|
|
509
|
+
function BatchOperationsExample() {
|
|
510
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
511
|
+
const [selectedItems, setSelectedItems] = useState(new Set());
|
|
512
|
+
const [selectAll, setSelectAll] = useState(false);
|
|
513
|
+
|
|
514
|
+
const itemsPerPage = 20;
|
|
515
|
+
const totalItems = 189;
|
|
516
|
+
const totalPages = Math.ceil(totalItems / itemsPerPage);
|
|
517
|
+
|
|
518
|
+
const mockItems = Array.from({ length: itemsPerPage }, (_, index) => {
|
|
519
|
+
const id = (currentPage - 1) * itemsPerPage + index + 1;
|
|
520
|
+
return {
|
|
521
|
+
id,
|
|
522
|
+
name: `Item ${id}`,
|
|
523
|
+
status: 'Active',
|
|
524
|
+
type: ['Document', 'Image', 'Video'][Math.floor(Math.random() * 3)]
|
|
525
|
+
};
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
const handleSelectAll = (checked) => {
|
|
529
|
+
setSelectAll(checked);
|
|
530
|
+
if (checked) {
|
|
531
|
+
const currentPageIds = mockItems.map(item => item.id);
|
|
532
|
+
setSelectedItems(new Set([...selectedItems, ...currentPageIds]));
|
|
533
|
+
} else {
|
|
534
|
+
const currentPageIds = new Set(mockItems.map(item => item.id));
|
|
535
|
+
setSelectedItems(new Set([...selectedItems].filter(id => !currentPageIds.has(id))));
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
const handlePageChange = (newPage) => {
|
|
540
|
+
setCurrentPage(newPage);
|
|
541
|
+
setSelectAll(false); // Reset select all when changing pages
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
return (
|
|
545
|
+
<div className="batch-operations-example">
|
|
546
|
+
<div className="operations-header">
|
|
547
|
+
<div className="selection-controls">
|
|
548
|
+
<Checkbox
|
|
549
|
+
checked={selectAll}
|
|
550
|
+
onCheckedChange={handleSelectAll}
|
|
551
|
+
label={`Select all on page ${currentPage}`}
|
|
552
|
+
/>
|
|
553
|
+
|
|
554
|
+
{selectedItems.size > 0 && (
|
|
555
|
+
<div className="batch-actions">
|
|
556
|
+
<Text type="BodySmall">
|
|
557
|
+
{selectedItems.size} items selected
|
|
558
|
+
</Text>
|
|
559
|
+
<Button size="Small" type="Outlined">
|
|
560
|
+
Delete Selected
|
|
561
|
+
</Button>
|
|
562
|
+
<Button size="Small" type="Outlined">
|
|
563
|
+
Export Selected
|
|
564
|
+
</Button>
|
|
565
|
+
</div>
|
|
566
|
+
)}
|
|
567
|
+
</div>
|
|
568
|
+
|
|
569
|
+
<div className="page-navigation">
|
|
570
|
+
<Text type="BodySmall">
|
|
571
|
+
Page {currentPage} of {totalPages} ({totalItems} total items)
|
|
572
|
+
</Text>
|
|
573
|
+
<PaginationNumberField
|
|
574
|
+
page={currentPage}
|
|
575
|
+
totalPages={totalPages}
|
|
576
|
+
onPageChanged={handlePageChange}
|
|
577
|
+
/>
|
|
578
|
+
</div>
|
|
579
|
+
</div>
|
|
580
|
+
|
|
581
|
+
<div className="items-list">
|
|
582
|
+
{mockItems.map(item => (
|
|
583
|
+
<Card key={item.id} className="batch-item">
|
|
584
|
+
<Checkbox
|
|
585
|
+
checked={selectedItems.has(item.id)}
|
|
586
|
+
onCheckedChange={(checked) => {
|
|
587
|
+
const newSelected = new Set(selectedItems);
|
|
588
|
+
if (checked) {
|
|
589
|
+
newSelected.add(item.id);
|
|
590
|
+
} else {
|
|
591
|
+
newSelected.delete(item.id);
|
|
592
|
+
}
|
|
593
|
+
setSelectedItems(newSelected);
|
|
594
|
+
}}
|
|
595
|
+
/>
|
|
596
|
+
|
|
597
|
+
<div className="item-info">
|
|
598
|
+
<Text type="BodyMedium">{item.name}</Text>
|
|
599
|
+
<Text type="BodySmall">{item.type}</Text>
|
|
600
|
+
</div>
|
|
601
|
+
|
|
602
|
+
<Chip size="Small" style="Success">
|
|
603
|
+
{item.status}
|
|
604
|
+
</Chip>
|
|
605
|
+
</Card>
|
|
606
|
+
))}
|
|
607
|
+
</div>
|
|
608
|
+
|
|
609
|
+
<div className="pagination-footer">
|
|
610
|
+
<Pagination
|
|
611
|
+
currentPage={currentPage}
|
|
612
|
+
totalPages={totalPages}
|
|
613
|
+
updateCurrentPage={handlePageChange}
|
|
614
|
+
/>
|
|
615
|
+
</div>
|
|
616
|
+
</div>
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### Real-time Page Validation
|
|
622
|
+
```tsx
|
|
623
|
+
function RealTimeValidationExample() {
|
|
624
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
625
|
+
const [inputValue, setInputValue] = useState('');
|
|
626
|
+
const [validationMessage, setValidationMessage] = useState('');
|
|
627
|
+
const [isValid, setIsValid] = useState(true);
|
|
628
|
+
const totalPages = 75;
|
|
629
|
+
|
|
630
|
+
const validatePageInput = (value) => {
|
|
631
|
+
if (value === '') {
|
|
632
|
+
setValidationMessage('');
|
|
633
|
+
setIsValid(true);
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const pageNumber = parseInt(value);
|
|
638
|
+
|
|
639
|
+
if (isNaN(pageNumber)) {
|
|
640
|
+
setValidationMessage('Please enter a valid number');
|
|
641
|
+
setIsValid(false);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (pageNumber < 1) {
|
|
646
|
+
setValidationMessage('Page number must be at least 1');
|
|
647
|
+
setIsValid(false);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if (pageNumber > totalPages) {
|
|
652
|
+
setValidationMessage(`Page number cannot exceed ${totalPages}`);
|
|
653
|
+
setIsValid(false);
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
setValidationMessage(`Valid page number (${pageNumber})`);
|
|
658
|
+
setIsValid(true);
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
const handleInputChange = (value) => {
|
|
662
|
+
setInputValue(value);
|
|
663
|
+
validatePageInput(value);
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
const applyPageChange = () => {
|
|
667
|
+
if (isValid && inputValue) {
|
|
668
|
+
setCurrentPage(parseInt(inputValue));
|
|
669
|
+
setInputValue('');
|
|
670
|
+
setValidationMessage('');
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
return (
|
|
675
|
+
<div className="realtime-validation-example">
|
|
676
|
+
<div className="current-page-display">
|
|
677
|
+
<Text type="Heading4">Current Page: {currentPage}</Text>
|
|
678
|
+
<Text type="BodyMedium">Content for page {currentPage} goes here.</Text>
|
|
679
|
+
</div>
|
|
680
|
+
|
|
681
|
+
<div className="validation-section">
|
|
682
|
+
<FormField
|
|
683
|
+
label="Enter Page Number"
|
|
684
|
+
helpText={validationMessage}
|
|
685
|
+
error={!isValid ? validationMessage : ''}
|
|
686
|
+
>
|
|
687
|
+
<div className="validated-input-group">
|
|
688
|
+
<Input
|
|
689
|
+
value={inputValue}
|
|
690
|
+
onValueChange={handleInputChange}
|
|
691
|
+
placeholder={`1-${totalPages}`}
|
|
692
|
+
state={!isValid ? 'Error' : validationMessage ? 'Success' : 'Default'}
|
|
693
|
+
/>
|
|
694
|
+
<Button
|
|
695
|
+
onClick={applyPageChange}
|
|
696
|
+
disabled={!isValid || !inputValue}
|
|
697
|
+
>
|
|
698
|
+
Apply
|
|
699
|
+
</Button>
|
|
700
|
+
</div>
|
|
701
|
+
</FormField>
|
|
702
|
+
|
|
703
|
+
<div className="standard-field">
|
|
704
|
+
<Text type="BodySmall">Or use the standard page field:</Text>
|
|
705
|
+
<PaginationNumberField
|
|
706
|
+
page={currentPage}
|
|
707
|
+
totalPages={totalPages}
|
|
708
|
+
onPageChanged={setCurrentPage}
|
|
709
|
+
/>
|
|
710
|
+
</div>
|
|
711
|
+
</div>
|
|
712
|
+
|
|
713
|
+
<Pagination
|
|
714
|
+
currentPage={currentPage}
|
|
715
|
+
totalPages={totalPages}
|
|
716
|
+
updateCurrentPage={setCurrentPage}
|
|
717
|
+
className="main-pagination"
|
|
718
|
+
/>
|
|
719
|
+
</div>
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
```
|