@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.4 → 0.1.6

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,518 @@
1
+ import { useState, useEffect, useCallback, useRef, useMemo } from 'react'
2
+
3
+ export interface ValidationRule {
4
+ type: 'required' | 'email' | 'minLength' | 'maxLength' | 'pattern' | 'custom'
5
+ value?: string | number | RegExp
6
+ message: string
7
+ validator?: (value: any) => boolean | Promise<boolean>
8
+ }
9
+
10
+ export interface ValidationState {
11
+ isValid: boolean
12
+ errors: string[]
13
+ isDirty: boolean
14
+ isTouched: boolean
15
+ isSubmitting: boolean
16
+ isSubmitted: boolean
17
+ }
18
+
19
+ export interface FormField {
20
+ name: string
21
+ value: any
22
+ rules: ValidationRule[]
23
+ validationState: ValidationState
24
+ }
25
+
26
+ export interface MobileFormValidationConfig {
27
+ enableTouchFeedback: boolean
28
+ enableHapticFeedback: boolean
29
+ enableSoundFeedback: boolean
30
+ validationDelay: number
31
+ enablePerformanceOptimization: boolean
32
+ maxValidationRetries: number
33
+ }
34
+
35
+ export interface ValidationCallbacks {
36
+ onValidationStart?: (fieldName: string) => void
37
+ onValidationComplete?: (fieldName: string, isValid: boolean, errors: string[]) => void
38
+ onFormSubmit?: (formData: Record<string, any>, isValid: boolean) => void
39
+ onValidationError?: (fieldName: string, errors: string[]) => void
40
+ onValidationSuccess?: (fieldName: string) => void
41
+ }
42
+
43
+ export interface MobileFormValidationState {
44
+ fields: Record<string, FormField>
45
+ overallValidation: ValidationState
46
+ isOptimized: boolean
47
+ performanceMetrics: {
48
+ validationCount: number
49
+ averageValidationTime: number
50
+ lastValidationTime: number
51
+ }
52
+ }
53
+
54
+ export const useMobileFormValidation = (
55
+ initialFields: Record<string, Omit<FormField, 'validationState'>>,
56
+ callbacks: ValidationCallbacks = {},
57
+ config: Partial<MobileFormValidationConfig> = {}
58
+ ) => {
59
+ const defaultConfig: MobileFormValidationConfig = {
60
+ enableTouchFeedback: true,
61
+ enableHapticFeedback: true,
62
+ enableSoundFeedback: false,
63
+ validationDelay: 300,
64
+ enablePerformanceOptimization: true,
65
+ maxValidationRetries: 3,
66
+ ...config
67
+ }
68
+
69
+ const [validationState, setValidationState] = useState<MobileFormValidationState>({
70
+ fields: Object.keys(initialFields).reduce((acc, fieldName) => {
71
+ acc[fieldName] = {
72
+ ...initialFields[fieldName],
73
+ validationState: {
74
+ isValid: true,
75
+ errors: [],
76
+ isDirty: false,
77
+ isTouched: false,
78
+ isSubmitting: false,
79
+ isSubmitted: false
80
+ }
81
+ }
82
+ return acc
83
+ }, {} as Record<string, FormField>),
84
+ overallValidation: {
85
+ isValid: true,
86
+ errors: [],
87
+ isDirty: false,
88
+ isTouched: false,
89
+ isSubmitting: false,
90
+ isSubmitted: false
91
+ },
92
+ isOptimized: false,
93
+ performanceMetrics: {
94
+ validationCount: 0,
95
+ averageValidationTime: 0,
96
+ lastValidationTime: 0
97
+ }
98
+ })
99
+
100
+ const validationTimersRef = useRef<Record<string, NodeJS.Timeout>>({})
101
+ const validationRetryCountRef = useRef<Record<string, number>>({})
102
+
103
+ // Trigger haptic feedback
104
+ const triggerHapticFeedback = useCallback((intensity: 'light' | 'medium' | 'strong' = 'medium') => {
105
+ if (!defaultConfig.enableHapticFeedback || !('vibrate' in navigator)) return
106
+
107
+ const vibrationPattern = {
108
+ light: 20,
109
+ medium: 50,
110
+ strong: 100
111
+ }
112
+
113
+ try {
114
+ navigator.vibrate(vibrationPattern[intensity])
115
+ } catch (error) {
116
+ console.warn('Haptic feedback not supported:', error)
117
+ }
118
+ }, [defaultConfig.enableHapticFeedback])
119
+
120
+ // Trigger sound feedback
121
+ const triggerSoundFeedback = useCallback((type: 'success' | 'error' = 'success') => {
122
+ if (!defaultConfig.enableSoundFeedback || !('AudioContext' in window)) return
123
+
124
+ try {
125
+ const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)()
126
+ const oscillator = audioContext.createOscillator()
127
+ const gainNode = audioContext.createGain()
128
+
129
+ oscillator.connect(gainNode)
130
+ gainNode.connect(audioContext.destination)
131
+
132
+ const soundConfig = {
133
+ success: { frequency: 800, duration: 0.1, volume: 0.1 },
134
+ error: { frequency: 400, duration: 0.2, volume: 0.15 }
135
+ }
136
+
137
+ const config = soundConfig[type]
138
+ oscillator.frequency.setValueAtTime(config.frequency, audioContext.currentTime)
139
+ gainNode.gain.setValueAtTime(config.volume, audioContext.currentTime)
140
+
141
+ oscillator.start(audioContext.currentTime)
142
+ oscillator.stop(audioContext.currentTime + config.duration)
143
+ } catch (error) {
144
+ console.warn('Sound feedback not supported:', error)
145
+ }
146
+ }, [defaultConfig.enableSoundFeedback])
147
+
148
+ // Validate a single field
149
+ const validateField = useCallback(async (
150
+ fieldName: string,
151
+ value: any,
152
+ rules: ValidationRule[]
153
+ ): Promise<{ isValid: boolean; errors: string[] }> => {
154
+ const errors: string[] = []
155
+ const startTime = performance.now()
156
+
157
+ for (const rule of rules) {
158
+ let isValid = true
159
+
160
+ try {
161
+ switch (rule.type) {
162
+ case 'required':
163
+ isValid = value !== null && value !== undefined && value !== ''
164
+ break
165
+
166
+ case 'email':
167
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
168
+ isValid = emailRegex.test(String(value))
169
+ break
170
+
171
+ case 'minLength':
172
+ isValid = String(value).length >= (rule.value as number)
173
+ break
174
+
175
+ case 'maxLength':
176
+ isValid = String(value).length <= (rule.value as number)
177
+ break
178
+
179
+ case 'pattern':
180
+ if (rule.value instanceof RegExp) {
181
+ isValid = rule.value.test(String(value))
182
+ }
183
+ break
184
+
185
+ case 'custom':
186
+ if (rule.validator) {
187
+ try {
188
+ isValid = await rule.validator(value)
189
+ } catch (error) {
190
+ console.error('Custom validation error:', error)
191
+ isValid = false
192
+ }
193
+ }
194
+ break
195
+ }
196
+
197
+ if (!isValid) {
198
+ errors.push(rule.message)
199
+ }
200
+ } catch (error) {
201
+ console.error(`Validation error for rule ${rule.type} in field ${fieldName}:`, error)
202
+ errors.push(rule.message)
203
+ }
204
+ }
205
+
206
+ const endTime = performance.now()
207
+ const validationTime = endTime - startTime
208
+
209
+ // Update performance metrics
210
+ setValidationState(prev => ({
211
+ ...prev,
212
+ performanceMetrics: {
213
+ validationCount: prev.performanceMetrics.validationCount + 1,
214
+ averageValidationTime: (prev.performanceMetrics.averageValidationTime * prev.performanceMetrics.validationCount + validationTime) / (prev.performanceMetrics.validationCount + 1),
215
+ lastValidationTime: validationTime
216
+ }
217
+ }))
218
+
219
+ return { isValid: errors.length === 0, errors }
220
+ }, [])
221
+
222
+ // Debounced field validation
223
+ const debouncedValidateField = useCallback((
224
+ fieldName: string,
225
+ value: any,
226
+ rules: ValidationRule[]
227
+ ) => {
228
+ // Clear existing timer
229
+ if (validationTimersRef.current[fieldName]) {
230
+ clearTimeout(validationTimersRef.current[fieldName])
231
+ }
232
+
233
+ // Set new timer
234
+ validationTimersRef.current[fieldName] = setTimeout(async () => {
235
+ callbacks.onValidationStart?.(fieldName)
236
+
237
+ try {
238
+ const result = await validateField(fieldName, value, rules)
239
+
240
+ setValidationState(prev => ({
241
+ ...prev,
242
+ fields: {
243
+ ...prev.fields,
244
+ [fieldName]: {
245
+ ...prev.fields[fieldName],
246
+ validationState: {
247
+ ...prev.fields[fieldName].validationState,
248
+ isValid: result.isValid,
249
+ errors: result.errors,
250
+ isDirty: true
251
+ }
252
+ }
253
+ }
254
+ }))
255
+
256
+ if (result.isValid) {
257
+ callbacks.onValidationSuccess?.(fieldName)
258
+ triggerHapticFeedback('light')
259
+ triggerSoundFeedback('success')
260
+ } else {
261
+ callbacks.onValidationError?.(fieldName, result.errors)
262
+ triggerHapticFeedback('strong')
263
+ triggerSoundFeedback('error')
264
+ }
265
+
266
+ callbacks.onValidationComplete?.(fieldName, result.isValid, result.errors)
267
+ } catch (error) {
268
+ console.error(`Validation error for field ${fieldName}:`, error)
269
+
270
+ // Retry validation if enabled
271
+ const retryCount = validationRetryCountRef.current[fieldName] || 0
272
+ if (retryCount < defaultConfig.maxValidationRetries) {
273
+ validationRetryCountRef.current[fieldName] = retryCount + 1
274
+ setTimeout(() => debouncedValidateField(fieldName, value, rules), 1000)
275
+ }
276
+ }
277
+ }, defaultConfig.validationDelay)
278
+ }, [validateField, callbacks, defaultConfig.validationDelay, defaultConfig.maxValidationRetries, triggerHapticFeedback, triggerSoundFeedback])
279
+
280
+ // Update field value and trigger validation
281
+ const updateField = useCallback((
282
+ fieldName: string,
283
+ value: any,
284
+ shouldValidate: boolean = true
285
+ ) => {
286
+ setValidationState(prev => ({
287
+ ...prev,
288
+ fields: {
289
+ ...prev.fields,
290
+ [fieldName]: {
291
+ ...prev.fields[fieldName],
292
+ value,
293
+ validationState: {
294
+ ...prev.fields[fieldName].validationState,
295
+ isTouched: true
296
+ }
297
+ }
298
+ }
299
+ }))
300
+
301
+ if (shouldValidate && validationState.fields[fieldName].rules.length > 0) {
302
+ debouncedValidateField(fieldName, value, validationState.fields[fieldName].rules)
303
+ }
304
+ }, [validationState.fields, debouncedValidateField])
305
+
306
+ // Touch field (mark as touched without validation)
307
+ const touchField = useCallback((fieldName: string) => {
308
+ setValidationState(prev => ({
309
+ ...prev,
310
+ fields: {
311
+ ...prev.fields,
312
+ [fieldName]: {
313
+ ...prev.fields[fieldName],
314
+ validationState: {
315
+ ...prev.fields[fieldName].validationState,
316
+ isTouched: true
317
+ }
318
+ }
319
+ }
320
+ }))
321
+ }, [])
322
+
323
+ // Validate all fields
324
+ const validateAllFields = useCallback(async (): Promise<boolean> => {
325
+ const fieldNames = Object.keys(validationState.fields)
326
+ const validationPromises = fieldNames.map(fieldName => {
327
+ const field = validationState.fields[fieldName]
328
+ return validateField(fieldName, field.value, field.rules)
329
+ })
330
+
331
+ try {
332
+ const results = await Promise.all(validationPromises)
333
+ const allValid = results.every(result => result.isValid)
334
+ const allErrors = results.flatMap(result => result.errors)
335
+
336
+ setValidationState(prev => ({
337
+ ...prev,
338
+ overallValidation: {
339
+ ...prev.overallValidation,
340
+ isValid: allValid,
341
+ errors: allErrors,
342
+ isDirty: true
343
+ }
344
+ }))
345
+
346
+ return allValid
347
+ } catch (error) {
348
+ console.error('Validation error:', error)
349
+ return false
350
+ }
351
+ }, [validationState.fields, validateField])
352
+
353
+ // Submit form
354
+ const submitForm = useCallback(async (): Promise<{ success: boolean; data: Record<string, any>; errors: string[] }> => {
355
+ setValidationState(prev => ({
356
+ ...prev,
357
+ overallValidation: {
358
+ ...prev.overallValidation,
359
+ isSubmitting: true
360
+ }
361
+ }))
362
+
363
+ try {
364
+ const isValid = await validateAllFields()
365
+
366
+ if (isValid) {
367
+ const formData = Object.keys(validationState.fields).reduce((acc, fieldName) => {
368
+ acc[fieldName] = validationState.fields[fieldName].value
369
+ return acc
370
+ }, {} as Record<string, any>)
371
+
372
+ setValidationState(prev => ({
373
+ ...prev,
374
+ overallValidation: {
375
+ ...prev.overallValidation,
376
+ isSubmitted: true,
377
+ isSubmitting: false
378
+ }
379
+ }))
380
+
381
+ callbacks.onFormSubmit?.(formData, true)
382
+ triggerHapticFeedback('medium')
383
+ triggerSoundFeedback('success')
384
+
385
+ return { success: true, data: formData, errors: [] }
386
+ } else {
387
+ setValidationState(prev => ({
388
+ ...prev,
389
+ overallValidation: {
390
+ ...prev.overallValidation,
391
+ isSubmitting: false
392
+ }
393
+ }))
394
+
395
+ callbacks.onFormSubmit?.({}, false)
396
+ triggerHapticFeedback('strong')
397
+ triggerSoundFeedback('error')
398
+
399
+ return { success: false, data: {}, errors: validationState.overallValidation.errors }
400
+ }
401
+ } catch (error) {
402
+ console.error('Form submission error:', error)
403
+
404
+ setValidationState(prev => ({
405
+ ...prev,
406
+ overallValidation: {
407
+ ...prev.overallValidation,
408
+ isSubmitting: false
409
+ }
410
+ }))
411
+
412
+ return { success: false, data: {}, errors: ['Form submission failed'] }
413
+ }
414
+ }, [validationState.fields, validationState.overallValidation.errors, validateAllFields, callbacks, triggerHapticFeedback, triggerSoundFeedback])
415
+
416
+ // Reset form
417
+ const resetForm = useCallback(() => {
418
+ setValidationState(prev => ({
419
+ ...prev,
420
+ fields: Object.keys(prev.fields).reduce((acc, fieldName) => {
421
+ acc[fieldName] = {
422
+ ...prev.fields[fieldName],
423
+ value: initialFields[fieldName].value,
424
+ validationState: {
425
+ isValid: true,
426
+ errors: [],
427
+ isDirty: false,
428
+ isTouched: false,
429
+ isSubmitting: false,
430
+ isSubmitted: false
431
+ }
432
+ }
433
+ return acc
434
+ }, {} as Record<string, FormField>),
435
+ overallValidation: {
436
+ isValid: true,
437
+ errors: [],
438
+ isDirty: false,
439
+ isTouched: false,
440
+ isSubmitting: false,
441
+ isSubmitted: false
442
+ }
443
+ }))
444
+
445
+ // Clear validation timers
446
+ Object.values(validationTimersRef.current).forEach(timer => clearTimeout(timer))
447
+ validationTimersRef.current = {}
448
+ validationRetryCountRef.current = {}
449
+ }, [initialFields])
450
+
451
+ // Get field validation state
452
+ const getFieldValidation = useCallback((fieldName: string) => {
453
+ return validationState.fields[fieldName]?.validationState || {
454
+ isValid: true,
455
+ errors: [],
456
+ isDirty: false,
457
+ isTouched: false,
458
+ isSubmitting: false,
459
+ isSubmitted: false
460
+ }
461
+ }, [validationState.fields])
462
+
463
+ // Check if form is valid
464
+ const isFormValid = useMemo(() => {
465
+ return Object.values(validationState.fields).every(field => field.validationState.isValid)
466
+ }, [validationState.fields])
467
+
468
+ // Check if form is dirty
469
+ const isFormDirty = useMemo(() => {
470
+ return Object.values(validationState.fields).some(field => field.validationState.isDirty)
471
+ }, [validationState.fields])
472
+
473
+ // Clean up timers on unmount
474
+ useEffect(() => {
475
+ return () => {
476
+ Object.values(validationTimersRef.current).forEach(timer => clearTimeout(timer))
477
+ }
478
+ }, [])
479
+
480
+ return {
481
+ validationState,
482
+ updateField,
483
+ touchField,
484
+ validateField: debouncedValidateField,
485
+ validateAllFields,
486
+ submitForm,
487
+ resetForm,
488
+ getFieldValidation,
489
+ isFormValid,
490
+ isFormDirty,
491
+ triggerHapticFeedback,
492
+ triggerSoundFeedback
493
+ }
494
+ }
495
+
496
+ // Convenience hook for basic form validation
497
+ export const useBasicFormValidation = (initialFields: Record<string, Omit<FormField, 'validationState'>>) => {
498
+ return useMobileFormValidation(initialFields, {}, {
499
+ enableTouchFeedback: true,
500
+ enableHapticFeedback: false,
501
+ enableSoundFeedback: false,
502
+ validationDelay: 500,
503
+ enablePerformanceOptimization: false,
504
+ maxValidationRetries: 1
505
+ })
506
+ }
507
+
508
+ // Convenience hook for enhanced form validation
509
+ export const useEnhancedFormValidation = (initialFields: Record<string, Omit<FormField, 'validationState'>>) => {
510
+ return useMobileFormValidation(initialFields, {}, {
511
+ enableTouchFeedback: true,
512
+ enableHapticFeedback: true,
513
+ enableSoundFeedback: true,
514
+ validationDelay: 300,
515
+ enablePerformanceOptimization: true,
516
+ maxValidationRetries: 3
517
+ })
518
+ }