@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.4 → 0.1.5

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 (164) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/index.d.ts +131 -131
  3. package/dist/index.esm.js +148 -148
  4. package/dist/index.js +148 -148
  5. package/dist/styles.css +1 -1
  6. package/package.json +1 -1
  7. package/src/components/ui/accessibility-demo.tsx +271 -0
  8. package/src/components/ui/advanced-component-architecture-demo.tsx +916 -0
  9. package/src/components/ui/advanced-transition-system-demo.tsx +670 -0
  10. package/src/components/ui/advanced-transition-system.tsx +395 -0
  11. package/src/components/ui/animation/animated-container.tsx +166 -0
  12. package/src/components/ui/animation/index.ts +19 -0
  13. package/src/components/ui/animation/staggered-container.tsx +68 -0
  14. package/src/components/ui/animation-demo.tsx +250 -0
  15. package/src/components/ui/badge.tsx +33 -0
  16. package/src/components/ui/battery-conscious-animation-demo.tsx +568 -0
  17. package/src/components/ui/border-radius-shadow-demo.tsx +187 -0
  18. package/src/components/ui/button.tsx +36 -0
  19. package/src/components/ui/card.tsx +207 -0
  20. package/src/components/ui/checkbox.tsx +30 -0
  21. package/src/components/ui/color-preview.tsx +411 -0
  22. package/src/components/ui/data-display/chart.tsx +653 -0
  23. package/src/components/ui/data-display/data-grid-simple.tsx +76 -0
  24. package/src/components/ui/data-display/data-grid.tsx +680 -0
  25. package/src/components/ui/data-display/list.tsx +456 -0
  26. package/src/components/ui/data-display/table.tsx +482 -0
  27. package/src/components/ui/data-display/timeline.tsx +441 -0
  28. package/src/components/ui/data-display/tree.tsx +602 -0
  29. package/src/components/ui/data-display/types.ts +536 -0
  30. package/src/components/ui/enterprise-mobile-experience-demo.tsx +749 -0
  31. package/src/components/ui/enterprise-mobile-experience.tsx +464 -0
  32. package/src/components/ui/feedback/alert.tsx +157 -0
  33. package/src/components/ui/feedback/progress.tsx +292 -0
  34. package/src/components/ui/feedback/skeleton.tsx +185 -0
  35. package/src/components/ui/feedback/toast.tsx +280 -0
  36. package/src/components/ui/feedback/types.ts +125 -0
  37. package/src/components/ui/font-preview.tsx +288 -0
  38. package/src/components/ui/form-demo.tsx +553 -0
  39. package/src/components/ui/hardware-acceleration-demo.tsx +547 -0
  40. package/src/components/ui/input.tsx +35 -0
  41. package/src/components/ui/label.tsx +16 -0
  42. package/src/components/ui/layout-demo.tsx +367 -0
  43. package/src/components/ui/layouts/adaptive-layout.tsx +139 -0
  44. package/src/components/ui/layouts/desktop-layout.tsx +224 -0
  45. package/src/components/ui/layouts/index.ts +10 -0
  46. package/src/components/ui/layouts/mobile-layout.tsx +162 -0
  47. package/src/components/ui/layouts/tablet-layout.tsx +197 -0
  48. package/src/components/ui/mobile-form-validation.tsx +451 -0
  49. package/src/components/ui/mobile-input-demo.tsx +201 -0
  50. package/src/components/ui/mobile-input.tsx +281 -0
  51. package/src/components/ui/mobile-skeleton-loading-demo.tsx +638 -0
  52. package/src/components/ui/navigation/breadcrumb.tsx +158 -0
  53. package/src/components/ui/navigation/index.ts +36 -0
  54. package/src/components/ui/navigation/menu.tsx +374 -0
  55. package/src/components/ui/navigation/navigation-demo.tsx +324 -0
  56. package/src/components/ui/navigation/pagination.tsx +272 -0
  57. package/src/components/ui/navigation/sidebar.tsx +383 -0
  58. package/src/components/ui/navigation/stepper.tsx +303 -0
  59. package/src/components/ui/navigation/tabs.tsx +205 -0
  60. package/src/components/ui/navigation/types.ts +299 -0
  61. package/src/components/ui/overlay/backdrop.tsx +81 -0
  62. package/src/components/ui/overlay/focus-manager.tsx +143 -0
  63. package/src/components/ui/overlay/index.ts +36 -0
  64. package/src/components/ui/overlay/modal.tsx +270 -0
  65. package/src/components/ui/overlay/overlay-manager.tsx +110 -0
  66. package/src/components/ui/overlay/popover.tsx +462 -0
  67. package/src/components/ui/overlay/portal.tsx +79 -0
  68. package/src/components/ui/overlay/tooltip.tsx +303 -0
  69. package/src/components/ui/overlay/types.ts +196 -0
  70. package/src/components/ui/performance-demo.tsx +596 -0
  71. package/src/components/ui/semantic-input-system-demo.tsx +502 -0
  72. package/src/components/ui/semantic-input-system-demo.tsx.disabled +873 -0
  73. package/src/components/ui/tablet-layout.tsx +192 -0
  74. package/src/components/ui/theme-customizer.tsx +386 -0
  75. package/src/components/ui/theme-preview.tsx +310 -0
  76. package/src/components/ui/theme-switcher.tsx +264 -0
  77. package/src/components/ui/theme-toggle.tsx +38 -0
  78. package/src/components/ui/token-demo.tsx +195 -0
  79. package/src/components/ui/touch-demo.tsx +462 -0
  80. package/src/components/ui/touch-friendly-interface-demo.tsx +519 -0
  81. package/src/components/ui/touch-friendly-interface.tsx +296 -0
  82. package/src/hooks/index.ts +190 -0
  83. package/src/hooks/use-accessibility-support.ts +518 -0
  84. package/src/hooks/use-adaptive-layout.ts +289 -0
  85. package/src/hooks/use-advanced-patterns.ts +294 -0
  86. package/src/hooks/use-advanced-transition-system.ts +393 -0
  87. package/src/hooks/use-animation-profile.ts +288 -0
  88. package/src/hooks/use-battery-animations.ts +384 -0
  89. package/src/hooks/use-battery-conscious-loading.ts +475 -0
  90. package/src/hooks/use-battery-optimization.ts +330 -0
  91. package/src/hooks/use-battery-status.ts +299 -0
  92. package/src/hooks/use-component-performance.ts +344 -0
  93. package/src/hooks/use-device-loading-states.ts +459 -0
  94. package/src/hooks/use-device.tsx +110 -0
  95. package/src/hooks/use-enterprise-mobile-experience.ts +488 -0
  96. package/src/hooks/use-form-feedback.ts +403 -0
  97. package/src/hooks/use-form-performance.ts +513 -0
  98. package/src/hooks/use-frame-rate.ts +251 -0
  99. package/src/hooks/use-gestures.ts +338 -0
  100. package/src/hooks/use-hardware-acceleration.ts +341 -0
  101. package/src/hooks/use-input-accessibility.ts +455 -0
  102. package/src/hooks/use-input-performance.ts +506 -0
  103. package/src/hooks/use-layout-performance.ts +319 -0
  104. package/src/hooks/use-loading-accessibility.ts +535 -0
  105. package/src/hooks/use-loading-performance.ts +473 -0
  106. package/src/hooks/use-memory-usage.ts +287 -0
  107. package/src/hooks/use-mobile-form-layout.ts +464 -0
  108. package/src/hooks/use-mobile-form-validation.ts +518 -0
  109. package/src/hooks/use-mobile-keyboard-optimization.ts +472 -0
  110. package/src/hooks/use-mobile-layout.ts +302 -0
  111. package/src/hooks/use-mobile-optimization.ts +406 -0
  112. package/src/hooks/use-mobile-skeleton.ts +402 -0
  113. package/src/hooks/use-mobile-touch.ts +414 -0
  114. package/src/hooks/use-performance-throttling.ts +348 -0
  115. package/src/hooks/use-performance.ts +316 -0
  116. package/src/hooks/use-reusable-architecture.ts +414 -0
  117. package/src/hooks/use-semantic-input-types.ts +357 -0
  118. package/src/hooks/use-semantic-input.ts +565 -0
  119. package/src/hooks/use-tablet-layout.ts +384 -0
  120. package/src/hooks/use-touch-friendly-input.ts +524 -0
  121. package/src/hooks/use-touch-friendly-interface.ts +331 -0
  122. package/src/hooks/use-touch-optimization.ts +375 -0
  123. package/src/index.ts +279 -279
  124. package/src/lib/utils.ts +6 -0
  125. package/src/themes/README.md +272 -0
  126. package/src/themes/ThemeContext.tsx +31 -0
  127. package/src/themes/ThemeProvider.tsx +232 -0
  128. package/src/themes/accessibility/index.ts +27 -0
  129. package/src/themes/accessibility.ts +259 -0
  130. package/src/themes/aria-patterns.ts +420 -0
  131. package/src/themes/base-themes.ts +55 -0
  132. package/src/themes/colorManager.ts +380 -0
  133. package/src/themes/examples/dark-theme.ts +154 -0
  134. package/src/themes/examples/minimal-theme.ts +108 -0
  135. package/src/themes/focus-management.ts +701 -0
  136. package/src/themes/fontLoader.ts +201 -0
  137. package/src/themes/high-contrast.ts +621 -0
  138. package/src/themes/index.ts +19 -0
  139. package/src/themes/inheritance.ts +227 -0
  140. package/src/themes/keyboard-navigation.ts +550 -0
  141. package/src/themes/motion-reduction.ts +662 -0
  142. package/src/themes/navigation.ts +238 -0
  143. package/src/themes/screen-reader.ts +645 -0
  144. package/src/themes/systemThemeDetector.ts +182 -0
  145. package/src/themes/themeCSSUpdater.ts +262 -0
  146. package/src/themes/themePersistence.ts +238 -0
  147. package/src/themes/themes/default.ts +586 -0
  148. package/src/themes/themes/harvey.ts +554 -0
  149. package/src/themes/themes/stan-design.ts +683 -0
  150. package/src/themes/types.ts +460 -0
  151. package/src/themes/useSystemTheme.ts +48 -0
  152. package/src/themes/useTheme.ts +87 -0
  153. package/src/themes/validation.ts +462 -0
  154. package/src/tokens/index.ts +34 -0
  155. package/src/tokens/tokenExporter.ts +397 -0
  156. package/src/tokens/tokenGenerator.ts +276 -0
  157. package/src/tokens/tokenManager.ts +248 -0
  158. package/src/tokens/tokenValidator.ts +543 -0
  159. package/src/tokens/types.ts +78 -0
  160. package/src/utils/bundle-analyzer.ts +260 -0
  161. package/src/utils/bundle-splitting.ts +483 -0
  162. package/src/utils/lazy-loading.ts +441 -0
  163. package/src/utils/performance-monitor.ts +513 -0
  164. package/src/utils/tree-shaking.ts +274 -0
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Navigation Components Demo
3
+ * Showcases all navigation components with different themes and configurations
4
+ */
5
+
6
+ import * as React from 'react';
7
+ import { useState } from 'react';
8
+ import { Breadcrumb } from './breadcrumb';
9
+ import { Tabs } from './tabs';
10
+ import { Menu } from './menu';
11
+ import { Sidebar } from './sidebar';
12
+ import { Stepper } from './stepper';
13
+ import { Pagination } from './pagination';
14
+ import { NavigationItem, NavigationGroup } from './types';
15
+
16
+ export const NavigationDemo: React.FC = () => {
17
+ const [currentTab, setCurrentTab] = useState('overview');
18
+ const [currentStep, setCurrentStep] = useState(0);
19
+ const [currentPage, setCurrentPage] = useState(1);
20
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
21
+ // const [menuOpen, setMenuOpen] = useState(false);
22
+
23
+ // Sample data for components
24
+ const breadcrumbItems = [
25
+ { id: 'home', label: 'Home', href: '/' },
26
+ { id: 'products', label: 'Products', href: '/products' },
27
+ { id: 'electronics', label: 'Electronics', href: '/products/electronics' },
28
+ { id: 'smartphones', label: 'Smartphones', href: '/products/electronics/smartphones' },
29
+ ];
30
+
31
+ const tabItems = [
32
+ {
33
+ id: 'overview',
34
+ label: 'Overview',
35
+ content: (
36
+ <div className="p-4">
37
+ <h3 className="text-lg font-semibold mb-2">Overview Tab</h3>
38
+ <p className="text-gray-600">This is the overview content with some sample text.</p>
39
+ </div>
40
+ ),
41
+ },
42
+ {
43
+ id: 'details',
44
+ label: 'Details',
45
+ content: (
46
+ <div className="p-4">
47
+ <h3 className="text-lg font-semibold mb-2">Details Tab</h3>
48
+ <p className="text-gray-600">Detailed information goes here.</p>
49
+ </div>
50
+ ),
51
+ },
52
+ {
53
+ id: 'settings',
54
+ label: 'Settings',
55
+ content: (
56
+ <div className="p-4">
57
+ <h3 className="text-lg font-semibold mb-2">Settings Tab</h3>
58
+ <p className="text-gray-600">Configuration options and settings.</p>
59
+ </div>
60
+ ),
61
+ },
62
+ ];
63
+
64
+ const stepperSteps = [
65
+ {
66
+ id: 'step1',
67
+ label: 'Account Setup',
68
+ description: 'Create your account and verify email',
69
+ status: 'completed' as const,
70
+ },
71
+ {
72
+ id: 'step2',
73
+ label: 'Profile Information',
74
+ description: 'Fill in your personal details',
75
+ status: 'active' as const,
76
+ },
77
+ {
78
+ id: 'step3',
79
+ label: 'Preferences',
80
+ description: 'Configure your account preferences',
81
+ status: 'pending' as const,
82
+ },
83
+ {
84
+ id: 'step4',
85
+ label: 'Review & Confirm',
86
+ description: 'Review your information and confirm',
87
+ status: 'pending' as const,
88
+ },
89
+ ];
90
+
91
+ const menuItems: NavigationItem[] = [
92
+ {
93
+ id: 'dashboard',
94
+ label: 'Dashboard',
95
+ description: 'Main dashboard view',
96
+ icon: '📊',
97
+ },
98
+ {
99
+ id: 'analytics',
100
+ label: 'Analytics',
101
+ description: 'View detailed analytics',
102
+ icon: '📈',
103
+ },
104
+ {
105
+ id: 'reports',
106
+ label: 'Reports',
107
+ description: 'Generate and view reports',
108
+ icon: '📋',
109
+ },
110
+ {
111
+ id: 'settings',
112
+ label: 'Settings',
113
+ description: 'Configure your account',
114
+ icon: '⚙️',
115
+ },
116
+ ];
117
+
118
+ const sidebarItems: NavigationItem[] = [
119
+ {
120
+ id: 'dashboard',
121
+ label: 'Dashboard',
122
+ icon: '📊',
123
+ active: true,
124
+ },
125
+ {
126
+ id: 'analytics',
127
+ label: 'Analytics',
128
+ icon: '📈',
129
+ },
130
+ {
131
+ id: 'reports',
132
+ label: 'Reports',
133
+ icon: '📋',
134
+ },
135
+ {
136
+ id: 'settings',
137
+ label: 'Settings',
138
+ icon: '⚙️',
139
+ },
140
+ ];
141
+
142
+ const sidebarGroups: NavigationGroup[] = [
143
+ {
144
+ id: 'management',
145
+ title: 'Management',
146
+ items: [
147
+ { id: 'users', label: 'Users', icon: '👥' },
148
+ { id: 'roles', label: 'Roles', icon: '🔐' },
149
+ { id: 'permissions', label: 'Permissions', icon: '🔑' },
150
+ ],
151
+ },
152
+ {
153
+ id: 'content',
154
+ title: 'Content',
155
+ items: [
156
+ { id: 'articles', label: 'Articles', icon: '📝' },
157
+ { id: 'media', label: 'Media', icon: '🖼️' },
158
+ { id: 'comments', label: 'Comments', icon: '💬' },
159
+ ],
160
+ },
161
+ ];
162
+
163
+ // const getThemeClasses = () => {
164
+ // return 'navigation-demo navigation-demo--stan-design';
165
+ // };
166
+
167
+ return (
168
+ <div className="space-y-8 p-6">
169
+ <div className="text-center">
170
+ <h1 className="text-3xl font-bold text-gray-900 mb-2">Navigation Components Demo</h1>
171
+ <p className="text-gray-600">Showcasing all navigation components with Stan Design theme</p>
172
+ </div>
173
+
174
+ {/* Breadcrumb Component */}
175
+ <div className="p-6">
176
+ <h2 className="text-xl font-semibold mb-4">Breadcrumb Component</h2>
177
+ <div className="space-y-4">
178
+ <Breadcrumb
179
+ items={breadcrumbItems}
180
+ onItemClick={(item) => console.log('Breadcrumb clicked:', item)}
181
+ />
182
+ <Breadcrumb
183
+ items={breadcrumbItems}
184
+ maxItems={3}
185
+ truncate={true}
186
+ />
187
+ </div>
188
+ </div>
189
+
190
+ {/* Pagination Component */}
191
+ <div className="p-6">
192
+ <h2 className="text-xl font-semibold mb-4">Pagination Component</h2>
193
+ <div className="space-y-4">
194
+ <Pagination
195
+ currentPage={currentPage}
196
+ totalPages={20}
197
+ totalItems={200}
198
+ onPageChange={setCurrentPage}
199
+ />
200
+ <Pagination
201
+ currentPage={currentPage}
202
+ totalPages={20}
203
+ variant="outlined"
204
+ size="sm"
205
+ showItemsPerPage={true}
206
+ showTotal={true}
207
+ onPageChange={setCurrentPage}
208
+ />
209
+ </div>
210
+ </div>
211
+
212
+ {/* Tabs Component */}
213
+ <div className="p-6">
214
+ <h2 className="text-xl font-semibold mb-4">Tabs Component</h2>
215
+ <div className="space-y-6">
216
+ <Tabs
217
+ tabs={tabItems}
218
+ activeTab={currentTab}
219
+ onTabChange={setCurrentTab}
220
+ variant="default"
221
+ />
222
+ <Tabs
223
+ tabs={tabItems}
224
+ activeTab={currentTab}
225
+ onTabChange={setCurrentTab}
226
+ variant="pills"
227
+ />
228
+ <Tabs
229
+ tabs={tabItems}
230
+ activeTab={currentTab}
231
+ onTabChange={setCurrentTab}
232
+ variant="underline"
233
+ />
234
+ </div>
235
+ </div>
236
+
237
+ {/* Stepper Component */}
238
+ <div className="p-6">
239
+ <h2 className="text-xl font-semibold mb-4">Stepper Component</h2>
240
+ <div className="space-y-6">
241
+ <Stepper
242
+ steps={stepperSteps}
243
+ currentStep={currentStep}
244
+ onStepChange={setCurrentStep}
245
+ variant="horizontal"
246
+ />
247
+ <Stepper
248
+ steps={stepperSteps}
249
+ currentStep={currentStep}
250
+ onStepChange={setCurrentStep}
251
+ variant="vertical"
252
+ />
253
+ </div>
254
+ </div>
255
+
256
+ {/* Menu Component */}
257
+ <div className="p-6">
258
+ <h2 className="text-xl font-semibold mb-4">Menu Component</h2>
259
+ <div className="space-y-4">
260
+ <Menu
261
+ items={menuItems}
262
+ variant="dropdown"
263
+ searchable={true}
264
+ selectable={true}
265
+ multiSelect={true}
266
+ selectedItems={[]} // No selected items for this demo
267
+ onSelectionChange={() => {}}
268
+ />
269
+ <Menu
270
+ items={menuItems}
271
+ variant="command"
272
+ />
273
+ </div>
274
+ </div>
275
+
276
+ {/* Sidebar Component */}
277
+ <div className="p-6">
278
+ <h2 className="text-xl font-semibold mb-4">Sidebar Component</h2>
279
+ <div className="flex space-x-4">
280
+ <div className="h-96">
281
+ <Sidebar
282
+ items={sidebarItems}
283
+ collapsed={sidebarCollapsed}
284
+ onCollapseChange={setSidebarCollapsed}
285
+ collapsible={true}
286
+ showToggle={true}
287
+ header={<div className="font-semibold text-lg">Navigation</div>}
288
+ footer={<div className="text-sm text-gray-500">v1.0.0</div>}
289
+ />
290
+ </div>
291
+ <div className="h-96">
292
+ <Sidebar
293
+ items={sidebarItems}
294
+ groups={sidebarGroups}
295
+ variant="collapsible"
296
+ size="lg"
297
+ />
298
+ </div>
299
+ </div>
300
+ </div>
301
+
302
+ {/* Theme Information */}
303
+ <div className="p-6">
304
+ <h2 className="text-xl font-semibold mb-4">Current Theme: Stan Design</h2>
305
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
306
+ <div className="text-center p-4 bg-gray-50 rounded-lg">
307
+ <h3 className="font-medium text-gray-900">Stan Design</h3>
308
+ <p className="text-sm text-gray-600">Default theme with gray tones</p>
309
+ </div>
310
+ <div className="text-center p-4 bg-blue-50 rounded-lg">
311
+ <h3 className="font-medium text-blue-900">Enterprise</h3>
312
+ <p className="text-sm text-blue-600">Professional blue theme</p>
313
+ </div>
314
+ <div className="text-center p-4 bg-purple-50 rounded-lg">
315
+ <h3 className="font-medium text-purple-900">Harvey</h3>
316
+ <p className="text-sm text-purple-600">Creative purple theme</p>
317
+ </div>
318
+ </div>
319
+ </div>
320
+ </div>
321
+ );
322
+ };
323
+
324
+ export default NavigationDemo;
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Pagination Component
3
+ * Provides comprehensive pagination with theme support and responsive design
4
+ */
5
+
6
+ import * as React from 'react';
7
+ import { useMemo } from 'react';
8
+ import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
9
+ import { PaginationProps, PaginationItem } from './types';
10
+
11
+ // Simple icon components
12
+ const ChevronDoubleLeftIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
13
+ <svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
14
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
15
+ </svg>
16
+ );
17
+
18
+ const ChevronDoubleRightIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
19
+ <svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
20
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 5l7 7-7 7m-8-14l7 7-7 7" />
21
+ </svg>
22
+ );
23
+
24
+ export const Pagination: React.FC<PaginationProps> = ({
25
+ currentPage = 1,
26
+ totalPages = 1,
27
+ totalItems,
28
+ itemsPerPage = 10,
29
+ showFirstLast = true,
30
+ showPrevNext = true,
31
+ showPageNumbers = true,
32
+ maxPageNumbers = 5,
33
+ size = 'md',
34
+ variant = 'default',
35
+ onPageChange,
36
+ onItemsPerPageChange,
37
+ itemsPerPageOptions = [10, 25, 50, 100],
38
+ showItemsPerPage = false,
39
+ showTotal = false,
40
+ totalLabel = 'Total',
41
+ disabled = false,
42
+ loading = false,
43
+ className = '',
44
+ 'data-testid': testId = 'pagination',
45
+ }) => {
46
+ // Memoize pagination items to avoid unnecessary recalculations
47
+ const paginationItems = useMemo((): PaginationItem[] => {
48
+ const items: PaginationItem[] = [];
49
+
50
+ if (showFirstLast) {
51
+ items.push({
52
+ type: 'first',
53
+ page: 1,
54
+ disabled: currentPage === 1 || disabled,
55
+ label: 'First',
56
+ onClick: () => onPageChange(1),
57
+ });
58
+ }
59
+
60
+ if (showPrevNext) {
61
+ items.push({
62
+ type: 'previous',
63
+ page: currentPage - 1,
64
+ disabled: currentPage === 1 || disabled,
65
+ label: 'Previous',
66
+ onClick: () => onPageChange(currentPage - 1),
67
+ });
68
+ }
69
+
70
+ if (showPageNumbers) {
71
+ const pageNumbers = generatePageNumbers(currentPage, totalPages, maxPageNumbers);
72
+
73
+ pageNumbers.forEach((pageNum) => {
74
+ if (pageNum === 'ellipsis') {
75
+ items.push({
76
+ type: 'ellipsis',
77
+ label: '...',
78
+ disabled: true,
79
+ });
80
+ } else {
81
+ items.push({
82
+ type: 'page',
83
+ page: pageNum as number,
84
+ active: pageNum === currentPage,
85
+ disabled: disabled,
86
+ label: pageNum.toString(),
87
+ onClick: () => onPageChange(pageNum as number),
88
+ });
89
+ }
90
+ });
91
+ }
92
+
93
+ if (showPrevNext) {
94
+ items.push({
95
+ type: 'next',
96
+ page: currentPage + 1,
97
+ disabled: currentPage === totalPages || disabled,
98
+ label: 'Next',
99
+ onClick: () => onPageChange(currentPage + 1),
100
+ });
101
+ }
102
+
103
+ if (showFirstLast) {
104
+ items.push({
105
+ type: 'last',
106
+ page: totalPages,
107
+ disabled: currentPage === totalPages || disabled,
108
+ label: 'Last',
109
+ onClick: () => onPageChange(totalPages),
110
+ });
111
+ }
112
+
113
+ return items;
114
+ }, [currentPage, totalPages, maxPageNumbers, showFirstLast, showPrevNext, showPageNumbers, disabled, onPageChange]);
115
+
116
+
117
+
118
+ function generatePageNumbers(current: number, total: number, max: number): (number | 'ellipsis')[] {
119
+ if (total <= max) {
120
+ return Array.from({ length: total }, (_, i) => i + 1);
121
+ }
122
+
123
+ const half = Math.floor(max / 2);
124
+ const start = Math.max(1, current - half);
125
+ const end = Math.min(total, start + max - 1);
126
+
127
+ const numbers: (number | 'ellipsis')[] = [];
128
+
129
+ if (start > 1) {
130
+ numbers.push(1);
131
+ if (start > 2) numbers.push('ellipsis');
132
+ }
133
+
134
+ for (let i = start; i <= end; i++) {
135
+ numbers.push(i);
136
+ }
137
+
138
+ if (end < total) {
139
+ if (end < total - 1) numbers.push('ellipsis');
140
+ numbers.push(total);
141
+ }
142
+
143
+ return numbers;
144
+ }
145
+
146
+ const getSizeClasses = () => {
147
+ switch (size) {
148
+ case 'sm':
149
+ return 'pagination__button--sm';
150
+ case 'lg':
151
+ return 'pagination__button--lg';
152
+ default: // md
153
+ return 'pagination__button--md';
154
+ }
155
+ };
156
+
157
+ const getVariantClasses = () => {
158
+ switch (variant) {
159
+ case 'outlined':
160
+ return 'pagination__button--outlined';
161
+ case 'minimal':
162
+ return 'pagination__button--minimal';
163
+ default: // default
164
+ return 'pagination__button--default';
165
+ }
166
+ };
167
+
168
+ const getThemeClasses = () => {
169
+ return 'pagination pagination--stan-design';
170
+ };
171
+
172
+ const getButtonClasses = (item: PaginationItem) => {
173
+ let classes = `pagination__button ${getSizeClasses()} ${getVariantClasses()}`;
174
+
175
+ if (item.disabled) {
176
+ classes += ' pagination__button--disabled';
177
+ } else if (item.active) {
178
+ classes += ' pagination__button--active';
179
+ } else {
180
+ classes += ' pagination__button--inactive';
181
+ }
182
+
183
+ return classes;
184
+ };
185
+
186
+ const handleItemsPerPageChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
187
+ const newItemsPerPage = parseInt(event.target.value, 10);
188
+ if (onItemsPerPageChange) {
189
+ onItemsPerPageChange(newItemsPerPage);
190
+ }
191
+ };
192
+
193
+ if (totalPages <= 1 && !showItemsPerPage && !showTotal) {
194
+ return null;
195
+ }
196
+
197
+ return (
198
+ <div className={`pagination__container ${getThemeClasses()} ${className}`} data-testid={testId}>
199
+ {/* Left side - Items per page and total */}
200
+ <div className="pagination__info">
201
+ {showItemsPerPage && (
202
+ <div className="pagination__items-per-page">
203
+ <label htmlFor="items-per-page" className="pagination__label">
204
+ Items per page:
205
+ </label>
206
+ <select
207
+ id="items-per-page"
208
+ value={itemsPerPage}
209
+ onChange={handleItemsPerPageChange}
210
+ disabled={disabled || loading}
211
+ className="pagination__select"
212
+ >
213
+ {itemsPerPageOptions.map((option) => (
214
+ <option key={option} value={option}>
215
+ {option}
216
+ </option>
217
+ ))}
218
+ </select>
219
+ </div>
220
+ )}
221
+
222
+ {showTotal && totalItems !== undefined && (
223
+ <div className="pagination__total">
224
+ {totalLabel}: <span className="pagination__total-count">{totalItems.toLocaleString()}</span>
225
+ </div>
226
+ )}
227
+ </div>
228
+
229
+ {/* Center - Page numbers */}
230
+ <div className="pagination__navigation">
231
+ {paginationItems.map((item, index) => {
232
+ if (item.type === 'ellipsis') {
233
+ return (
234
+ <span
235
+ key={`ellipsis-${index}`}
236
+ className="pagination__ellipsis"
237
+ aria-hidden="true"
238
+ >
239
+ {item.label}
240
+ </span>
241
+ );
242
+ }
243
+
244
+ const icon = item.type === 'first' ? <ChevronDoubleLeftIcon className="pagination__button-icon" /> :
245
+ item.type === 'previous' ? <ChevronLeftIcon className="pagination__button-icon" /> :
246
+ item.type === 'next' ? <ChevronRightIcon className="pagination__button-icon" /> :
247
+ item.type === 'last' ? <ChevronDoubleRightIcon className="pagination__button-icon" /> : null;
248
+
249
+ return (
250
+ <button
251
+ key={`${item.type}-${item.page || index}`}
252
+ onClick={item.onClick}
253
+ disabled={item.disabled}
254
+ className={getButtonClasses(item)}
255
+ aria-label={item.label}
256
+ aria-current={item.active ? 'page' : undefined}
257
+ >
258
+ {icon || item.label}
259
+ </button>
260
+ );
261
+ })}
262
+ </div>
263
+
264
+ {/* Right side - Page info */}
265
+ <div className="pagination__status">
266
+ {`Page ${currentPage} of ${totalPages}`}
267
+ </div>
268
+ </div>
269
+ );
270
+ };
271
+
272
+ export default Pagination;