@ticatec/uniface-element 0.2.3 → 0.3.0

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.
Files changed (178) hide show
  1. package/dist/accordion/README.md +169 -0
  2. package/dist/accordion/README_CN.md +176 -0
  3. package/dist/action-bar/README.md +275 -0
  4. package/dist/action-bar/README_CN.md +285 -0
  5. package/dist/app-layout/README.md +374 -0
  6. package/dist/app-layout/README_CN.md +381 -0
  7. package/dist/app-top-bar/README.md +357 -0
  8. package/dist/app-top-bar/README_CN.md +365 -0
  9. package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
  10. package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
  11. package/dist/base-calendar/CalendarBase.svelte +0 -3
  12. package/dist/box/README.md +385 -0
  13. package/dist/box/README_CN.md +393 -0
  14. package/dist/breadcrumbs/README.md +442 -0
  15. package/dist/breadcrumbs/README_CN.md +442 -0
  16. package/dist/button/Button.svelte +27 -7
  17. package/dist/button/Button.svelte.d.ts +3 -1
  18. package/dist/button/IconButton.svelte +26 -6
  19. package/dist/button/IconButton.svelte.d.ts +3 -1
  20. package/dist/button/IconButton_README.md +513 -0
  21. package/dist/button/IconButton_README_CN.md +513 -0
  22. package/dist/button/README.md +428 -0
  23. package/dist/button/README_CN.md +428 -0
  24. package/dist/button/TextButton.svelte +26 -6
  25. package/dist/button/TextButton.svelte.d.ts +3 -1
  26. package/dist/button/TextButton_README.md +571 -0
  27. package/dist/button/TextButton_README_CN.md +571 -0
  28. package/dist/card/README.md +666 -0
  29. package/dist/card/README_CN.md +666 -0
  30. package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
  31. package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
  32. package/dist/cascade-options-select/README.md +663 -2
  33. package/dist/cascade-options-select/README_CN.md +664 -0
  34. package/dist/checkbox/CheckBox.svelte +20 -6
  35. package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
  36. package/dist/checkbox/README.md +562 -0
  37. package/dist/checkbox/README_CN.md +727 -0
  38. package/dist/common-editor/NumberInput.svelte +39 -26
  39. package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
  40. package/dist/concise-data-table/ConciseListTable.svelte +133 -36
  41. package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
  42. package/dist/concise-data-table/DataCell.svelte +5 -6
  43. package/dist/concise-data-table/DataRow.svelte +22 -2
  44. package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
  45. package/dist/concise-data-table/README.md +606 -0
  46. package/dist/concise-data-table/README_CN.md +611 -0
  47. package/dist/context-menu/ContextMenu.svelte +138 -21
  48. package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
  49. package/dist/context-menu/ContextMenuItem.d.ts +20 -4
  50. package/dist/context-menu/README.md +551 -0
  51. package/dist/context-menu/README_CN.md +551 -0
  52. package/dist/criteria-field/CriteriaField.svelte +3 -5
  53. package/dist/criteria-field/README.md +532 -0
  54. package/dist/criteria-field/README_CN.md +532 -0
  55. package/dist/data-table/README.md +712 -0
  56. package/dist/data-table/README_CN.md +712 -0
  57. package/dist/date-picker/DatePicker.svelte +44 -7
  58. package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
  59. package/dist/date-picker/DateTimePicker.svelte +32 -8
  60. package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
  61. package/dist/date-picker/README.md +326 -0
  62. package/dist/date-picker/README_CN.md +316 -0
  63. package/dist/date-picker/ScrollBar.svelte +18 -8
  64. package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
  65. package/dist/date-picker/TimePanel.svelte +5 -5
  66. package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
  67. package/dist/date-range/README.md +374 -0
  68. package/dist/date-range/README_CN.md +374 -0
  69. package/dist/dialog/DialogBoard.svelte +1 -1
  70. package/dist/dialog/README.md +596 -0
  71. package/dist/dialog/README_CN.md +596 -0
  72. package/dist/drawer/README.md +679 -1
  73. package/dist/drawer/README_CN.md +679 -0
  74. package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
  75. package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
  76. package/dist/group-box/group-check-box/README.md +749 -0
  77. package/dist/group-box/group-check-box/README_CN.md +750 -0
  78. package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
  79. package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
  80. package/dist/group-box/group-radio-box/README.md +920 -0
  81. package/dist/group-box/group-radio-box/README_CN.md +920 -0
  82. package/dist/image-files/README.md +1346 -0
  83. package/dist/image-files/README_CN.md +1346 -0
  84. package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
  85. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
  86. package/dist/lib/forwardAllEvents.d.ts +3 -0
  87. package/dist/lib/forwardAllEvents.js +24 -0
  88. package/dist/list-box/README.md +579 -0
  89. package/dist/list-box/README_CN.md +682 -0
  90. package/dist/lookup-editor/LookupEditor.svelte +15 -3
  91. package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
  92. package/dist/lookup-editor/README.md +684 -0
  93. package/dist/lookup-editor/README_CN.md +684 -0
  94. package/dist/memo-editor/MemoEditor.svelte +77 -27
  95. package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
  96. package/dist/memo-editor/README.md +819 -0
  97. package/dist/memo-editor/README_CN.md +819 -0
  98. package/dist/message-box/README.md +398 -0
  99. package/dist/message-box/README_CN.md +398 -0
  100. package/dist/number-editor/NumberEditor.svelte +2 -2
  101. package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
  102. package/dist/number-editor/README.md +353 -22
  103. package/dist/number-editor/README_CN.md +357 -0
  104. package/dist/number-range/README.md +443 -0
  105. package/dist/number-range/README_CN.md +443 -0
  106. package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
  107. package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
  108. package/dist/options-multi-select/README.md +480 -0
  109. package/dist/options-multi-select/README_CN.md +480 -0
  110. package/dist/options-select/OptionsSelect.svelte +36 -5
  111. package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
  112. package/dist/options-select/README.md +632 -0
  113. package/dist/options-select/README_CN.md +632 -0
  114. package/dist/page/README.md +605 -0
  115. package/dist/page/README_CN.md +605 -0
  116. package/dist/pagination/README.md +946 -0
  117. package/dist/pagination/README_CN.md +946 -0
  118. package/dist/pagination-panel/README.md +1075 -0
  119. package/dist/pagination-panel/README_CN.md +1075 -0
  120. package/dist/popup-hint/README.md +841 -0
  121. package/dist/popup-hint/README_CN.md +840 -0
  122. package/dist/progress-bar/README.md +242 -0
  123. package/dist/progress-bar/README_CN.md +242 -0
  124. package/dist/progress-step-bar/README.md +316 -0
  125. package/dist/progress-step-bar/README_CN.md +316 -0
  126. package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
  127. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
  128. package/dist/prompts-text-editor/README.md +329 -0
  129. package/dist/prompts-text-editor/README_CN.md +329 -0
  130. package/dist/property-editor/README.md +969 -0
  131. package/dist/property-editor/README_CN.md +969 -0
  132. package/dist/radio-button/README.md +372 -0
  133. package/dist/radio-button/README_CN.md +372 -0
  134. package/dist/radio-button/RadioButton.svelte +32 -3
  135. package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
  136. package/dist/search-box/README.md +425 -0
  137. package/dist/search-box/README_CN.md +424 -0
  138. package/dist/search-box/SearchBox.svelte +22 -6
  139. package/dist/search-box/SearchBox.svelte.d.ts +4 -1
  140. package/dist/tabs/README.md +919 -0
  141. package/dist/tabs/README_CN.md +920 -0
  142. package/dist/tag/README.md +922 -0
  143. package/dist/tag/README_CN.md +922 -0
  144. package/dist/text-editor/PasswordEditor.svelte +17 -2
  145. package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
  146. package/dist/text-editor/PasswordEditor_README.md +551 -0
  147. package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
  148. package/dist/text-editor/README.md +466 -0
  149. package/dist/text-editor/README_CN.md +466 -0
  150. package/dist/text-editor/TextEditor.svelte +51 -19
  151. package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
  152. package/dist/ticatec-uniface-web.css +1 -0
  153. package/dist/time-editor/README.md +498 -24
  154. package/dist/time-editor/README_CN.md +498 -0
  155. package/dist/time-editor/TimeEditor.svelte +7 -3
  156. package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
  157. package/dist/toast/README.md +667 -0
  158. package/dist/toast/README_CN.md +667 -0
  159. package/dist/transfer/README.md +795 -0
  160. package/dist/transfer/Transfer.svelte +6 -4
  161. package/dist/transfer/Transfer.svelte.d.ts +3 -1
  162. package/dist/tree-view/README.md +761 -0
  163. package/dist/tree-view/README_CN.md +761 -0
  164. package/dist/tree-view/TreeView.svelte +5 -3
  165. package/dist/tree-view/TreeView.svelte.d.ts +3 -1
  166. package/dist/unit-number-editor/README.md +546 -20
  167. package/dist/unit-number-editor/README_CN.md +525 -0
  168. package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
  169. package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
  170. package/docs/form-field/cn/README_CN.md +364 -0
  171. package/docs/form-field/en/README.md +364 -0
  172. package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
  173. package/docs/form-panel/flex-form/en/README.md +586 -0
  174. package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
  175. package/docs/form-panel/flex-row-form/en/README.md +787 -0
  176. package/docs/form-panel/grid-form/en/README.md +744 -0
  177. package/package.json +1 -1
  178. package/dist/drawer/README-CN.md +0 -1
