ywana-core8 0.1.75 → 0.1.77

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 +10893 -1969
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.css +7768 -1096
  23. package/dist/index.css.map +1 -1
  24. package/dist/index.modern.js +10921 -2005
  25. package/dist/index.modern.js.map +1 -1
  26. package/dist/index.umd.js +10893 -1969
  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 +4 -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 +289 -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 +841 -0
  106. package/src/html/textfield2.example.js +1370 -0
  107. package/src/html/textfield2.js +1143 -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 +240 -10
  118. package/src/html/tree.example.js +475 -0
  119. package/src/html/tree.js +714 -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,99 +1,279 @@
1
1
  import React, { useEffect, useState, useCallback } from 'react'
2
+ import PropTypes from 'prop-types'
2
3
  import { Icon } from './icon'
3
4
  import { Text } from './text'
4
5
  import './button.css'
5
6
 
6
7
  /**
7
- * HTML Button
8
+ * Button component with enhanced features and accessibility
8
9
  */
9
- export const Button = ({ label, icon, action, disabled = false, outlined, raised, className, progress = 0 }) => {
10
+ export const Button = (props) => {
11
+ const {
12
+ id,
13
+ label,
14
+ icon,
15
+ action,
16
+ disabled = false,
17
+ loading = false,
18
+ outlined = false,
19
+ raised = false,
20
+ size = 'normal',
21
+ type = 'button',
22
+ className,
23
+ ariaLabel,
24
+ tooltip,
25
+ form,
26
+ onClick,
27
+ onFocus,
28
+ onBlur,
29
+ onKeyDown,
30
+ ...restProps
31
+ } = props
32
+
33
+ // Validate required props
34
+ if (!label && !icon && !ariaLabel) {
35
+ console.warn('Button component: label, icon, or ariaLabel prop is required for accessibility')
36
+ }
10
37
 
11
38
  const click = useCallback((event) => {
12
- if (!disabled) {
13
- event.stopPropagation();
14
- event.preventDefault();
15
- if (action) action()
39
+ if (!disabled && !loading) {
40
+ // Don't prevent default for form submissions
41
+ if (type !== 'submit') {
42
+ event.stopPropagation()
43
+ event.preventDefault()
44
+ }
45
+
46
+ if (action) action(event)
47
+ if (onClick) onClick(event)
48
+ }
49
+ }, [disabled, loading, action, onClick, type])
50
+
51
+ // Handle keyboard events for accessibility
52
+ const handleKeyDown = useCallback((event) => {
53
+ if (event.key === 'Enter' || event.key === ' ') {
54
+ if (type === 'button') {
55
+ event.preventDefault()
56
+ click(event)
57
+ }
16
58
  }
17
- }, [disabled, action]);
59
+ if (onKeyDown) onKeyDown(event)
60
+ }, [click, onKeyDown, type])
61
+
62
+ const handleFocus = useCallback((event) => {
63
+ if (onFocus) onFocus(event)
64
+ }, [onFocus])
65
+
66
+ const handleBlur = useCallback((event) => {
67
+ if (onBlur) onBlur(event)
68
+ }, [onBlur])
69
+
70
+ // Generate CSS classes
71
+ const variant = raised ? 'raised' : outlined ? 'outlined' : 'normal'
72
+ const state = disabled ? 'disabled' : loading ? 'loading' : ''
73
+ const safeClassName = className || ''
74
+
75
+ const cssClasses = [
76
+ 'btn',
77
+ variant,
78
+ size,
79
+ state,
80
+ safeClassName
81
+ ].filter(Boolean).join(' ')
82
+
83
+ // Accessibility attributes
84
+ const ariaAttributes = {
85
+ 'aria-label': ariaLabel || (icon && !label ? `${icon} button` : undefined),
86
+ 'aria-disabled': disabled || loading,
87
+ 'aria-busy': loading,
88
+ 'aria-describedby': tooltip ? `${id}-tooltip` : undefined
89
+ }
90
+
91
+ // Icon configuration
92
+ const iconProps = {
93
+ icon: loading ? 'hourglass_empty' : icon,
94
+ size: size === 'small' ? 'small' : size === 'large' ? 'normal' : 'small',
95
+ disabled: disabled || loading,
96
+ className: loading ? 'loading-icon' : ''
97
+ }
18
98
 
19
- let style = raised ? 'raised' : outlined ? 'outlined' : 'normal'
20
- if (disabled) style = `${style} disabled`
21
99
  return (
22
- <button className={`btn ${style} ${className}`} onClick={click}>
23
- {icon && <Icon icon={icon} size="small" clickable action={click} /> }
24
- <Text>{label}</Text>
100
+ <button
101
+ id={id}
102
+ type={type}
103
+ form={form}
104
+ className={cssClasses}
105
+ onClick={click}
106
+ onFocus={handleFocus}
107
+ onBlur={handleBlur}
108
+ onKeyDown={handleKeyDown}
109
+ disabled={disabled || loading}
110
+ {...ariaAttributes}
111
+ {...restProps}
112
+ >
113
+ {(icon || loading) && <Icon {...iconProps} />}
114
+ {label && <Text>{label}</Text>}
115
+ {loading && !icon && <span className="loading-text">Loading...</span>}
25
116
  </button>
26
117
  )
27
118
  }
