ywana-core8 0.1.75 → 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.
Files changed (122) hide show
  1. package/ACCORDION_EVALUATION.md +583 -0
  2. package/CHECKBOX_EVALUATION.md +273 -0
  3. package/CHIP_EVALUATION.md +542 -0
  4. package/COLOR_EVALUATION.md +524 -0
  5. package/COMPONENTS_EVALUATION.md +477 -0
  6. package/FORM_EVALUATION.md +459 -0
  7. package/HEADER_EVALUATION.md +436 -0
  8. package/ICON_EVALUATION.md +254 -0
  9. package/LIST_EVALUATION.md +574 -0
  10. package/PROGRESS_EVALUATION.md +450 -0
  11. package/RADIO_EVALUATION.md +439 -0
  12. package/RADIO_VISUAL_FIX.md +183 -0
  13. package/SECTION_IMPROVEMENTS.md +153 -0
  14. package/SWITCH_EVALUATION.md +335 -0
  15. package/SWITCH_VISUAL_FIX.md +232 -0
  16. package/TAB_EVALUATION.md +626 -0
  17. package/TEXTFIELD_EVALUATION.md +747 -0
  18. package/TOOLTIP_FIX.md +157 -0
  19. package/TREE_EVALUATION.md +708 -0
  20. package/dist/index.cjs +7900 -1615
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.css +6094 -1122
  23. package/dist/index.css.map +1 -1
  24. package/dist/index.modern.js +7929 -1645
  25. package/dist/index.modern.js.map +1 -1
  26. package/dist/index.umd.js +7900 -1615
  27. package/dist/index.umd.js.map +1 -1
  28. package/jest.config.js +24 -0
  29. package/package.json +10 -1
  30. package/src/html/accordion.css +208 -4
  31. package/src/html/accordion.example.js +390 -0
  32. package/src/html/accordion.js +284 -28
  33. package/src/html/accordion.unit.test.js +334 -0
  34. package/src/html/button.css +157 -16
  35. package/src/html/button.example.js +374 -0
  36. package/src/html/button.js +240 -60
  37. package/src/html/button.test.js +422 -0
  38. package/src/html/checkbox.css +74 -2
  39. package/src/html/checkbox.example.js +316 -0
  40. package/src/html/checkbox.js +113 -26
  41. package/src/html/checkbox.test.js +285 -0
  42. package/src/html/chip.css +230 -19
  43. package/src/html/chip.example.js +355 -0
  44. package/src/html/chip.js +321 -25
  45. package/src/html/chip.test.js +425 -0
  46. package/src/html/color.css +435 -6
  47. package/src/html/color.example.js +527 -0
  48. package/src/html/color.js +458 -9
  49. package/src/html/color.test.js +362 -4
  50. package/src/html/components.example.js +492 -0
  51. package/src/html/components_enhanced.test.js +581 -0
  52. package/src/html/form.css +70 -3
  53. package/src/html/form.example.js +385 -0
  54. package/src/html/form.js +232 -34
  55. package/src/html/form.test.js +369 -0
  56. package/src/html/header2.css +264 -0
  57. package/src/html/header2.example.js +411 -0
  58. package/src/html/header2.js +203 -0
  59. package/src/html/header2.test.js +377 -0
  60. package/src/html/icon.css +20 -2
  61. package/src/html/icon.example.js +268 -0
  62. package/src/html/icon.js +86 -16
  63. package/src/html/icon.test.js +231 -0
  64. package/src/html/index.js +1 -1
  65. package/src/html/list.css +393 -1
  66. package/src/html/list.example.js +404 -0
  67. package/src/html/list.js +583 -40
  68. package/src/html/list.test.js +383 -0
  69. package/src/html/progress.css +707 -17
  70. package/src/html/progress.example.js +424 -0
  71. package/src/html/progress.js +906 -9
  72. package/src/html/progress.test.js +313 -0
  73. package/src/html/property.css +399 -0
  74. package/src/html/property.example.js +553 -0
  75. package/src/html/property.js +393 -15
  76. package/src/html/property.test.js +351 -2
  77. package/src/html/radio-visual-test.js +289 -0
  78. package/src/html/radio.css +137 -11
  79. package/src/html/radio.example.js +389 -0
  80. package/src/html/radio.js +234 -10
  81. package/src/html/radio.test.js +318 -0
  82. package/src/html/section.example.js +99 -0
  83. package/src/html/section.js +40 -3
  84. package/src/html/section.test.js +131 -0
  85. package/src/html/selector.css +329 -3
  86. package/src/html/selector.js +369 -23
  87. package/src/html/switch-debug.js +197 -0
  88. package/src/html/switch-test-visual.js +294 -0
  89. package/src/html/switch.css +200 -0
  90. package/src/html/switch.example.js +461 -0
  91. package/src/html/switch.js +283 -23
  92. package/src/html/switch.test.js +355 -0
  93. package/src/html/tab.css +288 -0
  94. package/src/html/tab.example.js +446 -0
  95. package/src/html/tab.js +387 -22
  96. package/src/html/tab_enhanced.js +378 -0
  97. package/src/html/tab_enhanced.test.js +504 -0
  98. package/src/html/table2.css +576 -0
  99. package/src/html/table2.example.js +703 -0
  100. package/src/html/table2.js +1252 -0
  101. package/src/html/table2.migration.md +328 -0
  102. package/src/html/table2.test.js +582 -0
  103. package/src/html/text.css +375 -0
  104. package/src/html/text.js +311 -20
  105. package/src/html/textfield2.css +842 -0
  106. package/src/html/textfield2.example.js +499 -0
  107. package/src/html/textfield2.js +1130 -0
  108. package/src/html/textfield2.test.js +950 -0
  109. package/src/html/thumbnail.css +289 -2
  110. package/src/html/thumbnail.js +214 -9
  111. package/src/html/tokenfield.css +449 -1
  112. package/src/html/tokenfield.example.js +503 -0
  113. package/src/html/tokenfield.js +561 -56
  114. package/src/html/tokenfield.test.js +423 -0
  115. package/src/html/tooltip-positioning-demo.js +187 -0
  116. package/src/html/tooltip.css +25 -2
  117. package/src/html/tree.css +228 -0
  118. package/src/html/tree.example.js +475 -0
  119. package/src/html/tree.js +712 -28
  120. package/src/html/tree_enhanced.test.js +495 -0
  121. package/table2.test.js +454 -0
  122. package/src/html/button.tsx +0 -38
