@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.3 → 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.
- package/CHANGELOG.md +1 -1
- package/dist/index.d.ts +131 -131
- package/dist/index.esm.js +148 -148
- package/dist/index.js +148 -148
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ui/accessibility-demo.tsx +271 -0
- package/src/components/ui/advanced-component-architecture-demo.tsx +916 -0
- package/src/components/ui/advanced-transition-system-demo.tsx +670 -0
- package/src/components/ui/advanced-transition-system.tsx +395 -0
- package/src/components/ui/animation/animated-container.tsx +166 -0
- package/src/components/ui/animation/index.ts +19 -0
- package/src/components/ui/animation/staggered-container.tsx +68 -0
- package/src/components/ui/animation-demo.tsx +250 -0
- package/src/components/ui/badge.tsx +33 -0
- package/src/components/ui/battery-conscious-animation-demo.tsx +568 -0
- package/src/components/ui/border-radius-shadow-demo.tsx +187 -0
- package/src/components/ui/button.tsx +36 -0
- package/src/components/ui/card.tsx +207 -0
- package/src/components/ui/checkbox.tsx +30 -0
- package/src/components/ui/color-preview.tsx +411 -0
- package/src/components/ui/data-display/chart.tsx +653 -0
- package/src/components/ui/data-display/data-grid-simple.tsx +76 -0
- package/src/components/ui/data-display/data-grid.tsx +680 -0
- package/src/components/ui/data-display/list.tsx +456 -0
- package/src/components/ui/data-display/table.tsx +482 -0
- package/src/components/ui/data-display/timeline.tsx +441 -0
- package/src/components/ui/data-display/tree.tsx +602 -0
- package/src/components/ui/data-display/types.ts +536 -0
- package/src/components/ui/enterprise-mobile-experience-demo.tsx +749 -0
- package/src/components/ui/enterprise-mobile-experience.tsx +464 -0
- package/src/components/ui/feedback/alert.tsx +157 -0
- package/src/components/ui/feedback/progress.tsx +292 -0
- package/src/components/ui/feedback/skeleton.tsx +185 -0
- package/src/components/ui/feedback/toast.tsx +280 -0
- package/src/components/ui/feedback/types.ts +125 -0
- package/src/components/ui/font-preview.tsx +288 -0
- package/src/components/ui/form-demo.tsx +553 -0
- package/src/components/ui/hardware-acceleration-demo.tsx +547 -0
- package/src/components/ui/input.tsx +35 -0
- package/src/components/ui/label.tsx +16 -0
- package/src/components/ui/layout-demo.tsx +367 -0
- package/src/components/ui/layouts/adaptive-layout.tsx +139 -0
- package/src/components/ui/layouts/desktop-layout.tsx +224 -0
- package/src/components/ui/layouts/index.ts +10 -0
- package/src/components/ui/layouts/mobile-layout.tsx +162 -0
- package/src/components/ui/layouts/tablet-layout.tsx +197 -0
- package/src/components/ui/mobile-form-validation.tsx +451 -0
- package/src/components/ui/mobile-input-demo.tsx +201 -0
- package/src/components/ui/mobile-input.tsx +281 -0
- package/src/components/ui/mobile-skeleton-loading-demo.tsx +638 -0
- package/src/components/ui/navigation/breadcrumb.tsx +158 -0
- package/src/components/ui/navigation/index.ts +36 -0
- package/src/components/ui/navigation/menu.tsx +374 -0
- package/src/components/ui/navigation/navigation-demo.tsx +324 -0
- package/src/components/ui/navigation/pagination.tsx +272 -0
- package/src/components/ui/navigation/sidebar.tsx +383 -0
- package/src/components/ui/navigation/stepper.tsx +303 -0
- package/src/components/ui/navigation/tabs.tsx +205 -0
- package/src/components/ui/navigation/types.ts +299 -0
- package/src/components/ui/overlay/backdrop.tsx +81 -0
- package/src/components/ui/overlay/focus-manager.tsx +143 -0
- package/src/components/ui/overlay/index.ts +36 -0
- package/src/components/ui/overlay/modal.tsx +270 -0
- package/src/components/ui/overlay/overlay-manager.tsx +110 -0
- package/src/components/ui/overlay/popover.tsx +462 -0
- package/src/components/ui/overlay/portal.tsx +79 -0
- package/src/components/ui/overlay/tooltip.tsx +303 -0
- package/src/components/ui/overlay/types.ts +196 -0
- package/src/components/ui/performance-demo.tsx +596 -0
- package/src/components/ui/semantic-input-system-demo.tsx +502 -0
- package/src/components/ui/semantic-input-system-demo.tsx.disabled +873 -0
- package/src/components/ui/tablet-layout.tsx +192 -0
- package/src/components/ui/theme-customizer.tsx +386 -0
- package/src/components/ui/theme-preview.tsx +310 -0
- package/src/components/ui/theme-switcher.tsx +264 -0
- package/src/components/ui/theme-toggle.tsx +38 -0
- package/src/components/ui/token-demo.tsx +195 -0
- package/src/components/ui/touch-demo.tsx +462 -0
- package/src/components/ui/touch-friendly-interface-demo.tsx +519 -0
- package/src/components/ui/touch-friendly-interface.tsx +296 -0
- package/src/hooks/index.ts +190 -0
- package/src/hooks/use-accessibility-support.ts +518 -0
- package/src/hooks/use-adaptive-layout.ts +289 -0
- package/src/hooks/use-advanced-patterns.ts +294 -0
- package/src/hooks/use-advanced-transition-system.ts +393 -0
- package/src/hooks/use-animation-profile.ts +288 -0
- package/src/hooks/use-battery-animations.ts +384 -0
- package/src/hooks/use-battery-conscious-loading.ts +475 -0
- package/src/hooks/use-battery-optimization.ts +330 -0
- package/src/hooks/use-battery-status.ts +299 -0
- package/src/hooks/use-component-performance.ts +344 -0
- package/src/hooks/use-device-loading-states.ts +459 -0
- package/src/hooks/use-device.tsx +110 -0
- package/src/hooks/use-enterprise-mobile-experience.ts +488 -0
- package/src/hooks/use-form-feedback.ts +403 -0
- package/src/hooks/use-form-performance.ts +513 -0
- package/src/hooks/use-frame-rate.ts +251 -0
- package/src/hooks/use-gestures.ts +338 -0
- package/src/hooks/use-hardware-acceleration.ts +341 -0
- package/src/hooks/use-input-accessibility.ts +455 -0
- package/src/hooks/use-input-performance.ts +506 -0
- package/src/hooks/use-layout-performance.ts +319 -0
- package/src/hooks/use-loading-accessibility.ts +535 -0
- package/src/hooks/use-loading-performance.ts +473 -0
- package/src/hooks/use-memory-usage.ts +287 -0
- package/src/hooks/use-mobile-form-layout.ts +464 -0
- package/src/hooks/use-mobile-form-validation.ts +518 -0
- package/src/hooks/use-mobile-keyboard-optimization.ts +472 -0
- package/src/hooks/use-mobile-layout.ts +302 -0
- package/src/hooks/use-mobile-optimization.ts +406 -0
- package/src/hooks/use-mobile-skeleton.ts +402 -0
- package/src/hooks/use-mobile-touch.ts +414 -0
- package/src/hooks/use-performance-throttling.ts +348 -0
- package/src/hooks/use-performance.ts +316 -0
- package/src/hooks/use-reusable-architecture.ts +414 -0
- package/src/hooks/use-semantic-input-types.ts +357 -0
- package/src/hooks/use-semantic-input.ts +565 -0
- package/src/hooks/use-tablet-layout.ts +384 -0
- package/src/hooks/use-touch-friendly-input.ts +524 -0
- package/src/hooks/use-touch-friendly-interface.ts +331 -0
- package/src/hooks/use-touch-optimization.ts +375 -0
- package/src/index.ts +279 -279
- package/src/lib/utils.ts +6 -0
- package/src/themes/README.md +272 -0
- package/src/themes/ThemeContext.tsx +31 -0
- package/src/themes/ThemeProvider.tsx +232 -0
- package/src/themes/accessibility/index.ts +27 -0
- package/src/themes/accessibility.ts +259 -0
- package/src/themes/aria-patterns.ts +420 -0
- package/src/themes/base-themes.ts +55 -0
- package/src/themes/colorManager.ts +380 -0
- package/src/themes/examples/dark-theme.ts +154 -0
- package/src/themes/examples/minimal-theme.ts +108 -0
- package/src/themes/focus-management.ts +701 -0
- package/src/themes/fontLoader.ts +201 -0
- package/src/themes/high-contrast.ts +621 -0
- package/src/themes/index.ts +19 -0
- package/src/themes/inheritance.ts +227 -0
- package/src/themes/keyboard-navigation.ts +550 -0
- package/src/themes/motion-reduction.ts +662 -0
- package/src/themes/navigation.ts +238 -0
- package/src/themes/screen-reader.ts +645 -0
- package/src/themes/systemThemeDetector.ts +182 -0
- package/src/themes/themeCSSUpdater.ts +262 -0
- package/src/themes/themePersistence.ts +238 -0
- package/src/themes/themes/default.ts +586 -0
- package/src/themes/themes/harvey.ts +554 -0
- package/src/themes/themes/stan-design.ts +683 -0
- package/src/themes/types.ts +460 -0
- package/src/themes/useSystemTheme.ts +48 -0
- package/src/themes/useTheme.ts +87 -0
- package/src/themes/validation.ts +462 -0
- package/src/tokens/index.ts +34 -0
- package/src/tokens/tokenExporter.ts +397 -0
- package/src/tokens/tokenGenerator.ts +276 -0
- package/src/tokens/tokenManager.ts +248 -0
- package/src/tokens/tokenValidator.ts +543 -0
- package/src/tokens/types.ts +78 -0
- package/src/utils/bundle-analyzer.ts +260 -0
- package/src/utils/bundle-splitting.ts +483 -0
- package/src/utils/lazy-loading.ts +441 -0
- package/src/utils/performance-monitor.ts +513 -0
- 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;
|