xertica-ui 2.1.2 → 2.1.4

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 (181) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +1 -1
  3. package/bin/cli.ts +1 -1
  4. package/bin/generate-tokens.ts +13 -7
  5. package/components/assistant/xertica-assistant/index.ts +2 -0
  6. package/components/assistant/xertica-assistant/parts/AssistantCollapsedView.tsx +97 -0
  7. package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +104 -0
  8. package/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.tsx +81 -0
  9. package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +86 -0
  10. package/components/assistant/xertica-assistant/parts/AssistantHeader.tsx +77 -0
  11. package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +573 -0
  12. package/components/assistant/xertica-assistant/parts/AssistantTabBar.tsx +65 -0
  13. package/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.tsx +41 -0
  14. package/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.tsx +98 -0
  15. package/components/assistant/xertica-assistant/parts/index.ts +16 -0
  16. package/components/assistant/xertica-assistant/types.ts +139 -0
  17. package/components/assistant/xertica-assistant/use-assistant.ts +559 -0
  18. package/components/assistant/xertica-assistant/xertica-assistant.stories.tsx +200 -0
  19. package/components/assistant/xertica-assistant/xertica-assistant.tsx +198 -1460
  20. package/components/brand/theme-toggle/ThemeToggle.tsx +8 -27
  21. package/components/hooks/index.ts +3 -0
  22. package/components/hooks/use-layout-shortcuts.ts +46 -0
  23. package/components/layout/sidebar/index.ts +2 -0
  24. package/components/layout/sidebar/sidebar.stories.tsx +160 -8
  25. package/components/layout/sidebar/sidebar.tsx +606 -497
  26. package/components/layout/sidebar/use-sidebar.ts +104 -0
  27. package/components/media/audio-player/AudioPlayer.tsx +131 -206
  28. package/components/media/audio-player/use-audio-player.ts +298 -0
  29. package/components/pages/home-page/HomePage.tsx +1 -1
  30. package/components/pages/template-content/TemplateContent.tsx +5 -5
  31. package/components/pages/template-page/TemplatePage.tsx +5 -5
  32. package/components/shared/CustomTooltipContent.tsx +52 -0
  33. package/components/shared/layout-constants.ts +1 -1
  34. package/components/ui/chart/chart.stories.tsx +966 -7
  35. package/components/ui/chart/chart.tsx +918 -45
  36. package/components/ui/file-upload/file-upload.stories.tsx +100 -0
  37. package/components/ui/file-upload/file-upload.tsx +14 -74
  38. package/components/ui/file-upload/index.ts +1 -0
  39. package/components/ui/file-upload/use-file-upload.ts +181 -0
  40. package/components/ui/pagination/index.ts +2 -0
  41. package/components/ui/pagination/pagination.stories.tsx +94 -0
  42. package/components/ui/pagination/use-pagination.ts +194 -0
  43. package/components/ui/rich-text-editor/index.ts +2 -0
  44. package/components/ui/rich-text-editor/rich-text-editor.stories.tsx +129 -1
  45. package/components/ui/rich-text-editor/rich-text-editor.tsx +86 -305
  46. package/components/ui/rich-text-editor/use-rich-text-editor.ts +439 -0
  47. package/components/ui/stepper/index.ts +3 -1
  48. package/components/ui/stepper/stepper.stories.tsx +116 -0
  49. package/components/ui/stepper/stepper.tsx +4 -4
  50. package/components/ui/stepper/use-stepper.ts +137 -0
  51. package/components/ui/tree-view/index.ts +4 -1
  52. package/components/ui/tree-view/tree-view.stories.tsx +110 -4
  53. package/components/ui/tree-view/tree-view.tsx +17 -125
  54. package/components/ui/tree-view/use-tree-view.ts +229 -0
  55. package/contexts/AssistenteContext.tsx +17 -54
  56. package/contexts/BrandColorsContext.tsx +6 -17
  57. package/contexts/LayoutContext.tsx +5 -31
  58. package/dist/AssistantChart-BAudAfne.cjs +3591 -0
  59. package/dist/AssistantChart-BP8upjMk.js +3565 -0
  60. package/dist/AudioPlayer-1ypwE2Wh.cjs +936 -0
  61. package/dist/AudioPlayer-DuKXrCfy.js +937 -0
  62. package/dist/CustomTooltipContent-DHjkY0ww.js +40 -0
  63. package/dist/CustomTooltipContent-c_K-DWRr.cjs +56 -0
  64. package/dist/LanguageContext-BwhwC3G2.js +657 -0
  65. package/dist/LanguageContext-DvUt5jBg.cjs +656 -0
  66. package/dist/LayoutContext-BDmcZfMH.cjs +84 -0
  67. package/dist/LayoutContext-dbQvdC4O.js +85 -0
  68. package/dist/ThemeContext-RTy1m2Uq.js +82 -0
  69. package/dist/ThemeContext-bSzuOit2.cjs +81 -0
  70. package/dist/VerifyEmailPage-C_ihbcth.js +2828 -0
  71. package/dist/VerifyEmailPage-Dt7zgA4w.cjs +2827 -0
  72. package/dist/XerticaProvider-CW9hpCdF.cjs +39 -0
  73. package/dist/XerticaProvider-siSt9uG2.js +40 -0
  74. package/dist/XerticaXLogo-D8jf0SNv.cjs +214 -0
  75. package/dist/XerticaXLogo-fAJMy3H4.js +215 -0
  76. package/dist/assistant.cjs.js +2 -1
  77. package/dist/assistant.es.js +3 -2
  78. package/dist/brand.cjs.js +2 -2
  79. package/dist/brand.es.js +2 -2
  80. package/dist/cli.js +14 -8
  81. package/dist/components/assistant/xertica-assistant/index.d.ts +2 -0
  82. package/dist/components/assistant/xertica-assistant/parts/AssistantCollapsedView.d.ts +13 -0
  83. package/dist/components/assistant/xertica-assistant/parts/AssistantConversationList.d.ts +16 -0
  84. package/dist/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.d.ts +17 -0
  85. package/dist/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.d.ts +19 -0
  86. package/dist/components/assistant/xertica-assistant/parts/AssistantHeader.d.ts +11 -0
  87. package/dist/components/assistant/xertica-assistant/parts/AssistantMessageBubble.d.ts +29 -0
  88. package/dist/components/assistant/xertica-assistant/parts/AssistantTabBar.d.ts +13 -0
  89. package/dist/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.d.ts +4 -0
  90. package/dist/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.d.ts +17 -0
  91. package/dist/components/assistant/xertica-assistant/parts/index.d.ts +16 -0
  92. package/dist/components/assistant/xertica-assistant/types.d.ts +106 -0
  93. package/dist/components/assistant/xertica-assistant/use-assistant.d.ts +125 -0
  94. package/dist/components/assistant/xertica-assistant/xertica-assistant.d.ts +8 -97
  95. package/dist/components/hooks/index.d.ts +3 -0
  96. package/dist/components/hooks/use-layout-shortcuts.d.ts +22 -0
  97. package/dist/components/layout/sidebar/index.d.ts +2 -0
  98. package/dist/components/layout/sidebar/sidebar.d.ts +80 -0
  99. package/dist/components/layout/sidebar/use-sidebar.d.ts +22 -0
  100. package/dist/components/media/audio-player/AudioPlayer.d.ts +4 -1
  101. package/dist/components/media/audio-player/use-audio-player.d.ts +72 -0
  102. package/dist/components/shared/CustomTooltipContent.d.ts +20 -0
  103. package/dist/components/shared/layout-constants.d.ts +1 -1
  104. package/dist/components/ui/alert/alert.d.ts +1 -1
  105. package/dist/components/ui/badge/badge.d.ts +1 -1
  106. package/dist/components/ui/button/button.d.ts +2 -2
  107. package/dist/components/ui/chart/chart.d.ts +162 -5
  108. package/dist/components/ui/file-upload/file-upload.d.ts +2 -0
  109. package/dist/components/ui/file-upload/index.d.ts +1 -0
  110. package/dist/components/ui/file-upload/use-file-upload.d.ts +49 -0
  111. package/dist/components/ui/pagination/index.d.ts +2 -0
  112. package/dist/components/ui/pagination/use-pagination.d.ts +78 -0
  113. package/dist/components/ui/rich-text-editor/index.d.ts +2 -0
  114. package/dist/components/ui/rich-text-editor/use-rich-text-editor.d.ts +107 -0
  115. package/dist/components/ui/stepper/index.d.ts +3 -1
  116. package/dist/components/ui/stepper/stepper.d.ts +2 -2
  117. package/dist/components/ui/stepper/use-stepper.d.ts +60 -0
  118. package/dist/components/ui/tree-view/index.d.ts +4 -1
  119. package/dist/components/ui/tree-view/tree-view.d.ts +4 -6
  120. package/dist/components/ui/tree-view/use-tree-view.d.ts +60 -0
  121. package/dist/contexts/AssistenteContext.d.ts +10 -49
  122. package/dist/hooks.cjs.js +30 -10
  123. package/dist/hooks.es.js +25 -4
  124. package/dist/index.cjs.js +20 -9
  125. package/dist/index.es.js +38 -27
  126. package/dist/layout.cjs.js +82 -1
  127. package/dist/layout.es.js +83 -2
  128. package/dist/media.cjs.js +1 -1
  129. package/dist/media.es.js +1 -1
  130. package/dist/pages.cjs.js +1 -1
  131. package/dist/pages.es.js +1 -1
  132. package/dist/rich-text-editor-BmsjY03B.js +2949 -0
  133. package/dist/rich-text-editor-GS2kpTAK.cjs +2966 -0
  134. package/dist/sidebar-CVUGHOS_.cjs +756 -0
  135. package/dist/sidebar-CmvwjnVb.js +757 -0
  136. package/dist/ui.cjs.js +12 -2
  137. package/dist/ui.es.js +24 -14
  138. package/dist/use-audio-player-Bkh23vQ3.js +177 -0
  139. package/dist/use-audio-player-Dn1NR9xN.cjs +176 -0
  140. package/dist/utils/color-utils.d.ts +51 -0
  141. package/dist/xertica-assistant-BMqdyRVi.js +2082 -0
  142. package/dist/xertica-assistant-Bj3vBCq_.cjs +2081 -0
  143. package/dist/xertica-ui.css +1 -1
  144. package/docs/ai-usage.md +28 -10
  145. package/docs/architecture-improvements.md +463 -0
  146. package/docs/architecture.md +77 -1
  147. package/docs/components/assistant-chart.md +1 -1
  148. package/docs/components/assistant.md +159 -0
  149. package/docs/components/audio-player.md +46 -0
  150. package/docs/components/branding.md +251 -0
  151. package/docs/components/chart.md +354 -39
  152. package/docs/components/code-block.md +108 -0
  153. package/docs/components/file-upload.md +119 -2
  154. package/docs/components/formatted-document.md +113 -0
  155. package/docs/components/hooks.md +430 -0
  156. package/docs/components/image-with-fallback.md +106 -0
  157. package/docs/components/map-layers.md +140 -0
  158. package/docs/components/modern-chat-input.md +163 -0
  159. package/docs/components/pages.md +351 -0
  160. package/docs/components/pagination.md +187 -0
  161. package/docs/components/rich-text-editor.md +164 -0
  162. package/docs/components/sidebar.md +153 -4
  163. package/docs/components/stepper.md +157 -12
  164. package/docs/components/tree-view.md +164 -6
  165. package/docs/doc-audit.md +223 -0
  166. package/docs/getting-started.md +155 -1
  167. package/docs/guidelines.md +14 -8
  168. package/docs/layout.md +2 -2
  169. package/docs/llms.md +29 -9
  170. package/docs/patterns/detail-page.md +276 -0
  171. package/docs/patterns/settings.md +346 -0
  172. package/docs/patterns/wizard.md +217 -0
  173. package/guidelines/Guidelines.md +5 -3
  174. package/llms.txt +1 -1
  175. package/package.json +10 -10
  176. package/styles/xertica/tokens.css +41 -12
  177. package/templates/CLAUDE.md +16 -6
  178. package/templates/guidelines/Guidelines.md +16 -4
  179. package/templates/package.json +3 -3
  180. package/templates/src/styles/xertica/tokens.css +39 -10
  181. package/utils/color-utils.ts +72 -0
