Add ESLint React plugin (#1412)
* Add eslint-plugin-react * Enable display name rule
This commit is contained in:
parent
00595591c4
commit
a5b89dffa6
14 changed files with 612 additions and 625 deletions
|
@ -12,34 +12,32 @@ interface PressableWithHover extends PressableProps {
|
|||
hoverStyle: StyleProp<ViewStyle>
|
||||
}
|
||||
|
||||
export const PressableWithHover = forwardRef(
|
||||
(
|
||||
{
|
||||
children,
|
||||
style,
|
||||
hoverStyle,
|
||||
...props
|
||||
}: PropsWithChildren<PressableWithHover>,
|
||||
ref: Ref<any>,
|
||||
) => {
|
||||
const [isHovering, setIsHovering] = useState(false)
|
||||
export const PressableWithHover = forwardRef(function PressableWithHoverImpl(
|
||||
{
|
||||
children,
|
||||
style,
|
||||
hoverStyle,
|
||||
...props
|
||||
}: PropsWithChildren<PressableWithHover>,
|
||||
ref: Ref<any>,
|
||||
) {
|
||||
const [isHovering, setIsHovering] = useState(false)
|
||||
|
||||
const onHoverIn = useCallback(() => setIsHovering(true), [setIsHovering])
|
||||
const onHoverOut = useCallback(() => setIsHovering(false), [setIsHovering])
|
||||
style =
|
||||
typeof style !== 'function' && isHovering
|
||||
? addStyle(style, hoverStyle)
|
||||
: style
|
||||
const onHoverIn = useCallback(() => setIsHovering(true), [setIsHovering])
|
||||
const onHoverOut = useCallback(() => setIsHovering(false), [setIsHovering])
|
||||
style =
|
||||
typeof style !== 'function' && isHovering
|
||||
? addStyle(style, hoverStyle)
|
||||
: style
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
{...props}
|
||||
style={style}
|
||||
onHoverIn={onHoverIn}
|
||||
onHoverOut={onHoverOut}
|
||||
ref={ref}>
|
||||
{children}
|
||||
</Pressable>
|
||||
)
|
||||
},
|
||||
)
|
||||
return (
|
||||
<Pressable
|
||||
{...props}
|
||||
style={style}
|
||||
onHoverIn={onHoverIn}
|
||||
onHoverOut={onHoverOut}
|
||||
ref={ref}>
|
||||
{children}
|
||||
</Pressable>
|
||||
)
|
||||
})
|
||||
|
|
|
@ -42,100 +42,98 @@ export const ViewSelector = React.forwardRef<
|
|||
onRefresh?: () => void
|
||||
onEndReached?: (info: {distanceFromEnd: number}) => void
|
||||
}
|
||||
>(
|
||||
(
|
||||
{
|
||||
sections,
|
||||
items,
|
||||
refreshing,
|
||||
renderHeader,
|
||||
renderItem,
|
||||
ListFooterComponent,
|
||||
onSelectView,
|
||||
onScroll,
|
||||
onRefresh,
|
||||
onEndReached,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const pal = usePalette('default')
|
||||
const [selectedIndex, setSelectedIndex] = useState<number>(0)
|
||||
const flatListRef = React.useRef<FlatList>(null)
|
||||
|
||||
// events
|
||||
// =
|
||||
|
||||
const keyExtractor = React.useCallback((item: any) => item._reactKey, [])
|
||||
|
||||
const onPressSelection = React.useCallback(
|
||||
(index: number) => setSelectedIndex(clamp(index, 0, sections.length)),
|
||||
[setSelectedIndex, sections],
|
||||
)
|
||||
useEffect(() => {
|
||||
onSelectView?.(selectedIndex)
|
||||
}, [selectedIndex, onSelectView])
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
scrollToTop: () => {
|
||||
flatListRef.current?.scrollToOffset({offset: 0})
|
||||
},
|
||||
}))
|
||||
|
||||
// rendering
|
||||
// =
|
||||
|
||||
const renderItemInternal = React.useCallback(
|
||||
({item}: {item: any}) => {
|
||||
if (item === HEADER_ITEM) {
|
||||
if (renderHeader) {
|
||||
return renderHeader()
|
||||
}
|
||||
return <View />
|
||||
} else if (item === SELECTOR_ITEM) {
|
||||
return (
|
||||
<Selector
|
||||
items={sections}
|
||||
selectedIndex={selectedIndex}
|
||||
onSelect={onPressSelection}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return renderItem(item)
|
||||
}
|
||||
},
|
||||
[sections, selectedIndex, onPressSelection, renderHeader, renderItem],
|
||||
)
|
||||
|
||||
const data = React.useMemo(
|
||||
() => [HEADER_ITEM, SELECTOR_ITEM, ...items],
|
||||
[items],
|
||||
)
|
||||
return (
|
||||
<FlatList
|
||||
ref={flatListRef}
|
||||
data={data}
|
||||
keyExtractor={keyExtractor}
|
||||
renderItem={renderItemInternal}
|
||||
ListFooterComponent={ListFooterComponent}
|
||||
// NOTE sticky header disabled on android due to major performance issues -prf
|
||||
stickyHeaderIndices={isAndroid ? undefined : STICKY_HEADER_INDICES}
|
||||
onScroll={onScroll}
|
||||
onEndReached={onEndReached}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing!}
|
||||
onRefresh={onRefresh}
|
||||
tintColor={pal.colors.text}
|
||||
/>
|
||||
}
|
||||
onEndReachedThreshold={0.6}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
removeClippedSubviews={true}
|
||||
scrollIndicatorInsets={{right: 1}} // fixes a bug where the scroll indicator is on the middle of the screen https://github.com/bluesky-social/social-app/pull/464
|
||||
/>
|
||||
)
|
||||
>(function ViewSelectorImpl(
|
||||
{
|
||||
sections,
|
||||
items,
|
||||
refreshing,
|
||||
renderHeader,
|
||||
renderItem,
|
||||
ListFooterComponent,
|
||||
onSelectView,
|
||||
onScroll,
|
||||
onRefresh,
|
||||
onEndReached,
|
||||
},
|
||||
)
|
||||
ref,
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
const [selectedIndex, setSelectedIndex] = useState<number>(0)
|
||||
const flatListRef = React.useRef<FlatList>(null)
|
||||
|
||||
// events
|
||||
// =
|
||||
|
||||
const keyExtractor = React.useCallback((item: any) => item._reactKey, [])
|
||||
|
||||
const onPressSelection = React.useCallback(
|
||||
(index: number) => setSelectedIndex(clamp(index, 0, sections.length)),
|
||||
[setSelectedIndex, sections],
|
||||
)
|
||||
useEffect(() => {
|
||||
onSelectView?.(selectedIndex)
|
||||
}, [selectedIndex, onSelectView])
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
scrollToTop: () => {
|
||||
flatListRef.current?.scrollToOffset({offset: 0})
|
||||
},
|
||||
}))
|
||||
|
||||
// rendering
|
||||
// =
|
||||
|
||||
const renderItemInternal = React.useCallback(
|
||||
({item}: {item: any}) => {
|
||||
if (item === HEADER_ITEM) {
|
||||
if (renderHeader) {
|
||||
return renderHeader()
|
||||
}
|
||||
return <View />
|
||||
} else if (item === SELECTOR_ITEM) {
|
||||
return (
|
||||
<Selector
|
||||
items={sections}
|
||||
selectedIndex={selectedIndex}
|
||||
onSelect={onPressSelection}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return renderItem(item)
|
||||
}
|
||||
},
|
||||
[sections, selectedIndex, onPressSelection, renderHeader, renderItem],
|
||||
)
|
||||
|
||||
const data = React.useMemo(
|
||||
() => [HEADER_ITEM, SELECTOR_ITEM, ...items],
|
||||
[items],
|
||||
)
|
||||
return (
|
||||
<FlatList
|
||||
ref={flatListRef}
|
||||
data={data}
|
||||
keyExtractor={keyExtractor}
|
||||
renderItem={renderItemInternal}
|
||||
ListFooterComponent={ListFooterComponent}
|
||||
// NOTE sticky header disabled on android due to major performance issues -prf
|
||||
stickyHeaderIndices={isAndroid ? undefined : STICKY_HEADER_INDICES}
|
||||
onScroll={onScroll}
|
||||
onEndReached={onEndReached}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing!}
|
||||
onRefresh={onRefresh}
|
||||
tintColor={pal.colors.text}
|
||||
/>
|
||||
}
|
||||
onEndReachedThreshold={0.6}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
removeClippedSubviews={true}
|
||||
scrollIndicatorInsets={{right: 1}} // fixes a bug where the scroll indicator is on the middle of the screen https://github.com/bluesky-social/social-app/pull/464
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
export function Selector({
|
||||
selectedIndex,
|
||||
|
|
|
@ -38,7 +38,7 @@ export function CenteredView({
|
|||
return <View style={style} {...props} />
|
||||
}
|
||||
|
||||
export const FlatList = React.forwardRef(function <ItemT>(
|
||||
export const FlatList = React.forwardRef(function FlatListImpl<ItemT>(
|
||||
{
|
||||
contentContainerStyle,
|
||||
style,
|
||||
|
@ -99,7 +99,7 @@ export const FlatList = React.forwardRef(function <ItemT>(
|
|||
)
|
||||
})
|
||||
|
||||
export const ScrollView = React.forwardRef(function (
|
||||
export const ScrollView = React.forwardRef(function ScrollViewImpl(
|
||||
{contentContainerStyle, ...props}: React.PropsWithChildren<ScrollViewProps>,
|
||||
ref: React.Ref<RNScrollView>,
|
||||
) {
|
||||
|
|
|
@ -26,7 +26,7 @@ type PropsInner = TriggerableAnimatedProps & {
|
|||
export const TriggerableAnimated = React.forwardRef<
|
||||
TriggerableAnimatedRef,
|
||||
TriggerableAnimatedProps
|
||||
>(({children, ...props}, ref) => {
|
||||
>(function TriggerableAnimatedImpl({children, ...props}, ref) {
|
||||
const [anim, setAnim] = React.useState<TriggeredAnimation | undefined>(
|
||||
undefined,
|
||||
)
|
||||
|
|
|
@ -2,13 +2,12 @@ import React from 'react'
|
|||
import {isNative} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
|
||||
export const withBreakpoints =
|
||||
<P extends object>(
|
||||
Mobile: React.ComponentType<P>,
|
||||
Tablet: React.ComponentType<P>,
|
||||
Desktop: React.ComponentType<P>,
|
||||
): React.FC<P> =>
|
||||
(props: P) => {
|
||||
export const withBreakpoints = <P extends object>(
|
||||
Mobile: React.ComponentType<P>,
|
||||
Tablet: React.ComponentType<P>,
|
||||
Desktop: React.ComponentType<P>,
|
||||
): React.FC<P> =>
|
||||
function WithBreakpoints(props: P) {
|
||||
const {isMobile, isTabletOrMobile} = useWebMediaQueries()
|
||||
|
||||
if (isMobile || isNative) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue