@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.
- 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,402 @@
|
|
|
1
|
+
import { useState, useCallback, useRef, useEffect } from 'react'
|
|
2
|
+
|
|
3
|
+
export interface MobileSkeletonConfig {
|
|
4
|
+
enableMobileOptimization?: boolean
|
|
5
|
+
enablePerformanceOptimization?: boolean
|
|
6
|
+
enableBatteryOptimization?: boolean
|
|
7
|
+
enableAccessibilitySupport?: boolean
|
|
8
|
+
enableTouchOptimization?: boolean
|
|
9
|
+
animationDuration?: number
|
|
10
|
+
skeletonCount?: number
|
|
11
|
+
mobileBreakpoint?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SkeletonVariant {
|
|
15
|
+
id: string
|
|
16
|
+
name: string
|
|
17
|
+
width: string | number
|
|
18
|
+
height: string | number
|
|
19
|
+
borderRadius?: string | number
|
|
20
|
+
animation?: 'pulse' | 'wave' | 'shimmer' | 'fade'
|
|
21
|
+
mobileOptimized?: boolean
|
|
22
|
+
touchFriendly?: boolean
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DeviceLoadingState {
|
|
26
|
+
deviceType: 'mobile' | 'tablet' | 'desktop'
|
|
27
|
+
orientation: 'portrait' | 'landscape'
|
|
28
|
+
screenSize: 'small' | 'medium' | 'large'
|
|
29
|
+
loadingStrategy: 'skeleton' | 'spinner' | 'progress' | 'skeleton-spinner'
|
|
30
|
+
animationIntensity: 'low' | 'medium' | 'high'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface MobileSkeletonCallbacks {
|
|
34
|
+
onSkeletonCreated?: (variant: SkeletonVariant) => void
|
|
35
|
+
onLoadingStateChanged?: (state: DeviceLoadingState) => void
|
|
36
|
+
onPerformanceOptimized?: (optimization: string) => void
|
|
37
|
+
onBatteryOptimized?: (strategy: string) => void
|
|
38
|
+
onAccessibilityEnhanced?: (feature: string) => void
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const useMobileSkeleton = (
|
|
42
|
+
config: MobileSkeletonConfig = {},
|
|
43
|
+
callbacks: MobileSkeletonCallbacks = {}
|
|
44
|
+
) => {
|
|
45
|
+
const {
|
|
46
|
+
enablePerformanceOptimization = true,
|
|
47
|
+
enableBatteryOptimization = true,
|
|
48
|
+
enableAccessibilitySupport = true,
|
|
49
|
+
enableTouchOptimization = true,
|
|
50
|
+
mobileBreakpoint = 768
|
|
51
|
+
} = config
|
|
52
|
+
|
|
53
|
+
const [deviceState, setDeviceState] = useState<DeviceLoadingState>({
|
|
54
|
+
deviceType: 'desktop',
|
|
55
|
+
orientation: 'landscape',
|
|
56
|
+
screenSize: 'large',
|
|
57
|
+
loadingStrategy: 'skeleton',
|
|
58
|
+
animationIntensity: 'medium'
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const [skeletonVariants, setSkeletonVariants] = useState<SkeletonVariant[]>([])
|
|
62
|
+
const [isOptimizing, setIsOptimizing] = useState(false)
|
|
63
|
+
const [optimizations, setOptimizations] = useState<string[]>([])
|
|
64
|
+
const [performanceMetrics, setPerformanceMetrics] = useState({
|
|
65
|
+
renderTime: 0,
|
|
66
|
+
animationFrameRate: 60,
|
|
67
|
+
memoryUsage: 0,
|
|
68
|
+
batteryImpact: 'low'
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
const animationFrameRef = useRef<number | null>(null)
|
|
73
|
+
const performanceTimerRef = useRef<number | null>(null)
|
|
74
|
+
|
|
75
|
+
// Device detection and loading state management
|
|
76
|
+
const detectDeviceAndSetLoadingState = useCallback(() => {
|
|
77
|
+
const width = window.innerWidth
|
|
78
|
+
const height = window.innerHeight
|
|
79
|
+
const isMobile = width <= mobileBreakpoint
|
|
80
|
+
const isTablet = width > mobileBreakpoint && width <= 1024
|
|
81
|
+
const isPortrait = height > width
|
|
82
|
+
|
|
83
|
+
let deviceType: 'mobile' | 'tablet' | 'desktop'
|
|
84
|
+
let screenSize: 'small' | 'medium' | 'large'
|
|
85
|
+
let loadingStrategy: 'skeleton' | 'spinner' | 'progress' | 'skeleton-spinner'
|
|
86
|
+
let animationIntensity: 'low' | 'medium' | 'high'
|
|
87
|
+
|
|
88
|
+
if (isMobile) {
|
|
89
|
+
deviceType = 'mobile'
|
|
90
|
+
screenSize = 'small'
|
|
91
|
+
loadingStrategy = 'skeleton'
|
|
92
|
+
animationIntensity = 'low'
|
|
93
|
+
} else if (isTablet) {
|
|
94
|
+
deviceType = 'tablet'
|
|
95
|
+
screenSize = 'medium'
|
|
96
|
+
loadingStrategy = 'skeleton-spinner'
|
|
97
|
+
animationIntensity = 'medium'
|
|
98
|
+
} else {
|
|
99
|
+
deviceType = 'desktop'
|
|
100
|
+
screenSize = 'large'
|
|
101
|
+
loadingStrategy = 'skeleton'
|
|
102
|
+
animationIntensity = 'high'
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const newState: DeviceLoadingState = {
|
|
106
|
+
deviceType,
|
|
107
|
+
orientation: isPortrait ? 'portrait' : 'landscape',
|
|
108
|
+
screenSize,
|
|
109
|
+
loadingStrategy,
|
|
110
|
+
animationIntensity
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
setDeviceState(newState)
|
|
114
|
+
callbacks.onLoadingStateChanged?.(newState)
|
|
115
|
+
|
|
116
|
+
return newState
|
|
117
|
+
}, [mobileBreakpoint, callbacks])
|
|
118
|
+
|
|
119
|
+
// Create skeleton variants
|
|
120
|
+
const createSkeletonVariant = useCallback((
|
|
121
|
+
variant: Omit<SkeletonVariant, 'id'>
|
|
122
|
+
) => {
|
|
123
|
+
const id = `skeleton-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
|
124
|
+
const newVariant: SkeletonVariant = {
|
|
125
|
+
...variant,
|
|
126
|
+
id,
|
|
127
|
+
mobileOptimized: deviceState.deviceType === 'mobile',
|
|
128
|
+
touchFriendly: enableTouchOptimization && deviceState.deviceType === 'mobile'
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
setSkeletonVariants(prev => [...prev, newVariant])
|
|
132
|
+
callbacks.onSkeletonCreated?.(newVariant)
|
|
133
|
+
|
|
134
|
+
return id
|
|
135
|
+
}, [deviceState.deviceType, enableTouchOptimization, callbacks])
|
|
136
|
+
|
|
137
|
+
// Generate default skeleton variants
|
|
138
|
+
const generateDefaultSkeletons = useCallback(() => {
|
|
139
|
+
const defaults: SkeletonVariant[] = [
|
|
140
|
+
{
|
|
141
|
+
id: 'text-line',
|
|
142
|
+
name: 'Text Line',
|
|
143
|
+
width: '100%',
|
|
144
|
+
height: 16,
|
|
145
|
+
borderRadius: 4,
|
|
146
|
+
animation: 'pulse',
|
|
147
|
+
mobileOptimized: true,
|
|
148
|
+
touchFriendly: true
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: 'avatar',
|
|
152
|
+
name: 'Avatar',
|
|
153
|
+
width: 40,
|
|
154
|
+
height: 40,
|
|
155
|
+
borderRadius: '50%',
|
|
156
|
+
animation: 'shimmer',
|
|
157
|
+
mobileOptimized: true,
|
|
158
|
+
touchFriendly: true
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: 'card',
|
|
162
|
+
name: 'Card',
|
|
163
|
+
width: '100%',
|
|
164
|
+
height: 120,
|
|
165
|
+
borderRadius: 8,
|
|
166
|
+
animation: 'wave',
|
|
167
|
+
mobileOptimized: true,
|
|
168
|
+
touchFriendly: true
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'button',
|
|
172
|
+
name: 'Button',
|
|
173
|
+
width: 120,
|
|
174
|
+
height: 40,
|
|
175
|
+
borderRadius: 6,
|
|
176
|
+
animation: 'pulse',
|
|
177
|
+
mobileOptimized: true,
|
|
178
|
+
touchFriendly: true
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
setSkeletonVariants(defaults)
|
|
183
|
+
return defaults
|
|
184
|
+
}, [])
|
|
185
|
+
|
|
186
|
+
// Performance optimization
|
|
187
|
+
const optimizePerformance = useCallback(() => {
|
|
188
|
+
if (!enablePerformanceOptimization) return
|
|
189
|
+
|
|
190
|
+
setIsOptimizing(true)
|
|
191
|
+
|
|
192
|
+
setTimeout(() => {
|
|
193
|
+
const performanceOptimizations = [
|
|
194
|
+
'Animation frame rate optimized for mobile',
|
|
195
|
+
'Memory usage optimized for skeleton rendering',
|
|
196
|
+
'Render cycle optimization applied',
|
|
197
|
+
'Animation performance enhanced'
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
setOptimizations(prev => [...prev, ...performanceOptimizations])
|
|
201
|
+
setIsOptimizing(false)
|
|
202
|
+
|
|
203
|
+
performanceOptimizations.forEach(optimization => {
|
|
204
|
+
callbacks.onPerformanceOptimized?.(optimization)
|
|
205
|
+
})
|
|
206
|
+
}, 300)
|
|
207
|
+
}, [enablePerformanceOptimization, callbacks])
|
|
208
|
+
|
|
209
|
+
// Battery-conscious loading
|
|
210
|
+
const optimizeBatteryConsumption = useCallback(() => {
|
|
211
|
+
if (!enableBatteryOptimization) return
|
|
212
|
+
|
|
213
|
+
setIsOptimizing(true)
|
|
214
|
+
|
|
215
|
+
setTimeout(() => {
|
|
216
|
+
const batteryOptimizations = [
|
|
217
|
+
'Battery-conscious animation intensity applied',
|
|
218
|
+
'Reduced animation complexity for mobile',
|
|
219
|
+
'Power-efficient loading states enabled',
|
|
220
|
+
'Battery level monitoring active'
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
setOptimizations(prev => [...prev, ...batteryOptimizations])
|
|
224
|
+
setIsOptimizing(false)
|
|
225
|
+
|
|
226
|
+
batteryOptimizations.forEach(optimization => {
|
|
227
|
+
callbacks.onBatteryOptimized?.(optimization)
|
|
228
|
+
})
|
|
229
|
+
}, 250)
|
|
230
|
+
}, [enableBatteryOptimization, callbacks])
|
|
231
|
+
|
|
232
|
+
// Accessibility support
|
|
233
|
+
const enhanceAccessibility = useCallback(() => {
|
|
234
|
+
if (!enableAccessibilitySupport) return
|
|
235
|
+
|
|
236
|
+
setIsOptimizing(true)
|
|
237
|
+
|
|
238
|
+
setTimeout(() => {
|
|
239
|
+
const accessibilityEnhancements = [
|
|
240
|
+
'Screen reader support for loading states',
|
|
241
|
+
'Reduced motion support for animations',
|
|
242
|
+
'Focus management for skeleton elements',
|
|
243
|
+
'ARIA labels for loading indicators'
|
|
244
|
+
]
|
|
245
|
+
|
|
246
|
+
setOptimizations(prev => [...prev, ...accessibilityEnhancements])
|
|
247
|
+
setIsOptimizing(false)
|
|
248
|
+
|
|
249
|
+
accessibilityEnhancements.forEach(enhancement => {
|
|
250
|
+
callbacks.onAccessibilityEnhanced?.(enhancement)
|
|
251
|
+
})
|
|
252
|
+
}, 200)
|
|
253
|
+
}, [enableAccessibilitySupport, callbacks])
|
|
254
|
+
|
|
255
|
+
// Touch optimization
|
|
256
|
+
const optimizeTouchInteractions = useCallback(() => {
|
|
257
|
+
if (!enableTouchOptimization || deviceState.deviceType !== 'mobile') return
|
|
258
|
+
|
|
259
|
+
setIsOptimizing(true)
|
|
260
|
+
|
|
261
|
+
setTimeout(() => {
|
|
262
|
+
const touchOptimizations = [
|
|
263
|
+
'Touch-friendly skeleton interactions enabled',
|
|
264
|
+
'Touch target sizes optimized for mobile',
|
|
265
|
+
'Touch feedback animations applied',
|
|
266
|
+
'Gesture recognition for skeleton elements'
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
setOptimizations(prev => [...prev, ...touchOptimizations])
|
|
270
|
+
setIsOptimizing(false)
|
|
271
|
+
|
|
272
|
+
touchOptimizations.forEach(optimization => {
|
|
273
|
+
callbacks.onPerformanceOptimized?.(optimization)
|
|
274
|
+
})
|
|
275
|
+
}, 200)
|
|
276
|
+
}, [enableTouchOptimization, deviceState.deviceType, callbacks])
|
|
277
|
+
|
|
278
|
+
// Performance monitoring
|
|
279
|
+
const startPerformanceMonitoring = useCallback(() => {
|
|
280
|
+
if (!enablePerformanceOptimization) return () => {}
|
|
281
|
+
|
|
282
|
+
const startTime = performance.now()
|
|
283
|
+
let frameCount = 0
|
|
284
|
+
let lastTime = startTime
|
|
285
|
+
|
|
286
|
+
const measurePerformance = () => {
|
|
287
|
+
const currentTime = performance.now()
|
|
288
|
+
frameCount++
|
|
289
|
+
|
|
290
|
+
if (currentTime - lastTime >= 1000) {
|
|
291
|
+
const fps = Math.round((frameCount * 1000) / (currentTime - lastTime))
|
|
292
|
+
const renderTime = currentTime - startTime
|
|
293
|
+
|
|
294
|
+
setPerformanceMetrics(prev => ({
|
|
295
|
+
...prev,
|
|
296
|
+
renderTime,
|
|
297
|
+
animationFrameRate: fps
|
|
298
|
+
}))
|
|
299
|
+
|
|
300
|
+
frameCount = 0
|
|
301
|
+
lastTime = currentTime
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
animationFrameRef.current = requestAnimationFrame(measurePerformance)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
animationFrameRef.current = requestAnimationFrame(measurePerformance)
|
|
308
|
+
|
|
309
|
+
return () => {
|
|
310
|
+
if (animationFrameRef.current) {
|
|
311
|
+
cancelAnimationFrame(animationFrameRef.current)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}, [enablePerformanceOptimization])
|
|
315
|
+
|
|
316
|
+
// Auto-optimize based on device state
|
|
317
|
+
const autoOptimize = useCallback(() => {
|
|
318
|
+
if (deviceState.deviceType === 'mobile') {
|
|
319
|
+
optimizePerformance()
|
|
320
|
+
optimizeBatteryConsumption()
|
|
321
|
+
enhanceAccessibility()
|
|
322
|
+
optimizeTouchInteractions()
|
|
323
|
+
}
|
|
324
|
+
}, [deviceState.deviceType, optimizePerformance, optimizeBatteryConsumption, enhanceAccessibility, optimizeTouchInteractions])
|
|
325
|
+
|
|
326
|
+
// Initialize device detection and optimization
|
|
327
|
+
useEffect(() => {
|
|
328
|
+
detectDeviceAndSetLoadingState()
|
|
329
|
+
generateDefaultSkeletons()
|
|
330
|
+
|
|
331
|
+
// Set up resize listener
|
|
332
|
+
const handleResize = () => {
|
|
333
|
+
detectDeviceAndSetLoadingState()
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
window.addEventListener('resize', handleResize)
|
|
337
|
+
|
|
338
|
+
// Set up orientation change listener
|
|
339
|
+
const handleOrientationChange = () => {
|
|
340
|
+
setTimeout(detectDeviceAndSetLoadingState, 100)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
window.addEventListener('orientationchange', handleOrientationChange)
|
|
344
|
+
|
|
345
|
+
return () => {
|
|
346
|
+
window.removeEventListener('resize', handleResize)
|
|
347
|
+
window.removeEventListener('orientationchange', handleOrientationChange)
|
|
348
|
+
}
|
|
349
|
+
}, [detectDeviceAndSetLoadingState, generateDefaultSkeletons])
|
|
350
|
+
|
|
351
|
+
// Auto-optimize when device state changes
|
|
352
|
+
useEffect(() => {
|
|
353
|
+
autoOptimize()
|
|
354
|
+
}, [autoOptimize])
|
|
355
|
+
|
|
356
|
+
// Start performance monitoring
|
|
357
|
+
useEffect(() => {
|
|
358
|
+
const stopMonitoring = startPerformanceMonitoring()
|
|
359
|
+
|
|
360
|
+
return () => {
|
|
361
|
+
stopMonitoring()
|
|
362
|
+
}
|
|
363
|
+
}, [startPerformanceMonitoring])
|
|
364
|
+
|
|
365
|
+
// Cleanup on unmount
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
return () => {
|
|
368
|
+
if (animationFrameRef.current) {
|
|
369
|
+
cancelAnimationFrame(animationFrameRef.current)
|
|
370
|
+
}
|
|
371
|
+
if (performanceTimerRef.current) {
|
|
372
|
+
clearInterval(performanceTimerRef.current)
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}, [])
|
|
376
|
+
|
|
377
|
+
return {
|
|
378
|
+
// State
|
|
379
|
+
deviceState,
|
|
380
|
+
skeletonVariants,
|
|
381
|
+
isOptimizing,
|
|
382
|
+
optimizations,
|
|
383
|
+
performanceMetrics,
|
|
384
|
+
|
|
385
|
+
// Functions
|
|
386
|
+
createSkeletonVariant,
|
|
387
|
+
generateDefaultSkeletons,
|
|
388
|
+
optimizePerformance,
|
|
389
|
+
optimizeBatteryConsumption,
|
|
390
|
+
enhanceAccessibility,
|
|
391
|
+
optimizeTouchInteractions,
|
|
392
|
+
autoOptimize,
|
|
393
|
+
|
|
394
|
+
// Utility functions
|
|
395
|
+
isMobileOptimized: () => deviceState.deviceType === 'mobile',
|
|
396
|
+
getLoadingStrategy: () => deviceState.loadingStrategy,
|
|
397
|
+
getAnimationIntensity: () => deviceState.animationIntensity,
|
|
398
|
+
clearOptimizations: () => setOptimizations([])
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export default useMobileSkeleton
|