@@ -0,0 +1,1075 @@
1
+ # PaginationPanel
2
+
3
+ A comprehensive pagination control panel that combines page navigation, rows per page selection, and total records display in a unified interface.
4
+
5
+ ## Features
6
+
7
+ - **Complete Pagination**: Includes page navigation, row count selector, and summary info
8
+ - **Customizable Row Options**: Configure available rows per page options
9
+ - **Total Information Display**: Show total records with customizable formatting
10
+ - **Multiple Alignments**: Support for left, right, and center alignment
11
+ - **Size Variants**: Normal and big size options
12
+ - **Style Integration**: Inherits styling from base Pagination component
13
+ - **Custom Info Generator**: Flexible total information display with custom formatting
14
+ - **Event Handling**: Separate handlers for page changes and row count changes
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @ticatec/uniface-element
20
+ ```
21
+
22
+ ## Basic Usage
23
+
24
+ ```svelte
25
+ <script>
26
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
27
+
28
+ let currentPage = 1;
29
+ let totalPages = 10;
30
+ let totalRecords = 250;
31
+ let rowsPerPage = 25;
32
+
33
+ function handlePageChange(page) {
34
+ currentPage = page;
35
+ console.log('Page changed to:', page);
36
+ }
37
+
38
+ function handleRowCountChange(rows) {
39
+ rowsPerPage = rows;
40
+ // Recalculate total pages based on new row count
41
+ totalPages = Math.ceil(totalRecords / rows);
42
+ currentPage = 1; // Reset to first page
43
+ console.log('Rows per page changed to:', rows);
44
+ }
45
+ </script>
46
+
47
+ <PaginationPanel
48
+ pageNo={currentPage}
49
+ pageCount={totalPages}
50
+ total={totalRecords}
51
+ rowCount={rowsPerPage}
52
+ onPageChange={handlePageChange}
53
+ onRowCountChanged={handleRowCountChange}
54
+ />
55
+ ```
56
+
57
+ ## API Reference
58
+
59
+ ### Props
60
+
61
+ | Prop | Type | Default | Description |
62
+ |------|------|---------|-------------|
63
+ | `pageNo` | `number` | `1` | Current active page number |
64
+ | `pageCount` | `number` | `0` | Total number of pages |
65
+ | `total` | `number` | `null` | Total number of records |
66
+ | `rowCount` | `number` | `25` | Current rows per page setting |
67
+ | `rowsSet` | `Array<number>` | `[25, 50, 100]` | Available rows per page options |
68
+ | `type` | `'plain' \| 'round' \| 'circle'` | `'round'` | Visual style variant |
69
+ | `page$style` | `string` | `''` | Custom CSS styles for pagination component |
70
+ | `big` | `boolean` | `false` | Enable larger size variant |
71
+ | `rowCountLabel` | `string` | `'Rows/Page'` | Label for rows per page selector |
72
+ | `align` | `'left' \| 'right' \| ''` | `''` | Panel alignment |
73
+ | `generateInfo` | `GenerateTotalInfo \| null` | `null` | Custom function to generate total info text |
74
+ | `onPageChange` | `OnPageChange` | `undefined` | Page change event handler |
75
+ | `onRowCountChanged` | `OnRowCountChanged` | `undefined` | Row count change event handler |
76
+
77
+ ### Types
78
+
79
+ ```typescript
80
+ export type OnPageChange = (page: number) => void;
81
+ export type OnRowCountChanged = (rows: number) => void;
82
+ export type GenerateTotalInfo = (total: number, pageCount: number, pageNo: number, rows: number) => string;
83
+ ```
84
+
85
+ ## Examples
86
+
87
+ ### Data Table with Full Pagination
88
+
89
+ ```svelte
90
+ <script>
91
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
92
+
93
+ let users = [];
94
+ let currentPage = 1;
95
+ let totalPages = 1;
96
+ let totalUsers = 0;
97
+ let rowsPerPage = 25;
98
+ let loading = false;
99
+
100
+ async function loadUsers(page = 1, rows = 25) {
101
+ loading = true;
102
+
103
+ try {
104
+ // Simulate API call
105
+ await new Promise(resolve => setTimeout(resolve, 500));
106
+
107
+ // Mock data
108
+ totalUsers = 237; // Total records from API
109
+ totalPages = Math.ceil(totalUsers / rows);
110
+ currentPage = page;
111
+
112
+ const startIndex = (page - 1) * rows;
113
+ users = Array.from({ length: Math.min(rows, totalUsers - startIndex) }, (_, i) => ({
114
+ id: startIndex + i + 1,
115
+ name: `User ${startIndex + i + 1}`,
116
+ email: `user${startIndex + i + 1}@example.com`,
117
+ role: ['Admin', 'User', 'Moderator'][Math.floor(Math.random() * 3)],
118
+ status: Math.random() > 0.2 ? 'Active' : 'Inactive'
119
+ }));
120
+ } finally {
121
+ loading = false;
122
+ }
123
+ }
124
+
125
+ function handlePageChange(page) {
126
+ loadUsers(page, rowsPerPage);
127
+ }
128
+
129
+ function handleRowCountChange(rows) {
130
+ rowsPerPage = rows;
131
+ loadUsers(1, rows); // Reset to page 1 with new row count
132
+ }
133
+
134
+ // Custom info generator
135
+ function generateUserInfo(total, pageCount, pageNo, rows) {
136
+ const start = (pageNo - 1) * rows + 1;
137
+ const end = Math.min(pageNo * rows, total);
138
+ return `Showing <b>${start}-${end}</b> of <b>${total}</b> users`;
139
+ }
140
+
141
+ // Load initial data
142
+ loadUsers(currentPage, rowsPerPage);
143
+ </script>
144
+
145
+ <div class="user-management">
146
+ <h2>User Management</h2>
147
+
148
+ {#if loading}
149
+ <div class="loading">Loading users...</div>
150
+ {:else}
151
+ <table class="users-table">
152
+ <thead>
153
+ <tr>
154
+ <th>ID</th>
155
+ <th>Name</th>
156
+ <th>Email</th>
157
+ <th>Role</th>
158
+ <th>Status</th>
159
+ </tr>
160
+ </thead>
161
+ <tbody>
162
+ {#each users as user}
163
+ <tr>
164
+ <td>{user.id}</td>
165
+ <td>{user.name}</td>
166
+ <td>{user.email}</td>
167
+ <td>{user.role}</td>
168
+ <td class="status {user.status.toLowerCase()}">{user.status}</td>
169
+ </tr>
170
+ {/each}
171
+ </tbody>
172
+ </table>
173
+ {/if}
174
+
175
+ <PaginationPanel
176
+ pageNo={currentPage}
177
+ pageCount={totalPages}
178
+ total={totalUsers}
179
+ rowCount={rowsPerPage}
180
+ rowsSet={[10, 25, 50, 100]}
181
+ rowCountLabel="Users per page"
182
+ generateInfo={generateUserInfo}
183
+ onPageChange={handlePageChange}
184
+ onRowCountChanged={handleRowCountChange}
185
+ align="right"
186
+ />
187
+ </div>
188
+
189
+ <style>
190
+ .user-management {
191
+ max-width: 1200px;
192
+ margin: 0 auto;
193
+ padding: 20px;
194
+ }
195
+
196
+ .loading {
197
+ text-align: center;
198
+ padding: 40px;
199
+ color: #666;
200
+ }
201
+
202
+ .users-table {
203
+ width: 100%;
204
+ border-collapse: collapse;
205
+ margin-bottom: 20px;
206
+ }
207
+
208
+ .users-table th,
209
+ .users-table td {
210
+ padding: 12px;
211
+ text-align: left;
212
+ border-bottom: 1px solid #ddd;
213
+ }
214
+
215
+ .users-table th {
216
+ background-color: #f8f9fa;
217
+ font-weight: 600;
218
+ }
219
+
220
+ .status.active {
221
+ color: #28a745;
222
+ }
223
+
224
+ .status.inactive {
225
+ color: #dc3545;
226
+ }
227
+ </style>
228
+ ```
229
+
230
+ ### Product Catalog with Custom Styling
231
+
232
+ ```svelte
233
+ <script>
234
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
235
+
236
+ let products = [];
237
+ let currentPage = 1;
238
+ let totalPages = 1;
239
+ let totalProducts = 0;
240
+ let rowsPerPage = 12;
241
+ let category = 'all';
242
+
243
+ const categories = {
244
+ all: 'All Products',
245
+ electronics: 'Electronics',
246
+ clothing: 'Clothing',
247
+ books: 'Books'
248
+ };
249
+
250
+ async function loadProducts(page = 1, rows = 12, cat = 'all') {
251
+ // Simulate API call with category filter
252
+ const categoryTotals = {
253
+ all: 180,
254
+ electronics: 45,
255
+ clothing: 67,
256
+ books: 68
257
+ };
258
+
259
+ totalProducts = categoryTotals[cat];
260
+ totalPages = Math.ceil(totalProducts / rows);
261
+ currentPage = page;
262
+
263
+ const startIndex = (page - 1) * rows;
264
+ products = Array.from({ length: Math.min(rows, totalProducts - startIndex) }, (_, i) => ({
265
+ id: startIndex + i + 1,
266
+ name: `${categories[cat]} Product ${startIndex + i + 1}`,
267
+ price: (Math.random() * 200 + 20).toFixed(2),
268
+ image: `https://picsum.photos/200/200?random=${startIndex + i + 1}`,
269
+ rating: (Math.random() * 2 + 3).toFixed(1)
270
+ }));
271
+ }
272
+
273
+ function handlePageChange(page) {
274
+ loadProducts(page, rowsPerPage, category);
275
+ }
276
+
277
+ function handleRowCountChange(rows) {
278
+ rowsPerPage = rows;
279
+ loadProducts(1, rows, category);
280
+ }
281
+
282
+ function handleCategoryChange() {
283
+ loadProducts(1, rowsPerPage, category);
284
+ }
285
+
286
+ // Custom product info generator
287
+ function generateProductInfo(total, pageCount, pageNo, rows) {
288
+ return `
289
+ <span style="color: #007bff;">Page ${pageNo}</span> of
290
+ <span style="color: #007bff;">${pageCount}</span> •
291
+ <span style="color: #28a745;">${total}</span> products total
292
+ `;
293
+ }
294
+
295
+ // Load initial products
296
+ loadProducts(currentPage, rowsPerPage, category);
297
+ </script>
298
+
299
+ <div class="product-catalog">
300
+ <div class="catalog-header">
301
+ <h2>Product Catalog</h2>
302
+ <div class="category-filter">
303
+ <label>Category:</label>
304
+ <select bind:value={category} on:change={handleCategoryChange}>
305
+ {#each Object.entries(categories) as [key, value]}
306
+ <option value={key}>{value}</option>
307
+ {/each}
308
+ </select>
309
+ </div>
310
+ </div>
311
+
312
+ <div class="products-grid">
313
+ {#each products as product}
314
+ <div class="product-card">
315
+ <img src={product.image} alt={product.name} />
316
+ <h3>{product.name}</h3>
317
+ <div class="product-info">
318
+ <span class="price">${product.price}</span>
319
+ <span class="rating">⭐ {product.rating}</span>
320
+ </div>
321
+ </div>
322
+ {/each}
323
+ </div>
324
+
325
+ <PaginationPanel
326
+ pageNo={currentPage}
327
+ pageCount={totalPages}
328
+ total={totalProducts}
329
+ rowCount={rowsPerPage}
330
+ rowsSet={[6, 12, 24, 48]}
331
+ rowCountLabel="Products per page"
332
+ generateInfo={generateProductInfo}
333
+ onPageChange={handlePageChange}
334
+ onRowCountChanged={handleRowCountChange}
335
+ type="round"
336
+ big
337
+ />
338
+ </div>
339
+
340
+ <style>
341
+ .product-catalog {
342
+ max-width: 1200px;
343
+ margin: 0 auto;
344
+ padding: 20px;
345
+ }
346
+
347
+ .catalog-header {
348
+ display: flex;
349
+ justify-content: space-between;
350
+ align-items: center;
351
+ margin-bottom: 30px;
352
+ }
353
+
354
+ .category-filter {
355
+ display: flex;
356
+ align-items: center;
357
+ gap: 10px;
358
+ }
359
+
360
+ .category-filter select {
361
+ padding: 8px 12px;
362
+ border: 1px solid #ddd;
363
+ border-radius: 4px;
364
+ }
365
+
366
+ .products-grid {
367
+ display: grid;
368
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
369
+ gap: 24px;
370
+ margin-bottom: 40px;
371
+ min-height: 400px;
372
+ }
373
+
374
+ .product-card {
375
+ border: 1px solid #ddd;
376
+ border-radius: 8px;
377
+ padding: 16px;
378
+ text-align: center;
379
+ transition: transform 0.2s;
380
+ }
381
+
382
+ .product-card:hover {
383
+ transform: translateY(-2px);
384
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
385
+ }
386
+
387
+ .product-card img {
388
+ width: 100%;
389
+ height: 200px;
390
+ object-fit: cover;
391
+ border-radius: 4px;
392
+ margin-bottom: 12px;
393
+ }
394
+
395
+ .product-card h3 {
396
+ margin: 0 0 12px 0;
397
+ font-size: 16px;
398
+ }
399
+
400
+ .product-info {
401
+ display: flex;
402
+ justify-content: space-between;
403
+ align-items: center;
404
+ }
405
+
406
+ .price {
407
+ font-size: 18px;
408
+ font-weight: bold;
409
+ color: #007bff;
410
+ }
411
+
412
+ .rating {
413
+ color: #ff9500;
414
+ }
415
+ </style>
416
+ ```
417
+
418
+ ### Reports Dashboard
419
+
420
+ ```svelte
421
+ <script>
422
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
423
+
424
+ let reports = [];
425
+ let currentPage = 1;
426
+ let totalPages = 1;
427
+ let totalReports = 0;
428
+ let rowsPerPage = 15;
429
+ let dateRange = 'week';
430
+
431
+ async function loadReports(page = 1, rows = 15, range = 'week') {
432
+ // Simulate loading reports based on date range
433
+ const rangeTotals = {
434
+ today: 23,
435
+ week: 156,
436
+ month: 642,
437
+ year: 7834
438
+ };
439
+
440
+ totalReports = rangeTotals[range];
441
+ totalPages = Math.ceil(totalReports / rows);
442
+ currentPage = page;
443
+
444
+ const startIndex = (page - 1) * rows;
445
+ reports = Array.from({ length: Math.min(rows, totalReports - startIndex) }, (_, i) => ({
446
+ id: `RPT-${String(startIndex + i + 1).padStart(4, '0')}`,
447
+ title: `Report ${startIndex + i + 1}`,
448
+ type: ['Sales', 'Analytics', 'Performance', 'User Activity'][Math.floor(Math.random() * 4)],
449
+ createdAt: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000).toLocaleDateString(),
450
+ status: ['Completed', 'Processing', 'Failed'][Math.floor(Math.random() * 3)],
451
+ size: `${(Math.random() * 10 + 0.5).toFixed(1)} MB`
452
+ }));
453
+ }
454
+
455
+ function handlePageChange(page) {
456
+ loadReports(page, rowsPerPage, dateRange);
457
+ }
458
+
459
+ function handleRowCountChange(rows) {
460
+ rowsPerPage = rows;
461
+ loadReports(1, rows, dateRange);
462
+ }
463
+
464
+ function handleDateRangeChange() {
465
+ loadReports(1, rowsPerPage, dateRange);
466
+ }
467
+
468
+ // Custom report info generator
469
+ function generateReportInfo(total, pageCount, pageNo, rows) {
470
+ const start = (pageNo - 1) * rows + 1;
471
+ const end = Math.min(pageNo * rows, total);
472
+ return `
473
+ <div style="display: flex; align-items: center; gap: 16px;">
474
+ <span>Reports <b>${start}-${end}</b> of <b>${total}</b></span>
475
+ <span style="color: #666;">•</span>
476
+ <span style="color: #007bff;">Page ${pageNo}/${pageCount}</span>
477
+ </div>
478
+ `;
479
+ }
480
+
481
+ // Load initial reports
482
+ loadReports(currentPage, rowsPerPage, dateRange);
483
+ </script>
484
+
485
+ <div class="reports-dashboard">
486
+ <div class="dashboard-header">
487
+ <h2>Reports Dashboard</h2>
488
+ <div class="date-filter">
489
+ <label>Time Range:</label>
490
+ <select bind:value={dateRange} on:change={handleDateRangeChange}>
491
+ <option value="today">Today</option>
492
+ <option value="week">This Week</option>
493
+ <option value="month">This Month</option>
494
+ <option value="year">This Year</option>
495
+ </select>
496
+ </div>
497
+ </div>
498
+
499
+ <div class="reports-table-container">
500
+ <table class="reports-table">
501
+ <thead>
502
+ <tr>
503
+ <th>Report ID</th>
504
+ <th>Title</th>
505
+ <th>Type</th>
506
+ <th>Created</th>
507
+ <th>Status</th>
508
+ <th>Size</th>
509
+ <th>Actions</th>
510
+ </tr>
511
+ </thead>
512
+ <tbody>
513
+ {#each reports as report}
514
+ <tr>
515
+ <td><code>{report.id}</code></td>
516
+ <td>{report.title}</td>
517
+ <td><span class="badge type-{report.type.toLowerCase().replace(' ', '-')}">{report.type}</span></td>
518
+ <td>{report.createdAt}</td>
519
+ <td><span class="status status-{report.status.toLowerCase()}">{report.status}</span></td>
520
+ <td>{report.size}</td>
521
+ <td>
522
+ <button class="action-btn download">Download</button>
523
+ <button class="action-btn delete">Delete</button>
524
+ </td>
525
+ </tr>
526
+ {/each}
527
+ </tbody>
528
+ </table>
529
+ </div>
530
+
531
+ <PaginationPanel
532
+ pageNo={currentPage}
533
+ pageCount={totalPages}
534
+ total={totalReports}
535
+ rowCount={rowsPerPage}
536
+ rowsSet={[10, 15, 25, 50]}
537
+ rowCountLabel="Reports per page"
538
+ generateInfo={generateReportInfo}
539
+ onPageChange={handlePageChange}
540
+ onRowCountChanged={handleRowCountChange}
541
+ type="plain"
542
+ align="left"
543
+ />
544
+ </div>
545
+
546
+ <style>
547
+ .reports-dashboard {
548
+ max-width: 1400px;
549
+ margin: 0 auto;
550
+ padding: 20px;
551
+ }
552
+
553
+ .dashboard-header {
554
+ display: flex;
555
+ justify-content: space-between;
556
+ align-items: center;
557
+ margin-bottom: 30px;
558
+ }
559
+
560
+ .date-filter {
561
+ display: flex;
562
+ align-items: center;
563
+ gap: 10px;
564
+ }
565
+
566
+ .date-filter select {
567
+ padding: 8px 12px;
568
+ border: 1px solid #ddd;
569
+ border-radius: 4px;
570
+ }
571
+
572
+ .reports-table-container {
573
+ overflow-x: auto;
574
+ margin-bottom: 20px;
575
+ }
576
+
577
+ .reports-table {
578
+ width: 100%;
579
+ border-collapse: collapse;
580
+ min-width: 800px;
581
+ }
582
+
583
+ .reports-table th,
584
+ .reports-table td {
585
+ padding: 12px;
586
+ text-align: left;
587
+ border-bottom: 1px solid #ddd;
588
+ }
589
+
590
+ .reports-table th {
591
+ background-color: #f8f9fa;
592
+ font-weight: 600;
593
+ position: sticky;
594
+ top: 0;
595
+ }
596
+
597
+ .badge {
598
+ padding: 4px 8px;
599
+ border-radius: 12px;
600
+ font-size: 12px;
601
+ font-weight: 600;
602
+ text-transform: uppercase;
603
+ }
604
+
605
+ .badge.type-sales { background: #e3f2fd; color: #1976d2; }
606
+ .badge.type-analytics { background: #f3e5f5; color: #7b1fa2; }
607
+ .badge.type-performance { background: #e8f5e8; color: #388e3c; }
608
+ .badge.type-user-activity { background: #fff3e0; color: #f57c00; }
609
+
610
+ .status {
611
+ font-weight: 600;
612
+ }
613
+
614
+ .status.status-completed { color: #28a745; }
615
+ .status.status-processing { color: #ffc107; }
616
+ .status.status-failed { color: #dc3545; }
617
+
618
+ .action-btn {
619
+ padding: 4px 8px;
620
+ margin: 0 2px;
621
+ border: none;
622
+ border-radius: 4px;
623
+ cursor: pointer;
624
+ font-size: 12px;
625
+ }
626
+
627
+ .action-btn.download {
628
+ background: #007bff;
629
+ color: white;
630
+ }
631
+
632
+ .action-btn.delete {
633
+ background: #dc3545;
634
+ color: white;
635
+ }
636
+ </style>
637
+ ```
638
+
639
+ ### Log Viewer with Large Dataset
640
+
641
+ ```svelte
642
+ <script>
643
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
644
+
645
+ let logs = [];
646
+ let currentPage = 1;
647
+ let totalPages = 1;
648
+ let totalLogs = 0;
649
+ let rowsPerPage = 50;
650
+ let logLevel = 'all';
651
+ let searchTerm = '';
652
+
653
+ const logLevels = ['all', 'error', 'warning', 'info', 'debug'];
654
+
655
+ async function loadLogs(page = 1, rows = 50, level = 'all', search = '') {
656
+ // Simulate large log dataset
657
+ const levelMultipliers = {
658
+ all: 1,
659
+ error: 0.1,
660
+ warning: 0.15,
661
+ info: 0.6,
662
+ debug: 0.15
663
+ };
664
+
665
+ const baseLogs = 15000;
666
+ totalLogs = Math.floor(baseLogs * (level === 'all' ? 1 : levelMultipliers[level]));
667
+
668
+ if (search) {
669
+ totalLogs = Math.floor(totalLogs * 0.2); // Simulate search filtering
670
+ }
671
+
672
+ totalPages = Math.ceil(totalLogs / rows);
673
+ currentPage = page;
674
+
675
+ const startIndex = (page - 1) * rows;
676
+ logs = Array.from({ length: Math.min(rows, totalLogs - startIndex) }, (_, i) => {
677
+ const logIndex = startIndex + i + 1;
678
+ const levels = level === 'all' ? ['error', 'warning', 'info', 'debug'] : [level];
679
+ const randomLevel = levels[Math.floor(Math.random() * levels.length)];
680
+
681
+ return {
682
+ id: logIndex,
683
+ timestamp: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toISOString(),
684
+ level: randomLevel,
685
+ message: search
686
+ ? `Log message ${logIndex} containing "${search}" with additional details`
687
+ : `Log message ${logIndex} - ${randomLevel} level event occurred`,
688
+ source: ['auth', 'api', 'database', 'cache', 'queue'][Math.floor(Math.random() * 5)]
689
+ };
690
+ });
691
+ }
692
+
693
+ function handlePageChange(page) {
694
+ loadLogs(page, rowsPerPage, logLevel, searchTerm);
695
+ }
696
+
697
+ function handleRowCountChange(rows) {
698
+ rowsPerPage = rows;
699
+ loadLogs(1, rows, logLevel, searchTerm);
700
+ }
701
+
702
+ function handleLevelChange() {
703
+ loadLogs(1, rowsPerPage, logLevel, searchTerm);
704
+ }
705
+
706
+ function handleSearch() {
707
+ loadLogs(1, rowsPerPage, logLevel, searchTerm);
708
+ }
709
+
710
+ // Custom log info generator
711
+ function generateLogInfo(total, pageCount, pageNo, rows) {
712
+ const start = (pageNo - 1) * rows + 1;
713
+ const end = Math.min(pageNo * rows, total);
714
+ return `
715
+ <div style="font-family: monospace; font-size: 12px;">
716
+ Logs ${start.toLocaleString()}-${end.toLocaleString()} of ${total.toLocaleString()} • Page ${pageNo}/${pageCount}
717
+ </div>
718
+ `;
719
+ }
720
+
721
+ // Load initial logs
722
+ loadLogs(currentPage, rowsPerPage, logLevel, searchTerm);
723
+ </script>
724
+
725
+ <div class="log-viewer">
726
+ <div class="log-controls">
727
+ <h2>System Logs</h2>
728
+ <div class="filters">
729
+ <div class="filter-group">
730
+ <label>Level:</label>
731
+ <select bind:value={logLevel} on:change={handleLevelChange}>
732
+ {#each logLevels as level}
733
+ <option value={level}>{level.toUpperCase()}</option>
734
+ {/each}
735
+ </select>
736
+ </div>
737
+ <div class="filter-group">
738
+ <label>Search:</label>
739
+ <input
740
+ type="text"
741
+ bind:value={searchTerm}
742
+ placeholder="Search logs..."
743
+ on:keydown={(e) => e.key === 'Enter' && handleSearch()}
744
+ />
745
+ <button on:click={handleSearch}>Search</button>
746
+ </div>
747
+ </div>
748
+ </div>
749
+
750
+ <div class="logs-container">
751
+ {#each logs as log}
752
+ <div class="log-entry level-{log.level}">
753
+ <div class="log-header">
754
+ <span class="timestamp">{new Date(log.timestamp).toLocaleString()}</span>
755
+ <span class="level level-{log.level}">{log.level.toUpperCase()}</span>
756
+ <span class="source">[{log.source}]</span>
757
+ </div>
758
+ <div class="log-message">{log.message}</div>
759
+ </div>
760
+ {/each}
761
+ </div>
762
+
763
+ <PaginationPanel
764
+ pageNo={currentPage}
765
+ pageCount={totalPages}
766
+ total={totalLogs}
767
+ rowCount={rowsPerPage}
768
+ rowsSet={[25, 50, 100, 200]}
769
+ rowCountLabel="Logs per page"
770
+ generateInfo={generateLogInfo}
771
+ onPageChange={handlePageChange}
772
+ onRowCountChanged={handleRowCountChange}
773
+ type="circle"
774
+ />
775
+ </div>
776
+
777
+ <style>
778
+ .log-viewer {
779
+ max-width: 1200px;
780
+ margin: 0 auto;
781
+ padding: 20px;
782
+ }
783
+
784
+ .log-controls {
785
+ margin-bottom: 20px;
786
+ }
787
+
788
+ .log-controls h2 {
789
+ margin: 0 0 16px 0;
790
+ }
791
+
792
+ .filters {
793
+ display: flex;
794
+ gap: 20px;
795
+ align-items: center;
796
+ flex-wrap: wrap;
797
+ }
798
+
799
+ .filter-group {
800
+ display: flex;
801
+ align-items: center;
802
+ gap: 8px;
803
+ }
804
+
805
+ .filter-group select,
806
+ .filter-group input {
807
+ padding: 6px 10px;
808
+ border: 1px solid #ddd;
809
+ border-radius: 4px;
810
+ }
811
+
812
+ .filter-group button {
813
+ padding: 6px 12px;
814
+ background: #007bff;
815
+ color: white;
816
+ border: none;
817
+ border-radius: 4px;
818
+ cursor: pointer;
819
+ }
820
+
821
+ .logs-container {
822
+ background: #1e1e1e;
823
+ border-radius: 8px;
824
+ padding: 16px;
825
+ margin-bottom: 20px;
826
+ max-height: 600px;
827
+ overflow-y: auto;
828
+ font-family: 'Courier New', monospace;
829
+ }
830
+
831
+ .log-entry {
832
+ margin-bottom: 12px;
833
+ padding: 8px;
834
+ border-radius: 4px;
835
+ border-left: 4px solid;
836
+ }
837
+
838
+ .log-entry.level-error {
839
+ background: rgba(220, 53, 69, 0.1);
840
+ border-left-color: #dc3545;
841
+ }
842
+
843
+ .log-entry.level-warning {
844
+ background: rgba(255, 193, 7, 0.1);
845
+ border-left-color: #ffc107;
846
+ }
847
+
848
+ .log-entry.level-info {
849
+ background: rgba(0, 123, 255, 0.1);
850
+ border-left-color: #007bff;
851
+ }
852
+
853
+ .log-entry.level-debug {
854
+ background: rgba(108, 117, 125, 0.1);
855
+ border-left-color: #6c757d;
856
+ }
857
+
858
+ .log-header {
859
+ display: flex;
860
+ gap: 12px;
861
+ align-items: center;
862
+ margin-bottom: 4px;
863
+ font-size: 12px;
864
+ }
865
+
866
+ .timestamp {
867
+ color: #adb5bd;
868
+ }
869
+
870
+ .level {
871
+ font-weight: bold;
872
+ padding: 2px 6px;
873
+ border-radius: 3px;
874
+ font-size: 10px;
875
+ }
876
+
877
+ .level.level-error { background: #dc3545; color: white; }
878
+ .level.level-warning { background: #ffc107; color: black; }
879
+ .level.level-info { background: #007bff; color: white; }
880
+ .level.level-debug { background: #6c757d; color: white; }
881
+
882
+ .source {
883
+ color: #28a745;
884
+ }
885
+
886
+ .log-message {
887
+ color: #f8f9fa;
888
+ font-size: 13px;
889
+ line-height: 1.4;
890
+ }
891
+ </style>
892
+ ```
893
+
894
+ ### Mobile-Responsive Panel
895
+
896
+ ```svelte
897
+ <script>
898
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
899
+ import { onMount } from 'svelte';
900
+
901
+ let currentPage = 1;
902
+ let totalPages = 15;
903
+ let totalItems = 300;
904
+ let rowsPerPage = 20;
905
+ let isMobile = false;
906
+
907
+ onMount(() => {
908
+ const checkMobile = () => {
909
+ isMobile = window.innerWidth < 768;
910
+ };
911
+
912
+ checkMobile();
913
+ window.addEventListener('resize', checkMobile);
914
+
915
+ return () => window.removeEventListener('resize', checkMobile);
916
+ });
917
+
918
+ function handlePageChange(page) {
919
+ currentPage = page;
920
+ }
921
+
922
+ function handleRowCountChange(rows) {
923
+ rowsPerPage = rows;
924
+ totalPages = Math.ceil(totalItems / rows);
925
+ currentPage = 1;
926
+ }
927
+
928
+ // Mobile-friendly info generator
929
+ function generateMobileInfo(total, pageCount, pageNo, rows) {
930
+ if (isMobile) {
931
+ return `<div style="font-size: 12px; text-align: center;">${pageNo}/${pageCount} • ${total} items</div>`;
932
+ }
933
+ return `Showing ${(pageNo - 1) * rows + 1}-${Math.min(pageNo * rows, total)} of ${total} items`;
934
+ }
935
+ </script>
936
+
937
+ <div class="mobile-demo">
938
+ <h2>Mobile-Responsive Pagination</h2>
939
+ <p>Resize your browser to see mobile adaptations</p>
940
+
941
+ <div class="content-grid">
942
+ {#each Array(rowsPerPage) as _, i}
943
+ <div class="content-item">
944
+ Item {(currentPage - 1) * rowsPerPage + i + 1}
945
+ </div>
946
+ {/each}
947
+ </div>
948
+
949
+ <PaginationPanel
950
+ pageNo={currentPage}
951
+ pageCount={totalPages}
952
+ total={totalItems}
953
+ rowCount={rowsPerPage}
954
+ rowsSet={isMobile ? [10, 20] : [10, 20, 50]}
955
+ rowCountLabel={isMobile ? "Per page" : "Items per page"}
956
+ generateInfo={generateMobileInfo}
957
+ onPageChange={handlePageChange}
958
+ onRowCountChanged={handleRowCountChange}
959
+ type="round"
960
+ big={!isMobile}
961
+ align={isMobile ? "" : "right"}
962
+ />
963
+ </div>
964
+
965
+ <style>
966
+ .mobile-demo {
967
+ max-width: 800px;
968
+ margin: 0 auto;
969
+ padding: 20px;
970
+ }
971
+
972
+ .content-grid {
973
+ display: grid;
974
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
975
+ gap: 16px;
976
+ margin-bottom: 30px;
977
+ }
978
+
979
+ .content-item {
980
+ padding: 20px;
981
+ background: #f8f9fa;
982
+ border: 1px solid #dee2e6;
983
+ border-radius: 8px;
984
+ text-align: center;
985
+ }
986
+
987
+ @media (max-width: 767px) {
988
+ .content-grid {
989
+ grid-template-columns: 1fr 1fr;
990
+ gap: 12px;
991
+ }
992
+
993
+ .content-item {
994
+ padding: 16px;
995
+ font-size: 14px;
996
+ }
997
+ }
998
+ </style>
999
+ ```
1000
+
1001
+ ## Best Practices
1002
+
1003
+ 1. **Data Loading**: Implement proper loading states during page transitions
1004
+ 2. **URL Synchronization**: Keep URL parameters in sync with pagination state
1005
+ 3. **Performance**: Use efficient data fetching strategies for large datasets
1006
+ 4. **User Experience**: Provide clear feedback about current state and total items
1007
+ 5. **Mobile Optimization**: Adapt row options and info display for mobile devices
1008
+ 6. **Accessibility**: Ensure all controls are keyboard accessible
1009
+ 7. **Error Handling**: Handle API failures gracefully with retry options
1010
+
1011
+ ## Styling
1012
+
1013
+ The PaginationPanel component combines styling from multiple sub-components:
1014
+
1015
+ ```css
1016
+ .uniface-pagination-panel {
1017
+ display: flex;
1018
+ align-items: center;
1019
+ justify-content: space-between;
1020
+ gap: 16px;
1021
+ padding: 16px 0;
1022
+ }
1023
+
1024
+ .uniface-pagination-panel.left {
1025
+ justify-content: flex-start;
1026
+ }
1027
+
1028
+ .uniface-pagination-panel.right {
1029
+ justify-content: flex-end;
1030
+ }
1031
+
1032
+ .page-options {
1033
+ display: flex;
1034
+ align-items: center;
1035
+ gap: 8px;
1036
+ font-size: 14px;
1037
+ }
1038
+
1039
+ .pagination {
1040
+ flex: 0 0 auto;
1041
+ }
1042
+
1043
+ .pagination-info {
1044
+ font-size: 14px;
1045
+ color: #666;
1046
+ }
1047
+
1048
+ /* Mobile responsive */
1049
+ @media (max-width: 767px) {
1050
+ .uniface-pagination-panel {
1051
+ flex-direction: column;
1052
+ gap: 12px;
1053
+ }
1054
+
1055
+ .page-options,
1056
+ .pagination-info {
1057
+ font-size: 12px;
1058
+ }
1059
+ }
1060
+ ```
1061
+
1062
+ ## Accessibility
1063
+
1064
+ - Full keyboard navigation support
1065
+ - ARIA labels for all interactive elements
1066
+ - Screen reader announcements for page changes
1067
+ - High contrast mode compatibility
1068
+ - Focus management between controls
1069
+
1070
+ ## Related Components
1071
+
1072
+ - [Pagination](../pagination/README.md) - Core pagination component
1073
+ - [OptionsSelect](../options-select/README.md) - Row count selector
1074
+ - [DataTable](../data-table/README.md) - Data tables with pagination
1075
+ - [Button](../button/README.md) - For custom pagination actions