diff --git a/example/src/App.tsx b/example/src/App.tsx
index 73244aa..e14c119 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -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 (
@@ -19,17 +16,15 @@ export default function App() {
}}
>
{}}
>
-
+
@@ -77,103 +66,28 @@ export default function App() {
- {/* Body*/}
- {
- return (
-
- );
- }}
- renderItem={({ item, index }) => (
- {
- if (index % 3 === 0) return 'right';
- if (index % 2 === 0) return 'center';
-
- return 'left';
- })()}
- text={'List Item Tooltip ' + index}
- >
-
- {`${item}`}
-
-
- )}
- ListFooterComponent={() => (
-
-
-
-
- There may be situations where you need to add the overflow:
- 'visible' style.
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
- )}
- />
+ {/* {*/}
+ {/* return (*/}
+ {/* */}
+ {/* );*/}
+ {/* }}*/}
+ {/*/>*/}
);
}
diff --git a/src/index.tsx b/src/index.tsx
index b74e165..da128c3 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,4 +1,10 @@
-import React, { useEffect, useState } from 'react';
+import React, {
+ useCallback,
+ useEffect,
+ useMemo,
+ useRef,
+ useState,
+} from 'react';
import {
Animated,
Dimensions,
@@ -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?: {
@@ -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,
@@ -77,26 +82,24 @@ 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,
@@ -104,31 +107,64 @@ const Tooltip = ({
),
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;
@@ -247,37 +283,16 @@ const Tooltip = ({
);
- 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 사용
{
- setCurrentIsVisible((prevState) => !prevState);
+ if (!onPress) {
+ return;
+ }
+
+ runAnimation(false);
onPress && onPress();
}}
style={{
@@ -301,7 +316,7 @@ const Tooltip = ({
/>
)}
- {requiredConfirmation && (
+ {onPress && (
<>