@@ -0,0 +1,351 @@
1
+ # Page Templates — Xertica UI
2
+
3
+ Xertica UI ships 8 ready-to-use page templates covering authentication flows, the main dashboard shell, and a fully-featured component showcase. All templates are exported from `xertica-ui/pages`.
4
+
5
+ ---
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import {
11
+ LoginPage,
12
+ ForgotPasswordPage,
13
+ ResetPasswordPage,
14
+ VerifyEmailPage,
15
+ HomePage,
16
+ HomeContent,
17
+ TemplatePage,
18
+ TemplateContent,
19
+ } from 'xertica-ui/pages';
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Authentication Pages
25
+
26
+ ### `LoginPage`
27
+
28
+ A complete, responsive login screen with a hero image side-panel (desktop) and a focused authentication form.
29
+
30
+ **Features:**
31
+ - Email + password form with validation
32
+ - Loading state during submission
33
+ - Error message display
34
+ - Social/SSO provider placeholders (Google, MT Login, gov.br)
35
+ - Language selector (`LanguageSelector`)
36
+ - Xertica logo
37
+ - Link to forgot-password flow (via `react-router-dom`)
38
+
39
+ **Props:**
40
+
41
+ | Prop | Type | Description |
42
+ |---|---|---|
43
+ | `onLogin` | `(email: string, password: string) => boolean` | Authentication handler. Return `true` on success, `false` to show an error. |
44
+
45
+ **Usage:**
46
+
47
+ ```tsx
48
+ import { LoginPage } from 'xertica-ui/pages';
49
+ import { useNavigate } from 'react-router-dom';
50
+
51
+ function AuthRoute() {
52
+ const navigate = useNavigate();
53
+
54
+ const handleLogin = (email: string, password: string): boolean => {
55
+ if (!email || !password) return false;
56
+ // call your auth API here
57
+ navigate('/home');
58
+ return true;
59
+ };
60
+
61
+ return <LoginPage onLogin={handleLogin} />;
62
+ }
63
+ ```
64
+
65
+ ---
66
+
67
+ ### `ForgotPasswordPage`
68
+
69
+ A password recovery form where users enter their email to receive a reset link.
70
+
71
+ **Features:**
72
+ - Email input with validation
73
+ - Success state (shows confirmation message after submission)
74
+ - Back-to-login navigation link
75
+ - Xertica logo + hero image
76
+
77
+ **Props:**
78
+
79
+ | Prop | Type | Description |
80
+ |---|---|---|
81
+ | `onSubmit` | `(email: string) => void` | Called when the user submits the recovery form |
82
+
83
+ **Usage:**
84
+
85
+ ```tsx
86
+ import { ForgotPasswordPage } from 'xertica-ui/pages';
87
+
88
+ <ForgotPasswordPage
89
+ onSubmit={(email) => {
90
+ // send password reset email
91
+ console.log('Reset requested for:', email);
92
+ }}
93
+ />
94
+ ```
95
+
96
+ ---
97
+
98
+ ### `ResetPasswordPage`
99
+
100
+ A new-password form for users arriving via a password reset link.
101
+
102
+ **Features:**
103
+ - New password + confirm password fields
104
+ - Password match validation
105
+ - Success state after reset
106
+
107
+ **Props:**
108
+
109
+ | Prop | Type | Description |
110
+ |---|---|---|
111
+ | `onReset` | `(password: string) => void` | Called with the new password when the form is submitted |
112
+
113
+ **Usage:**
114
+
115
+ ```tsx
116
+ import { ResetPasswordPage } from 'xertica-ui/pages';
117
+
118
+ <ResetPasswordPage
119
+ onReset={(newPassword) => {
120
+ // call your reset API with the token from the URL
121
+ console.log('New password:', newPassword);
122
+ }}
123
+ />
124
+ ```
125
+
126
+ ---
127
+
128
+ ### `VerifyEmailPage`
129
+
130
+ An email verification confirmation screen shown after registration.
131
+
132
+ **Features:**
133
+ - Confirmation message with email address display
134
+ - "Resend email" action
135
+ - Back-to-login link
136
+
137
+ **Props:**
138
+
139
+ | Prop | Type | Description |
140
+ |---|---|---|
141
+ | `email` | `string` | The email address to display in the confirmation message |
142
+ | `onResend` | `() => void` | Called when the user clicks "Resend verification email" |
143
+
144
+ **Usage:**
145
+
146
+ ```tsx
147
+ import { VerifyEmailPage } from 'xertica-ui/pages';
148
+
149
+ <VerifyEmailPage
150
+ email="user@example.com"
151
+ onResend={() => {
152
+ // resend verification email
153
+ }}
154
+ />
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Dashboard Pages
160
+
161
+ ### `HomePage`
162
+
163
+ The root dashboard page. Assembles `Sidebar`, `HomeContent`, and `XerticaAssistant` into a full-screen layout.
164
+
165
+ **Features:**
166
+ - Full-screen `h-screen` layout with sidebar + main content + assistant
167
+ - Integrates `LayoutContext` for synchronized sidebar/assistant state
168
+ - Falls back to local state if `LayoutContext` is not available (standalone usage)
169
+ - Pre-configured `XerticaAssistant` in demo mode with sample suggestions
170
+
171
+ **Props:**
172
+
173
+ | Prop | Type | Description |
174
+ |---|---|---|
175
+ | `user` | `{ email: string } \| null` | Currently logged-in user |
176
+ | `onLogout` | `() => void` | Logout handler passed to the Sidebar footer |
177
+
178
+ **Usage:**
179
+
180
+ ```tsx
181
+ import { HomePage } from 'xertica-ui/pages';
182
+
183
+ <HomePage
184
+ user={{ email: 'user@example.com' }}
185
+ onLogout={() => {
186
+ // clear session and redirect to login
187
+ navigate('/login');
188
+ }}
189
+ />
190
+ ```
191
+
192
+ > **Note**: `HomePage` uses `react-router-dom` hooks internally. It must be rendered inside a `<BrowserRouter>` (or equivalent).
193
+
194
+ ---
195
+
196
+ ### `HomeContent`
197
+
198
+ The main content area of the dashboard — used inside `HomePage`. Can also be used standalone to build custom page shells.
199
+
200
+ **Features:**
201
+ - `Header` with breadcrumbs, user menu, and actions
202
+ - Stats cards row
203
+ - Charts section
204
+ - Recent activity table
205
+
206
+ **Props:**
207
+
208
+ | Prop | Type | Description |
209
+ |---|---|---|
210
+ | `user` | `{ email: string } \| null` | User object for the header |
211
+ | `onLogout` | `() => void` | Logout handler |
212
+ | `sidebarExpanded` | `boolean` | Controls header left padding |
213
+ | `sidebarWidth` | `number` | Sidebar width in pixels |
214
+ | `onToggleSidebar` | `() => void` | Sidebar toggle callback |
215
+ | `onToggleAssistant` | `() => void` | Assistant toggle callback |
216
+
217
+ **Usage:**
218
+
219
+ ```tsx
220
+ import { HomeContent } from 'xertica-ui/pages';
221
+ import { useLayout } from 'xertica-ui/hooks';
222
+
223
+ function MyDashboard({ user, onLogout }) {
224
+ const { sidebarExpanded, sidebarWidth, toggleSidebar, toggleAssistente } = useLayout();
225
+ return (
226
+ <HomeContent
227
+ user={user}
228
+ onLogout={onLogout}
229
+ sidebarExpanded={sidebarExpanded}
230
+ sidebarWidth={sidebarWidth}
231
+ onToggleSidebar={toggleSidebar}
232
+ onToggleAssistant={toggleAssistente}
233
+ />
234
+ );
235
+ }
236
+ ```
237
+
238
+ ---
239
+
240
+ ### `TemplatePage`
241
+
242
+ A complete layout shell identical to `HomePage` but with `TemplateContent` as the main area. Use this as the **primary reference** for building new pages in a Xertica UI project.
243
+
244
+ **Features:**
245
+ - Full-screen layout: Sidebar + TemplateContent + XerticaAssistant
246
+ - Synchronized layout state via `LayoutContext`
247
+ - Demonstrates all major layout patterns
248
+
249
+ **Props:**
250
+
251
+ | Prop | Type | Description |
252
+ |---|---|---|
253
+ | `user` | `{ email: string } \| null` | Currently logged-in user |
254
+ | `onLogout` | `() => void` | Logout handler |
255
+
256
+ **Usage:**
257
+
258
+ ```tsx
259
+ import { TemplatePage } from 'xertica-ui/pages';
260
+
261
+ // Use as a starting point for new feature pages
262
+ <TemplatePage
263
+ user={currentUser}
264
+ onLogout={handleLogout}
265
+ />
266
+ ```
267
+
268
+ ---
269
+
270
+ ### `TemplateContent`
271
+
272
+ The main content area of `TemplatePage`. Contains a comprehensive showcase of all Xertica UI components — useful as a living reference during development.
273
+
274
+ **Features:**
275
+ - `Header` with full breadcrumb, user menu, and action buttons
276
+ - All form elements (Input, Select, Checkbox, Switch, Slider, etc.)
277
+ - Data display components (Table, Chart, StatsCard, Timeline, TreeView)
278
+ - Overlay components (Dialog, Sheet, Drawer, Popover, Tooltip)
279
+ - Media components (AudioPlayer, VideoPlayer)
280
+ - AI components (XerticaAssistant in full-page mode)
281
+
282
+ **Props:**
283
+
284
+ | Prop | Type | Description |
285
+ |---|---|---|
286
+ | `user` | `{ email: string } \| null` | User object for the header |
287
+ | `onLogout` | `() => void` | Logout handler |
288
+ | `sidebarExpanded` | `boolean` | Controls header left padding |
289
+ | `sidebarWidth` | `number` | Sidebar width in pixels |
290
+ | `onToggleSidebar` | `() => void` | Sidebar toggle callback |
291
+ | `onToggleAssistant` | `() => void` | Assistant toggle callback |
292
+
293
+ ---
294
+
295
+ ## Page Architecture Pattern
296
+
297
+ All dashboard pages follow the same three-column layout pattern:
298
+
299
+ ```
300
+ ┌─────────────────────────────────────────────────────┐
301
+ │ Sidebar │ Main Content │Assistant │
302
+ │ (fixed) │ Header + scrollable body │ (fixed) │
303
+ └─────────────────────────────────────────────────────┘
304
+ ```
305
+
306
+ ```tsx
307
+ // Standard page shell pattern
308
+ function MyPage({ user, onLogout }) {
309
+ const { sidebarExpanded, sidebarWidth, assistenteExpanded,
310
+ toggleSidebar, toggleAssistente } = useLayout();
311
+ const location = useLocation();
312
+ const navigate = useNavigate();
313
+
314
+ return (
315
+ <div className="h-screen flex bg-muted overflow-hidden relative">
316
+ <Sidebar
317
+ expanded={sidebarExpanded}
318
+ width={sidebarWidth}
319
+ onToggle={toggleSidebar}
320
+ user={user}
321
+ onLogout={onLogout}
322
+ location={location}
323
+ navigate={navigate}
324
+ routes={routes}
325
+ />
326
+ <MyContent
327
+ sidebarExpanded={sidebarExpanded}
328
+ sidebarWidth={sidebarWidth}
329
+ onToggleSidebar={toggleSidebar}
330
+ onToggleAssistant={toggleAssistente}
331
+ />
332
+ <XerticaAssistant
333
+ isExpanded={assistenteExpanded}
334
+ onToggle={toggleAssistente}
335
+ mode="demo"
336
+ />
337
+ </div>
338
+ );
339
+ }
340
+ ```
341
+
342
+ ---
343
+
344
+ ## AI Rules
345
+
346
+ > [!IMPORTANT]
347
+ > - **Use `TemplatePage` as the reference**: When building a new page, copy the structure from `TemplatePage` — it demonstrates the correct three-column layout with synchronized state.
348
+ > - **Router dependency**: All dashboard pages use `useLocation` and `useNavigate` from `react-router-dom`. They must be rendered inside a `<BrowserRouter>`.
349
+ > - **`LayoutContext` is optional**: Pages use `useOptionalLayout()` and fall back to local state if the context is not available. This allows standalone usage in Storybook or tests.
350
+ > - **Authentication pages are standalone**: `LoginPage`, `ForgotPasswordPage`, `ResetPasswordPage`, and `VerifyEmailPage` do not use `LayoutContext` and can be rendered without `XerticaProvider`.
351
+ > - **Do not add business logic to page shells**: Page components (`HomePage`, `TemplatePage`) are layout containers. Business logic belongs in content components (`HomeContent`, `TemplateContent`) or custom feature components.
@@ -4,6 +4,26 @@
4
4
 
5
5
  A navigation control for moving through pages of a large dataset. Renders Previous/Next buttons, numbered page buttons, and ellipsis for large page counts. Use it below data tables to control which page of records is displayed.
6
6
 
7
+ The package also exports a **headless `usePagination` hook** that computes the full page item list (numbers + ellipsis) and exposes navigation helpers — use it when you need full control over the pagination UI.
8
+
9
+ ---
10
+
11
+ ## Exports
12
+
13
+ | Export | Description |
14
+ |---|---|
15
+ | `Pagination` | Root nav wrapper |
16
+ | `PaginationContent` | Flex container for all items |
17
+ | `PaginationItem` | Individual item wrapper |
18
+ | `PaginationLink` | Numbered page button |
19
+ | `PaginationPrevious` | "Previous" button with left arrow |
20
+ | `PaginationNext` | "Next" button with right arrow |
21
+ | `PaginationEllipsis` | "..." indicator for skipped pages |
22
+ | `usePagination` | Headless hook — all logic, no UI |
23
+ | `UsePaginationProps` | TypeScript props type for the hook |
24
+ | `UsePaginationReturn` | TypeScript return type for the hook |
25
+ | `PaginationPageItem` | Union type for page items returned by the hook |
26
+
7
27
  ---
8
28
 
9
29
  ## When to Use
@@ -108,11 +128,178 @@ const totalPages = 10;
108
128
 
109
129
  ---
110
130
 
131
+ ## `usePagination` Hook
132
+
133
+ A headless hook that computes the full page item list (page numbers + ellipsis markers) and exposes navigation helpers. Supports both **uncontrolled** (internal state) and **controlled** (external `page` prop) modes.
134
+
135
+ ### Props
136
+
137
+ | Prop | Type | Default | Description |
138
+ |---|---|---|---|
139
+ | `totalItems` | `number` | — | **Required.** Total number of items across all pages |
140
+ | `pageSize` | `number` | `10` | Number of items per page |
141
+ | `initialPage` | `number` | `1` | Initial page (uncontrolled mode only) |
142
+ | `page` | `number` | — | Controlled current page — when provided, the hook uses this value instead of internal state |
143
+ | `onPageChange` | `(page: number) => void` | — | Called whenever the page changes |
144
+ | `siblingCount` | `number` | `1` | Number of page buttons to show on each side of the current page |
145
+
146
+ ### Return Value
147
+
148
+ | Property | Type | Description |
149
+ |---|---|---|
150
+ | `currentPage` | `number` | The currently active page (1-indexed) |
151
+ | `totalPages` | `number` | Total number of pages |
152
+ | `startIndex` | `number` | Zero-based index of the first item on the current page |
153
+ | `endIndex` | `number` | Zero-based index of the last item on the current page (exclusive) |
154
+ | `canGoPrev` | `boolean` | Whether navigating to the previous page is possible |
155
+ | `canGoNext` | `boolean` | Whether navigating to the next page is possible |
156
+ | `isFirstPage` | `boolean` | Whether the current page is the first page |
157
+ | `isLastPage` | `boolean` | Whether the current page is the last page |
158
+ | `items` | `PaginationPageItem[]` | Ordered list of page items to render (see below) |
159
+ | `goTo` | `(page: number) => void` | Navigate to a specific page number |
160
+ | `next` | `() => void` | Navigate to the next page |
161
+ | `prev` | `() => void` | Navigate to the previous page |
162
+ | `first` | `() => void` | Navigate to the first page |
163
+ | `last` | `() => void` | Navigate to the last page |
164
+
165
+ ### `PaginationPageItem` Type
166
+
167
+ ```typescript
168
+ type PaginationPageItem =
169
+ | { type: 'page'; page: number }
170
+ | { type: 'ellipsis'; key: string };
171
+ ```
172
+
173
+ The `items` array is ready to render directly — map over it and render `<PaginationLink>` for `type: 'page'` items and `<PaginationEllipsis>` for `type: 'ellipsis'` items.
174
+
175
+ ### Uncontrolled Example
176
+
177
+ ```tsx
178
+ import {
179
+ usePagination,
180
+ Pagination,
181
+ PaginationContent,
182
+ PaginationItem,
183
+ PaginationLink,
184
+ PaginationPrevious,
185
+ PaginationNext,
186
+ PaginationEllipsis,
187
+ } from 'xertica-ui/ui';
188
+
189
+ function MyTable({ data }: { data: Record<string, unknown>[] }) {
190
+ const {
191
+ currentPage,
192
+ totalPages,
193
+ startIndex,
194
+ endIndex,
195
+ canGoPrev,
196
+ canGoNext,
197
+ items,
198
+ next,
199
+ prev,
200
+ } = usePagination({ totalItems: data.length, pageSize: 10 });
201
+
202
+ const pageData = data.slice(startIndex, endIndex);
203
+
204
+ return (
205
+ <div className="space-y-4">
206
+ <table>
207
+ {/* render pageData rows */}
208
+ </table>
209
+
210
+ <Pagination>
211
+ <PaginationContent>
212
+ <PaginationItem>
213
+ <PaginationPrevious onClick={prev} aria-disabled={!canGoPrev} />
214
+ </PaginationItem>
215
+
216
+ {items.map((item) =>
217
+ item.type === 'ellipsis' ? (
218
+ <PaginationItem key={item.key}>
219
+ <PaginationEllipsis />
220
+ </PaginationItem>
221
+ ) : (
222
+ <PaginationItem key={item.page}>
223
+ <PaginationLink
224
+ isActive={item.page === currentPage}
225
+ onClick={() => goTo(item.page)}
226
+ >
227
+ {item.page}
228
+ </PaginationLink>
229
+ </PaginationItem>
230
+ )
231
+ )}
232
+
233
+ <PaginationItem>
234
+ <PaginationNext onClick={next} aria-disabled={!canGoNext} />
235
+ </PaginationItem>
236
+ </PaginationContent>
237
+ </Pagination>
238
+ </div>
239
+ );
240
+ }
241
+ ```
242
+
243
+ ### Controlled Example (API-driven pagination)
244
+
245
+ ```tsx
246
+ import { usePagination } from 'xertica-ui/ui';
247
+ import { useState } from 'react';
248
+
249
+ function ServerPaginatedTable({ totalItems }: { totalItems: number }) {
250
+ const [page, setPage] = useState(1);
251
+
252
+ const { items, canGoPrev, canGoNext, next, prev, goTo, currentPage } =
253
+ usePagination({
254
+ totalItems,
255
+ pageSize: 20,
256
+ page, // controlled
257
+ onPageChange: setPage,
258
+ });
259
+
260
+ // fetch data for `page` from your API...
261
+
262
+ return (
263
+ <Pagination>
264
+ <PaginationContent>
265
+ <PaginationItem>
266
+ <PaginationPrevious onClick={prev} aria-disabled={!canGoPrev} />
267
+ </PaginationItem>
268
+ {items.map((item) =>
269
+ item.type === 'ellipsis' ? (
270
+ <PaginationItem key={item.key}><PaginationEllipsis /></PaginationItem>
271
+ ) : (
272
+ <PaginationItem key={item.page}>
273
+ <PaginationLink
274
+ isActive={item.page === currentPage}
275
+ onClick={() => goTo(item.page)}
276
+ >
277
+ {item.page}
278
+ </PaginationLink>
279
+ </PaginationItem>
280
+ )
281
+ )}
282
+ <PaginationItem>
283
+ <PaginationNext onClick={next} aria-disabled={!canGoNext} />
284
+ </PaginationItem>
285
+ </PaginationContent>
286
+ </Pagination>
287
+ );
288
+ }
289
+ ```
290
+
291
+ ---
292
+
111
293
  ## AI Rules
112
294
 
113
295
  - Place Pagination below the `<Table>` inside the same `<Card>` wrapping both.
114
296
  - Use `isActive` on the currently selected page link.
115
297
  - For controlled pagination (API-driven), use `onClick` instead of `href` on `PaginationLink`.
298
+ - When using `usePagination`, use `startIndex` and `endIndex` to slice client-side data arrays: `data.slice(startIndex, endIndex)`.
299
+ - For server-side pagination, pass `page` and `onPageChange` to `usePagination` to use controlled mode — the hook will not manage internal state.
300
+ - Always render `PaginationEllipsis` for `item.type === 'ellipsis'` items from the `items` array — never skip them.
301
+ - `totalItems` is the count of **all** records, not just the current page.
302
+ - Pages are **1-indexed** — the first page is `1`, not `0`.
116
303
 
117
304
  ---
118
305