@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,195 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './card';
|
|
3
|
+
import { Badge } from './badge';
|
|
4
|
+
import { Button } from './button';
|
|
5
|
+
import { useTheme } from '../../themes';
|
|
6
|
+
import { createTokenManager } from '../../tokens';
|
|
7
|
+
|
|
8
|
+
export const TokenDemo: React.FC = () => {
|
|
9
|
+
const { currentTheme, currentThemeConfig } = useTheme();
|
|
10
|
+
const [tokenManager] = useState(() => createTokenManager());
|
|
11
|
+
const [exportFormat, setExportFormat] = useState<'json' | 'css' | 'scss' | 'js' | 'ts'>('json');
|
|
12
|
+
const [exportedTokens, setExportedTokens] = useState<string>('');
|
|
13
|
+
const [tokenStats, setTokenStats] = useState<any>(null);
|
|
14
|
+
|
|
15
|
+
const generateTokens = () => {
|
|
16
|
+
if (currentThemeConfig) {
|
|
17
|
+
const tokens = tokenManager.generateTokens(currentThemeConfig);
|
|
18
|
+
const stats = tokenManager.getTokenStats();
|
|
19
|
+
setTokenStats(stats);
|
|
20
|
+
return tokens;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const exportTokens = () => {
|
|
26
|
+
if (currentThemeConfig) {
|
|
27
|
+
const tokens = tokenManager.generateTokens(currentThemeConfig);
|
|
28
|
+
const exported = tokenManager.exportTokens(tokens, exportFormat);
|
|
29
|
+
setExportedTokens(exported);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const exportAllFormats = () => {
|
|
34
|
+
if (currentThemeConfig) {
|
|
35
|
+
const tokens = tokenManager.generateTokens(currentThemeConfig);
|
|
36
|
+
const allFormats = ['json', 'css', 'scss', 'js', 'ts'] as const;
|
|
37
|
+
const results = allFormats.map(format => ({
|
|
38
|
+
format,
|
|
39
|
+
content: tokenManager.exportTokens(tokens, format)
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
const combined = results.map(r => `=== ${r.format.toUpperCase()} ===\n${r.content}\n\n`).join('');
|
|
43
|
+
setExportedTokens(combined);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const clearTokens = () => {
|
|
48
|
+
tokenManager.clearTokens();
|
|
49
|
+
setTokenStats(null);
|
|
50
|
+
setExportedTokens('');
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div className="space-y-6">
|
|
55
|
+
<Card>
|
|
56
|
+
<CardHeader>
|
|
57
|
+
<CardTitle className="flex items-center gap-2">
|
|
58
|
+
🎨 Design Token System
|
|
59
|
+
<Badge variant="outline">Story 8</Badge>
|
|
60
|
+
</CardTitle>
|
|
61
|
+
<CardDescription>
|
|
62
|
+
Generate, validate, and export design tokens from your current theme
|
|
63
|
+
</CardDescription>
|
|
64
|
+
</CardHeader>
|
|
65
|
+
<CardContent className="space-y-4">
|
|
66
|
+
<div className="flex flex-wrap gap-2">
|
|
67
|
+
<Button onClick={generateTokens} variant="default">
|
|
68
|
+
Generate Tokens
|
|
69
|
+
</Button>
|
|
70
|
+
<Button onClick={exportTokens} variant="outline">
|
|
71
|
+
Export {exportFormat.toUpperCase()}
|
|
72
|
+
</Button>
|
|
73
|
+
<Button onClick={exportAllFormats} variant="outline">
|
|
74
|
+
Export All Formats
|
|
75
|
+
</Button>
|
|
76
|
+
<Button onClick={clearTokens} variant="destructive">
|
|
77
|
+
Clear Tokens
|
|
78
|
+
</Button>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div className="flex items-center gap-4">
|
|
82
|
+
<label className="text-sm font-medium">Export Format:</label>
|
|
83
|
+
<select
|
|
84
|
+
value={exportFormat}
|
|
85
|
+
onChange={(e) => setExportFormat(e.target.value as any)}
|
|
86
|
+
className="px-3 py-1 border rounded text-sm"
|
|
87
|
+
>
|
|
88
|
+
<option value="json">JSON</option>
|
|
89
|
+
<option value="css">CSS</option>
|
|
90
|
+
<option value="scss">SCSS</option>
|
|
91
|
+
<option value="js">JavaScript</option>
|
|
92
|
+
<option value="ts">TypeScript</option>
|
|
93
|
+
</select>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
{tokenStats && (
|
|
97
|
+
<div className="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
|
|
98
|
+
<h4 className="font-semibold mb-3">Token Statistics</h4>
|
|
99
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
|
|
100
|
+
<div>
|
|
101
|
+
<span className="font-medium">Total Themes:</span>
|
|
102
|
+
<div className="text-lg font-bold">{tokenStats.totalThemes}</div>
|
|
103
|
+
</div>
|
|
104
|
+
<div>
|
|
105
|
+
<span className="font-medium">Total Tokens:</span>
|
|
106
|
+
<div className="text-lg font-bold">{tokenStats.totalTokens}</div>
|
|
107
|
+
</div>
|
|
108
|
+
<div>
|
|
109
|
+
<span className="font-medium">Current Theme:</span>
|
|
110
|
+
<div className="text-lg font-bold">{currentTheme}</div>
|
|
111
|
+
</div>
|
|
112
|
+
<div>
|
|
113
|
+
<span className="font-medium">Theme Version:</span>
|
|
114
|
+
<div className="text-lg font-bold">{currentThemeConfig?.meta.version || 'N/A'}</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
{tokenStats.tokenBreakdown && (
|
|
119
|
+
<div className="mt-4">
|
|
120
|
+
<h5 className="font-medium mb-2">Token Breakdown:</h5>
|
|
121
|
+
<div className="flex flex-wrap gap-2">
|
|
122
|
+
{Object.entries(tokenStats.tokenBreakdown).map(([category, count]) => (
|
|
123
|
+
<Badge key={category} variant="secondary">
|
|
124
|
+
{category}: {count as number}
|
|
125
|
+
</Badge>
|
|
126
|
+
))}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
)}
|
|
130
|
+
</div>
|
|
131
|
+
)}
|
|
132
|
+
</CardContent>
|
|
133
|
+
</Card>
|
|
134
|
+
|
|
135
|
+
{exportedTokens && (
|
|
136
|
+
<Card>
|
|
137
|
+
<CardHeader>
|
|
138
|
+
<CardTitle>Exported Tokens</CardTitle>
|
|
139
|
+
<CardDescription>
|
|
140
|
+
Tokens exported in {exportFormat.toUpperCase()} format
|
|
141
|
+
</CardDescription>
|
|
142
|
+
</CardHeader>
|
|
143
|
+
<CardContent>
|
|
144
|
+
<div className="relative">
|
|
145
|
+
<Button
|
|
146
|
+
onClick={() => navigator.clipboard.writeText(exportedTokens)}
|
|
147
|
+
variant="outline"
|
|
148
|
+
size="sm"
|
|
149
|
+
className="absolute top-2 right-2"
|
|
150
|
+
>
|
|
151
|
+
Copy
|
|
152
|
+
</Button>
|
|
153
|
+
<pre className="bg-gray-900 text-green-400 p-4 rounded-lg text-sm overflow-x-auto max-h-96">
|
|
154
|
+
<code>{exportedTokens}</code>
|
|
155
|
+
</pre>
|
|
156
|
+
</div>
|
|
157
|
+
</CardContent>
|
|
158
|
+
</Card>
|
|
159
|
+
)}
|
|
160
|
+
|
|
161
|
+
<Card>
|
|
162
|
+
<CardHeader>
|
|
163
|
+
<CardTitle>Current Theme Info</CardTitle>
|
|
164
|
+
<CardDescription>
|
|
165
|
+
Information about the currently active theme
|
|
166
|
+
</CardDescription>
|
|
167
|
+
</CardHeader>
|
|
168
|
+
<CardContent>
|
|
169
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
170
|
+
<div>
|
|
171
|
+
<h4 className="font-medium mb-2">Theme Details</h4>
|
|
172
|
+
<div className="space-y-2 text-sm">
|
|
173
|
+
<div><span className="font-medium">Name:</span> {currentThemeConfig?.meta.name}</div>
|
|
174
|
+
<div><span className="font-medium">Description:</span> {currentThemeConfig?.meta.description}</div>
|
|
175
|
+
<div><span className="font-medium">Category:</span> {currentThemeConfig?.meta.category}</div>
|
|
176
|
+
<div><span className="font-medium">Version:</span> {currentThemeConfig?.meta.version}</div>
|
|
177
|
+
<div><span className="font-medium">Author:</span> {currentThemeConfig?.meta.author}</div>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
<div>
|
|
181
|
+
<h4 className="font-medium mb-2">Font Configuration</h4>
|
|
182
|
+
<div className="space-y-2 text-sm">
|
|
183
|
+
<div><span className="font-medium">Primary:</span> {currentThemeConfig?.fonts.primary.family}</div>
|
|
184
|
+
<div><span className="font-medium">Secondary:</span> {currentThemeConfig?.fonts.secondary.family}</div>
|
|
185
|
+
<div><span className="font-medium">Display:</span> {currentThemeConfig?.fonts.display.family}</div>
|
|
186
|
+
<div><span className="font-medium">Body:</span> {currentThemeConfig?.fonts.body.family}</div>
|
|
187
|
+
<div><span className="font-medium">Mono:</span> {currentThemeConfig?.fonts.mono.family}</div>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
</CardContent>
|
|
192
|
+
</Card>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
};
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import React, { useState, useRef } from 'react'
|
|
2
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './card'
|
|
3
|
+
import { Button } from './button'
|
|
4
|
+
import { Badge } from './badge'
|
|
5
|
+
import { useGestures, useTouchOptimization, useMobileTouch } from '../../hooks'
|
|
6
|
+
import { useDevice } from '../../hooks/use-device'
|
|
7
|
+
|
|
8
|
+
export const TouchDemo: React.FC = () => {
|
|
9
|
+
const [activeTab, setActiveTab] = useState<'overview' | 'gestures' | 'optimization' | 'mobile'>('overview')
|
|
10
|
+
const [gestureHistory, setGestureHistory] = useState<Array<{ type: string; details: any; timestamp: Date }>>([])
|
|
11
|
+
const [touchFeedback, setTouchFeedback] = useState<string>('')
|
|
12
|
+
|
|
13
|
+
const gestureElementRef = useRef<HTMLDivElement>(null)
|
|
14
|
+
const optimizationElementRef = useRef<HTMLDivElement>(null)
|
|
15
|
+
const mobileTouchElementRef = useRef<HTMLDivElement>(null)
|
|
16
|
+
|
|
17
|
+
const device = useDevice()
|
|
18
|
+
|
|
19
|
+
// Gesture recognition hook
|
|
20
|
+
const {
|
|
21
|
+
isGestureActive,
|
|
22
|
+
currentGestureType,
|
|
23
|
+
resetGestureState
|
|
24
|
+
} = useGestures(gestureElementRef, {
|
|
25
|
+
onSwipe: (gesture: any) => {
|
|
26
|
+
const gestureInfo = {
|
|
27
|
+
type: 'Swipe',
|
|
28
|
+
details: `${gesture.direction} - ${gesture.distance.toFixed(0)}px, ${gesture.velocity.toFixed(1)}px/ms`,
|
|
29
|
+
timestamp: new Date()
|
|
30
|
+
}
|
|
31
|
+
setGestureHistory(prev => [gestureInfo, ...prev.slice(0, 9)])
|
|
32
|
+
},
|
|
33
|
+
onPinch: (gesture: any) => {
|
|
34
|
+
const gestureInfo = {
|
|
35
|
+
type: 'Pinch',
|
|
36
|
+
details: `Scale: ${gesture.scale.toFixed(2)}, Distance: ${gesture.distance.toFixed(0)}px`,
|
|
37
|
+
timestamp: new Date()
|
|
38
|
+
}
|
|
39
|
+
setGestureHistory(prev => [gestureInfo, ...prev.slice(0, 9)])
|
|
40
|
+
},
|
|
41
|
+
onTap: (position: any) => {
|
|
42
|
+
const gestureInfo = {
|
|
43
|
+
type: 'Tap',
|
|
44
|
+
details: `Position: (${position.x}, ${position.y})`,
|
|
45
|
+
timestamp: new Date()
|
|
46
|
+
}
|
|
47
|
+
setGestureHistory(prev => [gestureInfo, ...prev.slice(0, 9)])
|
|
48
|
+
},
|
|
49
|
+
onLongPress: (position: any) => {
|
|
50
|
+
const gestureInfo = {
|
|
51
|
+
type: 'Long Press',
|
|
52
|
+
details: `Position: (${position.x}, ${position.y})`,
|
|
53
|
+
timestamp: new Date()
|
|
54
|
+
}
|
|
55
|
+
setGestureHistory(prev => [gestureInfo, ...prev.slice(0, 9)])
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// Touch optimization hook
|
|
60
|
+
const {
|
|
61
|
+
optimizationState,
|
|
62
|
+
performanceMetrics,
|
|
63
|
+
applyOptimizations,
|
|
64
|
+
resetOptimizations
|
|
65
|
+
} = useTouchOptimization(optimizationElementRef, {
|
|
66
|
+
onTouchPerformanceWarning: (metrics: any) => {
|
|
67
|
+
console.warn('Touch performance warning:', metrics)
|
|
68
|
+
},
|
|
69
|
+
onBatteryOptimization: (enabled: any) => {
|
|
70
|
+
console.log('Battery optimization:', enabled ? 'enabled' : 'disabled')
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// Mobile touch hook
|
|
75
|
+
const {
|
|
76
|
+
mobileTouchState,
|
|
77
|
+
clearAllGestureHints,
|
|
78
|
+
getTouchFeedbackClasses
|
|
79
|
+
} = useMobileTouch(mobileTouchElementRef, {
|
|
80
|
+
onTouchFeedback: (state: any) => {
|
|
81
|
+
setTouchFeedback(`${state.feedbackType} feedback - ${state.feedbackIntensity} intensity`)
|
|
82
|
+
},
|
|
83
|
+
onGestureHint: (hint: any) => {
|
|
84
|
+
console.log('Gesture hint:', hint)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const clearGestureHistory = () => {
|
|
89
|
+
setGestureHistory([])
|
|
90
|
+
resetGestureState()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const getPerformanceScoreColor = (score: string) => {
|
|
94
|
+
switch (score) {
|
|
95
|
+
case 'excellent': return 'text-green-600'
|
|
96
|
+
case 'good': return 'text-blue-600'
|
|
97
|
+
case 'fair': return 'text-yellow-600'
|
|
98
|
+
case 'poor': return 'text-red-600'
|
|
99
|
+
default: return 'text-gray-600'
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const getBatteryImpactColor = (impact: string) => {
|
|
104
|
+
switch (impact) {
|
|
105
|
+
case 'low': return 'text-green-600'
|
|
106
|
+
case 'medium': return 'text-yellow-600'
|
|
107
|
+
case 'high': return 'text-red-600'
|
|
108
|
+
default: return 'text-gray-600'
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div className="space-y-6">
|
|
114
|
+
{/* Tab Navigation */}
|
|
115
|
+
<div className="flex flex-wrap gap-2">
|
|
116
|
+
{[
|
|
117
|
+
{ id: 'overview', label: 'Overview', icon: '📱' },
|
|
118
|
+
{ id: 'gestures', label: 'Gesture Recognition', icon: '👆' },
|
|
119
|
+
{ id: 'optimization', label: 'Touch Optimization', icon: '⚡' },
|
|
120
|
+
{ id: 'mobile', label: 'Mobile Touch', icon: '📱' }
|
|
121
|
+
].map((tab) => (
|
|
122
|
+
<Button
|
|
123
|
+
key={tab.id}
|
|
124
|
+
variant={activeTab === tab.id ? 'default' : 'outline'}
|
|
125
|
+
size="sm"
|
|
126
|
+
onClick={() => setActiveTab(tab.id as any)}
|
|
127
|
+
className="touch-button"
|
|
128
|
+
>
|
|
129
|
+
{tab.icon} {tab.label}
|
|
130
|
+
</Button>
|
|
131
|
+
))}
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
{/* Overview Tab */}
|
|
135
|
+
{activeTab === 'overview' && (
|
|
136
|
+
<div className="space-y-4">
|
|
137
|
+
<Card className="touch-card">
|
|
138
|
+
<CardHeader>
|
|
139
|
+
<CardTitle className="flex items-center gap-2">
|
|
140
|
+
🎯 Touch Optimization & Gesture Support
|
|
141
|
+
<Badge variant="outline">Story 5 Implementation</Badge>
|
|
142
|
+
</CardTitle>
|
|
143
|
+
<CardDescription>
|
|
144
|
+
Comprehensive touch optimization system with gesture recognition, performance monitoring, and mobile-first interactions
|
|
145
|
+
</CardDescription>
|
|
146
|
+
</CardHeader>
|
|
147
|
+
<CardContent className="space-y-4">
|
|
148
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
149
|
+
<div className="space-y-2">
|
|
150
|
+
<h4 className="font-semibold">Device Information</h4>
|
|
151
|
+
<div className="text-sm space-y-1">
|
|
152
|
+
<p>Screen Size: <Badge variant="secondary">{device.screenSize}</Badge></p>
|
|
153
|
+
<p>Touch Device: <Badge variant="secondary">{device.touchDevice ? 'Yes' : 'No'}</Badge></p>
|
|
154
|
+
<p>Orientation: <Badge variant="secondary">{device.orientation}</Badge></p>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
<div className="space-y-2">
|
|
158
|
+
<h4 className="font-semibold">Touch Capabilities</h4>
|
|
159
|
+
<div className="text-sm space-y-1">
|
|
160
|
+
<p>Max Touch Points: <Badge variant="secondary">{mobileTouchState.deviceCapabilities.maxTouchPoints}</Badge></p>
|
|
161
|
+
<p>Haptic Support: <Badge variant="secondary">{mobileTouchState.deviceCapabilities.supportsHaptics ? 'Yes' : 'No'}</Badge></p>
|
|
162
|
+
<p>Audio Support: <Badge variant="secondary">{mobileTouchState.deviceCapabilities.supportsAudio ? 'Yes' : 'No'}</Badge></p>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
168
|
+
<div className="text-center p-4 bg-gray-50 rounded-lg">
|
|
169
|
+
<div className="text-2xl mb-2">👆</div>
|
|
170
|
+
<h4 className="font-semibold">Gesture Recognition</h4>
|
|
171
|
+
<p className="text-sm text-gray-600">Swipe, pinch, tap, and long press detection</p>
|
|
172
|
+
</div>
|
|
173
|
+
<div className="text-center p-4 bg-gray-50 rounded-lg">
|
|
174
|
+
<div className="text-2xl mb-2">⚡</div>
|
|
175
|
+
<h4 className="font-semibold">Performance Optimization</h4>
|
|
176
|
+
<p className="text-sm text-gray-600">Touch event optimization and battery awareness</p>
|
|
177
|
+
</div>
|
|
178
|
+
<div className="text-center p-4 bg-gray-50 rounded-lg">
|
|
179
|
+
<div className="text-2xl mb-2">📱</div>
|
|
180
|
+
<h4 className="font-semibold">Mobile Touch</h4>
|
|
181
|
+
<p className="text-sm text-gray-600">Touch feedback, haptics, and gesture hints</p>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</CardContent>
|
|
185
|
+
</Card>
|
|
186
|
+
</div>
|
|
187
|
+
)}
|
|
188
|
+
|
|
189
|
+
{/* Gesture Recognition Tab */}
|
|
190
|
+
{activeTab === 'gestures' && (
|
|
191
|
+
<div className="space-y-4">
|
|
192
|
+
<Card className="touch-card">
|
|
193
|
+
<CardHeader>
|
|
194
|
+
<CardTitle className="flex items-center gap-2">
|
|
195
|
+
👆 Gesture Recognition
|
|
196
|
+
<Badge variant={isGestureActive ? 'default' : 'secondary'}>
|
|
197
|
+
{isGestureActive ? 'Active' : 'Inactive'}
|
|
198
|
+
</Badge>
|
|
199
|
+
</CardTitle>
|
|
200
|
+
<CardDescription>
|
|
201
|
+
Test gesture recognition on the interactive area below. Try swiping, pinching, tapping, and long pressing.
|
|
202
|
+
</CardDescription>
|
|
203
|
+
</CardHeader>
|
|
204
|
+
<CardContent className="space-y-4">
|
|
205
|
+
<div className="flex gap-2">
|
|
206
|
+
<Button onClick={resetGestureState} variant="outline" size="sm">
|
|
207
|
+
Reset Gestures
|
|
208
|
+
</Button>
|
|
209
|
+
<Button onClick={clearGestureHistory} variant="outline" size="sm">
|
|
210
|
+
Clear History
|
|
211
|
+
</Button>
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
215
|
+
{/* Interactive Gesture Area */}
|
|
216
|
+
<div
|
|
217
|
+
ref={gestureElementRef}
|
|
218
|
+
className="min-h-[300px] border-2 border-dashed border-gray-300 rounded-lg p-4 flex items-center justify-center bg-gray-50 touch-target"
|
|
219
|
+
style={{ touchAction: 'manipulation' }}
|
|
220
|
+
>
|
|
221
|
+
<div className="text-center">
|
|
222
|
+
<div className="text-4xl mb-2">👆</div>
|
|
223
|
+
<p className="font-medium">Gesture Test Area</p>
|
|
224
|
+
<p className="text-sm text-gray-600">
|
|
225
|
+
{currentGestureType !== 'none' ? `Current: ${currentGestureType}` : 'Touch to start'}
|
|
226
|
+
</p>
|
|
227
|
+
<p className="text-xs text-gray-500 mt-2">
|
|
228
|
+
Swipe, pinch, tap, or long press here
|
|
229
|
+
</p>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
{/* Gesture History */}
|
|
234
|
+
<div className="space-y-2">
|
|
235
|
+
<h4 className="font-semibold">Gesture History</h4>
|
|
236
|
+
<div className="max-h-[300px] overflow-y-auto space-y-2">
|
|
237
|
+
{gestureHistory.length === 0 ? (
|
|
238
|
+
<p className="text-gray-500 text-sm">No gestures detected yet</p>
|
|
239
|
+
) : (
|
|
240
|
+
gestureHistory.map((gesture, index) => (
|
|
241
|
+
<div key={index} className="p-2 bg-gray-50 rounded text-sm">
|
|
242
|
+
<div className="flex justify-between items-start">
|
|
243
|
+
<span className="font-medium">{gesture.type}</span>
|
|
244
|
+
<span className="text-xs text-gray-500">
|
|
245
|
+
{gesture.timestamp.toLocaleTimeString()}
|
|
246
|
+
</span>
|
|
247
|
+
</div>
|
|
248
|
+
<p className="text-gray-600">{gesture.details}</p>
|
|
249
|
+
</div>
|
|
250
|
+
))
|
|
251
|
+
)}
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
</CardContent>
|
|
256
|
+
</Card>
|
|
257
|
+
</div>
|
|
258
|
+
)}
|
|
259
|
+
|
|
260
|
+
{/* Touch Optimization Tab */}
|
|
261
|
+
{activeTab === 'optimization' && (
|
|
262
|
+
<div className="space-y-4">
|
|
263
|
+
<Card className="touch-card">
|
|
264
|
+
<CardHeader>
|
|
265
|
+
<CardTitle className="flex items-center gap-2">
|
|
266
|
+
⚡ Touch Optimization
|
|
267
|
+
<Badge variant={optimizationState.isOptimized ? 'default' : 'secondary'}>
|
|
268
|
+
{optimizationState.isOptimized ? 'Optimized' : 'Not Optimized'}
|
|
269
|
+
</Badge>
|
|
270
|
+
</CardTitle>
|
|
271
|
+
<CardDescription>
|
|
272
|
+
Monitor touch performance and apply optimizations for better user experience.
|
|
273
|
+
</CardDescription>
|
|
274
|
+
</CardHeader>
|
|
275
|
+
<CardContent className="space-y-4">
|
|
276
|
+
<div className="flex gap-2">
|
|
277
|
+
<Button onClick={applyOptimizations} variant="default" size="sm">
|
|
278
|
+
Apply Optimizations
|
|
279
|
+
</Button>
|
|
280
|
+
<Button onClick={resetOptimizations} variant="outline" size="sm">
|
|
281
|
+
Reset Optimizations
|
|
282
|
+
</Button>
|
|
283
|
+
</div>
|
|
284
|
+
|
|
285
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
286
|
+
{/* Optimization Status */}
|
|
287
|
+
<div className="space-y-3">
|
|
288
|
+
<h4 className="font-semibold">Optimization Status</h4>
|
|
289
|
+
<div className="space-y-2 text-sm">
|
|
290
|
+
<div className="flex justify-between">
|
|
291
|
+
<span>Touch Action:</span>
|
|
292
|
+
<Badge variant="outline">{optimizationState.currentTouchAction}</Badge>
|
|
293
|
+
</div>
|
|
294
|
+
<div className="flex justify-between">
|
|
295
|
+
<span>Passive Listeners:</span>
|
|
296
|
+
<Badge variant={optimizationState.passiveListenersEnabled ? 'default' : 'secondary'}>
|
|
297
|
+
{optimizationState.passiveListenersEnabled ? 'Enabled' : 'Disabled'}
|
|
298
|
+
</Badge>
|
|
299
|
+
</div>
|
|
300
|
+
<div className="flex justify-between">
|
|
301
|
+
<span>Battery Optimization:</span>
|
|
302
|
+
<Badge variant={optimizationState.batteryOptimizationEnabled ? 'default' : 'secondary'}>
|
|
303
|
+
{optimizationState.batteryOptimizationEnabled ? 'Enabled' : 'Disabled'}
|
|
304
|
+
</Badge>
|
|
305
|
+
</div>
|
|
306
|
+
<div className="flex justify-between">
|
|
307
|
+
<span>Throttling:</span>
|
|
308
|
+
<Badge variant={optimizationState.throttlingEnabled ? 'default' : 'secondary'}>
|
|
309
|
+
{optimizationState.throttlingEnabled ? 'Enabled' : 'Disabled'}
|
|
310
|
+
</Badge>
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
{/* Performance Metrics */}
|
|
316
|
+
<div className="space-y-3">
|
|
317
|
+
<h4 className="font-semibold">Performance Metrics</h4>
|
|
318
|
+
<div className="space-y-2 text-sm">
|
|
319
|
+
<div className="flex justify-between">
|
|
320
|
+
<span>Touch Events:</span>
|
|
321
|
+
<span>{performanceMetrics.touchEventCount}</span>
|
|
322
|
+
</div>
|
|
323
|
+
<div className="flex justify-between">
|
|
324
|
+
<span>Avg Duration:</span>
|
|
325
|
+
<span>{performanceMetrics.averageTouchDuration.toFixed(1)}ms</span>
|
|
326
|
+
</div>
|
|
327
|
+
<div className="flex justify-between">
|
|
328
|
+
<span>Latency:</span>
|
|
329
|
+
<span>{performanceMetrics.touchEventLatency.toFixed(1)}ms</span>
|
|
330
|
+
</div>
|
|
331
|
+
<div className="flex justify-between">
|
|
332
|
+
<span>Performance:</span>
|
|
333
|
+
<span className={getPerformanceScoreColor(performanceMetrics.performanceScore)}>
|
|
334
|
+
{performanceMetrics.performanceScore}
|
|
335
|
+
</span>
|
|
336
|
+
</div>
|
|
337
|
+
<div className="flex justify-between">
|
|
338
|
+
<span>Battery Impact:</span>
|
|
339
|
+
<span className={getBatteryImpactColor(performanceMetrics.batteryImpact)}>
|
|
340
|
+
{performanceMetrics.batteryImpact}
|
|
341
|
+
</span>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
|
|
347
|
+
{/* Test Area */}
|
|
348
|
+
<div
|
|
349
|
+
ref={optimizationElementRef}
|
|
350
|
+
className="min-h-[200px] border-2 border-dashed border-gray-300 rounded-lg p-4 flex items-center justify-center bg-gray-50 touch-target"
|
|
351
|
+
style={{ touchAction: optimizationState.currentTouchAction }}
|
|
352
|
+
>
|
|
353
|
+
<div className="text-center">
|
|
354
|
+
<div className="text-2xl mb-2">⚡</div>
|
|
355
|
+
<p className="font-medium">Optimization Test Area</p>
|
|
356
|
+
<p className="text-sm text-gray-600">
|
|
357
|
+
Touch here to test optimizations
|
|
358
|
+
</p>
|
|
359
|
+
</div>
|
|
360
|
+
</div>
|
|
361
|
+
</CardContent>
|
|
362
|
+
</Card>
|
|
363
|
+
</div>
|
|
364
|
+
)}
|
|
365
|
+
|
|
366
|
+
{/* Mobile Touch Tab */}
|
|
367
|
+
{activeTab === 'mobile' && (
|
|
368
|
+
<div className="space-y-4">
|
|
369
|
+
<Card className="touch-card">
|
|
370
|
+
<CardHeader>
|
|
371
|
+
<CardTitle className="flex items-center gap-2">
|
|
372
|
+
📱 Mobile Touch Behaviors
|
|
373
|
+
<Badge variant={mobileTouchState.isActive ? 'default' : 'secondary'}>
|
|
374
|
+
{mobileTouchState.isActive ? 'Active' : 'Inactive'}
|
|
375
|
+
</Badge>
|
|
376
|
+
</CardTitle>
|
|
377
|
+
<CardDescription>
|
|
378
|
+
Experience mobile touch feedback, haptics, and gesture hints.
|
|
379
|
+
</CardDescription>
|
|
380
|
+
</CardHeader>
|
|
381
|
+
<CardContent className="space-y-4">
|
|
382
|
+
<div className="flex gap-2">
|
|
383
|
+
<Button onClick={clearAllGestureHints} variant="outline" size="sm">
|
|
384
|
+
Clear Hints
|
|
385
|
+
</Button>
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
389
|
+
{/* Touch Feedback Status */}
|
|
390
|
+
<div className="space-y-3">
|
|
391
|
+
<h4 className="font-semibold">Touch Feedback Status</h4>
|
|
392
|
+
<div className="space-y-2 text-sm">
|
|
393
|
+
<div className="flex justify-between">
|
|
394
|
+
<span>Touch Count:</span>
|
|
395
|
+
<Badge variant="outline">{mobileTouchState.touchCount}</Badge>
|
|
396
|
+
</div>
|
|
397
|
+
<div className="flex justify-between">
|
|
398
|
+
<span>Feedback Type:</span>
|
|
399
|
+
<Badge variant="outline">{mobileTouchState.currentFeedback.feedbackType}</Badge>
|
|
400
|
+
</div>
|
|
401
|
+
<div className="flex justify-between">
|
|
402
|
+
<span>Intensity:</span>
|
|
403
|
+
<Badge variant="outline">{mobileTouchState.currentFeedback.feedbackIntensity}</Badge>
|
|
404
|
+
</div>
|
|
405
|
+
<div className="flex justify-between">
|
|
406
|
+
<span>Active Hints:</span>
|
|
407
|
+
<Badge variant="outline">{mobileTouchState.activeGestureHints.length}</Badge>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
{touchFeedback && (
|
|
411
|
+
<div className="p-2 bg-blue-50 border border-blue-200 rounded text-sm">
|
|
412
|
+
{touchFeedback}
|
|
413
|
+
</div>
|
|
414
|
+
)}
|
|
415
|
+
</div>
|
|
416
|
+
|
|
417
|
+
{/* Active Gesture Hints */}
|
|
418
|
+
<div className="space-y-3">
|
|
419
|
+
<h4 className="font-semibold">Active Gesture Hints</h4>
|
|
420
|
+
<div className="max-h-[200px] overflow-y-auto space-y-2">
|
|
421
|
+
{mobileTouchState.activeGestureHints.length === 0 ? (
|
|
422
|
+
<p className="text-gray-500 text-sm">No active hints</p>
|
|
423
|
+
) : (
|
|
424
|
+
mobileTouchState.activeGestureHints.map((hint: any, index: number) => (
|
|
425
|
+
<div key={index} className="p-2 bg-yellow-50 border border-yellow-200 rounded text-sm">
|
|
426
|
+
<div className="flex justify-between items-start">
|
|
427
|
+
<span className="font-medium">{hint.type}</span>
|
|
428
|
+
<span className="text-xs text-gray-500">
|
|
429
|
+
{new Date(hint.timeout).toLocaleTimeString()}
|
|
430
|
+
</span>
|
|
431
|
+
</div>
|
|
432
|
+
<p className="text-gray-600">{hint.message}</p>
|
|
433
|
+
</div>
|
|
434
|
+
))
|
|
435
|
+
)}
|
|
436
|
+
</div>
|
|
437
|
+
</div>
|
|
438
|
+
</div>
|
|
439
|
+
|
|
440
|
+
{/* Mobile Touch Test Area */}
|
|
441
|
+
<div
|
|
442
|
+
ref={mobileTouchElementRef}
|
|
443
|
+
className={`min-h-[300px] border-2 border-dashed border-gray-300 rounded-lg p-4 flex items-center justify-center bg-gray-50 touch-target ${getTouchFeedbackClasses()}`}
|
|
444
|
+
>
|
|
445
|
+
<div className="text-center">
|
|
446
|
+
<div className="text-4xl mb-2">📱</div>
|
|
447
|
+
<p className="font-medium">Mobile Touch Test Area</p>
|
|
448
|
+
<p className="text-sm text-gray-600">
|
|
449
|
+
{mobileTouchState.isActive ? 'Touch active' : 'Touch to start'}
|
|
450
|
+
</p>
|
|
451
|
+
<p className="text-xs text-gray-500 mt-2">
|
|
452
|
+
Experience haptic feedback and touch sounds
|
|
453
|
+
</p>
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
</CardContent>
|
|
457
|
+
</Card>
|
|
458
|
+
</div>
|
|
459
|
+
)}
|
|
460
|
+
</div>
|
|
461
|
+
)
|
|
462
|
+
}
|