ywana-core8 0.1.74 → 0.1.76
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/ACCORDION_EVALUATION.md +583 -0
- package/CHECKBOX_EVALUATION.md +273 -0
- package/CHIP_EVALUATION.md +542 -0
- package/COLOR_EVALUATION.md +524 -0
- package/COMPONENTS_EVALUATION.md +477 -0
- package/FORM_EVALUATION.md +459 -0
- package/HEADER_EVALUATION.md +436 -0
- package/ICON_EVALUATION.md +254 -0
- package/LIST_EVALUATION.md +574 -0
- package/PROGRESS_EVALUATION.md +450 -0
- package/RADIO_EVALUATION.md +439 -0
- package/RADIO_VISUAL_FIX.md +183 -0
- package/SECTION_IMPROVEMENTS.md +153 -0
- package/SWITCH_EVALUATION.md +335 -0
- package/SWITCH_VISUAL_FIX.md +232 -0
- package/TAB_EVALUATION.md +626 -0
- package/TEXTFIELD_EVALUATION.md +747 -0
- package/TOOLTIP_FIX.md +157 -0
- package/TREE_EVALUATION.md +708 -0
- package/dist/index.cjs +7900 -1615
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +6094 -1122
- package/dist/index.css.map +1 -1
- package/dist/index.modern.js +7929 -1645
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +7900 -1615
- package/dist/index.umd.js.map +1 -1
- package/jest.config.js +24 -0
- package/package.json +10 -1
- package/src/html/accordion.css +208 -4
- package/src/html/accordion.example.js +390 -0
- package/src/html/accordion.js +284 -28
- package/src/html/accordion.unit.test.js +334 -0
- package/src/html/button.css +157 -16
- package/src/html/button.example.js +374 -0
- package/src/html/button.js +240 -60
- package/src/html/button.test.js +422 -0
- package/src/html/checkbox.css +74 -2
- package/src/html/checkbox.example.js +316 -0
- package/src/html/checkbox.js +113 -26
- package/src/html/checkbox.test.js +285 -0
- package/src/html/chip.css +230 -19
- package/src/html/chip.example.js +355 -0
- package/src/html/chip.js +321 -25
- package/src/html/chip.test.js +425 -0
- package/src/html/color.css +435 -6
- package/src/html/color.example.js +527 -0
- package/src/html/color.js +458 -9
- package/src/html/color.test.js +362 -4
- package/src/html/components.example.js +492 -0
- package/src/html/components_enhanced.test.js +581 -0
- package/src/html/form.css +70 -3
- package/src/html/form.example.js +385 -0
- package/src/html/form.js +232 -34
- package/src/html/form.test.js +369 -0
- package/src/html/header2.css +264 -0
- package/src/html/header2.example.js +411 -0
- package/src/html/header2.js +203 -0
- package/src/html/header2.test.js +377 -0
- package/src/html/icon.css +20 -2
- package/src/html/icon.example.js +268 -0
- package/src/html/icon.js +86 -16
- package/src/html/icon.test.js +231 -0
- package/src/html/index.js +1 -1
- package/src/html/list.css +393 -1
- package/src/html/list.example.js +404 -0
- package/src/html/list.js +583 -40
- package/src/html/list.test.js +383 -0
- package/src/html/progress.css +707 -17
- package/src/html/progress.example.js +424 -0
- package/src/html/progress.js +906 -9
- package/src/html/progress.test.js +313 -0
- package/src/html/property.css +399 -0
- package/src/html/property.example.js +553 -0
- package/src/html/property.js +393 -15
- package/src/html/property.test.js +351 -2
- package/src/html/radio-visual-test.js +289 -0
- package/src/html/radio.css +137 -11
- package/src/html/radio.example.js +389 -0
- package/src/html/radio.js +234 -10
- package/src/html/radio.test.js +318 -0
- package/src/html/section.example.js +99 -0
- package/src/html/section.js +40 -3
- package/src/html/section.test.js +131 -0
- package/src/html/selector.css +329 -3
- package/src/html/selector.js +369 -23
- package/src/html/switch-debug.js +197 -0
- package/src/html/switch-test-visual.js +294 -0
- package/src/html/switch.css +200 -0
- package/src/html/switch.example.js +461 -0
- package/src/html/switch.js +283 -23
- package/src/html/switch.test.js +355 -0
- package/src/html/tab.css +288 -0
- package/src/html/tab.example.js +446 -0
- package/src/html/tab.js +387 -22
- package/src/html/tab_enhanced.js +378 -0
- package/src/html/tab_enhanced.test.js +504 -0
- package/src/html/table2.css +576 -0
- package/src/html/table2.example.js +703 -0
- package/src/html/table2.js +1252 -0
- package/src/html/table2.migration.md +328 -0
- package/src/html/table2.test.js +582 -0
- package/src/html/text.css +375 -0
- package/src/html/text.js +311 -20
- package/src/html/textfield.js +1 -1
- package/src/html/textfield2.css +842 -0
- package/src/html/textfield2.example.js +499 -0
- package/src/html/textfield2.js +1130 -0
- package/src/html/textfield2.test.js +950 -0
- package/src/html/thumbnail.css +289 -2
- package/src/html/thumbnail.js +214 -9
- package/src/html/tokenfield.css +449 -1
- package/src/html/tokenfield.example.js +503 -0
- package/src/html/tokenfield.js +561 -56
- package/src/html/tokenfield.test.js +423 -0
- package/src/html/tooltip-positioning-demo.js +187 -0
- package/src/html/tooltip.css +25 -2
- package/src/html/tree.css +228 -0
- package/src/html/tree.example.js +475 -0
- package/src/html/tree.js +712 -28
- package/src/html/tree_enhanced.test.js +495 -0
- package/table2.test.js +454 -0
- package/src/html/button.tsx +0 -38
@@ -0,0 +1,499 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
import { TextField2, TextArea2, PasswordField2, DropDown2, DateRange2 } from './textfield2'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Ejemplos de uso de los componentes TextField2 mejorados
|
6
|
+
*/
|
7
|
+
export const TextField2Examples = () => {
|
8
|
+
const [formData, setFormData] = useState({})
|
9
|
+
const [validationErrors, setValidationErrors] = useState({})
|
10
|
+
|
11
|
+
const handleFieldChange = (id, value) => {
|
12
|
+
setFormData(prev => ({
|
13
|
+
...prev,
|
14
|
+
[id]: value
|
15
|
+
}))
|
16
|
+
}
|
17
|
+
|
18
|
+
const handleValidation = (id, isValid, message) => {
|
19
|
+
setValidationErrors(prev => ({
|
20
|
+
...prev,
|
21
|
+
[id]: isValid ? null : message
|
22
|
+
}))
|
23
|
+
}
|
24
|
+
|
25
|
+
// Validaciones personalizadas
|
26
|
+
const validateEmail = (value) => {
|
27
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
28
|
+
return {
|
29
|
+
valid: emailRegex.test(value),
|
30
|
+
message: emailRegex.test(value) ? '' : 'Please enter a valid email address'
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
const validatePassword = (value) => {
|
35
|
+
const hasLength = value.length >= 8
|
36
|
+
const hasUpper = /[A-Z]/.test(value)
|
37
|
+
const hasLower = /[a-z]/.test(value)
|
38
|
+
const hasNumber = /\d/.test(value)
|
39
|
+
|
40
|
+
const valid = hasLength && hasUpper && hasLower && hasNumber
|
41
|
+
let message = ''
|
42
|
+
|
43
|
+
if (!valid) {
|
44
|
+
const missing = []
|
45
|
+
if (!hasLength) missing.push('8+ characters')
|
46
|
+
if (!hasUpper) missing.push('uppercase letter')
|
47
|
+
if (!hasLower) missing.push('lowercase letter')
|
48
|
+
if (!hasNumber) missing.push('number')
|
49
|
+
message = `Password must contain: ${missing.join(', ')}`
|
50
|
+
}
|
51
|
+
|
52
|
+
return { valid, message }
|
53
|
+
}
|
54
|
+
|
55
|
+
const validatePhone = (value) => {
|
56
|
+
const phoneRegex = /^\+?[\d\s\-\(\)]{10,}$/
|
57
|
+
return phoneRegex.test(value)
|
58
|
+
}
|
59
|
+
|
60
|
+
// Opciones para dropdowns
|
61
|
+
const countryOptions = [
|
62
|
+
{ value: 'us', label: 'United States', icon: 'flag' },
|
63
|
+
{ value: 'ca', label: 'Canada', icon: 'flag' },
|
64
|
+
{ value: 'mx', label: 'Mexico', icon: 'flag' },
|
65
|
+
{ value: 'uk', label: 'United Kingdom', icon: 'flag' },
|
66
|
+
{ value: 'de', label: 'Germany', icon: 'flag' },
|
67
|
+
{ value: 'fr', label: 'France', icon: 'flag' },
|
68
|
+
{ value: 'es', label: 'Spain', icon: 'flag' },
|
69
|
+
{ value: 'it', label: 'Italy', icon: 'flag' }
|
70
|
+
]
|
71
|
+
|
72
|
+
const skillOptions = [
|
73
|
+
{ value: 'react', label: 'React', category: 'Frontend' },
|
74
|
+
{ value: 'vue', label: 'Vue.js', category: 'Frontend' },
|
75
|
+
{ value: 'angular', label: 'Angular', category: 'Frontend' },
|
76
|
+
{ value: 'nodejs', label: 'Node.js', category: 'Backend' },
|
77
|
+
{ value: 'python', label: 'Python', category: 'Backend' },
|
78
|
+
{ value: 'java', label: 'Java', category: 'Backend' },
|
79
|
+
{ value: 'docker', label: 'Docker', category: 'DevOps' },
|
80
|
+
{ value: 'kubernetes', label: 'Kubernetes', category: 'DevOps' }
|
81
|
+
]
|
82
|
+
|
83
|
+
const priorityOptions = [
|
84
|
+
{ value: 'low', label: 'Low Priority', icon: 'arrow_downward' },
|
85
|
+
{ value: 'medium', label: 'Medium Priority', icon: 'remove' },
|
86
|
+
{ value: 'high', label: 'High Priority', icon: 'arrow_upward' },
|
87
|
+
{ value: 'urgent', label: 'Urgent', icon: 'warning' }
|
88
|
+
]
|
89
|
+
|
90
|
+
return (
|
91
|
+
<div style={{ padding: '2rem', maxWidth: '1200px', maxHeight: '100vh', overflow: 'auto' }}>
|
92
|
+
<h1>Ejemplos de Componentes TextField2 Mejorados</h1>
|
93
|
+
|
94
|
+
<div style={{
|
95
|
+
background: '#f8f9fa',
|
96
|
+
padding: '1rem',
|
97
|
+
borderRadius: '8px',
|
98
|
+
marginBottom: '2rem',
|
99
|
+
border: '1px solid #e9ecef'
|
100
|
+
}}>
|
101
|
+
<h3>✅ Mejoras Implementadas:</h3>
|
102
|
+
<ul>
|
103
|
+
<li>🛡️ <strong>Validación robusta</strong> - PropTypes, validación personalizable, mensajes de error</li>
|
104
|
+
<li>♿ <strong>Accesibilidad completa</strong> - ARIA, roles, live regions, soporte de teclado</li>
|
105
|
+
<li>📝 <strong>Documentación completa</strong> - PropTypes detallados y ejemplos</li>
|
106
|
+
<li>🎯 <strong>Estados avanzados</strong> - disabled, error, focused, invalid, readonly</li>
|
107
|
+
<li>🎨 <strong>CSS mejorado</strong> - Altura automática, responsive, temas</li>
|
108
|
+
<li>⚡ <strong>Debouncing</strong> - Control de frecuencia de onChange</li>
|
109
|
+
<li>🔧 <strong>Componentes especializados</strong> - TextField2, TextArea2, PasswordField2, DropDown2, DateRange2</li>
|
110
|
+
<li>🧪 <strong>Pruebas exhaustivas</strong> - 39 pruebas que cubren toda la funcionalidad</li>
|
111
|
+
</ul>
|
112
|
+
</div>
|
113
|
+
|
114
|
+
{/* TextField2 básicos */}
|
115
|
+
<section style={{ marginBottom: '2rem' }}>
|
116
|
+
<h3>TextField2 - Campos de Texto Básicos</h3>
|
117
|
+
<div style={{
|
118
|
+
background: '#fff',
|
119
|
+
padding: '1.5rem',
|
120
|
+
borderRadius: '8px',
|
121
|
+
border: '1px solid #ddd',
|
122
|
+
display: 'grid',
|
123
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
124
|
+
gap: '1rem'
|
125
|
+
}}>
|
126
|
+
<TextField2
|
127
|
+
id="firstName"
|
128
|
+
label="First Name"
|
129
|
+
placeholder="Enter your first name"
|
130
|
+
value={formData.firstName || ''}
|
131
|
+
required={true}
|
132
|
+
onChange={handleFieldChange}
|
133
|
+
helperText="Required field"
|
134
|
+
/>
|
135
|
+
|
136
|
+
<TextField2
|
137
|
+
id="lastName"
|
138
|
+
label="Last Name"
|
139
|
+
placeholder="Enter your last name"
|
140
|
+
value={formData.lastName || ''}
|
141
|
+
outlined={true}
|
142
|
+
onChange={handleFieldChange}
|
143
|
+
/>
|
144
|
+
|
145
|
+
<TextField2
|
146
|
+
id="email"
|
147
|
+
type="email"
|
148
|
+
label="Email Address"
|
149
|
+
placeholder="user@example.com"
|
150
|
+
value={formData.email || ''}
|
151
|
+
required={true}
|
152
|
+
outlined={true}
|
153
|
+
validation={validateEmail}
|
154
|
+
onChange={handleFieldChange}
|
155
|
+
onValidation={handleValidation}
|
156
|
+
autoComplete="email"
|
157
|
+
/>
|
158
|
+
|
159
|
+
<TextField2
|
160
|
+
id="phone"
|
161
|
+
type="tel"
|
162
|
+
label="Phone Number"
|
163
|
+
placeholder="+1 (555) 123-4567"
|
164
|
+
value={formData.phone || ''}
|
165
|
+
validation={validatePhone}
|
166
|
+
onChange={handleFieldChange}
|
167
|
+
onValidation={handleValidation}
|
168
|
+
autoComplete="tel"
|
169
|
+
/>
|
170
|
+
|
171
|
+
<TextField2
|
172
|
+
id="website"
|
173
|
+
type="url"
|
174
|
+
label="Website"
|
175
|
+
placeholder="https://example.com"
|
176
|
+
value={formData.website || ''}
|
177
|
+
outlined={true}
|
178
|
+
onChange={handleFieldChange}
|
179
|
+
autoComplete="url"
|
180
|
+
/>
|
181
|
+
|
182
|
+
<TextField2
|
183
|
+
id="age"
|
184
|
+
type="number"
|
185
|
+
label="Age"
|
186
|
+
placeholder="25"
|
187
|
+
value={formData.age || ''}
|
188
|
+
min="18"
|
189
|
+
max="100"
|
190
|
+
onChange={handleFieldChange}
|
191
|
+
/>
|
192
|
+
</div>
|
193
|
+
</section>
|
194
|
+
|
195
|
+
{/* PasswordField2 */}
|
196
|
+
<section style={{ marginBottom: '2rem' }}>
|
197
|
+
<h3>PasswordField2 - Campos de Contraseña</h3>
|
198
|
+
<div style={{
|
199
|
+
background: '#fff',
|
200
|
+
padding: '1.5rem',
|
201
|
+
borderRadius: '8px',
|
202
|
+
border: '1px solid #ddd',
|
203
|
+
display: 'grid',
|
204
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
205
|
+
gap: '1rem'
|
206
|
+
}}>
|
207
|
+
<PasswordField2
|
208
|
+
id="password"
|
209
|
+
label="Password"
|
210
|
+
placeholder="Enter a strong password"
|
211
|
+
value={formData.password || ''}
|
212
|
+
required={true}
|
213
|
+
outlined={true}
|
214
|
+
validation={validatePassword}
|
215
|
+
onChange={handleFieldChange}
|
216
|
+
onValidation={handleValidation}
|
217
|
+
helperText="Must contain 8+ chars, uppercase, lowercase, and number"
|
218
|
+
autoComplete="new-password"
|
219
|
+
/>
|
220
|
+
|
221
|
+
<PasswordField2
|
222
|
+
id="confirmPassword"
|
223
|
+
label="Confirm Password"
|
224
|
+
placeholder="Confirm your password"
|
225
|
+
value={formData.confirmPassword || ''}
|
226
|
+
required={true}
|
227
|
+
outlined={true}
|
228
|
+
validation={(value) => value === formData.password}
|
229
|
+
error={formData.confirmPassword && formData.confirmPassword !== formData.password ? 'Passwords do not match' : ''}
|
230
|
+
onChange={handleFieldChange}
|
231
|
+
autoComplete="new-password"
|
232
|
+
/>
|
233
|
+
</div>
|
234
|
+
</section>
|
235
|
+
|
236
|
+
{/* TextArea2 */}
|
237
|
+
<section style={{ marginBottom: '2rem' }}>
|
238
|
+
<h3>TextArea2 - Áreas de Texto</h3>
|
239
|
+
<div style={{
|
240
|
+
background: '#fff',
|
241
|
+
padding: '1.5rem',
|
242
|
+
borderRadius: '8px',
|
243
|
+
border: '1px solid #ddd'
|
244
|
+
}}>
|
245
|
+
<div style={{ display: 'grid', gap: '1rem' }}>
|
246
|
+
<TextArea2
|
247
|
+
id="bio"
|
248
|
+
label="Biography"
|
249
|
+
placeholder="Tell us about yourself..."
|
250
|
+
value={formData.bio || ''}
|
251
|
+
rows={4}
|
252
|
+
maxLength={500}
|
253
|
+
outlined={true}
|
254
|
+
onChange={handleFieldChange}
|
255
|
+
helperText={`${(formData.bio || '').length}/500 characters`}
|
256
|
+
/>
|
257
|
+
|
258
|
+
<TextArea2
|
259
|
+
id="comments"
|
260
|
+
label="Additional Comments"
|
261
|
+
placeholder="Any additional information..."
|
262
|
+
value={formData.comments || ''}
|
263
|
+
rows={3}
|
264
|
+
onChange={handleFieldChange}
|
265
|
+
/>
|
266
|
+
</div>
|
267
|
+
</div>
|
268
|
+
</section>
|
269
|
+
|
270
|
+
{/* DropDown2 */}
|
271
|
+
<section style={{ marginBottom: '2rem' }}>
|
272
|
+
<h3>DropDown2 - Menús Desplegables</h3>
|
273
|
+
<div style={{
|
274
|
+
background: '#fff',
|
275
|
+
padding: '1.5rem',
|
276
|
+
borderRadius: '8px',
|
277
|
+
border: '1px solid #ddd',
|
278
|
+
display: 'grid',
|
279
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
280
|
+
gap: '1rem'
|
281
|
+
}}>
|
282
|
+
<DropDown2
|
283
|
+
id="country"
|
284
|
+
label="Country"
|
285
|
+
placeholder="Select your country"
|
286
|
+
options={countryOptions}
|
287
|
+
value={formData.country || ''}
|
288
|
+
outlined={true}
|
289
|
+
searchable={true}
|
290
|
+
clearable={true}
|
291
|
+
onChange={handleFieldChange}
|
292
|
+
helperText="Searchable dropdown"
|
293
|
+
/>
|
294
|
+
|
295
|
+
<DropDown2
|
296
|
+
id="skills"
|
297
|
+
label="Skills"
|
298
|
+
placeholder="Select your skills"
|
299
|
+
options={skillOptions}
|
300
|
+
value={formData.skills || []}
|
301
|
+
multiple={true}
|
302
|
+
outlined={true}
|
303
|
+
searchable={true}
|
304
|
+
clearable={true}
|
305
|
+
groupBy="category"
|
306
|
+
onChange={handleFieldChange}
|
307
|
+
helperText="Multiple selection with grouping"
|
308
|
+
/>
|
309
|
+
|
310
|
+
<DropDown2
|
311
|
+
id="priority"
|
312
|
+
label="Priority Level"
|
313
|
+
placeholder="Select priority"
|
314
|
+
options={priorityOptions}
|
315
|
+
value={formData.priority || ''}
|
316
|
+
outlined={true}
|
317
|
+
onChange={handleFieldChange}
|
318
|
+
renderOption={(option) => (
|
319
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
320
|
+
<span>{option.label}</span>
|
321
|
+
</div>
|
322
|
+
)}
|
323
|
+
/>
|
324
|
+
</div>
|
325
|
+
</section>
|
326
|
+
|
327
|
+
{/* DateRange2 */}
|
328
|
+
<section style={{ marginBottom: '2rem' }}>
|
329
|
+
<h3>DateRange2 - Rangos de Fechas</h3>
|
330
|
+
<div style={{
|
331
|
+
background: '#fff',
|
332
|
+
padding: '1.5rem',
|
333
|
+
borderRadius: '8px',
|
334
|
+
border: '1px solid #ddd',
|
335
|
+
display: 'grid',
|
336
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(400px, 1fr))',
|
337
|
+
gap: '1rem'
|
338
|
+
}}>
|
339
|
+
<DateRange2
|
340
|
+
id="projectDates"
|
341
|
+
label="Project Duration"
|
342
|
+
value={formData.projectDates || {}}
|
343
|
+
outlined={true}
|
344
|
+
required={true}
|
345
|
+
minDate="2024-01-01"
|
346
|
+
maxDate="2025-12-31"
|
347
|
+
onChange={handleFieldChange}
|
348
|
+
onValidation={handleValidation}
|
349
|
+
helperText="Select start and end dates for the project"
|
350
|
+
/>
|
351
|
+
|
352
|
+
<DateRange2
|
353
|
+
id="vacationDates"
|
354
|
+
label="Vacation Period"
|
355
|
+
value={formData.vacationDates || {}}
|
356
|
+
outlined={true}
|
357
|
+
onChange={handleFieldChange}
|
358
|
+
helperText="Optional vacation dates"
|
359
|
+
/>
|
360
|
+
</div>
|
361
|
+
</section>
|
362
|
+
|
363
|
+
{/* Estados especiales */}
|
364
|
+
<section style={{ marginBottom: '2rem' }}>
|
365
|
+
<h3>Estados Especiales</h3>
|
366
|
+
<div style={{
|
367
|
+
background: '#fff',
|
368
|
+
padding: '1.5rem',
|
369
|
+
borderRadius: '8px',
|
370
|
+
border: '1px solid #ddd',
|
371
|
+
display: 'grid',
|
372
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
373
|
+
gap: '1rem'
|
374
|
+
}}>
|
375
|
+
<TextField2
|
376
|
+
id="disabledField"
|
377
|
+
label="Disabled Field"
|
378
|
+
value="Cannot edit this"
|
379
|
+
disabled={true}
|
380
|
+
outlined={true}
|
381
|
+
helperText="This field is disabled"
|
382
|
+
/>
|
383
|
+
|
384
|
+
<TextField2
|
385
|
+
id="readOnlyField"
|
386
|
+
label="Read-Only Field"
|
387
|
+
value="Read-only value"
|
388
|
+
readOnly={true}
|
389
|
+
outlined={true}
|
390
|
+
helperText="This field is read-only"
|
391
|
+
/>
|
392
|
+
|
393
|
+
<TextField2
|
394
|
+
id="errorField"
|
395
|
+
label="Field with Error"
|
396
|
+
value="Invalid value"
|
397
|
+
outlined={true}
|
398
|
+
error="This field has an error"
|
399
|
+
/>
|
400
|
+
|
401
|
+
<TextField2
|
402
|
+
id="debouncedField"
|
403
|
+
label="Debounced Field"
|
404
|
+
placeholder="Type to see debouncing..."
|
405
|
+
value={formData.debouncedField || ''}
|
406
|
+
outlined={true}
|
407
|
+
debounceMs={500}
|
408
|
+
onChange={handleFieldChange}
|
409
|
+
helperText="Changes are debounced by 500ms"
|
410
|
+
/>
|
411
|
+
</div>
|
412
|
+
</section>
|
413
|
+
|
414
|
+
{/* Estado actual del formulario */}
|
415
|
+
<section style={{ marginBottom: '2rem' }}>
|
416
|
+
<h3>Estado Actual del Formulario</h3>
|
417
|
+
<div style={{
|
418
|
+
background: '#f8f9fa',
|
419
|
+
padding: '1rem',
|
420
|
+
borderRadius: '4px',
|
421
|
+
border: '1px solid #dee2e6'
|
422
|
+
}}>
|
423
|
+
<h4>Datos:</h4>
|
424
|
+
<pre style={{
|
425
|
+
background: '#ffffff',
|
426
|
+
padding: '1rem',
|
427
|
+
borderRadius: '4px',
|
428
|
+
fontSize: '0.8rem',
|
429
|
+
overflow: 'auto',
|
430
|
+
maxHeight: '200px'
|
431
|
+
}}>
|
432
|
+
{JSON.stringify(formData, null, 2)}
|
433
|
+
</pre>
|
434
|
+
|
435
|
+
<h4>Errores de Validación:</h4>
|
436
|
+
<pre style={{
|
437
|
+
background: '#ffffff',
|
438
|
+
padding: '1rem',
|
439
|
+
borderRadius: '4px',
|
440
|
+
fontSize: '0.8rem',
|
441
|
+
overflow: 'auto',
|
442
|
+
maxHeight: '100px'
|
443
|
+
}}>
|
444
|
+
{JSON.stringify(Object.fromEntries(
|
445
|
+
Object.entries(validationErrors).filter(([_, error]) => error)
|
446
|
+
), null, 2)}
|
447
|
+
</pre>
|
448
|
+
</div>
|
449
|
+
</section>
|
450
|
+
|
451
|
+
{/* Comparación antes/después */}
|
452
|
+
<section style={{ marginBottom: '2rem' }}>
|
453
|
+
<h3>Comparación: TextField Original vs TextField2</h3>
|
454
|
+
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }}>
|
455
|
+
<div style={{
|
456
|
+
background: '#ffebee',
|
457
|
+
padding: '1rem',
|
458
|
+
borderRadius: '4px',
|
459
|
+
border: '1px solid #ffcdd2'
|
460
|
+
}}>
|
461
|
+
<h4>❌ TextField Original</h4>
|
462
|
+
<ul>
|
463
|
+
<li>Sin PropTypes</li>
|
464
|
+
<li>Sin accesibilidad</li>
|
465
|
+
<li>Manipulación directa del DOM</li>
|
466
|
+
<li>CSS con altura fija</li>
|
467
|
+
<li>Sin validación integrada</li>
|
468
|
+
<li>Sin debouncing</li>
|
469
|
+
<li>Sin estados de error</li>
|
470
|
+
<li>DropDown complejo y frágil</li>
|
471
|
+
<li>DateRange básico</li>
|
472
|
+
</ul>
|
473
|
+
</div>
|
474
|
+
<div style={{
|
475
|
+
background: '#e8f5e8',
|
476
|
+
padding: '1rem',
|
477
|
+
borderRadius: '4px',
|
478
|
+
border: '1px solid #c8e6c9'
|
479
|
+
}}>
|
480
|
+
<h4>✅ TextField2 Mejorado</h4>
|
481
|
+
<ul>
|
482
|
+
<li>PropTypes completos</li>
|
483
|
+
<li>Accesibilidad total (WCAG 2.1 AA)</li>
|
484
|
+
<li>Sin manipulación directa del DOM</li>
|
485
|
+
<li>CSS con altura automática</li>
|
486
|
+
<li>Validación personalizable</li>
|
487
|
+
<li>Debouncing configurable</li>
|
488
|
+
<li>Estados completos de error</li>
|
489
|
+
<li>DropDown2 robusto y accesible</li>
|
490
|
+
<li>DateRange2 con validación</li>
|
491
|
+
</ul>
|
492
|
+
</div>
|
493
|
+
</div>
|
494
|
+
</section>
|
495
|
+
</div>
|
496
|
+
)
|
497
|
+
}
|
498
|
+
|
499
|
+
export default TextField2Examples
|