Skip to content

Commit

Permalink
Merge pull request #5 from WayneKim92/release/v1.0.2
Browse files Browse the repository at this point in the history
Release/v1.0.2
  • Loading branch information
WayneKim92 authored Aug 28, 2024
2 parents c2d9d17 + f38405a commit 8701dfa
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 168 deletions.
138 changes: 26 additions & 112 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { FlatList, SafeAreaView, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView, StyleSheet, Text, View, TextInput } from 'react-native';
import Tooltip from 'react-native-good-tooltip';
import { useState } from 'react';

export default function App() {
const data = [
'In FlatList',
'zIndex must be specified using',
'CellRendererComponent.',
];
const [inputText, setInputText] = useState('초기 텍스트');

return (
<SafeAreaView style={styles.container}>
Expand All @@ -19,31 +16,23 @@ export default function App() {
}}
>
<Tooltip
isVisible={true}
text="This is a tooltip"
placement={'bottom'}
anchor={'left'}
requiredConfirmation
onPress={() => {}}
>
<View style={[styles.box, { backgroundColor: 'red' }]} />

Check warning on line 24 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { backgroundColor: 'red' }
</Tooltip>

<Tooltip
isVisible={true}
text="This is a tooltip"
placement={'bottom'}
styles={{ color: 'black' }}

Check warning on line 30 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { color: 'black' }
>
<View style={[styles.box, { backgroundColor: 'green' }]} />

Check warning on line 32 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { backgroundColor: 'green' }
</Tooltip>

<Tooltip
isVisible={true}
text="This is a tooltip"
placement={'bottom'}
anchor={'right'}
requiredConfirmation
>
<Tooltip text="This is a tooltip" placement={'bottom'} anchor={'right'}>
<View style={[styles.box, { backgroundColor: 'blue' }]} />

Check warning on line 36 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { backgroundColor: 'blue' }
</Tooltip>
</View>
Expand Down Expand Up @@ -77,103 +66,28 @@ export default function App() {
</View>
</View>

{/* Body*/}
<FlatList
data={data}
// style={{ flexGrow: 1 }}
CellRendererComponent={({ index, style, ...props }) => {
return (
<View
style={[
style,
{
zIndex: data.length - index,
},
]}
{...props}
/>
);
}}
renderItem={({ item, index }) => (
<Tooltip
isVisible={true}
placement={'bottom'}
anchor={(() => {
if (index % 3 === 0) return 'right';
if (index % 2 === 0) return 'center';

return 'left';
})()}
text={'List Item Tooltip ' + index}
>
<View
style={{
paddingVertical: 15,
backgroundColor: 'blue',
opacity: 0.4,
justifyContent: 'center',
alignItems: 'flex-end',
paddingHorizontal: 16,
}}
>
<Text style={{ color: 'white' }}>{`${item}`}</Text>
</View>
</Tooltip>
)}
ListFooterComponent={() => (
<View
style={{
justifyContent: 'flex-end',
alignItems: 'center',
backgroundColor: '#8851bc',
height: 500,
}}
>
<Tooltip
placement={'top'}
anchor={'right'}
text={'Top RIght'}
isVisible={true}
requiredConfirmation
>
<View style={{ height: 50, backgroundColor: 'red', zIndex: 0 }}>
<Text>
There may be situations where you need to add the overflow:
'visible' style.
</Text>
</View>
</Tooltip>
<Tooltip placement={'bottom'} text={'Input Text'} visible={true}>
<TextInput
value={inputText}
placeholder={'Input text'}
onChangeText={setInputText}
style={{ padding: 16, backgroundColor: 'gray' }}
/>
</Tooltip>

<View style={{ zIndex: 0 }}>
<Tooltip
isVisible={true}
text="Left Tooltip"
placement={'left'}
anchor={'top'}
requiredConfirmation
>
<View style={[styles.box, { backgroundColor: 'red' }]} />
</Tooltip>
<Tooltip
isVisible={true}
text="Center Tooltip"
placement={'right'}
anchor={'center'}
>
<View style={[styles.box, { backgroundColor: 'green' }]} />
</Tooltip>
<Tooltip
isVisible={true}
text="Center Tooltip"
placement={'left'}
anchor={'bottom'}
>
<View style={[styles.box, { backgroundColor: 'blue' }]} />
</Tooltip>
</View>
</View>
)}
/>
{/*<FlatList*/}
{/* data={[1, 2, 3]}*/}
{/* renderItem={() => {*/}
{/* return (*/}
{/* <TextInput*/}
{/* value={inputText}*/}
{/* onChangeText={setInputText}*/}
{/* placeholder={'Input text'}*/}
{/* style={{ padding: 16, backgroundColor: 'gray' }}*/}
{/* />*/}
{/* );*/}
{/* }}*/}
{/*/>*/}
</SafeAreaView>
);
}
Expand Down
127 changes: 71 additions & 56 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { useEffect, useState } from 'react';
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import {
Animated,
Dimensions,
Expand All @@ -25,6 +31,8 @@ const TOOLTIP_STYLE = {
};

interface ToolTipProps {
visible?: boolean;
rerenderKey?: any;
placement: 'top' | 'bottom' | 'left' | 'right';
anchor?: 'center' | 'left' | 'right' | 'top' | 'bottom';
offset?: {
Expand Down Expand Up @@ -53,17 +61,14 @@ interface ToolTipProps {
};
text: string | React.ReactElement;
children?: React.ReactElement;
isVisible: boolean;
onPress?: () => void;
onVisibleChange?: (isVisible: boolean) => void;
disableAutoHide?: boolean;
delayShowTime?: number;
autoHideTime?: number;
requiredConfirmation?: boolean;
}

const Tooltip = ({
isVisible,
visible,
anchor = 'center',
styles = {
tooltipStyle: TOOLTIP_STYLE,
Expand All @@ -77,58 +82,89 @@ const Tooltip = ({
offset,
arrowElement,
onVisibleChange,
disableAutoHide = false,
delayShowTime = 0,
autoHideTime = 5000,
requiredConfirmation = false,
}: ToolTipProps) => {
const [currentIsVisible, setCurrentIsVisible] = useState(false);
const showAnimationRef = useRef(false);
const hideAnimationRef = useRef(false);
const animatedValue = useMemo(() => new Animated.Value(0), []);

const [tooltipPosition, setTooltipPosition] = useState({
top: 0,
left: Platform.OS === 'android' && placement === 'right' ? -4 : 0,
});
const [tooltipSize, setTooltipSize] = useState({ width: 0, height: 0 });
const animatedValue = new Animated.Value(0);

const isVerticalPlacement = placement === 'top' || placement === 'bottom';
const tooltipColor = (() => {
if (styles?.color) return styles?.color;

return '#3Eb489';
})();

const arrowStyle = {
...createArrowShape(
styles?.arrowSize?.width || ARROW_SIZE.width,
styles?.arrowSize?.height || ARROW_SIZE.height
),
borderBottomColor: tooltipColor,
};
const transformsStyle = (() => {
const { x, y } = getAnchorPoint(placement, anchor);

useEffect(() => {
if (
autoHideTime > 0 &&
disableAutoHide === false &&
requiredConfirmation === false
) {
setTimeout(() => {
// 기본적으로 5초 뒤 사라짐 처리
setCurrentIsVisible(false);
}, autoHideTime);
}
}, [autoHideTime, disableAutoHide, requiredConfirmation]);
return withAnchorPoint(
{ transform: [{ scale: animatedValue }] },
{ x, y },
{ width: tooltipSize.width, height: tooltipSize.height }
);
})();

const runAnimation = useCallback(
(isShowAnimation: boolean) => {
if (isShowAnimation) {
if (showAnimationRef.current) return;

Animated.spring(animatedValue, {
toValue: 1,
speed: 6,
useNativeDriver: true,
}).start(() => {
onVisibleChange && onVisibleChange(true);
});
showAnimationRef.current = true;
} else {
if (hideAnimationRef.current) return;

Animated.timing(animatedValue, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start(() => {
onVisibleChange && onVisibleChange(false);
});
hideAnimationRef.current = true;
}
},
[animatedValue, onVisibleChange]
);

// show animation
useEffect(() => {
if (onVisibleChange) {
onVisibleChange(isVisible);
if (visible !== undefined && !visible) {
return;
}
}, [isVisible, onVisibleChange]);

useEffect(() => {
setTimeout(() => {
setCurrentIsVisible(isVisible);
runAnimation(true);
}, delayShowTime);
}, [delayShowTime, isVisible]);
}, [delayShowTime, runAnimation, visible]);

// hide animation
useEffect(() => {
if (onPress) return;

setTimeout(() => {
runAnimation(false);
}, delayShowTime + autoHideTime);
}, [autoHideTime, delayShowTime, onPress, runAnimation]);

const handleVerticalTooltipLayout = (event: LayoutChangeEvent) => {
const { width, height } = event.nativeEvent.layout;
Expand Down Expand Up @@ -247,37 +283,16 @@ const Tooltip = ({
</View>
);

const transformsStyle = (() => {
const { x, y } = getAnchorPoint(placement, anchor);

if (currentIsVisible) {
Animated.spring(animatedValue, {
toValue: 1,
speed: 6,
useNativeDriver: true,
}).start();
} else {
animatedValue.setValue(1);
Animated.timing(animatedValue, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start();
}

return withAnchorPoint(
{ transform: [{ scale: animatedValue }] },
{ x, y },
{ width: tooltipSize.width, height: tooltipSize.height }
);
})();

const renderTooltipContent = () => (
// View Overflow 영역에 있는 Tooltip을 선택하기 위해 TouchableOpacity 사용
<TouchableOpacity
activeOpacity={1}
onPress={() => {
setCurrentIsVisible((prevState) => !prevState);
if (!onPress) {
return;
}

runAnimation(false);
onPress && onPress();
}}
style={{
Expand All @@ -301,7 +316,7 @@ const Tooltip = ({
/>
)}

{requiredConfirmation && (
{onPress && (
<>
<View style={{ width: 8 }} />
<Image
Expand Down

0 comments on commit 8701dfa

Please sign in to comment.