simplify pressable changes
This commit is contained in:
@@ -1,110 +1,12 @@
|
||||
import React from 'react'
|
||||
import {AccessibilityProps, ViewStyle} from 'react-native'
|
||||
import {PressableEvent} from 'react-native-gesture-handler/lib/typescript/components/Pressable/PressableProps'
|
||||
import {
|
||||
BlueskyBottomSheetPressable,
|
||||
BlueskyBottomSheetPressableProps,
|
||||
} from '@haileyok/bluesky-bottom-sheet'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {
|
||||
ButtonContext,
|
||||
useSharedButtonStyles,
|
||||
VariantProps,
|
||||
} from '#/components/Button'
|
||||
|
||||
export function BottomSheetButton({
|
||||
children,
|
||||
label,
|
||||
color,
|
||||
variant,
|
||||
shape = 'default',
|
||||
size,
|
||||
disabled,
|
||||
style,
|
||||
...rest
|
||||
}: BlueskyBottomSheetPressableProps &
|
||||
AccessibilityProps &
|
||||
VariantProps & {
|
||||
/**
|
||||
* For a11y, try to make this descriptive and clear
|
||||
*/
|
||||
label: string
|
||||
}) {
|
||||
const [state, setState] = React.useState({
|
||||
pressed: false,
|
||||
hovered: false,
|
||||
focused: false,
|
||||
})
|
||||
|
||||
const onPressInOuter = rest.onPressIn
|
||||
const onPressIn = React.useCallback(
|
||||
(e: PressableEvent) => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
pressed: true,
|
||||
}))
|
||||
onPressInOuter?.(e)
|
||||
},
|
||||
[setState, onPressInOuter],
|
||||
)
|
||||
const onPressOutOuter = rest.onPressOut
|
||||
const onPressOut = React.useCallback(
|
||||
(e: PressableEvent) => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
pressed: false,
|
||||
}))
|
||||
onPressOutOuter?.(e)
|
||||
},
|
||||
[setState, onPressOutOuter],
|
||||
)
|
||||
|
||||
const {baseStyles, hoverStyles} = useSharedButtonStyles({
|
||||
/**
|
||||
* For a11y, try to make this descriptive and clear
|
||||
*/
|
||||
color,
|
||||
variant,
|
||||
shape,
|
||||
size,
|
||||
disabled,
|
||||
})
|
||||
|
||||
const context = React.useMemo<ButtonContext>(
|
||||
() => ({
|
||||
...state,
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
disabled: disabled || false,
|
||||
}),
|
||||
[state, variant, color, size, disabled],
|
||||
)
|
||||
import {Button, ButtonProps} from '#/components/Button'
|
||||
import {NormalizedPressable} from '#/components/NormalizedPressable'
|
||||
|
||||
export function BottomSheetButton({children, ...rest}: ButtonProps) {
|
||||
return (
|
||||
<BlueskyBottomSheetPressable
|
||||
style={[
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
baseStyles,
|
||||
style as ViewStyle,
|
||||
...(state.hovered || state.pressed ? [hoverStyles] : []),
|
||||
]}
|
||||
aria-label={label}
|
||||
aria-pressed={state.pressed}
|
||||
accessibilityLabel={label}
|
||||
accessibilityHint={undefined}
|
||||
accessibilityState={{
|
||||
disabled: disabled || false,
|
||||
}}
|
||||
onPressIn={onPressIn}
|
||||
onPressOut={onPressOut}
|
||||
{...rest}>
|
||||
<ButtonContext.Provider value={context}>
|
||||
{typeof children === 'function' ? children(context) : children}
|
||||
</ButtonContext.Provider>
|
||||
</BlueskyBottomSheetPressable>
|
||||
<Button {...rest} Component={NormalizedPressable}>
|
||||
{children}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ export type ButtonProps = Pick<
|
||||
style?: StyleProp<ViewStyle>
|
||||
hoverStyle?: StyleProp<ViewStyle>
|
||||
children: NonTextElements | ((context: ButtonContext) => NonTextElements)
|
||||
Component?: React.ComponentType<PressableProps>
|
||||
}
|
||||
|
||||
export type ButtonTextProps = TextProps &
|
||||
@@ -116,6 +117,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||
disabled = false,
|
||||
style,
|
||||
hoverStyle: hoverStyleProp,
|
||||
Component = Pressable,
|
||||
...rest
|
||||
},
|
||||
ref,
|
||||
@@ -237,7 +239,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||
const flattenedBaseStyles = flatten([baseStyles, style])
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
<Component
|
||||
role="button"
|
||||
accessibilityHint={undefined} // optional
|
||||
{...rest}
|
||||
@@ -288,7 +290,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||
<Context.Provider value={context}>
|
||||
{typeof children === 'function' ? children(context) : children}
|
||||
</Context.Provider>
|
||||
</Pressable>
|
||||
</Component>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react'
|
||||
import {StyleProp, View, ViewStyle} from 'react-native'
|
||||
import {BlueskyBottomSheetPressable as Pressable} from '@haileyok/bluesky-bottom-sheet'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import flattenReactChildren from 'react-keyed-flatten-children'
|
||||
@@ -19,6 +18,7 @@ import {
|
||||
ItemTextProps,
|
||||
TriggerProps,
|
||||
} from '#/components/Menu/types'
|
||||
import {NormalizedPressable} from '#/components/NormalizedPressable'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export {
|
||||
@@ -117,7 +117,7 @@ export function Item({children, label, style, onPress, ...rest}: ItemProps) {
|
||||
} = useInteractionState()
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
<NormalizedPressable
|
||||
{...rest}
|
||||
accessibilityHint=""
|
||||
accessibilityLabel={label}
|
||||
@@ -151,7 +151,7 @@ export function Item({children, label, style, onPress, ...rest}: ItemProps) {
|
||||
<ItemContext.Provider value={{disabled: Boolean(rest.disabled)}}>
|
||||
{children}
|
||||
</ItemContext.Provider>
|
||||
</Pressable>
|
||||
</NormalizedPressable>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import {
|
||||
GestureResponderEvent,
|
||||
PressableProps,
|
||||
} from 'react-native'
|
||||
import {PressableEvent} from 'react-native-gesture-handler/lib/typescript/components/Pressable/PressableProps'
|
||||
import {BlueskyBottomSheetPressableProps} from '@haileyok/bluesky-bottom-sheet'
|
||||
|
||||
import {TextStyleProp, ViewStyleProp} from '#/alf'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
@@ -89,10 +87,10 @@ export type TriggerChildProps =
|
||||
}
|
||||
|
||||
export type ItemProps = React.PropsWithChildren<
|
||||
Omit<BlueskyBottomSheetPressableProps, 'style'> &
|
||||
Omit<PressableProps, 'style'> &
|
||||
ViewStyleProp & {
|
||||
label: string
|
||||
onPress: (e: PressableEvent | GestureResponderEvent) => void
|
||||
onPress: (e: GestureResponderEvent) => void
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
GestureResponderEvent,
|
||||
NativeMouseEvent,
|
||||
NativeSyntheticEvent,
|
||||
PressableProps,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {Pressable as BSPressable} from 'react-native-gesture-handler'
|
||||
import {PressableEvent} from 'react-native-gesture-handler/lib/typescript/components/Pressable/PressableProps'
|
||||
|
||||
function pressableEventToGestureResponderEvent(
|
||||
event: PressableEvent,
|
||||
): GestureResponderEvent {
|
||||
return {
|
||||
nativeEvent: {
|
||||
...event.nativeEvent,
|
||||
touches: [],
|
||||
changedTouches: [],
|
||||
identifier: event.nativeEvent.identifier.toString(),
|
||||
target: event.nativeEvent.target.toString(),
|
||||
},
|
||||
target: null,
|
||||
currentTarget: null,
|
||||
preventDefault() {},
|
||||
stopPropagation() {},
|
||||
cancelable: false,
|
||||
defaultPrevented: false,
|
||||
eventPhase: 0,
|
||||
isTrusted: false,
|
||||
bubbles: false,
|
||||
timeStamp: event.nativeEvent.timestamp,
|
||||
isDefaultPrevented(): boolean {
|
||||
return false
|
||||
},
|
||||
isPropagationStopped(): boolean {
|
||||
return false
|
||||
},
|
||||
persist() {},
|
||||
type: 'press',
|
||||
}
|
||||
}
|
||||
|
||||
function pressableEventToMouseEvent(
|
||||
event: PressableEvent,
|
||||
): MouseEvent & NativeSyntheticEvent<NativeMouseEvent> {
|
||||
return {
|
||||
...event.nativeEvent,
|
||||
target: null,
|
||||
currentTarget: null,
|
||||
preventDefault() {},
|
||||
stopPropagation() {},
|
||||
cancelable: false,
|
||||
defaultPrevented: false,
|
||||
eventPhase: 0,
|
||||
isTrusted: false,
|
||||
bubbles: false,
|
||||
timeStamp: event.nativeEvent.timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
export const NormalizedPressable = React.forwardRef<View, PressableProps>(
|
||||
function NormalizedPressable(
|
||||
{
|
||||
onPress,
|
||||
onLongPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onHoverIn,
|
||||
onHoverOut,
|
||||
onFocus: _onFocus,
|
||||
...rest
|
||||
},
|
||||
ref,
|
||||
) {
|
||||
const onNormalizedPress = (event: PressableEvent) => {
|
||||
if (!onPress) return
|
||||
onPress(pressableEventToGestureResponderEvent(event))
|
||||
}
|
||||
|
||||
const onNormalizedLongPress = (event: PressableEvent) => {
|
||||
if (!onLongPress) return
|
||||
onLongPress(pressableEventToGestureResponderEvent(event))
|
||||
}
|
||||
|
||||
const onNormalizedPressIn = (event: PressableEvent) => {
|
||||
if (!onPressIn) return
|
||||
onPressIn(pressableEventToGestureResponderEvent(event))
|
||||
}
|
||||
|
||||
const onNormalizedPressOut = (event: PressableEvent) => {
|
||||
if (!onPressOut) return
|
||||
onPressOut(pressableEventToGestureResponderEvent(event))
|
||||
}
|
||||
|
||||
const onNormalizedHoverIn = (event: PressableEvent) => {
|
||||
if (!onHoverIn) return
|
||||
onHoverIn(pressableEventToMouseEvent(event))
|
||||
}
|
||||
|
||||
const onNormalizedHoverOut = (event: PressableEvent) => {
|
||||
if (!onHoverOut) return
|
||||
onHoverOut(pressableEventToMouseEvent(event))
|
||||
}
|
||||
|
||||
return (
|
||||
<View ref={ref}>
|
||||
<BSPressable
|
||||
onPress={onNormalizedPress}
|
||||
onLongPress={onNormalizedLongPress}
|
||||
onPressIn={onNormalizedPressIn}
|
||||
onPressOut={onNormalizedPressOut}
|
||||
onHoverIn={onNormalizedHoverIn}
|
||||
onHoverOut={onNormalizedHoverOut}
|
||||
{...rest}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
import {Pressable as NormalizedPressable} from 'react-native'
|
||||
|
||||
export {NormalizedPressable}
|
||||
Reference in New Issue
Block a user