28
119
 
29
120
  /**
30
- * Action Button
121
+ * ActionButton component for handling multi-state button workflows
31
122
  */
32
123
  export const ActionButton = (props) => {
124
+ const {
125
+ states,
126
+ state,
127
+ className,
128
+ disabled = false,
129
+ onStateChange,
130
+ ...restProps
131
+ } = props
33
132
 
34
- const { states, state, className } = props
133
+ const [currentState, setCurrentState] = useState(state)
134
+ const [isExecuting, setIsExecuting] = useState(false)
35
135
 
36
- const [_state, setState] = useState()
136
+ // Validate required props
137
+ if (!states || typeof states !== 'object') {
138
+ console.warn('ActionButton component: states prop is required and must be an object')
139
+ return null
140
+ }
37
141
 
142
+ if (!state) {
143
+ console.warn('ActionButton component: state prop is required')
144
+ return null
145
+ }
146
+
147
+ // Sync with external state
38
148
  useEffect(() => {
39
- setState(state)
149
+ setCurrentState(state)
40
150
  }, [state])
41
151
 
152
+ // Auto-execute when state changes
42
153
  useEffect(() => {
43
- if (states[_state] && states[_state].autoexec) execute()
44
- }, [_state])
154
+ if (states[currentState] && states[currentState].autoexec && !isExecuting) {
155
+ execute()
156
+ }
157
+ }, [currentState, states, isExecuting])
45
158
 
46
159
  async function execute() {
47
- if (states[_state]) {
48
- const newState = await states[_state].action()
49
- if (newState) setState(newState)
160
+ if (disabled || isExecuting) return
161
+
162
+ const stateConfig = states[currentState]
163
+ if (!stateConfig) return
164
+
165
+ try {
166
+ setIsExecuting(true)
167
+
168
+ if (stateConfig.action) {
169
+ const newState = await stateConfig.action()
170
+ if (newState && states[newState]) {
171
+ setCurrentState(newState)
172
+ if (onStateChange) onStateChange(newState)
173
+ }
174
+ }
175
+ } catch (error) {
176
+ console.error('ActionButton execution error:', error)
177
+ // Try to transition to error state if it exists
178
+ if (states.error) {
179
+ setCurrentState('error')
180
+ if (onStateChange) onStateChange('error')
181
+ }
182
+ } finally {
183
+ setIsExecuting(false)
50
184
  }
51
185
  }
52
186
 
53
- if (!_state) return null
54
- const { icon, label } = states[_state]
187
+ if (!currentState || !states[currentState]) return null
188
+
189
+ const stateConfig = states[currentState]
190
+ const { icon, label, disabled: stateDisabled } = stateConfig
191
+ const safeClassName = className || ''
55
192
 
56
193
  return (
57
- <Button {...props} icon={icon} label={label} action={execute} className={`${className} action-btn ${_state}`} />
194
+ <Button
195
+ {...restProps}
196
+ icon={icon}
197
+ label={label}
198
+ action={execute}
199
+ disabled={disabled || stateDisabled || isExecuting}
200
+ loading={isExecuting && currentState === 'running'}
201
+ className={`${safeClassName} action-btn ${currentState}`}
202
+ />
58
203
  )
204
+ }
59
205
 
