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.
- 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 +10893 -1969
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +7768 -1096
- package/dist/index.css.map +1 -1
- package/dist/index.modern.js +10921 -2005
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +10893 -1969
- 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 +4 -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 +289 -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/textfield2.css +841 -0
- package/src/html/textfield2.example.js +1370 -0
- package/src/html/textfield2.js +1143 -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 +240 -10
- package/src/html/tree.example.js +475 -0
- package/src/html/tree.js +714 -28
- package/src/html/tree_enhanced.test.js +495 -0
- package/table2.test.js +454 -0
- package/src/html/button.tsx +0 -38
package/src/html/button.js
CHANGED
@@ -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
|
-
*
|
8
|
+
* Button component with enhanced features and accessibility
|
8
9
|
*/
|
9
|
-
export const Button = (
|
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
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
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
|
23
|
-
|
24
|
-
|
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
|
-
*
|
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
|
133
|
+
const [currentState, setCurrentState] = useState(state)
|
134
|
+
const [isExecuting, setIsExecuting] = useState(false)
|
35
135
|
|
36
|
-
|
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
|
-
|
149
|
+
setCurrentState(state)
|
40
150
|
}, [state])
|
41
151
|
|
152
|
+
// Auto-execute when state changes
|
42
153
|
useEffect(() => {
|
43
|
-
if (states[
|
44
|
-
|
154
|
+
if (states[currentState] && states[currentState].autoexec && !isExecuting) {
|
155
|
+
execute()
|
156
|
+
}
|
157
|
+
}, [currentState, states, isExecuting])
|
45
158
|
|
46
159
|
async function execute() {
|
47
|
-
if (
|
48
|
-
|
49
|
-
|
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 (!
|
54
|
-
|
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
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
97
|
-
|
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
|
}
|