ywana-core8 0.1.103 → 0.2.2
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/dist/index.css +4941 -324
- package/dist/index.js +42339 -0
- package/dist/index.js.map +1 -0
- package/dist/index.modern.js +37459 -31678
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +39635 -34010
- package/dist/index.umd.js.map +1 -1
- package/package.json +26 -29
- package/src/Test.stories.jsx +28 -0
- package/src/desktop/Desktop.stories.jsx +110 -0
- package/src/desktop/WindowContext.js +135 -0
- package/src/desktop/WindowManager.js +355 -0
- package/src/desktop/desktop.css +55 -4
- package/src/desktop/desktop.js +312 -6
- package/src/desktop/index.js +7 -0
- package/src/desktop/window.css +229 -36
- package/src/desktop/window.js +255 -20
- package/src/desktop.backup/desktop.css +6 -0
- package/src/desktop.backup/desktop.js +13 -0
- package/src/desktop.backup/window.css +58 -0
- package/src/desktop.backup/window.js +27 -0
- package/src/html/Accordion.stories.jsx +178 -0
- package/src/html/Button.stories.jsx +175 -0
- package/src/html/Checkbox.stories.jsx +131 -0
- package/src/html/Chip.stories.jsx +189 -0
- package/src/html/Color.stories.jsx +234 -0
- package/src/html/Form.stories.jsx +271 -0
- package/src/html/Icon.stories.jsx +233 -0
- package/src/html/Progress.stories.jsx +247 -0
- package/src/html/Radio.stories.jsx +289 -0
- package/src/html/StyleTest.stories.jsx +81 -0
- package/src/html/Switch.stories.jsx +329 -0
- package/src/html/Tab.stories.jsx +239 -0
- package/src/html/Table.stories.jsx +188 -0
- package/src/html/Table2.stories.jsx +238 -0
- package/src/html/TextField2.stories.jsx +337 -0
- package/src/html/Tree.stories.jsx +285 -0
- package/src/html/accordion.example.js +0 -74
- package/src/html/accordion.js +1 -6
- package/src/html/button.js +2 -13
- package/src/html/checkbox.js +1 -9
- package/src/html/chip.js +2 -19
- package/src/html/color.js +1 -14
- package/src/html/form.js +4 -15
- package/src/html/header2.js +1 -12
- package/src/html/icon.js +1 -7
- package/src/html/index.js +1 -1
- package/src/html/list.js +1 -19
- package/src/html/menu.js +9 -5
- package/src/html/progress.js +5 -53
- package/src/html/property.js +9 -25
- package/src/html/radio.js +2 -16
- package/src/html/section.js +1 -6
- package/src/html/selector.js +2 -19
- package/src/html/switch.css +134 -100
- package/src/html/switch.example.js +46 -36
- package/src/html/switch.js +43 -192
- package/src/html/tab.js +3 -24
- package/src/html/text.js +1 -12
- package/src/html/textfield2.js +5 -42
- package/src/html/thumbnail.js +1 -12
- package/src/html/tokenfield.js +2 -21
- package/src/html/tree.js +3 -35
- package/src/index.js +1 -0
- package/__previewjs__/Wrapper.tsx +0 -14
- package/build-doc.sh +0 -10
- package/db/db.json +0 -89
- package/db/routes.json +0 -0
- package/dist/index.cjs +0 -36722
- package/dist/index.cjs.map +0 -1
- package/dist/index.css.map +0 -1
- package/doc/README.md +0 -196
- package/doc/evalulations/ACCORDION_EVALUATION.md +0 -583
- package/doc/evalulations/CHECKBOX_EVALUATION.md +0 -273
- package/doc/evalulations/CHIP_EVALUATION.md +0 -542
- package/doc/evalulations/COLOR_EVALUATION.md +0 -524
- package/doc/evalulations/COMPONENTS_EVALUATION.md +0 -477
- package/doc/evalulations/FORM_EVALUATION.md +0 -459
- package/doc/evalulations/HEADER_EVALUATION.md +0 -436
- package/doc/evalulations/ICON_EVALUATION.md +0 -254
- package/doc/evalulations/LIST_EVALUATION.md +0 -574
- package/doc/evalulations/PROGRESS_EVALUATION.md +0 -450
- package/doc/evalulations/RADIO_EVALUATION.md +0 -439
- package/doc/evalulations/RADIO_VISUAL_FIX.md +0 -183
- package/doc/evalulations/SECTION_IMPROVEMENTS.md +0 -153
- package/doc/evalulations/SWITCH_EVALUATION.md +0 -335
- package/doc/evalulations/SWITCH_VISUAL_FIX.md +0 -232
- package/doc/evalulations/TAB_EVALUATION.md +0 -626
- package/doc/evalulations/TEXTFIELD_EVALUATION.md +0 -747
- package/doc/evalulations/TOOLTIP_FIX.md +0 -157
- package/doc/evalulations/TREE_EVALUATION.md +0 -708
- package/doc/index.html +0 -0
- package/doc/package-lock.json +0 -17298
- package/doc/package.json +0 -34
- package/doc/public/index.html +0 -24
- package/doc/scripts/generate-examples.js +0 -129
- package/doc/src/App.css +0 -171
- package/doc/src/App.js +0 -114
- package/doc/src/components/ExamplePage.js +0 -129
- package/doc/src/components/WelcomePage.js +0 -84
- package/doc/src/index.css +0 -246
- package/doc/src/index.js +0 -17
- package/doc/src/theme.css +0 -256
- package/jest.config.js +0 -24
- package/preview.config.js +0 -38
- package/publish.sh +0 -6
- package/src/desktop/dektop.test.js +0 -11
- package/src/domain/CollectionAPI.test.js +0 -19
- package/src/domain/ContentEditor.test.js +0 -52
- package/src/domain2/CollectionAPI.test.js +0 -19
- package/src/domain2/CollectionContext.test.js +0 -71
- package/src/domain2/CollectionPage.test.js +0 -112
- package/src/domain2/DynamicForm.test.js +0 -47
- package/src/html/accordion.test.js +0 -37
- package/src/html/accordion.unit.test.js +0 -334
- package/src/html/button.example.new.js +0 -416
- package/src/html/button.test.js +0 -422
- package/src/html/checkbox.test.js +0 -285
- package/src/html/chip.test.js +0 -425
- package/src/html/color.example.js.backup +0 -527
- package/src/html/color.test.js +0 -377
- package/src/html/components.example.js.backup +0 -492
- package/src/html/components_enhanced.test.js +0 -581
- package/src/html/form.example.js.backup +0 -385
- package/src/html/form.test.js +0 -369
- package/src/html/header2.example.js.backup +0 -411
- package/src/html/header2.test.js +0 -377
- package/src/html/icon.example.js.backup +0 -268
- package/src/html/icon.test.js +0 -231
- package/src/html/label.test.js +0 -0
- package/src/html/list.example.js.backup +0 -404
- package/src/html/list.test.js +0 -383
- package/src/html/progress.example.js.backup +0 -424
- package/src/html/progress.test.js +0 -313
- package/src/html/property.example.js.backup +0 -553
- package/src/html/property.test.js +0 -371
- package/src/html/radio.example.js.backup +0 -389
- package/src/html/radio.test.js +0 -318
- package/src/html/section.example.js.backup +0 -99
- package/src/html/section.test.js +0 -131
- package/src/html/selector.test.js +0 -20
- package/src/html/switch.example.js.backup +0 -461
- package/src/html/switch.test.js +0 -355
- package/src/html/tab.example.js.backup +0 -446
- package/src/html/tab.test.js +0 -25
- package/src/html/tab_enhanced.test.js +0 -504
- package/src/html/table.test.js +0 -70
- package/src/html/table2.test.js +0 -582
- package/src/html/text.test.js +0 -15
- package/src/html/textfield.test.js +0 -51
- package/src/html/textfield2.example.js.backup +0 -1370
- package/src/html/textfield2.test.js +0 -950
- package/src/html/tokenfield.example.js.backup +0 -503
- package/src/html/tokenfield.test.js +0 -423
- package/src/html/tree.example.js.backup +0 -475
- package/src/html/tree.test.js +0 -43
- package/src/html/tree_enhanced.test.js +0 -495
- package/src/http/token.test.js +0 -50
- package/src/incubator/pdfViewer.js +0 -33
- package/src/incubator/wizard.test.js +0 -127
- package/src/site/site.test.js +0 -230
- package/src/site/view.test.js +0 -41
- package/src/widgets/calendar/Calendar.test.js +0 -28
- package/src/widgets/explorer/Explorer.test.js +0 -121
- package/src/widgets/ide/editor.test.js +0 -33
- package/src/widgets/kanban/Kanban.test.js +0 -78
- package/src/widgets/login/LoginBox.test.js +0 -12
- package/src/widgets/login/ResetPasswordBox.test.js +0 -34
- package/src/widgets/login/validations.test.js +0 -51
- package/src/widgets/planner/Planner.test.js +0 -60
- package/src/widgets/upload/Upload.test.js +0 -32
- package/table2.test.js +0 -454
package/src/html/header2.test.js
DELETED
@@ -1,377 +0,0 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { Header2 } from './header2'
|
3
|
-
|
4
|
-
// Pruebas unitarias para el componente Header2
|
5
|
-
describe('Header2 Component', () => {
|
6
|
-
// Mock de los componentes dependientes
|
7
|
-
const mockText = jest.fn()
|
8
|
-
const mockIcon = jest.fn()
|
9
|
-
|
10
|
-
beforeEach(() => {
|
11
|
-
jest.clearAllMocks()
|
12
|
-
|
13
|
-
// Mock del componente Text
|
14
|
-
jest.doMock('./text', () => ({
|
15
|
-
Text: mockText
|
16
|
-
}))
|
17
|
-
|
18
|
-
// Mock del componente Icon
|
19
|
-
jest.doMock('./icon', () => ({
|
20
|
-
Icon: mockIcon
|
21
|
-
}))
|
22
|
-
|
23
|
-
// Mock de console.warn para las pruebas
|
24
|
-
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
25
|
-
})
|
26
|
-
|
27
|
-
afterEach(() => {
|
28
|
-
console.warn.mockRestore()
|
29
|
-
})
|
30
|
-
|
31
|
-
test('component exports correctly', () => {
|
32
|
-
expect(Header2).toBeDefined()
|
33
|
-
expect(typeof Header2).toBe('function')
|
34
|
-
})
|
35
|
-
|
36
|
-
test('component has correct PropTypes', () => {
|
37
|
-
expect(Header2.propTypes).toBeDefined()
|
38
|
-
expect(Header2.propTypes.title).toBeDefined()
|
39
|
-
expect(Header2.propTypes.icon).toBeDefined()
|
40
|
-
expect(Header2.propTypes.iconSrc).toBeDefined()
|
41
|
-
expect(Header2.propTypes.img).toBeDefined()
|
42
|
-
expect(Header2.propTypes.caption).toBeDefined()
|
43
|
-
expect(Header2.propTypes.prominent).toBeDefined()
|
44
|
-
expect(Header2.propTypes.dense).toBeDefined()
|
45
|
-
expect(Header2.propTypes.primary).toBeDefined()
|
46
|
-
expect(Header2.propTypes.secondary).toBeDefined()
|
47
|
-
expect(Header2.propTypes.clickable).toBeDefined()
|
48
|
-
expect(Header2.propTypes.disabled).toBeDefined()
|
49
|
-
expect(Header2.propTypes.loading).toBeDefined()
|
50
|
-
expect(Header2.propTypes.className).toBeDefined()
|
51
|
-
expect(Header2.propTypes.children).toBeDefined()
|
52
|
-
expect(Header2.propTypes.action).toBeDefined()
|
53
|
-
expect(Header2.propTypes.ariaLabel).toBeDefined()
|
54
|
-
expect(Header2.propTypes.role).toBeDefined()
|
55
|
-
expect(Header2.propTypes.onClick).toBeDefined()
|
56
|
-
expect(Header2.propTypes.onIconClick).toBeDefined()
|
57
|
-
})
|
58
|
-
|
59
|
-
test('component has correct defaultProps', () => {
|
60
|
-
expect(Header2.defaultProps).toBeDefined()
|
61
|
-
expect(Header2.defaultProps.caption).toBe(false)
|
62
|
-
expect(Header2.defaultProps.prominent).toBe(false)
|
63
|
-
expect(Header2.defaultProps.dense).toBe(false)
|
64
|
-
expect(Header2.defaultProps.primary).toBe(false)
|
65
|
-
expect(Header2.defaultProps.secondary).toBe(false)
|
66
|
-
expect(Header2.defaultProps.clickable).toBe(false)
|
67
|
-
expect(Header2.defaultProps.disabled).toBe(false)
|
68
|
-
expect(Header2.defaultProps.loading).toBe(false)
|
69
|
-
expect(Header2.defaultProps.role).toBe('banner')
|
70
|
-
expect(Header2.defaultProps.className).toBe('')
|
71
|
-
})
|
72
|
-
|
73
|
-
test('warns when no accessibility props are provided', () => {
|
74
|
-
const validateAccessibility = (title, icon, iconSrc, ariaLabel) => {
|
75
|
-
if (!title && !icon && !iconSrc && !ariaLabel) {
|
76
|
-
console.warn('Header2 component: title, icon, iconSrc, or ariaLabel should be provided for accessibility')
|
77
|
-
}
|
78
|
-
}
|
79
|
-
|
80
|
-
validateAccessibility(null, null, null, null)
|
81
|
-
expect(console.warn).toHaveBeenCalledWith('Header2 component: title, icon, iconSrc, or ariaLabel should be provided for accessibility')
|
82
|
-
|
83
|
-
console.warn.mockClear()
|
84
|
-
validateAccessibility('Test Title', null, null, null)
|
85
|
-
expect(console.warn).not.toHaveBeenCalled()
|
86
|
-
})
|
87
|
-
|
88
|
-
test('CSS classes generation maintains original logic', () => {
|
89
|
-
const generateClasses = (caption, prominent, dense, primary, secondary, disabled, loading, className) => {
|
90
|
-
const captionClass = caption ? 'caption' : ''
|
91
|
-
const prominentClass = prominent ? 'prominent' : ''
|
92
|
-
const denseClass = dense ? 'dense' : ''
|
93
|
-
let themeClass = primary ? 'primary' : ''
|
94
|
-
themeClass = secondary ? 'secondary' : themeClass
|
95
|
-
|
96
|
-
return [
|
97
|
-
'header2',
|
98
|
-
captionClass,
|
99
|
-
prominentClass,
|
100
|
-
denseClass,
|
101
|
-
themeClass,
|
102
|
-
disabled && 'disabled',
|
103
|
-
loading && 'loading',
|
104
|
-
className || ''
|
105
|
-
].filter(Boolean).join(' ')
|
106
|
-
}
|
107
|
-
|
108
|
-
// Test basic header
|
109
|
-
expect(generateClasses(false, false, false, false, false, false, false, ''))
|
110
|
-
.toBe('header2')
|
111
|
-
|
112
|
-
// Test caption variant
|
113
|
-
expect(generateClasses(true, false, false, false, false, false, false, ''))
|
114
|
-
.toBe('header2 caption')
|
115
|
-
|
116
|
-
// Test prominent variant
|
117
|
-
expect(generateClasses(false, true, false, false, false, false, false, ''))
|
118
|
-
.toBe('header2 prominent')
|
119
|
-
|
120
|
-
// Test dense variant
|
121
|
-
expect(generateClasses(false, false, true, false, false, false, false, ''))
|
122
|
-
.toBe('header2 dense')
|
123
|
-
|
124
|
-
// Test primary theme
|
125
|
-
expect(generateClasses(false, false, false, true, false, false, false, ''))
|
126
|
-
.toBe('header2 primary')
|
127
|
-
|
128
|
-
// Test secondary theme (overrides primary)
|
129
|
-
expect(generateClasses(false, false, false, true, true, false, false, ''))
|
130
|
-
.toBe('header2 secondary')
|
131
|
-
|
132
|
-
// Test disabled state
|
133
|
-
expect(generateClasses(false, false, false, false, false, true, false, ''))
|
134
|
-
.toBe('header2 disabled')
|
135
|
-
|
136
|
-
// Test loading state
|
137
|
-
expect(generateClasses(false, false, false, false, false, false, true, ''))
|
138
|
-
.toBe('header2 loading')
|
139
|
-
|
140
|
-
// Test custom className
|
141
|
-
expect(generateClasses(false, false, false, false, false, false, false, 'custom-class'))
|
142
|
-
.toBe('header2 custom-class')
|
143
|
-
|
144
|
-
// Test combination
|
145
|
-
expect(generateClasses(true, false, false, true, false, false, false, 'custom'))
|
146
|
-
.toBe('header2 caption primary custom')
|
147
|
-
})
|
148
|
-
|
149
|
-
test('icon element generation maintains original logic', () => {
|
150
|
-
const generateIconElement = (icon, iconSrc, clickable, disabled, loading, handleIconClick, ariaLabel, title) => {
|
151
|
-
if (icon) {
|
152
|
-
return {
|
153
|
-
type: 'Icon',
|
154
|
-
props: {
|
155
|
-
icon: icon,
|
156
|
-
clickable: clickable && !disabled && !loading,
|
157
|
-
action: handleIconClick,
|
158
|
-
disabled: disabled,
|
159
|
-
ariaLabel: `${icon} icon`
|
160
|
-
}
|
161
|
-
}
|
162
|
-
} else if (iconSrc) {
|
163
|
-
return {
|
164
|
-
type: 'img',
|
165
|
-
props: {
|
166
|
-
className: 'header2-icon',
|
167
|
-
src: iconSrc,
|
168
|
-
alt: ariaLabel || title || 'Header icon',
|
169
|
-
onClick: clickable && !disabled && !loading ? handleIconClick : undefined,
|
170
|
-
style: {
|
171
|
-
cursor: clickable && !disabled && !loading ? 'pointer' : 'default',
|
172
|
-
opacity: disabled ? 0.6 : 1
|
173
|
-
}
|
174
|
-
}
|
175
|
-
}
|
176
|
-
}
|
177
|
-
return null
|
178
|
-
}
|
179
|
-
|
180
|
-
const mockHandler = jest.fn()
|
181
|
-
|
182
|
-
// Test with icon
|
183
|
-
const iconResult = generateIconElement('home', null, true, false, false, mockHandler, null, null)
|
184
|
-
expect(iconResult.type).toBe('Icon')
|
185
|
-
expect(iconResult.props.icon).toBe('home')
|
186
|
-
expect(iconResult.props.clickable).toBe(true)
|
187
|
-
expect(iconResult.props.ariaLabel).toBe('home icon')
|
188
|
-
|
189
|
-
// Test with iconSrc
|
190
|
-
const imgResult = generateIconElement(null, '/icon.png', true, false, false, mockHandler, 'Custom label', 'Title')
|
191
|
-
expect(imgResult.type).toBe('img')
|
192
|
-
expect(imgResult.props.src).toBe('/icon.png')
|
193
|
-
expect(imgResult.props.alt).toBe('Custom label')
|
194
|
-
expect(imgResult.props.style.cursor).toBe('pointer')
|
195
|
-
|
196
|
-
// Test disabled state
|
197
|
-
const disabledResult = generateIconElement('home', null, true, true, false, mockHandler, null, null)
|
198
|
-
expect(disabledResult.props.clickable).toBe(false)
|
199
|
-
|
200
|
-
// Test loading state
|
201
|
-
const loadingResult = generateIconElement('home', null, true, false, true, mockHandler, null, null)
|
202
|
-
expect(loadingResult.props.clickable).toBe(false)
|
203
|
-
|
204
|
-
// Test no icon
|
205
|
-
const noIconResult = generateIconElement(null, null, true, false, false, mockHandler, null, null)
|
206
|
-
expect(noIconResult).toBeNull()
|
207
|
-
})
|
208
|
-
|
209
|
-
test('background style generation maintains original logic', () => {
|
210
|
-
const generateBackgroundStyle = (img) => {
|
211
|
-
return img ? { backgroundImage: `url(${img})` } : {}
|
212
|
-
}
|
213
|
-
|
214
|
-
expect(generateBackgroundStyle(null)).toEqual({})
|
215
|
-
expect(generateBackgroundStyle('')).toEqual({})
|
216
|
-
expect(generateBackgroundStyle('/bg.jpg')).toEqual({ backgroundImage: 'url(/bg.jpg)' })
|
217
|
-
expect(generateBackgroundStyle('https://example.com/bg.png')).toEqual({ backgroundImage: 'url(https://example.com/bg.png)' })
|
218
|
-
})
|
219
|
-
|
220
|
-
test('accessibility attributes generation works correctly', () => {
|
221
|
-
const generateAriaAttributes = (ariaLabel, title, disabled, loading, role) => {
|
222
|
-
return {
|
223
|
-
'aria-label': ariaLabel || (typeof title === 'string' ? title : 'Header'),
|
224
|
-
'aria-disabled': disabled,
|
225
|
-
'aria-busy': loading,
|
226
|
-
role: role
|
227
|
-
}
|
228
|
-
}
|
229
|
-
|
230
|
-
// Test with string title
|
231
|
-
const result1 = generateAriaAttributes(null, 'Test Title', false, false, 'banner')
|
232
|
-
expect(result1['aria-label']).toBe('Test Title')
|
233
|
-
expect(result1['aria-disabled']).toBe(false)
|
234
|
-
expect(result1['aria-busy']).toBe(false)
|
235
|
-
expect(result1.role).toBe('banner')
|
236
|
-
|
237
|
-
// Test with custom aria-label
|
238
|
-
const result2 = generateAriaAttributes('Custom Label', 'Test Title', false, false, 'banner')
|
239
|
-
expect(result2['aria-label']).toBe('Custom Label')
|
240
|
-
|
241
|
-
// Test with non-string title
|
242
|
-
const result3 = generateAriaAttributes(null, { type: 'span', children: 'Complex Title' }, false, false, 'banner')
|
243
|
-
expect(result3['aria-label']).toBe('Header')
|
244
|
-
|
245
|
-
// Test disabled state
|
246
|
-
const result4 = generateAriaAttributes(null, 'Test Title', true, false, 'banner')
|
247
|
-
expect(result4['aria-disabled']).toBe(true)
|
248
|
-
|
249
|
-
// Test loading state
|
250
|
-
const result5 = generateAriaAttributes(null, 'Test Title', false, true, 'banner')
|
251
|
-
expect(result5['aria-busy']).toBe(true)
|
252
|
-
|
253
|
-
// Test custom role
|
254
|
-
const result6 = generateAriaAttributes(null, 'Test Title', false, false, 'heading')
|
255
|
-
expect(result6.role).toBe('heading')
|
256
|
-
})
|
257
|
-
|
258
|
-
test('icon click handling works correctly', () => {
|
259
|
-
const mockOnIconClick = jest.fn()
|
260
|
-
const mockAction = jest.fn()
|
261
|
-
|
262
|
-
const simulateIconClick = (disabled, loading, onIconClick, action) => {
|
263
|
-
if (disabled || loading) return false
|
264
|
-
|
265
|
-
if (onIconClick) {
|
266
|
-
onIconClick({})
|
267
|
-
return true
|
268
|
-
} else if (action) {
|
269
|
-
action({})
|
270
|
-
return true
|
271
|
-
}
|
272
|
-
return false
|
273
|
-
}
|
274
|
-
|
275
|
-
// Normal click with onIconClick
|
276
|
-
expect(simulateIconClick(false, false, mockOnIconClick, null)).toBe(true)
|
277
|
-
expect(mockOnIconClick).toHaveBeenCalled()
|
278
|
-
|
279
|
-
mockOnIconClick.mockClear()
|
280
|
-
|
281
|
-
// Normal click with action (fallback)
|
282
|
-
expect(simulateIconClick(false, false, null, mockAction)).toBe(true)
|
283
|
-
expect(mockAction).toHaveBeenCalled()
|
284
|
-
|
285
|
-
mockAction.mockClear()
|
286
|
-
|
287
|
-
// Disabled click
|
288
|
-
expect(simulateIconClick(true, false, mockOnIconClick, null)).toBe(false)
|
289
|
-
expect(mockOnIconClick).not.toHaveBeenCalled()
|
290
|
-
|
291
|
-
// Loading click
|
292
|
-
expect(simulateIconClick(false, true, mockOnIconClick, null)).toBe(false)
|
293
|
-
expect(mockOnIconClick).not.toHaveBeenCalled()
|
294
|
-
|
295
|
-
// No handlers
|
296
|
-
expect(simulateIconClick(false, false, null, null)).toBe(false)
|
297
|
-
})
|
298
|
-
|
299
|
-
test('header click handling works correctly', () => {
|
300
|
-
const mockOnClick = jest.fn()
|
301
|
-
|
302
|
-
const simulateHeaderClick = (disabled, loading, onClick) => {
|
303
|
-
if (disabled || loading) return false
|
304
|
-
|
305
|
-
if (onClick) {
|
306
|
-
onClick({})
|
307
|
-
return true
|
308
|
-
}
|
309
|
-
return false
|
310
|
-
}
|
311
|
-
|
312
|
-
// Normal click
|
313
|
-
expect(simulateHeaderClick(false, false, mockOnClick)).toBe(true)
|
314
|
-
expect(mockOnClick).toHaveBeenCalled()
|
315
|
-
|
316
|
-
mockOnClick.mockClear()
|
317
|
-
|
318
|
-
// Disabled click
|
319
|
-
expect(simulateHeaderClick(true, false, mockOnClick)).toBe(false)
|
320
|
-
expect(mockOnClick).not.toHaveBeenCalled()
|
321
|
-
|
322
|
-
// Loading click
|
323
|
-
expect(simulateHeaderClick(false, true, mockOnClick)).toBe(false)
|
324
|
-
expect(mockOnClick).not.toHaveBeenCalled()
|
325
|
-
|
326
|
-
// No handler
|
327
|
-
expect(simulateHeaderClick(false, false, null)).toBe(false)
|
328
|
-
})
|
329
|
-
|
330
|
-
test('title element generation maintains original logic', () => {
|
331
|
-
const generateTitleElement = (title) => {
|
332
|
-
return title ? {
|
333
|
-
type: 'label',
|
334
|
-
className: 'header2-title',
|
335
|
-
children: { type: 'Text', children: title }
|
336
|
-
} : null
|
337
|
-
}
|
338
|
-
|
339
|
-
expect(generateTitleElement(null)).toBeNull()
|
340
|
-
expect(generateTitleElement('')).toBeNull()
|
341
|
-
|
342
|
-
const result = generateTitleElement('Test Title')
|
343
|
-
expect(result.type).toBe('label')
|
344
|
-
expect(result.className).toBe('header2-title')
|
345
|
-
expect(result.children.children).toBe('Test Title')
|
346
|
-
})
|
347
|
-
|
348
|
-
test('theme class logic maintains original behavior', () => {
|
349
|
-
const generateThemeClass = (primary, secondary) => {
|
350
|
-
let themeClass = primary ? 'primary' : ''
|
351
|
-
themeClass = secondary ? 'secondary' : themeClass
|
352
|
-
return themeClass
|
353
|
-
}
|
354
|
-
|
355
|
-
expect(generateThemeClass(false, false)).toBe('')
|
356
|
-
expect(generateThemeClass(true, false)).toBe('primary')
|
357
|
-
expect(generateThemeClass(false, true)).toBe('secondary')
|
358
|
-
expect(generateThemeClass(true, true)).toBe('secondary') // secondary overrides primary
|
359
|
-
})
|
360
|
-
|
361
|
-
test('maintains exact same height calculations as original', () => {
|
362
|
-
const getHeaderHeight = (caption, prominent, dense) => {
|
363
|
-
if (prominent) return '12.8rem'
|
364
|
-
if (caption) return '4rem'
|
365
|
-
if (dense) return '2.4rem'
|
366
|
-
return '3rem' // min-height for normal
|
367
|
-
}
|
368
|
-
|
369
|
-
expect(getHeaderHeight(false, false, false)).toBe('3rem')
|
370
|
-
expect(getHeaderHeight(true, false, false)).toBe('4rem')
|
371
|
-
expect(getHeaderHeight(false, true, false)).toBe('12.8rem')
|
372
|
-
expect(getHeaderHeight(false, false, true)).toBe('2.4rem')
|
373
|
-
|
374
|
-
// Prominent takes precedence
|
375
|
-
expect(getHeaderHeight(true, true, true)).toBe('12.8rem')
|
376
|
-
})
|
377
|
-
})
|
@@ -1,268 +0,0 @@
|
|
1
|
-
import React, { useState } from 'react'
|
2
|
-
import { Icon } from './icon'
|
3
|
-
|
4
|
-
/**
|
5
|
-
* Ejemplos de uso del componente Icon mejorado
|
6
|
-
*/
|
7
|
-
export const IconExamples = () => {
|
8
|
-
const [clickCount, setClickCount] = useState(0)
|
9
|
-
const [isDisabled, setIsDisabled] = useState(false)
|
10
|
-
|
11
|
-
const handleClick = () => {
|
12
|
-
setClickCount(prev => prev + 1)
|
13
|
-
}
|
14
|
-
|
15
|
-
const toggleDisabled = () => {
|
16
|
-
setIsDisabled(prev => !prev)
|
17
|
-
}
|
18
|
-
|
19
|
-
return (
|
20
|
-
<div style={{ padding: '2rem', maxWidth: '800px' }}>
|
21
|
-
<h1>Ejemplos del Componente Icon Mejorado</h1>
|
22
|
-
|
23
|
-
<div style={{
|
24
|
-
background: '#f8f9fa',
|
25
|
-
padding: '1rem',
|
26
|
-
borderRadius: '8px',
|
27
|
-
marginBottom: '2rem',
|
28
|
-
border: '1px solid #e9ecef'
|
29
|
-
}}>
|
30
|
-
<h3>✅ Mejoras Implementadas:</h3>
|
31
|
-
<ul>
|
32
|
-
<li>🛡️ <strong>Manejo seguro de className</strong> - No falla con valores undefined</li>
|
33
|
-
<li>♿ <strong>Accesibilidad mejorada</strong> - Atributos ARIA y soporte de teclado</li>
|
34
|
-
<li>📝 <strong>PropTypes y documentación</strong> - Validación y documentación completa</li>
|
35
|
-
<li>🎯 <strong>Validación de props</strong> - Advertencias para props requeridos</li>
|
36
|
-
<li>🎨 <strong>CSS mejorado</strong> - Cursor consistente y estados de focus</li>
|
37
|
-
<li>⌨️ <strong>Soporte de teclado</strong> - Enter y Espacio para activar</li>
|
38
|
-
<li>🧪 <strong>Pruebas unitarias</strong> - 11 pruebas que cubren toda la funcionalidad</li>
|
39
|
-
</ul>
|
40
|
-
</div>
|
41
|
-
|
42
|
-
{/* Iconos básicos */}
|
43
|
-
<section style={{ marginBottom: '2rem' }}>
|
44
|
-
<h3>Iconos Básicos</h3>
|
45
|
-
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
46
|
-
<Icon icon="home" />
|
47
|
-
<Icon icon="settings" />
|
48
|
-
<Icon icon="favorite" />
|
49
|
-
<Icon icon="info" />
|
50
|
-
</div>
|
51
|
-
<p><em>Iconos simples sin interacción</em></p>
|
52
|
-
</section>
|
53
|
-
|
54
|
-
{/* Diferentes tamaños */}
|
55
|
-
<section style={{ marginBottom: '2rem' }}>
|
56
|
-
<h3>Diferentes Tamaños</h3>
|
57
|
-
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
58
|
-
<Icon icon="star" size="small" />
|
59
|
-
<Icon icon="star" size="normal" />
|
60
|
-
<Icon icon="star" size="large" />
|
61
|
-
</div>
|
62
|
-
<p><em>Tamaños: small, normal, large</em></p>
|
63
|
-
</section>
|
64
|
-
|
65
|
-
{/* Iconos clickables */}
|
66
|
-
<section style={{ marginBottom: '2rem' }}>
|
67
|
-
<h3>Iconos Clickables</h3>
|
68
|
-
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
69
|
-
<Icon
|
70
|
-
icon="thumb_up"
|
71
|
-
clickable
|
72
|
-
action={handleClick}
|
73
|
-
tooltip={{
|
74
|
-
text: 'Hacer clic para incrementar',
|
75
|
-
top: '-3rem',
|
76
|
-
left: '-2rem'
|
77
|
-
}}
|
78
|
-
/>
|
79
|
-
<Icon
|
80
|
-
icon="refresh"
|
81
|
-
clickable
|
82
|
-
action={() => setClickCount(0)}
|
83
|
-
tooltip={{
|
84
|
-
text: 'Resetear contador',
|
85
|
-
top: '-3rem',
|
86
|
-
left: '-2rem'
|
87
|
-
}}
|
88
|
-
/>
|
89
|
-
<span>Clics: {clickCount}</span>
|
90
|
-
</div>
|
91
|
-
<p><em>Prueba hacer clic en los iconos o usar Enter/Espacio cuando tengan focus</em></p>
|
92
|
-
</section>
|
93
|
-
|
94
|
-
{/* Estados disabled */}
|
95
|
-
<section style={{ marginBottom: '2rem' }}>
|
96
|
-
<h3>Estados Disabled</h3>
|
97
|
-
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
98
|
-
<Icon
|
99
|
-
icon="toggle_on"
|
100
|
-
clickable
|
101
|
-
action={toggleDisabled}
|
102
|
-
tooltip={{
|
103
|
-
text: 'Alternar estado disabled',
|
104
|
-
top: '-3rem',
|
105
|
-
left: '-3rem'
|
106
|
-
}}
|
107
|
-
/>
|
108
|
-
<Icon
|
109
|
-
icon="delete"
|
110
|
-
clickable
|
111
|
-
disabled={isDisabled}
|
112
|
-
action={() => alert('¡Eliminado!')}
|
113
|
-
tooltip={{
|
114
|
-
text: isDisabled ? 'Icono deshabilitado' : 'Eliminar elemento',
|
115
|
-
top: '-3rem',
|
116
|
-
left: '-2rem'
|
117
|
-
}}
|
118
|
-
/>
|
119
|
-
<span>Estado: {isDisabled ? 'Disabled' : 'Enabled'}</span>
|
120
|
-
</div>
|
121
|
-
<p><em>El primer icono alterna el estado del segundo</em></p>
|
122
|
-
</section>
|
123
|
-
|
124
|
-
{/* Iconos con tooltips */}
|
125
|
-
<section style={{ marginBottom: '2rem' }}>
|
126
|
-
<h3>Iconos con Tooltips</h3>
|
127
|
-
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
128
|
-
<Icon
|
129
|
-
icon="help"
|
130
|
-
clickable
|
131
|
-
tooltip={{
|
132
|
-
text: 'Ayuda y soporte',
|
133
|
-
top: '-3rem',
|
134
|
-
left: '-2rem'
|
135
|
-
}}
|
136
|
-
action={() => alert('¡Ayuda!')}
|
137
|
-
/>
|
138
|
-
<Icon
|
139
|
-
icon="download"
|
140
|
-
clickable
|
141
|
-
tooltip={{
|
142
|
-
text: 'Descargar archivo',
|
143
|
-
top: '-3rem',
|
144
|
-
left: '-2rem'
|
145
|
-
}}
|
146
|
-
action={() => alert('¡Descargando!')}
|
147
|
-
/>
|
148
|
-
<Icon
|
149
|
-
icon="share"
|
150
|
-
clickable
|
151
|
-
tooltip={{
|
152
|
-
text: 'Compartir contenido',
|
153
|
-
top: '-3rem',
|
154
|
-
left: '-2rem'
|
155
|
-
}}
|
156
|
-
action={() => alert('¡Compartiendo!')}
|
157
|
-
/>
|
158
|
-
</div>
|
159
|
-
<p><em>Tooltips posicionados para no interferir con los clics</em></p>
|
160
|
-
</section>
|
161
|
-
|
162
|
-
{/* Accesibilidad */}
|
163
|
-
<section style={{ marginBottom: '2rem' }}>
|
164
|
-
<h3>Accesibilidad Mejorada</h3>
|
165
|
-
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
166
|
-
<Icon
|
167
|
-
icon="accessibility"
|
168
|
-
clickable
|
169
|
-
ariaLabel="Configuración de accesibilidad"
|
170
|
-
action={() => alert('Configuración de accesibilidad')}
|
171
|
-
/>
|
172
|
-
<Icon
|
173
|
-
icon="visibility"
|
174
|
-
clickable
|
175
|
-
ariaLabel="Alternar visibilidad"
|
176
|
-
action={() => alert('Visibilidad alternada')}
|
177
|
-
/>
|
178
|
-
<Icon
|
179
|
-
icon="hearing"
|
180
|
-
clickable
|
181
|
-
ariaLabel="Configuración de audio"
|
182
|
-
action={() => alert('Configuración de audio')}
|
183
|
-
/>
|
184
|
-
</div>
|
185
|
-
<p><em>Iconos con etiquetas ARIA personalizadas y soporte completo de teclado</em></p>
|
186
|
-
</section>
|
187
|
-
|
188
|
-
{/* Clases personalizadas */}
|
189
|
-
<section style={{ marginBottom: '2rem' }}>
|
190
|
-
<h3>Clases CSS Personalizadas</h3>
|
191
|
-
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
192
|
-
<Icon
|
193
|
-
icon="palette"
|
194
|
-
className="custom-icon-style"
|
195
|
-
style={{ color: '#e91e63' }}
|
196
|
-
/>
|
197
|
-
<Icon
|
198
|
-
icon="brush"
|
199
|
-
className="another-custom-class"
|
200
|
-
style={{ color: '#2196f3' }}
|
201
|
-
/>
|
202
|
-
<Icon
|
203
|
-
icon="color_lens"
|
204
|
-
className={undefined} // Manejo seguro de undefined
|
205
|
-
style={{ color: '#4caf50' }}
|
206
|
-
/>
|
207
|
-
</div>
|
208
|
-
<p><em>Manejo seguro de className, incluso con valores undefined</em></p>
|
209
|
-
</section>
|
210
|
-
|
211
|
-
{/* Demostración de validación */}
|
212
|
-
<section style={{ marginBottom: '2rem' }}>
|
213
|
-
<h3>Validación de Props</h3>
|
214
|
-
<div style={{
|
215
|
-
background: '#fff3cd',
|
216
|
-
padding: '1rem',
|
217
|
-
borderRadius: '4px',
|
218
|
-
border: '1px solid #ffeaa7'
|
219
|
-
}}>
|
220
|
-
<p><strong>Prueba en la consola del navegador:</strong></p>
|
221
|
-
<p>El componente ahora valida que la prop <code>icon</code> sea requerida y muestra advertencias apropiadas.</p>
|
222
|
-
<p>También valida tipos de props en desarrollo para detectar errores temprano.</p>
|
223
|
-
</div>
|
224
|
-
</section>
|
225
|
-
|
226
|
-
{/* Comparación antes/después */}
|
227
|
-
<section>
|
228
|
-
<h3>Comparación: Antes vs Después</h3>
|
229
|
-
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }}>
|
230
|
-
<div style={{
|
231
|
-
background: '#ffebee',
|
232
|
-
padding: '1rem',
|
233
|
-
borderRadius: '4px',
|
234
|
-
border: '1px solid #ffcdd2'
|
235
|
-
}}>
|
236
|
-
<h4>❌ Antes</h4>
|
237
|
-
<ul>
|
238
|
-
<li>className undefined causaba errores</li>
|
239
|
-
<li>Sin validación de props</li>
|
240
|
-
<li>Sin accesibilidad</li>
|
241
|
-
<li>Sin soporte de teclado</li>
|
242
|
-
<li>Cursor inconsistente</li>
|
243
|
-
<li>Sin documentación</li>
|
244
|
-
</ul>
|
245
|
-
</div>
|
246
|
-
<div style={{
|
247
|
-
background: '#e8f5e8',
|
248
|
-
padding: '1rem',
|
249
|
-
borderRadius: '4px',
|
250
|
-
border: '1px solid #c8e6c9'
|
251
|
-
}}>
|
252
|
-
<h4>✅ Después</h4>
|
253
|
-
<ul>
|
254
|
-
<li>Manejo seguro de todas las props</li>
|
255
|
-
<li>PropTypes completos</li>
|
256
|
-
<li>Atributos ARIA apropiados</li>
|
257
|
-
<li>Soporte completo de teclado</li>
|
258
|
-
<li>Estados visuales consistentes</li>
|
259
|
-
<li>Documentación y ejemplos</li>
|
260
|
-
</ul>
|
261
|
-
</div>
|
262
|
-
</div>
|
263
|
-
</section>
|
264
|
-
</div>
|
265
|
-
)
|
266
|
-
}
|
267
|
-
|
268
|
-
export default IconExamples
|