@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,459 @@
1
+ import { useState, useCallback, useRef, useEffect } from 'react'
2
+
3
+ export interface DeviceLoadingStatesConfig {
4
+ enableMobileStates?: boolean
5
+ enableTabletStates?: boolean
6
+ enableDesktopStates?: boolean
7
+ enableAdaptiveBehavior?: boolean
8
+ enableOrientationSupport?: boolean
9
+ enablePerformanceAdaptation?: boolean
10
+ }
11
+
12
+ export interface LoadingState {
13
+ id: string
14
+ name: string
15
+ type: 'skeleton' | 'spinner' | 'progress' | 'skeleton-spinner' | 'custom'
16
+ duration: number
17
+ complexity: 'low' | 'medium' | 'high'
18
+ mobileOptimized: boolean
19
+ tabletOptimized: boolean
20
+ desktopOptimized: boolean
21
+ orientation: 'portrait' | 'landscape' | 'both'
22
+ performance: 'low' | 'medium' | 'high'
23
+ }
24
+
25
+ export interface DeviceSpecificState {
26
+ deviceType: 'mobile' | 'tablet' | 'desktop'
27
+ orientation: 'portrait' | 'landscape'
28
+ screenSize: 'small' | 'medium' | 'large'
29
+ performanceLevel: 'low' | 'medium' | 'high'
30
+ batteryLevel: 'critical' | 'low' | 'medium' | 'high'
31
+ loadingStates: LoadingState[]
32
+ activeState: LoadingState | null
33
+ adaptiveBehavior: boolean
34
+ }
35
+
36
+ export interface DeviceLoadingStatesCallbacks {
37
+ onLoadingStateChanged?: (state: LoadingState) => void
38
+ onDeviceStateChanged?: (deviceState: DeviceSpecificState) => void
39
+ onAdaptiveBehaviorEnabled?: (behavior: string) => void
40
+ onPerformanceAdapted?: (adaptation: string) => void
41
+ }
42
+
43
+ export const useDeviceLoadingStates = (
44
+ config: DeviceLoadingStatesConfig = {},
45
+ callbacks: DeviceLoadingStatesCallbacks = {}
46
+ ) => {
47
+ const {
48
+ enableMobileStates = true,
49
+ enableTabletStates = true,
50
+ enableDesktopStates = true,
51
+ enableAdaptiveBehavior: enableAdaptiveBehaviorConfig = true,
52
+ enablePerformanceAdaptation = true
53
+ } = config
54
+
55
+ const [deviceState, setDeviceState] = useState<DeviceSpecificState>({
56
+ deviceType: 'desktop',
57
+ orientation: 'landscape',
58
+ screenSize: 'large',
59
+ performanceLevel: 'high',
60
+ batteryLevel: 'high',
61
+ loadingStates: [],
62
+ activeState: null,
63
+ adaptiveBehavior: false
64
+ })
65
+
66
+ const [isAdapting, setIsAdapting] = useState(false)
67
+ const [adaptations, setAdaptations] = useState<string[]>([])
68
+ const [performanceMetrics, setPerformanceMetrics] = useState({
69
+ frameRate: 60,
70
+ renderTime: 0,
71
+ memoryUsage: 0,
72
+ batteryDrain: 'low'
73
+ })
74
+
75
+
76
+ const performanceTimerRef = useRef<number | null>(null)
77
+ const batteryCheckRef = useRef<number | null>(null)
78
+
79
+ // Device detection
80
+ const detectDevice = useCallback(() => {
81
+ const width = window.innerWidth
82
+ const height = window.innerHeight
83
+ const isPortrait = height > width
84
+
85
+ let deviceType: 'mobile' | 'tablet' | 'desktop'
86
+ let screenSize: 'small' | 'medium' | 'large'
87
+ let performanceLevel: 'low' | 'medium' | 'high'
88
+
89
+ if (width <= 768) {
90
+ deviceType = 'mobile'
91
+ screenSize = 'small'
92
+ performanceLevel = 'low'
93
+ } else if (width <= 1024) {
94
+ deviceType = 'tablet'
95
+ screenSize = 'medium'
96
+ performanceLevel = 'medium'
97
+ } else {
98
+ deviceType = 'desktop'
99
+ screenSize = 'large'
100
+ performanceLevel = 'high'
101
+ }
102
+
103
+ const newDeviceState: DeviceSpecificState = {
104
+ ...deviceState,
105
+ deviceType,
106
+ orientation: isPortrait ? 'portrait' : 'landscape',
107
+ screenSize,
108
+ performanceLevel
109
+ }
110
+
111
+ setDeviceState(newDeviceState)
112
+ callbacks.onDeviceStateChanged?.(newDeviceState)
113
+
114
+ return newDeviceState
115
+ }, [deviceState, callbacks])
116
+
117
+ // Create loading states
118
+ const createLoadingState = useCallback((
119
+ state: Omit<LoadingState, 'id'>
120
+ ) => {
121
+ const id = `loading-state-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
122
+ const newState: LoadingState = {
123
+ ...state,
124
+ id
125
+ }
126
+
127
+ setDeviceState(prev => ({
128
+ ...prev,
129
+ loadingStates: [...prev.loadingStates, newState]
130
+ }))
131
+
132
+ return id
133
+ }, [])
134
+
135
+ // Generate device-specific loading states
136
+ const generateDeviceLoadingStates = useCallback(() => {
137
+ const mobileStates: LoadingState[] = [
138
+ {
139
+ id: 'mobile-skeleton',
140
+ name: 'Mobile Skeleton',
141
+ type: 'skeleton',
142
+ duration: 1000,
143
+ complexity: 'low',
144
+ mobileOptimized: true,
145
+ tabletOptimized: false,
146
+ desktopOptimized: false,
147
+ orientation: 'both',
148
+ performance: 'low'
149
+ },
150
+ {
151
+ id: 'mobile-spinner',
152
+ name: 'Mobile Spinner',
153
+ type: 'spinner',
154
+ duration: 800,
155
+ complexity: 'low',
156
+ mobileOptimized: true,
157
+ tabletOptimized: false,
158
+ desktopOptimized: false,
159
+ orientation: 'both',
160
+ performance: 'low'
161
+ }
162
+ ]
163
+
164
+ const tabletStates: LoadingState[] = [
165
+ {
166
+ id: 'tablet-skeleton-spinner',
167
+ name: 'Tablet Skeleton + Spinner',
168
+ type: 'skeleton-spinner',
169
+ duration: 1200,
170
+ complexity: 'medium',
171
+ mobileOptimized: false,
172
+ tabletOptimized: true,
173
+ desktopOptimized: false,
174
+ orientation: 'both',
175
+ performance: 'medium'
176
+ },
177
+ {
178
+ id: 'tablet-progress',
179
+ name: 'Tablet Progress',
180
+ type: 'progress',
181
+ duration: 1500,
182
+ complexity: 'medium',
183
+ mobileOptimized: false,
184
+ tabletOptimized: true,
185
+ desktopOptimized: false,
186
+ orientation: 'both',
187
+ performance: 'medium'
188
+ }
189
+ ]
190
+
191
+ const desktopStates: LoadingState[] = [
192
+ {
193
+ id: 'desktop-skeleton',
194
+ name: 'Desktop Skeleton',
195
+ type: 'skeleton',
196
+ duration: 2000,
197
+ complexity: 'high',
198
+ mobileOptimized: false,
199
+ tabletOptimized: false,
200
+ desktopOptimized: true,
201
+ orientation: 'both',
202
+ performance: 'high'
203
+ },
204
+ {
205
+ id: 'desktop-custom',
206
+ name: 'Desktop Custom',
207
+ type: 'custom',
208
+ duration: 2500,
209
+ complexity: 'high',
210
+ mobileOptimized: false,
211
+ tabletOptimized: false,
212
+ desktopOptimized: true,
213
+ orientation: 'both',
214
+ performance: 'high'
215
+ }
216
+ ]
217
+
218
+ const allStates = [
219
+ ...(enableMobileStates ? mobileStates : []),
220
+ ...(enableTabletStates ? tabletStates : []),
221
+ ...(enableDesktopStates ? desktopStates : [])
222
+ ]
223
+
224
+ setDeviceState(prev => ({
225
+ ...prev,
226
+ loadingStates: allStates
227
+ }))
228
+
229
+ return allStates
230
+ }, [enableMobileStates, enableTabletStates, enableDesktopStates])
231
+
232
+ // Set active loading state
233
+ const setActiveLoadingState = useCallback((stateId: string) => {
234
+ const state = deviceState.loadingStates.find(s => s.id === stateId)
235
+ if (state) {
236
+ setDeviceState(prev => ({
237
+ ...prev,
238
+ activeState: state
239
+ }))
240
+ callbacks.onLoadingStateChanged?.(state)
241
+ }
242
+ }, [deviceState.loadingStates, callbacks])
243
+
244
+ // Adaptive behavior
245
+ const enableAdaptiveBehavior = useCallback(() => {
246
+ if (!enableAdaptiveBehaviorConfig) return
247
+
248
+ setIsAdapting(true)
249
+
250
+ setTimeout(() => {
251
+ const adaptiveFeatures = [
252
+ 'Device-specific loading state adaptation enabled',
253
+ 'Performance-based state selection active',
254
+ 'Battery-conscious state switching enabled',
255
+ 'Orientation-aware state adaptation active'
256
+ ]
257
+
258
+ setAdaptations(prev => [...prev, ...adaptiveFeatures])
259
+ setDeviceState(prev => ({
260
+ ...prev,
261
+ adaptiveBehavior: true
262
+ }))
263
+ setIsAdapting(false)
264
+
265
+ adaptiveFeatures.forEach(feature => {
266
+ callbacks.onAdaptiveBehaviorEnabled?.(feature)
267
+ })
268
+ }, 300)
269
+ }, [enableAdaptiveBehaviorConfig, callbacks])
270
+
271
+ // Performance adaptation
272
+ const adaptToPerformance = useCallback(() => {
273
+ if (!enablePerformanceAdaptation) return
274
+
275
+ setIsAdapting(true)
276
+
277
+ setTimeout(() => {
278
+ const performanceAdaptations = [
279
+ 'Loading state complexity adapted to performance',
280
+ 'Animation duration optimized for device capability',
281
+ 'Memory usage optimized for loading states',
282
+ 'Frame rate adaptation for smooth animations'
283
+ ]
284
+
285
+ setAdaptations(prev => [...prev, ...performanceAdaptations])
286
+ setIsAdapting(false)
287
+
288
+ performanceAdaptations.forEach(adaptation => {
289
+ callbacks.onPerformanceAdapted?.(adaptation)
290
+ })
291
+ }, 250)
292
+ }, [enablePerformanceAdaptation, callbacks])
293
+
294
+ // Auto-adapt based on device state
295
+ const autoAdapt = useCallback(() => {
296
+ if (deviceState.adaptiveBehavior) {
297
+ enableAdaptiveBehavior()
298
+ adaptToPerformance()
299
+ }
300
+ }, [deviceState.adaptiveBehavior, enableAdaptiveBehavior, adaptToPerformance])
301
+
302
+ // Performance monitoring
303
+ const startPerformanceMonitoring = useCallback(() => {
304
+ if (!enablePerformanceAdaptation) return () => {}
305
+
306
+ let frameCount = 0
307
+ let lastTime = performance.now()
308
+
309
+ const measurePerformance = () => {
310
+ const currentTime = performance.now()
311
+ frameCount++
312
+
313
+ if (currentTime - lastTime >= 1000) {
314
+ const fps = Math.round((frameCount * 1000) / (currentTime - lastTime))
315
+ const renderTime = currentTime - lastTime
316
+
317
+ setPerformanceMetrics(prev => ({
318
+ ...prev,
319
+ frameRate: fps,
320
+ renderTime
321
+ }))
322
+
323
+ frameCount = 0
324
+ lastTime = currentTime
325
+ }
326
+
327
+ performanceTimerRef.current = window.setTimeout(measurePerformance, 16)
328
+ }
329
+
330
+ performanceTimerRef.current = window.setTimeout(measurePerformance, 16)
331
+
332
+ return () => {
333
+ if (performanceTimerRef.current) {
334
+ clearTimeout(performanceTimerRef.current)
335
+ }
336
+ }
337
+ }, [enablePerformanceAdaptation])
338
+
339
+ // Battery monitoring
340
+ const startBatteryMonitoring = useCallback(() => {
341
+ if (!enablePerformanceAdaptation) return () => {}
342
+
343
+ const checkBattery = async () => {
344
+ try {
345
+ if ('getBattery' in navigator) {
346
+ const battery = await (navigator as any).getBattery()
347
+ const level = battery.level
348
+
349
+ let batteryLevel: 'critical' | 'low' | 'medium' | 'high'
350
+ if (level <= 0.1) batteryLevel = 'critical'
351
+ else if (level <= 0.3) batteryLevel = 'low'
352
+ else if (level <= 0.7) batteryLevel = 'medium'
353
+ else batteryLevel = 'high'
354
+
355
+ setDeviceState(prev => ({
356
+ ...prev,
357
+ batteryLevel
358
+ }))
359
+ }
360
+ } catch (error) {
361
+ console.warn('Battery monitoring failed:', error)
362
+ }
363
+ }
364
+
365
+ batteryCheckRef.current = window.setInterval(checkBattery, 10000)
366
+
367
+ return () => {
368
+ if (batteryCheckRef.current) {
369
+ clearInterval(batteryCheckRef.current)
370
+ }
371
+ }
372
+ }, [enablePerformanceAdaptation])
373
+
374
+ // Initialize device detection and loading states
375
+ useEffect(() => {
376
+ detectDevice()
377
+ generateDeviceLoadingStates()
378
+
379
+ // Set up resize listener
380
+ const handleResize = () => {
381
+ detectDevice()
382
+ }
383
+
384
+ window.addEventListener('resize', handleResize)
385
+
386
+ // Set up orientation change listener
387
+ const handleOrientationChange = () => {
388
+ setTimeout(detectDevice, 100)
389
+ }
390
+
391
+ window.addEventListener('orientationchange', handleOrientationChange)
392
+
393
+ return () => {
394
+ window.removeEventListener('resize', handleResize)
395
+ window.removeEventListener('orientationchange', handleOrientationChange)
396
+ }
397
+ }, [detectDevice, generateDeviceLoadingStates])
398
+
399
+ // Auto-adapt when device state changes
400
+ useEffect(() => {
401
+ autoAdapt()
402
+ }, [autoAdapt])
403
+
404
+ // Start monitoring
405
+ useEffect(() => {
406
+ const stopPerformanceMonitoring = startPerformanceMonitoring()
407
+ const stopBatteryMonitoring = startBatteryMonitoring()
408
+
409
+ return () => {
410
+ stopPerformanceMonitoring()
411
+ stopBatteryMonitoring()
412
+ }
413
+ }, [startPerformanceMonitoring, startBatteryMonitoring])
414
+
415
+ // Cleanup on unmount
416
+ useEffect(() => {
417
+ return () => {
418
+ if (performanceTimerRef.current) {
419
+ clearTimeout(performanceTimerRef.current)
420
+ }
421
+ if (batteryCheckRef.current) {
422
+ clearInterval(batteryCheckRef.current)
423
+ }
424
+ }
425
+ }, [])
426
+
427
+ return {
428
+ // State
429
+ deviceState,
430
+ isAdapting,
431
+ adaptations,
432
+ performanceMetrics,
433
+
434
+ // Functions
435
+ createLoadingState,
436
+ generateDeviceLoadingStates,
437
+ setActiveLoadingState,
438
+ enableAdaptiveBehavior,
439
+ adaptToPerformance,
440
+ autoAdapt,
441
+
442
+ // Utility functions
443
+ isMobileDevice: () => deviceState.deviceType === 'mobile',
444
+ isTabletDevice: () => deviceState.deviceType === 'tablet',
445
+ isDesktopDevice: () => deviceState.deviceType === 'desktop',
446
+ getActiveState: () => deviceState.activeState,
447
+ getLoadingStatesForDevice: () => deviceState.loadingStates.filter(state => {
448
+ switch (deviceState.deviceType) {
449
+ case 'mobile': return state.mobileOptimized
450
+ case 'tablet': return state.tabletOptimized
451
+ case 'desktop': return state.desktopOptimized
452
+ default: return false
453
+ }
454
+ }),
455
+ clearAdaptations: () => setAdaptations([])
456
+ }
457
+ }
458
+
459
+ export default useDeviceLoadingStates
@@ -0,0 +1,110 @@
1
+ import { useState, useEffect } from 'react'
2
+
3
+ export interface DeviceInfo {
4
+ isMobile: boolean
5
+ isTablet: boolean
6
+ isDesktop: boolean
7
+ screenSize: 'mobile' | 'tablet' | 'desktop'
8
+ orientation: 'portrait' | 'landscape'
9
+ touchDevice: boolean
10
+ }
11
+
12
+ // Breakpoints based on common device sizes
13
+ const BREAKPOINTS = {
14
+ mobile: 768,
15
+ tablet: 1024,
16
+ desktop: 1440
17
+ } as const
18
+
19
+ /**
20
+ * Enhanced device detection hook with tablet-specific support
21
+ * Provides detailed device information including orientation and touch capabilities
22
+ */
23
+ export const useDevice = (): DeviceInfo => {
24
+ const [deviceInfo, setDeviceInfo] = useState<DeviceInfo>({
25
+ isMobile: false,
26
+ isTablet: false,
27
+ isDesktop: false,
28
+ screenSize: 'desktop',
29
+ orientation: 'landscape',
30
+ touchDevice: false
31
+ })
32
+
33
+ useEffect(() => {
34
+ const updateDeviceInfo = () => {
35
+ const width = window.innerWidth
36
+ const height = window.innerHeight
37
+
38
+ // Determine device type based on width
39
+ const isMobile = width < BREAKPOINTS.mobile
40
+ const isTablet = width >= BREAKPOINTS.mobile && width < BREAKPOINTS.tablet
41
+ const isDesktop = width >= BREAKPOINTS.tablet
42
+
43
+ // Determine screen size category
44
+ let screenSize: DeviceInfo['screenSize']
45
+ if (isMobile) screenSize = 'mobile'
46
+ else if (isTablet) screenSize = 'tablet'
47
+ else screenSize = 'desktop'
48
+
49
+ // Determine orientation
50
+ const orientation: DeviceInfo['orientation'] = width > height ? 'landscape' : 'portrait'
51
+
52
+ // Detect touch capability
53
+ const touchDevice = 'ontouchstart' in window ||
54
+ navigator.maxTouchPoints > 0 ||
55
+ // @ts-ignore - some browsers use this property
56
+ navigator.msMaxTouchPoints > 0
57
+
58
+ const newDeviceInfo = {
59
+ isMobile,
60
+ isTablet,
61
+ isDesktop,
62
+ screenSize,
63
+ orientation,
64
+ touchDevice
65
+ }
66
+
67
+ setDeviceInfo(newDeviceInfo)
68
+ }
69
+
70
+ // Initial detection
71
+ updateDeviceInfo()
72
+
73
+ // Listen for resize events
74
+ window.addEventListener('resize', updateDeviceInfo)
75
+
76
+ // Listen for orientation changes
77
+ window.addEventListener('orientationchange', () => {
78
+ // Small delay to ensure dimensions are updated
79
+ setTimeout(updateDeviceInfo, 100)
80
+ })
81
+
82
+ return () => {
83
+ window.removeEventListener('resize', updateDeviceInfo)
84
+ window.removeEventListener('orientationchange', updateDeviceInfo)
85
+ }
86
+ }, [])
87
+
88
+ return deviceInfo
89
+ }
90
+
91
+ // Convenience hooks for specific use cases
92
+ export const useIsMobile = () => useDevice().isMobile
93
+ export const useIsTablet = () => useDevice().isTablet
94
+ export const useIsDesktop = () => useDevice().isDesktop
95
+ export const useOrientation = () => useDevice().orientation
96
+ export const useIsTouchDevice = () => useDevice().touchDevice
97
+
98
+ // Utility function to get device-specific classes
99
+ export const getDeviceClasses = (deviceInfo: DeviceInfo): string => {
100
+ const classes = []
101
+
102
+ classes.push(`screen-${deviceInfo.screenSize}`)
103
+ classes.push(`orientation-${deviceInfo.orientation}`)
104
+
105
+ if (deviceInfo.touchDevice) {
106
+ classes.push('touch-device')
107
+ }
108
+
109
+ return classes.join(' ')
110
+ }