@@ -1,57 +1,403 @@
1
- import React, { useEffect, useState } from 'react'
1
+ import React, { useEffect, useState, useCallback, useRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { Icon } from './icon'
2
4
  import './selector.css'
3
5
 
4
6
  /**
5
- * Multi Selector
7
+ * Enhanced Multi Selector component with improved functionality while maintaining 100% compatibility
6
8
  */
7
9
  export const MultiSelector = (props) => {
10
+ const {
11
+ // Original props (100% compatible)
12
+ options = [],
13
+ className,
14
+ onChange,
15
+ // New enhanced props (all optional for compatibility)
16
+ disabled = false,
17
+ maxSelections,
18
+ minSelections = 0,
19
+ searchable = false,
20
+ searchPlaceholder = "Search options...",
21
+ variant = 'default',
22
+ size = 'medium',
23
+ allowClear = false,
24
+ onClear,
25
+ loading = false,
26
+ empty = false,
27
+ emptyMessage = "No options available",
28
+ ariaLabel,
29
+ style,
30
+ ...restProps
31
+ } = props
8
32
 
9
- const { options = [], className } = props
10
33
  const [selections, setSelections] = useState([])
34
+ const [searchTerm, setSearchTerm] = useState('')
35
+ const selectorRef = useRef(null)
11
36
 
37
+ // Initialize selections (maintaining original logic)
12
38
  useEffect(() => {
13
39
  const initialSelections = options.filter(option => option.selected === true).map(option => option.value)
14
40
  setSelections(initialSelections)
41
+ }, [options])
42
+
43
+ // Validate props
44
+ useEffect(() => {
45
+ if (!Array.isArray(options)) {
46
+ console.warn('MultiSelector: options prop must be an array')
47
+ }
48
+ }, [options])
49
+
50
+ // Enhanced toggle function (maintaining original behavior)
51
+ const toggleSelection = useCallback((value) => {
52
+ if (disabled) return
53
+
54
+ setSelections(prev => {
55
+ const isSelected = prev.includes(value)
56
+ let next
57
+
58
+ if (isSelected) {
59
+ // Removing selection
60
+ if (prev.length <= minSelections) {
61
+ console.warn(`MultiSelector: Cannot remove selection. Minimum ${minSelections} selections required.`)
62
+ return prev
63
+ }
64
+ next = prev.filter(item => item !== value)
65
+ } else {
66
+ // Adding selection
67
+ if (maxSelections && prev.length >= maxSelections) {
68
+ console.warn(`MultiSelector: Cannot add selection. Maximum ${maxSelections} selections allowed.`)
69
+ return prev
70
+ }
71
+ next = prev.concat([value])
72
+ }
73
+
74
+ if (onChange) onChange(next)
75
+ return next
76
+ })
77
+ }, [disabled, onChange, maxSelections, minSelections])
78
+
79
+ // Handle clear all
80
+ const handleClear = useCallback(() => {
81
+ if (disabled || minSelections > 0) return
82
+
83
+ setSelections([])
84
+ if (onChange) onChange([])
85
+ if (onClear) onClear()
86
+ }, [disabled, minSelections, onChange, onClear])
87
+
88
+ // Handle search
89
+ const handleSearch = useCallback((event) => {
90
+ setSearchTerm(event.target.value)
15
91
  }, [])
16
92
 
17
- function toggleSelection(value) {
18
- const { onChange } = props
19
- const next = selections.includes(value)
20
- ? selections.filter(item => item != value)
21
- : selections.concat([value])
22
- setSelections(next)
23
- if (onChange) onChange(next)
24
- }
93
+ // Filter options based on search
94
+ const filteredOptions = searchable && searchTerm
95
+ ? options.filter(option =>
96
+ option.label?.toLowerCase().includes(searchTerm.toLowerCase()) ||
97
+ option.value?.toString().toLowerCase().includes(searchTerm.toLowerCase())
98
+ )
99
+ : options
25
100
 
26
- const items = options.map(option => ({
101
+ // Generate items (maintaining original logic)
102
+ const items = filteredOptions.map(option => ({
27
103
  ...option,
28
104
  selected: selections.includes(option.value),
29
- onToggle: toggleSelection
105
+ onToggle: toggleSelection,
106
+ disabled: disabled || option.disabled,
107
+ variant,
108
+ size
30
109
  }))
31
110
 
111
+ // Generate CSS classes
112
+ const cssClasses = [
113
+ 'multiselector',
114
+ `multiselector--${variant}`,
115
+ `multiselector--${size}`,
116
+ disabled && 'multiselector--disabled',
117
+ loading && 'multiselector--loading',
118
+ searchable && 'multiselector--searchable',
119
+ className
120
+ ].filter(Boolean).join(' ')
121
+
122
+ // Accessibility attributes
123
+ const ariaAttributes = {
124
+ 'aria-label': ariaLabel || 'Multi selector',
125
+ 'aria-disabled': disabled,
126
+ 'aria-busy': loading,
127
+ role: 'group'
128
+ }
129
+
130
+ // Show loading state
131
+ if (loading) {
132
+ return (
133
+ <div className={cssClasses} style={style} {...ariaAttributes} {...restProps}>
134
+ <div className="multiselector__loading">
135
+ <Icon icon="hourglass_empty" size="medium" />
136
+ <span>Loading options...</span>
137
+ </div>
138
+ </div>
139
+ )
140
+ }
141
+
142
+ // Show empty state
143
+ if (empty || options.length === 0) {
144
+ return (
145
+ <div className={cssClasses} style={style} {...ariaAttributes} {...restProps}>
146
+ <div className="multiselector__empty">
147
+ <Icon icon="inbox" size="medium" />
148
+ <span>{emptyMessage}</span>
149
+ </div>
150
+ </div>
151
+ )
152
+ }
153
+
32
154
  return (
33
- <ul className={`multiselector ${className}`}>
34
- {items.map(option => <ToggleButton {...option} />)}
35
- </ul>
155
+ <div className={cssClasses} style={style} ref={selectorRef} {...ariaAttributes} {...restProps}>
156
+ {/* Search input */}
157
+ {searchable && (
158
+ <div className="multiselector__search">
159
+ <input
160
+ type="text"
161
+ placeholder={searchPlaceholder}
162
+ value={searchTerm}
163
+ onChange={handleSearch}
164
+ className="multiselector__search-input"
165
+ disabled={disabled}
166
+ />
167
+ <Icon icon="search" size="small" className="multiselector__search-icon" />
168
+ </div>
169
+ )}
170
+
171
+ {/* Clear button */}
172
+ {allowClear && selections.length > 0 && minSelections === 0 && (
173
+ <div className="multiselector__controls">
174
+ <button
175
+ type="button"
176
+ onClick={handleClear}
177
+ disabled={disabled}
178
+ className="multiselector__clear-button"
179
+ aria-label="Clear all selections"
180
+ >
181
+ <Icon icon="clear" size="small" />
182
+ Clear All ({selections.length})
183
+ </button>
184
+ </div>
185
+ )}
186
+
187
+ {/* Options list (maintaining original structure) */}
188
+ <ul className="multiselector__options">
189
+ {items.map((option, index) => (
190
+ <ToggleButton key={option.value || index} {...option} />
191
+ ))}
192
+ </ul>
193
+
194
+ {/* Selection summary */}
195
+ {(maxSelections || minSelections > 0) && (
196
+ <div className="multiselector__summary">
197
+ <span className="multiselector__count">
198
+ {selections.length}
199
+ {maxSelections && ` / ${maxSelections}`}
200
+ {maxSelections ? ' selected' : ` of ${options.length} selected`}
201
+ </span>
202
+ {minSelections > 0 && selections.length < minSelections && (
203
+ <span className="multiselector__warning">
204
+ Minimum {minSelections} required
205
+ </span>
206
+ )}
207
+ </div>
208
+ )}
209
+ </div>
36
210
  )
37
211
  }
38
212
 
39
213
  /**
40
- * Toggle Button
214
+ * Enhanced Toggle Button component with improved functionality while maintaining 100% compatibility
41
215
  */
42
216
  export const ToggleButton = (props) => {
217
+ const {
218
+ // Original props (100% compatible)
219
+ label,
220
+ value,
221
+ selected = false,
222
+ onToggle,
223
+ // New enhanced props (all optional for compatibility)
224
+ disabled = false,
225
+ icon,
226
+ variant = 'default',
227
+ size = 'medium',
228
+ tooltip,
229
+ className,
230
+ style,
231
+ ...restProps
232
+ } = props
43
233
 
44
- const { label, value, selected = false, onToggle } = props
45
-
46
- function toggle() {
234
+ // Handle toggle (maintaining original behavior)
235
+ const handleToggle = useCallback(() => {
236
+ if (disabled) return
47
237
  if (onToggle) onToggle(value)
238
+ }, [disabled, onToggle, value])
239
+
240
+ // Handle keyboard interaction
241
+ const handleKeyDown = useCallback((event) => {
242
+ if (disabled) return
243
+
244
+ switch (event.key) {
245
+ case 'Enter':
246
+ case ' ':
247
+ event.preventDefault()
248
+ if (onToggle) onToggle(value)
249
+ break
250
+ default:
251
+ break
252
+ }
253
+ }, [disabled, onToggle, value])
254
+
255
+ // Generate CSS classes (maintaining original logic)
256
+ const cssClasses = [
257
+ 'toggle-button',
258
+ selected && 'selected',
259
+ `toggle-button--${variant}`,
260
+ `toggle-button--${size}`,
261
+ disabled && 'toggle-button--disabled',
262
+ value && `toggle-button--${value}`,
263
+ className
264
+ ].filter(Boolean).join(' ')
265
+
266
+ // Accessibility attributes
267
+ const ariaAttributes = {
268
+ 'aria-pressed': selected,
269
+ 'aria-disabled': disabled,
270
+ 'aria-label': tooltip || (typeof label === 'string' ? label : `Toggle ${value}`),
271
+ role: 'button',
272
+ tabIndex: disabled ? -1 : 0
48
273
  }
49
274
 
50
- const selectedStyle = selected ? 'selected' : ''
51
275
  return (
52
- <li className={`${selectedStyle} ${value}`} onClick={toggle}>
53
- {label}
276
+ <li
277
+ className={cssClasses}
278
+ onClick={handleToggle}
279
+ onKeyDown={handleKeyDown}
280
+ title={tooltip}
281
+ style={style}
282
+ {...ariaAttributes}
283
+ {...restProps}
284
+ >
285
+ {/* Icon */}
286
+ {icon && (
287
+ <Icon
288
+ icon={icon}
289
+ size={size === 'small' ? 'small' : 'medium'}
290
+ className="toggle-button__icon"
291
+ disabled={disabled}
292
+ />
293
+ )}
294
+
295
+ {/* Label */}
296
+ <span className="toggle-button__label">
297
+ {label}
298
+ </span>
299
+
300
+ {/* Selected indicator */}
301
+ {selected && (
302
+ <Icon
303
+ icon="check"
304
+ size="small"
305
+ className="toggle-button__check"
306
+ />
307
+ )}
54
308
  </li>
55
309
  )
310
+ }
311
+
312
+ // PropTypes for MultiSelector
313
+ MultiSelector.propTypes = {
314
+ /** Array of option objects */
315
+ options: PropTypes.arrayOf(PropTypes.shape({
316
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
317
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
318
+ selected: PropTypes.bool,
319
+ disabled: PropTypes.bool,
320
+ icon: PropTypes.string
321
+ })),
322
+ /** Additional CSS classes */
323
+ className: PropTypes.string,
324
+ /** Change callback */
325
+ onChange: PropTypes.func,
326
+ /** Disabled state */
327
+ disabled: PropTypes.bool,
328
+ /** Maximum selections allowed */
329
+ maxSelections: PropTypes.number,
330
+ /** Minimum selections required */
331
+ minSelections: PropTypes.number,
332
+ /** Enable search functionality */
333
+ searchable: PropTypes.bool,
334
+ /** Search input placeholder */
335
+ searchPlaceholder: PropTypes.string,
336
+ /** Visual variant */
337
+ variant: PropTypes.oneOf(['default', 'outlined', 'filled']),
338
+ /** Size variant */
339
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
340
+ /** Allow clear all button */
341
+ allowClear: PropTypes.bool,
342
+ /** Clear callback */
343
+ onClear: PropTypes.func,
344
+ /** Loading state */
345
+ loading: PropTypes.bool,
346
+ /** Empty state */
347
+ empty: PropTypes.bool,
348
+ /** Empty state message */
349
+ emptyMessage: PropTypes.string,
350
+ /** ARIA label */
351
+ ariaLabel: PropTypes.string,
352
+ /** Inline styles */
353
+ style: PropTypes.object
354
+ }
355
+
356
+ MultiSelector.defaultProps = {
357
+ options: [],
358
+ disabled: false,
359
+ minSelections: 0,
360
+ searchable: false,
361
+ searchPlaceholder: "Search options...",
362
+ variant: 'default',
363
+ size: 'medium',
364
+ allowClear: false,
365
+ loading: false,
366
+ empty: false,
367
+ emptyMessage: "No options available"
368
+ }
369
+
370
+ // PropTypes for ToggleButton
371
+ ToggleButton.propTypes = {
372
+ /** Button label */
373
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
374
+ /** Button value */
375
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
376
+ /** Selected state */
377
+ selected: PropTypes.bool,
378
+ /** Toggle callback */
379
+ onToggle: PropTypes.func,
380
+ /** Disabled state */
381
+ disabled: PropTypes.bool,
382
+ /** Icon name */
383
+ icon: PropTypes.string,
384
+ /** Visual variant */
385
+ variant: PropTypes.oneOf(['default', 'outlined', 'filled']),
386
+ /** Size variant */
387
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
388
+ /** Tooltip text */
389
+ tooltip: PropTypes.string,
390
+ /** Additional CSS classes */
391
+ className: PropTypes.string,
392
+ /** Inline styles */
393
+ style: PropTypes.object
394
+ }
56
395
 
396
+ ToggleButton.defaultProps = {
397
+ selected: false,
398
+ disabled: false,
399
+ variant: 'default',
400
+ size: 'medium'
57
401
  }
402
+
403
+ export default MultiSelector
@@ -0,0 +1,197 @@
1
+ import React, { useState } from 'react'
2
+ import RSwitch from 'react-switch'
3
+ import { Switch, Switch2 } from './switch'
4
+
5
+ /**
6
+ * Componente de debug para verificar que los switches se ven correctamente
7
+ */
8
+ export const SwitchDebug = () => {
9
+ const [checked, setChecked] = useState(false)
10
+
11
+ return (
12
+ <div style={{ padding: '2rem', maxWidth: '600px' }}>
13
+ <h1>🔍 Debug de Switches</h1>
14
+
15
+ {/* React Switch directo */}
16
+ <section style={{ marginBottom: '2rem' }}>
17
+ <h3>React Switch Directo (sin wrapper)</h3>
18
+ <div style={{
19
+ background: '#fff',
20
+ padding: '1.5rem',
21
+ borderRadius: '8px',
22
+ border: '1px solid #ddd'
23
+ }}>
24
+ <div style={{ display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem' }}>
25
+ <span>Estado: {checked ? 'ON' : 'OFF'}</span>
26
+ <RSwitch
27
+ checked={checked}
28
+ onChange={setChecked}
29
+ onColor="#2693e6"
30
+ offColor="#ccc"
31
+ onHandleColor="#ffffff"
32
+ offHandleColor="#ffffff"
33
+ handleDiameter={18}
34
+ uncheckedIcon={false}
35
+ checkedIcon={false}
36
+ boxShadow="0px 2px 4px rgba(0, 0, 0, 0.2)"
37
+ activeBoxShadow="0px 0px 0px 3px rgba(38, 147, 230, 0.2)"
38
+ height={20}
39
+ width={48}
40
+ />
41
+ </div>
42
+ <p style={{ fontSize: '0.9rem', color: '#666' }}>
43
+ Este es react-switch sin ningún wrapper. Si no se ve bien, el problema es con la librería o CSS global.
44
+ </p>
45
+ </div>
46
+ </section>
47
+
48
+ {/* Nuestro Switch wrapper */}
49
+ <section style={{ marginBottom: '2rem' }}>
50
+ <h3>Nuestro Switch (wrapper)</h3>
51
+ <div style={{
52
+ background: '#fff',
53
+ padding: '1.5rem',
54
+ borderRadius: '8px',
55
+ border: '1px solid #ddd'
56
+ }}>
57
+ <Switch
58
+ id="debug-switch"
59
+ label="Switch con wrapper"
60
+ checked={checked}
61
+ onChange={(id, value) => setChecked(value)}
62
+ />
63
+ <p style={{ fontSize: '0.9rem', color: '#666', marginTop: '1rem' }}>
64
+ Este usa nuestro wrapper. Debería verse igual que el de arriba.
65
+ </p>
66
+ </div>
67
+ </section>
68
+
69
+ {/* Switch2 para comparación */}
70
+ <section style={{ marginBottom: '2rem' }}>
71
+ <h3>Switch2 (Material Icons)</h3>
72
+ <div style={{
73
+ background: '#fff',
74
+ padding: '1.5rem',
75
+ borderRadius: '8px',
76
+ border: '1px solid #ddd'
77
+ }}>
78
+ <Switch2
79
+ id="debug-switch2"
80
+ label="Switch2 con iconos"
81
+ checked={checked}
82
+ onChange={(id, value) => setChecked(value)}
83
+ />
84
+ <p style={{ fontSize: '0.9rem', color: '#666', marginTop: '1rem' }}>
85
+ Este usa iconos Material. Debería mostrar toggle_on/toggle_off.
86
+ </p>
87
+ </div>
88
+ </section>
89
+
90
+ {/* Diferentes estados */}
91
+ <section style={{ marginBottom: '2rem' }}>
92
+ <h3>Diferentes Estados</h3>
93
+ <div style={{
94
+ background: '#fff',
95
+ padding: '1.5rem',
96
+ borderRadius: '8px',
97
+ border: '1px solid #ddd'
98
+ }}>
99
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1rem' }}>
100
+ <div>
101
+ <h4>Normal OFF</h4>
102
+ <RSwitch
103
+ checked={false}
104
+ onChange={() => {}}
105
+ onColor="#2693e6"
106
+ offColor="#ccc"
107
+ height={20}
108
+ width={48}
109
+ handleDiameter={18}
110
+ uncheckedIcon={false}
111
+ checkedIcon={false}
112
+ />
113
+ </div>
114
+ <div>
115
+ <h4>Normal ON</h4>
116
+ <RSwitch
117
+ checked={true}
118
+ onChange={() => {}}
119
+ onColor="#2693e6"
120
+ offColor="#ccc"
121
+ height={20}
122
+ width={48}
123
+ handleDiameter={18}
124
+ uncheckedIcon={false}
125
+ checkedIcon={false}
126
+ />
127
+ </div>
128
+ <div>
129
+ <h4>Disabled OFF</h4>
130
+ <RSwitch
131
+ checked={false}
132
+ onChange={() => {}}
133
+ disabled={true}
134
+ onColor="#2693e6"
135
+ offColor="#ccc"
136
+ height={20}
137
+ width={48}
138
+ handleDiameter={18}
139
+ uncheckedIcon={false}
140
+ checkedIcon={false}
141
+ />
142
+ </div>
143
+ <div>
144
+ <h4>Disabled ON</h4>
145
+ <RSwitch
146
+ checked={true}
147
+ onChange={() => {}}
148
+ disabled={true}
149
+ onColor="#2693e6"
150
+ offColor="#ccc"
151
+ height={20}
152
+ width={48}
153
+ handleDiameter={18}
154
+ uncheckedIcon={false}
155
+ checkedIcon={false}
156
+ />
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </section>
161
+
162
+ {/* Información de debug */}
163
+ <section>
164
+ <h3>Información de Debug</h3>
165
+ <div style={{
166
+ background: '#f8f9fa',
167
+ padding: '1rem',
168
+ borderRadius: '4px',
169
+ border: '1px solid #dee2e6'
170
+ }}>
171
+ <h4>¿Qué deberías ver?</h4>
172
+ <ul>
173
+ <li><strong>Switch OFF:</strong> Fondo gris (#ccc), handle blanco a la izquierda</li>
174
+ <li><strong>Switch ON:</strong> Fondo azul (#2693e6), handle blanco a la derecha</li>
175
+ <li><strong>Handle:</strong> Círculo blanco con sombra sutil</li>
176
+ <li><strong>Transición:</strong> Animación suave al cambiar estado</li>
177
+ </ul>
178
+
179
+ <h4>Si solo ves un círculo gris:</h4>
180
+ <ul>
181
+ <li>Verifica que react-switch esté instalado: <code>npm list react-switch</code></li>
182
+ <li>Revisa la consola del navegador por errores</li>
183
+ <li>Verifica que no hay CSS conflictivo</li>
184
+ <li>Asegúrate de que las props de color se están aplicando</li>
185
+ </ul>
186
+
187
+ <h4>Estado actual:</h4>
188
+ <pre style={{ background: '#fff', padding: '0.5rem', borderRadius: '4px' }}>
189
+ {JSON.stringify({ checked }, null, 2)}
190
+ </pre>
191
+ </div>
192
+ </section>
193
+ </div>
194
+ )
195
+ }
196
+
197
+ export default SwitchDebug