@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.
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,464 @@
1
+ import { useState, useEffect, useCallback, useRef } from 'react'
2
+
3
+ export interface LayoutConfig {
4
+ enableTouchOptimization: boolean
5
+ enableKeyboardOptimization: boolean
6
+ enableResponsiveBehavior: boolean
7
+ enablePerformanceOptimization: boolean
8
+ touchTargetSize: number
9
+ spacingMultiplier: number
10
+ maxFieldWidth: number
11
+ enableAutoFocus: boolean
12
+ }
13
+
14
+ export interface LayoutState {
15
+ isMobile: boolean
16
+ isTablet: boolean
17
+ isDesktop: boolean
18
+ orientation: 'portrait' | 'landscape'
19
+ keyboardVisible: boolean
20
+ viewportHeight: number
21
+ viewportWidth: number
22
+ safeAreaInsets: {
23
+ top: number
24
+ bottom: number
25
+ left: number
26
+ right: number
27
+ }
28
+ }
29
+
30
+ export interface LayoutCallbacks {
31
+ onLayoutChange?: (layout: LayoutState) => void
32
+ onOrientationChange?: (orientation: 'portrait' | 'landscape') => void
33
+ onKeyboardVisibilityChange?: (visible: boolean) => void
34
+ onViewportChange?: (width: number, height: number) => void
35
+ }
36
+
37
+ export interface MobileFormLayoutState {
38
+ layout: LayoutState
39
+ isOptimized: boolean
40
+ currentSpacing: number
41
+ currentFieldWidth: number
42
+ performanceMetrics: {
43
+ layoutUpdates: number
44
+ lastUpdateTime: number
45
+ optimizationScore: number
46
+ }
47
+ }
48
+
49
+ export const useMobileFormLayout = (
50
+ callbacks: LayoutCallbacks = {},
51
+ config: Partial<LayoutConfig> = {}
52
+ ) => {
53
+ const defaultConfig: LayoutConfig = {
54
+ enableTouchOptimization: true,
55
+ enableKeyboardOptimization: true,
56
+ enableResponsiveBehavior: true,
57
+ enablePerformanceOptimization: true,
58
+ touchTargetSize: 44,
59
+ spacingMultiplier: 1.2,
60
+ maxFieldWidth: 400,
61
+ enableAutoFocus: true,
62
+ ...config
63
+ }
64
+
65
+ const [layoutState, setLayoutState] = useState<MobileFormLayoutState>({
66
+ layout: {
67
+ isMobile: false,
68
+ isTablet: false,
69
+ isDesktop: false,
70
+ orientation: 'portrait',
71
+ keyboardVisible: false,
72
+ viewportHeight: window.innerHeight,
73
+ viewportWidth: window.innerWidth,
74
+ safeAreaInsets: { top: 0, bottom: 0, left: 0, right: 0 }
75
+ },
76
+ isOptimized: false,
77
+ currentSpacing: defaultConfig.touchTargetSize * defaultConfig.spacingMultiplier,
78
+ currentFieldWidth: Math.min(window.innerWidth - 32, defaultConfig.maxFieldWidth),
79
+ performanceMetrics: {
80
+ layoutUpdates: 0,
81
+ lastUpdateTime: 0,
82
+ optimizationScore: 0
83
+ }
84
+ })
85
+
86
+ const resizeObserverRef = useRef<ResizeObserver | null>(null)
87
+ const layoutUpdateTimerRef = useRef<NodeJS.Timeout | null>(null)
88
+ const keyboardTimerRef = useRef<NodeJS.Timeout | null>(null)
89
+
90
+ // Detect device type
91
+ const detectDeviceType = useCallback(() => {
92
+ const width = window.innerWidth
93
+ const userAgent = navigator.userAgent.toLowerCase()
94
+
95
+ let isMobile = false
96
+ let isTablet = false
97
+ let isDesktop = false
98
+
99
+ // Check screen size
100
+ if (width < 768) {
101
+ isMobile = true
102
+ } else if (width < 1024) {
103
+ isTablet = true
104
+ } else {
105
+ isDesktop = true
106
+ }
107
+
108
+ // Check user agent for mobile devices
109
+ if (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent)) {
110
+ isMobile = true
111
+ isTablet = width >= 768 && width < 1024
112
+ isDesktop = false
113
+ }
114
+
115
+ return { isMobile, isTablet, isDesktop }
116
+ }, [])
117
+
118
+ // Detect orientation
119
+ const detectOrientation = useCallback((): 'portrait' | 'landscape' => {
120
+ if (window.innerHeight > window.innerWidth) {
121
+ return 'portrait'
122
+ }
123
+ return 'landscape'
124
+ }, [])
125
+
126
+ // Get safe area insets (for devices with notches)
127
+ const getSafeAreaInsets = useCallback(() => {
128
+ const style = getComputedStyle(document.documentElement)
129
+
130
+ return {
131
+ top: parseInt(style.getPropertyValue('--sat') || '0'),
132
+ bottom: parseInt(style.getPropertyValue('--sab') || '0'),
133
+ left: parseInt(style.getPropertyValue('--sal') || '0'),
134
+ right: parseInt(style.getPropertyValue('--sar') || '0')
135
+ }
136
+ }, [])
137
+
138
+ // Detect keyboard visibility
139
+ const detectKeyboardVisibility = useCallback(() => {
140
+ if (!defaultConfig.enableKeyboardOptimization) return false
141
+
142
+ const currentHeight = window.innerHeight
143
+ const currentWidth = window.innerWidth
144
+
145
+ // Simple heuristic: if height decreases significantly and width stays the same
146
+ // it's likely the keyboard appeared
147
+ const heightRatio = currentHeight / layoutState.layout.viewportHeight
148
+ const widthRatio = currentWidth / layoutState.layout.viewportWidth
149
+
150
+ return heightRatio < 0.8 && widthRatio > 0.95
151
+ }, [defaultConfig.enableKeyboardOptimization, layoutState.layout.viewportHeight, layoutState.layout.viewportWidth])
152
+
153
+ // Update layout state
154
+ const updateLayout = useCallback(() => {
155
+ const deviceType = detectDeviceType()
156
+ const orientation = detectOrientation()
157
+ const safeAreaInsets = getSafeAreaInsets()
158
+ const keyboardVisible = detectKeyboardVisibility()
159
+
160
+ const newLayout: LayoutState = {
161
+ ...deviceType,
162
+ orientation,
163
+ keyboardVisible,
164
+ viewportHeight: window.innerHeight,
165
+ viewportWidth: window.innerWidth,
166
+ safeAreaInsets
167
+ }
168
+
169
+ // Calculate optimal spacing and field width
170
+ let spacing = defaultConfig.touchTargetSize * defaultConfig.spacingMultiplier
171
+ let fieldWidth = Math.min(window.innerWidth - 32, defaultConfig.maxFieldWidth)
172
+
173
+ // Adjust for mobile devices
174
+ if (newLayout.isMobile) {
175
+ spacing = Math.max(spacing, 16) // Minimum spacing for mobile
176
+ fieldWidth = Math.min(fieldWidth, window.innerWidth - 24) // Account for safe areas
177
+ }
178
+
179
+ // Adjust for keyboard visibility
180
+ if (newLayout.keyboardVisible) {
181
+ spacing = Math.max(spacing * 0.8, 12) // Reduce spacing when keyboard is visible
182
+ fieldWidth = Math.min(fieldWidth, window.innerWidth - 16)
183
+ }
184
+
185
+ // Adjust for orientation
186
+ if (newLayout.orientation === 'landscape' && newLayout.isMobile) {
187
+ spacing = Math.max(spacing * 0.9, 14)
188
+ fieldWidth = Math.min(fieldWidth, window.innerHeight - 24)
189
+ }
190
+
191
+ setLayoutState(prev => {
192
+ const newState = {
193
+ ...prev,
194
+ layout: newLayout,
195
+ currentSpacing: spacing,
196
+ currentFieldWidth: fieldWidth,
197
+ performanceMetrics: {
198
+ ...prev.performanceMetrics,
199
+ layoutUpdates: prev.performanceMetrics.layoutUpdates + 1,
200
+ lastUpdateTime: Date.now()
201
+ }
202
+ }
203
+
204
+ // Calculate optimization score
205
+ const score = calculateOptimizationScore(newState)
206
+ newState.performanceMetrics.optimizationScore = score
207
+ newState.isOptimized = score >= 0.8
208
+
209
+ return newState
210
+ })
211
+
212
+ // Notify callbacks
213
+ callbacks.onLayoutChange?.(newLayout)
214
+ callbacks.onOrientationChange?.(orientation)
215
+ callbacks.onKeyboardVisibilityChange?.(keyboardVisible)
216
+ callbacks.onViewportChange?.(window.innerWidth, window.innerHeight)
217
+ }, [
218
+ detectDeviceType,
219
+ detectOrientation,
220
+ getSafeAreaInsets,
221
+ detectKeyboardVisibility,
222
+ defaultConfig.touchTargetSize,
223
+ defaultConfig.spacingMultiplier,
224
+ defaultConfig.maxFieldWidth,
225
+ callbacks
226
+ ])
227
+
228
+ // Calculate optimization score
229
+ const calculateOptimizationScore = useCallback((state: MobileFormLayoutState): number => {
230
+ let score = 0
231
+ const { layout, currentSpacing, currentFieldWidth } = state
232
+
233
+ // Touch target optimization (40% weight)
234
+ if (currentSpacing >= defaultConfig.touchTargetSize) {
235
+ score += 0.4
236
+ } else if (currentSpacing >= defaultConfig.touchTargetSize * 0.8) {
237
+ score += 0.3
238
+ } else if (currentSpacing >= defaultConfig.touchTargetSize * 0.6) {
239
+ score += 0.2
240
+ }
241
+
242
+ // Field width optimization (30% weight)
243
+ const optimalWidth = Math.min(layout.viewportWidth - 32, defaultConfig.maxFieldWidth)
244
+ const widthRatio = currentFieldWidth / optimalWidth
245
+ if (widthRatio >= 0.9) {
246
+ score += 0.3
247
+ } else if (widthRatio >= 0.7) {
248
+ score += 0.2
249
+ } else if (widthRatio >= 0.5) {
250
+ score += 0.1
251
+ }
252
+
253
+ // Responsive behavior (20% weight)
254
+ if (layout.isMobile && layout.orientation === 'portrait') {
255
+ score += 0.2
256
+ } else if (layout.isMobile && layout.orientation === 'landscape') {
257
+ score += 0.15
258
+ } else if (layout.isTablet) {
259
+ score += 0.1
260
+ }
261
+
262
+ // Performance optimization (10% weight)
263
+ if (state.performanceMetrics.layoutUpdates < 10) {
264
+ score += 0.1
265
+ } else if (state.performanceMetrics.layoutUpdates < 20) {
266
+ score += 0.05
267
+ }
268
+
269
+ return Math.min(score, 1)
270
+ }, [defaultConfig.touchTargetSize, defaultConfig.maxFieldWidth])
271
+
272
+ // Debounced layout update
273
+ const debouncedUpdateLayout = useCallback(() => {
274
+ if (layoutUpdateTimerRef.current) {
275
+ clearTimeout(layoutUpdateTimerRef.current)
276
+ }
277
+
278
+ layoutUpdateTimerRef.current = setTimeout(() => {
279
+ updateLayout()
280
+ }, 100) // 100ms debounce
281
+ }, [updateLayout])
282
+
283
+ // Handle window resize
284
+ const handleResize = useCallback(() => {
285
+ if (defaultConfig.enableResponsiveBehavior) {
286
+ debouncedUpdateLayout()
287
+ }
288
+ }, [defaultConfig.enableResponsiveBehavior, debouncedUpdateLayout])
289
+
290
+ // Handle orientation change
291
+ const handleOrientationChange = useCallback(() => {
292
+ if (defaultConfig.enableResponsiveBehavior) {
293
+ // Add delay for orientation change to complete
294
+ setTimeout(() => {
295
+ updateLayout()
296
+ }, 300)
297
+ }
298
+ }, [defaultConfig.enableResponsiveBehavior, updateLayout])
299
+
300
+ // Handle keyboard visibility changes
301
+ const handleKeyboardChange = useCallback(() => {
302
+ if (defaultConfig.enableKeyboardOptimization) {
303
+ if (keyboardTimerRef.current) {
304
+ clearTimeout(keyboardTimerRef.current)
305
+ }
306
+
307
+ keyboardTimerRef.current = setTimeout(() => {
308
+ updateLayout()
309
+ }, 150) // Small delay to detect keyboard changes
310
+ }
311
+ }, [defaultConfig.enableKeyboardOptimization, updateLayout])
312
+
313
+ // Set up resize observer for more precise layout detection
314
+ useEffect(() => {
315
+ if (defaultConfig.enablePerformanceOptimization && 'ResizeObserver' in window) {
316
+ resizeObserverRef.current = new ResizeObserver(() => {
317
+ handleResize()
318
+ })
319
+
320
+ resizeObserverRef.current.observe(document.body)
321
+ }
322
+
323
+ return () => {
324
+ if (resizeObserverRef.current) {
325
+ resizeObserverRef.current.disconnect()
326
+ }
327
+ }
328
+ }, [defaultConfig.enablePerformanceOptimization, handleResize])
329
+
330
+ // Set up window event listeners
331
+ useEffect(() => {
332
+ if (defaultConfig.enableResponsiveBehavior) {
333
+ window.addEventListener('resize', handleResize)
334
+ window.addEventListener('orientationchange', handleOrientationChange)
335
+
336
+ // Listen for visual viewport changes (better for mobile)
337
+ if ('visualViewport' in window) {
338
+ (window as any).visualViewport.addEventListener('resize', handleKeyboardChange)
339
+ }
340
+ }
341
+
342
+ return () => {
343
+ window.removeEventListener('resize', handleResize)
344
+ window.removeEventListener('orientationchange', handleOrientationChange)
345
+
346
+ if ('visualViewport' in window) {
347
+ (window as any).visualViewport.removeEventListener('resize', handleKeyboardChange)
348
+ }
349
+ }
350
+ }, [defaultConfig.enableResponsiveBehavior, handleResize, handleOrientationChange, handleKeyboardChange])
351
+
352
+ // Initial layout detection
353
+ useEffect(() => {
354
+ updateLayout()
355
+ }, [updateLayout])
356
+
357
+ // Get CSS classes for layout optimization
358
+ const getLayoutClasses = useCallback(() => {
359
+ const { layout, isOptimized } = layoutState
360
+ const classes = ['mobile-form-layout']
361
+
362
+ if (layout.isMobile) {
363
+ classes.push('layout-mobile')
364
+ if (layout.orientation === 'portrait') {
365
+ classes.push('layout-portrait')
366
+ } else {
367
+ classes.push('layout-landscape')
368
+ }
369
+ } else if (layout.isTablet) {
370
+ classes.push('layout-tablet')
371
+ } else {
372
+ classes.push('layout-desktop')
373
+ }
374
+
375
+ if (layout.keyboardVisible) {
376
+ classes.push('layout-keyboard-visible')
377
+ }
378
+
379
+ if (isOptimized) {
380
+ classes.push('layout-optimized')
381
+ }
382
+
383
+ return classes.join(' ')
384
+ }, [layoutState])
385
+
386
+ // Get CSS variables for dynamic styling
387
+ const getLayoutCSSVariables = useCallback(() => {
388
+ const { currentSpacing, currentFieldWidth } = layoutState
389
+
390
+ return {
391
+ '--mobile-spacing': `${currentSpacing}px`,
392
+ '--mobile-field-width': `${currentFieldWidth}px`,
393
+ '--touch-target-size': `${defaultConfig.touchTargetSize}px`,
394
+ '--safe-area-top': `${layoutState.layout.safeAreaInsets.top}px`,
395
+ '--safe-area-bottom': `${layoutState.layout.safeAreaInsets.bottom}px`,
396
+ '--safe-area-left': `${layoutState.layout.safeAreaInsets.left}px`,
397
+ '--safe-area-right': `${layoutState.layout.safeAreaInsets.right}px`
398
+ }
399
+ }, [layoutState, defaultConfig.touchTargetSize])
400
+
401
+ // Auto-focus first input when layout changes
402
+ const autoFocusFirstInput = useCallback(() => {
403
+ if (!defaultConfig.enableAutoFocus) return
404
+
405
+ const firstInput = document.querySelector('input, textarea, select') as HTMLElement
406
+ if (firstInput && layoutState.layout.isMobile) {
407
+ // Small delay to ensure layout is stable
408
+ setTimeout(() => {
409
+ firstInput.focus()
410
+ }, 100)
411
+ }
412
+ }, [defaultConfig.enableAutoFocus, layoutState.layout.isMobile])
413
+
414
+ // Clean up timers on unmount
415
+ useEffect(() => {
416
+ return () => {
417
+ if (layoutUpdateTimerRef.current) {
418
+ clearTimeout(layoutUpdateTimerRef.current)
419
+ }
420
+ if (keyboardTimerRef.current) {
421
+ clearTimeout(keyboardTimerRef.current)
422
+ }
423
+ }
424
+ }, [])
425
+
426
+ return {
427
+ layoutState,
428
+ updateLayout,
429
+ getLayoutClasses,
430
+ getLayoutCSSVariables,
431
+ autoFocusFirstInput,
432
+ isMobile: layoutState.layout.isMobile,
433
+ isTablet: layoutState.layout.isTablet,
434
+ isDesktop: layoutState.layout.isDesktop,
435
+ orientation: layoutState.layout.orientation,
436
+ keyboardVisible: layoutState.layout.keyboardVisible,
437
+ currentSpacing: layoutState.currentSpacing,
438
+ currentFieldWidth: layoutState.currentFieldWidth,
439
+ isOptimized: layoutState.isOptimized,
440
+ performanceMetrics: layoutState.performanceMetrics
441
+ }
442
+ }
443
+
444
+ // Convenience hook for basic mobile layout
445
+ export const useBasicMobileLayout = () => {
446
+ return useMobileFormLayout({}, {
447
+ enableTouchOptimization: true,
448
+ enableKeyboardOptimization: false,
449
+ enableResponsiveBehavior: true,
450
+ enablePerformanceOptimization: false,
451
+ enableAutoFocus: false
452
+ })
453
+ }
454
+
455
+ // Convenience hook for enhanced mobile layout
456
+ export const useEnhancedMobileLayout = () => {
457
+ return useMobileFormLayout({}, {
458
+ enableTouchOptimization: true,
459
+ enableKeyboardOptimization: true,
460
+ enableResponsiveBehavior: true,
461
+ enablePerformanceOptimization: true,
462
+ enableAutoFocus: true
463
+ })
464
+ }