@codeleap/web 3.17.0 → 3.18.1
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/package.json +1 -1
- package/src/components/ActionIcon/index.tsx +13 -10
- package/src/components/Checkbox/index.tsx +5 -2
- package/src/components/Grid/index.tsx +1 -1
- package/src/components/Modal/index.tsx +35 -2
- package/src/components/SegmentedControl/index.tsx +5 -1
- package/src/components/Switch/index.tsx +7 -3
- package/src/components/Touchable/index.tsx +4 -0
package/package.json
CHANGED
|
@@ -20,6 +20,7 @@ export type ActionIconProps = Omit<TouchableProps, 'styles' | 'variants'> & Comp
|
|
|
20
20
|
|
|
21
21
|
const defaultProps: Partial<ActionIconProps> = {
|
|
22
22
|
disabled: false,
|
|
23
|
+
tabIndex: 0,
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export const ActionIcon = (props: ActionIconProps) => {
|
|
@@ -28,7 +29,7 @@ export const ActionIcon = (props: ActionIconProps) => {
|
|
|
28
29
|
...props,
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
const {
|
|
32
|
+
const {
|
|
32
33
|
icon,
|
|
33
34
|
name,
|
|
34
35
|
iconProps,
|
|
@@ -39,30 +40,31 @@ export const ActionIcon = (props: ActionIconProps) => {
|
|
|
39
40
|
children,
|
|
40
41
|
disabled,
|
|
41
42
|
debugName,
|
|
42
|
-
...touchableProps
|
|
43
|
+
...touchableProps
|
|
43
44
|
} = allProps
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
const variantStyles = useDefaultComponentStyle<'u:ActionIcon', typeof ActionIconPresets>('u:ActionIcon', {
|
|
46
47
|
responsiveVariants,
|
|
47
|
-
variants,
|
|
48
|
+
variants,
|
|
48
49
|
styles,
|
|
49
|
-
rootElement: 'touchableWrapper'
|
|
50
|
+
rootElement: 'touchableWrapper',
|
|
50
51
|
})
|
|
51
52
|
|
|
52
53
|
const isPressable = TypeGuards.isFunction(onPress) && !disabled
|
|
53
54
|
|
|
54
55
|
const WrapperComponent: any = isPressable ? Touchable : View
|
|
55
56
|
|
|
56
|
-
const handlePress = () => {
|
|
57
|
+
const handlePress = (e) => {
|
|
57
58
|
if (!isPressable) return
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
if (onPress && (e?.type === 'click' || e?.keyCode === 13 || e?.key === 'Enter')) {
|
|
60
|
+
onPress?.()
|
|
61
|
+
}
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
const getStyles = (key: ActionIconParts) => ({
|
|
63
65
|
...variantStyles[key],
|
|
64
66
|
...(disabled ? variantStyles[`${key}:disabled`] : {}),
|
|
65
|
-
...(isPressable ? variantStyles[`${key}:pressable`] : {})
|
|
67
|
+
...(isPressable ? variantStyles[`${key}:pressable`] : {}),
|
|
66
68
|
})
|
|
67
69
|
|
|
68
70
|
return (
|
|
@@ -72,7 +74,8 @@ export const ActionIcon = (props: ActionIconProps) => {
|
|
|
72
74
|
debugName={debugName}
|
|
73
75
|
{
|
|
74
76
|
...(isPressable && {
|
|
75
|
-
onPress: handlePress,
|
|
77
|
+
onPress: () => handlePress({ type: 'click' }),
|
|
78
|
+
onKeyDown: handlePress,
|
|
76
79
|
})
|
|
77
80
|
}
|
|
78
81
|
{...touchableProps}
|
|
@@ -113,9 +113,9 @@ export const Checkbox = (props: CheckboxProps) => {
|
|
|
113
113
|
|
|
114
114
|
const _checkboxOnLeft = checkboxOnLeft ?? variantStyles.__props?.checkboxOnLeft
|
|
115
115
|
|
|
116
|
-
const handleChange = () => {
|
|
116
|
+
const handleChange = (e) => {
|
|
117
117
|
if (disabled) return
|
|
118
|
-
if (onValueChange) onValueChange?.(!value)
|
|
118
|
+
if (onValueChange && (e?.type === 'click' || e?.keyCode === 13 || e?.key === 'Enter')) onValueChange?.(!value)
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
return <InputBase
|
|
@@ -142,6 +142,8 @@ export const Checkbox = (props: CheckboxProps) => {
|
|
|
142
142
|
animate={boxAnimation}
|
|
143
143
|
transition={variantStyles['box:transition']}
|
|
144
144
|
onClick={handleChange}
|
|
145
|
+
onKeyDown={handleChange}
|
|
146
|
+
tabIndex={0}
|
|
145
147
|
>
|
|
146
148
|
<motion.div
|
|
147
149
|
css={[
|
|
@@ -151,6 +153,7 @@ export const Checkbox = (props: CheckboxProps) => {
|
|
|
151
153
|
initial={false}
|
|
152
154
|
animate={checkmarkWrapperAnimation}
|
|
153
155
|
transition={variantStyles['checkmarkWrapper:transition']}
|
|
156
|
+
|
|
154
157
|
>
|
|
155
158
|
<Icon
|
|
156
159
|
debugName={debugName}
|
|
@@ -185,7 +185,7 @@ export const ModalContent = (
|
|
|
185
185
|
} = modalProps
|
|
186
186
|
|
|
187
187
|
const id = useId()
|
|
188
|
-
|
|
188
|
+
const modalRef = useRef(null)
|
|
189
189
|
const variantStyles = useDefaultComponentStyle<'u:Modal', typeof ModalPresets>('u:Modal', {
|
|
190
190
|
responsiveVariants,
|
|
191
191
|
variants,
|
|
@@ -210,6 +210,39 @@ export const ModalContent = (
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
const handleTabKeyPress = (e: React.KeyboardEvent<HTMLDivElement>, { firstElement, lastElement }: Record<'firstElement' |'lastElement', HTMLDivElement>) => {
|
|
214
|
+
if (e.key === 'Tab' || e?.keyCode === 9) {
|
|
215
|
+
if (e.shiftKey && document.activeElement === firstElement) {
|
|
216
|
+
e.preventDefault()
|
|
217
|
+
lastElement.focus()
|
|
218
|
+
} else if (
|
|
219
|
+
!e.shiftKey &&
|
|
220
|
+
document.activeElement === lastElement
|
|
221
|
+
) {
|
|
222
|
+
e.preventDefault()
|
|
223
|
+
firstElement.focus()
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
onUpdate(() => {
|
|
229
|
+
if (visible) {
|
|
230
|
+
const modalElement = modalRef.current
|
|
231
|
+
|
|
232
|
+
const focusableElements = modalElement.querySelectorAll('[tabindex]:not([tabindex="-1"])') as NodeListOf<HTMLDivElement>
|
|
233
|
+
const firstElement = focusableElements[0]
|
|
234
|
+
const lastElement = focusableElements[focusableElements.length - 1]
|
|
235
|
+
|
|
236
|
+
modalElement.addEventListener('keydown', (e) => handleTabKeyPress(e, { firstElement, lastElement }))
|
|
237
|
+
modalElement.addEventListener('keydown', closeOnEscPress)
|
|
238
|
+
|
|
239
|
+
return () => {
|
|
240
|
+
modalElement.removeEventListener('keydown', (e) => handleTabKeyPress(e, { firstElement, lastElement }))
|
|
241
|
+
modalElement.removeEventListener('keydown', closeOnEscPress)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}, [visible])
|
|
245
|
+
|
|
213
246
|
useIsomorphicEffect(() => {
|
|
214
247
|
const modal = document.getElementById(id)
|
|
215
248
|
if (modal) modal.focus()
|
|
@@ -227,6 +260,7 @@ export const ModalContent = (
|
|
|
227
260
|
|
|
228
261
|
return (
|
|
229
262
|
<View
|
|
263
|
+
ref={modalRef}
|
|
230
264
|
aria-hidden={!visible}
|
|
231
265
|
css={[
|
|
232
266
|
variantStyles.wrapper,
|
|
@@ -266,7 +300,6 @@ export const ModalContent = (
|
|
|
266
300
|
style,
|
|
267
301
|
]}
|
|
268
302
|
className='content'
|
|
269
|
-
onKeyDown={closeOnEscPress}
|
|
270
303
|
tabIndex={0}
|
|
271
304
|
id={id}
|
|
272
305
|
aria-modal={true}
|
|
@@ -135,7 +135,9 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
135
135
|
largestWidth,
|
|
136
136
|
]
|
|
137
137
|
|
|
138
|
-
const onSelectTab = (option: SegmentedControlOptionProps) => {
|
|
138
|
+
const onSelectTab = (option: SegmentedControlOptionProps, e?: React.KeyboardEvent<HTMLDivElement>) => {
|
|
139
|
+
if (!!e && e?.keyCode !== 13 || e?.key !== 'Enter') return null
|
|
140
|
+
|
|
139
141
|
if (!debounceEnabled || !TypeGuards.isNumber(debounce)) {
|
|
140
142
|
onValueChange(option.value)
|
|
141
143
|
return
|
|
@@ -171,6 +173,7 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
171
173
|
label={o.label}
|
|
172
174
|
value={o.value}
|
|
173
175
|
onPress={() => onSelectTab(o)}
|
|
176
|
+
onKeyDown={(e) => onSelectTab(o, e)}
|
|
174
177
|
key={idx}
|
|
175
178
|
icon={o.icon}
|
|
176
179
|
selected={value === o.value}
|
|
@@ -179,6 +182,7 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
179
182
|
disabled={disabled}
|
|
180
183
|
textProps={textProps}
|
|
181
184
|
iconProps={iconProps}
|
|
185
|
+
tabIndex={0}
|
|
182
186
|
{...props?.touchableProps}
|
|
183
187
|
/>
|
|
184
188
|
))}
|
|
@@ -89,10 +89,12 @@ export const Switch = (props: SwitchProps) => {
|
|
|
89
89
|
|
|
90
90
|
const _switchOnLeft = switchOnLeft ?? variantStyles.__props?.switchOnLeft
|
|
91
91
|
|
|
92
|
-
const handleChange = () => {
|
|
92
|
+
const handleChange = (e?: React.KeyboardEvent<HTMLDivElement>) => {
|
|
93
93
|
if (disabled) return
|
|
94
|
-
if (
|
|
95
|
-
|
|
94
|
+
if (e?.type === 'click' || e?.keyCode === 13 || e?.key === 'Enter') {
|
|
95
|
+
if (onValueChange) onValueChange?.(!value)
|
|
96
|
+
if (onChange) onChange?.(!value)
|
|
97
|
+
}
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
return <InputBase
|
|
@@ -118,6 +120,8 @@ export const Switch = (props: SwitchProps) => {
|
|
|
118
120
|
animate={trackAnimation}
|
|
119
121
|
transition={variantStyles['track:transition']}
|
|
120
122
|
onClick={handleChange}
|
|
123
|
+
onKeyDown={handleChange}
|
|
124
|
+
tabIndex={0}
|
|
121
125
|
>
|
|
122
126
|
<motion.div
|
|
123
127
|
css={[
|
|
@@ -38,6 +38,7 @@ const defaultProps: TouchableProps<'button'> = {
|
|
|
38
38
|
analyticsEnabled: false,
|
|
39
39
|
analyticsName: null,
|
|
40
40
|
analyticsData: {},
|
|
41
|
+
tabIndex: 0,
|
|
41
42
|
}
|
|
42
43
|
export const TouchableCP = <T extends NativeHTMLElement = 'button'>(
|
|
43
44
|
touchableProps: TouchableProps<T>,
|
|
@@ -105,6 +106,8 @@ export const TouchableCP = <T extends NativeHTMLElement = 'button'>(
|
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
const _onPress = () => {
|
|
109
|
+
if (event && (event?.type !== 'click' && event?.keyCode !== 13 && event?.key !== 'Enter')) return null
|
|
110
|
+
|
|
108
111
|
logger.log(
|
|
109
112
|
`<${debugComponent || 'Touchable'}/> pressed`,
|
|
110
113
|
{ debugName, debugComponent },
|
|
@@ -150,6 +153,7 @@ export const TouchableCP = <T extends NativeHTMLElement = 'button'>(
|
|
|
150
153
|
{...props}
|
|
151
154
|
debugName={debugName}
|
|
152
155
|
onClick={handleClick}
|
|
156
|
+
onKeyDown={handleClick}
|
|
153
157
|
ref={ref}
|
|
154
158
|
css={_styles}
|
|
155
159
|
/>
|