206
+ // PropTypes para Button
207
+ Button.propTypes = {
208
+ /** Unique identifier for the button */
209
+ id: PropTypes.string,
210
+ /** Button text label */
211
+ label: PropTypes.string,
212
+ /** Icon name for Material Icons */
213
+ icon: PropTypes.string,
214
+ /** Click handler function */
215
+ action: PropTypes.func,
216
+ /** Whether the button is disabled */
217
+ disabled: PropTypes.bool,
218
+ /** Whether the button is in loading state */
219
+ loading: PropTypes.bool,
220
+ /** Whether the button has outlined style */
221
+ outlined: PropTypes.bool,
222
+ /** Whether the button has raised style */
223
+ raised: PropTypes.bool,
224
+ /** Size variant of the button */
225
+ size: PropTypes.oneOf(['small', 'normal', 'large']),
226
+ /** Button type for forms */
227
+ type: PropTypes.oneOf(['button', 'submit', 'reset']),
228
+ /** Additional CSS classes */
229
+ className: PropTypes.string,
230
+ /** Accessibility label for screen readers */
231
+ ariaLabel: PropTypes.string,
232
+ /** Tooltip configuration */
233
+ tooltip: PropTypes.string,
234
+ /** Form ID for submit buttons */
235
+ form: PropTypes.string,
236
+ /** Click event handler */
237
+ onClick: PropTypes.func,
238
+ /** Focus event handler */
239
+ onFocus: PropTypes.func,
240
+ /** Blur event handler */
241
+ onBlur: PropTypes.func,
242
+ /** KeyDown event handler */
243
+ onKeyDown: PropTypes.func
60
244
  }
61
245
 
62
- const ActionButtonTest = (props) => {
63
-
64
- const states = {
65
- normal: {
66
- icon: "add",
67
- label: "Create Job",
68
- action: () => {
69
- return "running"
70
- },
71
- },
72
- running: {
73
- icon: "rotate_right",
74
- label: "Creating Job",
75
- autoexec: true,
76
- action: () => {
77
- console.log("Creating Job")
78
- return new Promise((resolve, reject) => {
79
- setTimeout(() => {
80
- resolve("success")
81
- }, 5000)
82
- })
83
- },
84
- },
85
- success: {
86
- icon: "task_alt",
87
- label: "Job Created"
88
-
89
- },
90
- error: {
91
- icon: "error",
92
- label: "Error"
93
- }
94
- }
246
+ Button.defaultProps = {
247
+ disabled: false,
248
+ loading: false,
249
+ outlined: false,
250
+ raised: false,
251
+ size: 'normal',
252
+ type: 'button',
253
+ className: ''
254
+ }
95
255
 
96
- return (
97
- <ActionButton states={states} state="normal" raised/>
98
- )
256
+ // PropTypes para ActionButton
257
+ ActionButton.propTypes = {
258
+ /** Object defining button states and their configurations */
259
+ states: PropTypes.objectOf(PropTypes.shape({
260
+ icon: PropTypes.string,
261
+ label: PropTypes.string,
262
+ action: PropTypes.func,
263
+ autoexec: PropTypes.bool,
264
+ disabled: PropTypes.bool
265
+ })).isRequired,
266
+ /** Current state key */
267
+ state: PropTypes.string.isRequired,
268
+ /** Whether the button is disabled */
269
+ disabled: PropTypes.bool,
270
+ /** Additional CSS classes */
271
+ className: PropTypes.string,
272
+ /** State change callback */
273
+ onStateChange: PropTypes.func
274
+ }
275
+
276
+ ActionButton.defaultProps = {
277
+ disabled: false,
278
+ className: ''
99
279
  }