UNPKG

@nguyentc21/react-native-tooltip

Version:
238 lines 8.86 kB
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } import React, { useState, useEffect, useRef, useCallback, useReducer, useMemo } from 'react'; import { View, Pressable, Keyboard, StyleSheet, useWindowDimensions } from 'react-native'; import { NestedModal } from '@nguyentc21/react-native-modal-view'; import Caret from './Caret'; import { useCaretPosition, useTooltipPosition } from '../hooks/usePosition'; import useFinalPlacement from '../hooks/useFinalPlacement'; import useContainerStyles from '../hooks/useContainerStyles'; import useContentContainerStyles from '../hooks/useContentContainerStyles'; import useOffsetViewStyles from '../hooks/useOffsetViewStyles'; import { DEFAULT_BORDER_RADIUS, DEFAULT_CARET_SIZE, DEFAULT_ON_PRESS_ACTION_TYPE, DEFAULT_PLACEMENT, DEFAULT_TOOLTIP_OFFSET, DEFAULT_SCREEN_PADDING, DEFAULT_TOOLTIP_BACKGROUND, DEFAULT_BACKDROP_COLOR } from '../constants'; import useStableCallback from '../utils/useStableCallback'; function Tooltip(props) { const { visible, content, backgroundColor = DEFAULT_TOOLTIP_BACKGROUND, backdropColor = DEFAULT_BACKDROP_COLOR, borderRadius = DEFAULT_BORDER_RADIUS, placement = DEFAULT_PLACEMENT, forcePlacement, caretSize = DEFAULT_CARET_SIZE, hideCaret, offset = DEFAULT_TOOLTIP_OFFSET, screenPadding = DEFAULT_SCREEN_PADDING, actionType = DEFAULT_ON_PRESS_ACTION_TYPE, expose, extraData, modalContainerStyle, containerStyle, contentContainerStyle, onClose, onOpen, onDidOpen, ...pressableProps } = props; const _caretSize = !hideCaret ? caretSize : 0; const { onPress, onLongPress } = pressableProps; const [tooltipContentLayoutState, setTooltipContentLayoutState] = useState(); const [tooltipContainerLayoutState, setTooltipContainerLayoutState] = useState(); const [targetContentLayoutState, setTargetContentLayoutState] = useState(); const [visibleState, setVisibleState] = useState(false); const [safeAreaInsetsState, setSafeAreaInsetsState] = useState({ top: screenPadding, bottom: screenPadding, left: screenPadding, right: screenPadding }); const [tick, bumpTick] = useReducer(x => x + 1, 0); const _visible = visible ?? visibleState; const contentRef = useRef(null); const windowDimensions = useWindowDimensions(); const tooltipContentLayout = useMemo(() => { if (!tooltipContainerLayoutState || !tooltipContentLayoutState) return undefined; return { ...tooltipContentLayoutState, x: tooltipContainerLayoutState.x + tooltipContentLayoutState.x, y: tooltipContainerLayoutState.y + tooltipContentLayoutState.y }; }, [tooltipContentLayoutState, tooltipContainerLayoutState]); const finalPlacement = useFinalPlacement({ safeAreaInsets: safeAreaInsetsState, dimension: windowDimensions, placement, forcePlacement, targetContentLayout: targetContentLayoutState, tooltipContentLayout, borderRadius }); const tooltipPosition = useTooltipPosition({ safeAreaInsets: safeAreaInsetsState, dimension: windowDimensions, placement: finalPlacement, targetContentLayout: targetContentLayoutState, tooltipContentLayout }); const caretPosition = useCaretPosition({ placement: finalPlacement, targetContentLayout: targetContentLayoutState, tooltipContentLayout, caretSize: _caretSize }); const { containerStyles, wrapContainerStyles } = useContainerStyles({ tooltipPosition, placement: finalPlacement }); const contentContainerStyles = useContentContainerStyles({ caretSize: _caretSize, borderRadius }); const offsetViewStyles = useOffsetViewStyles({ caretSize: _caretSize, placement: finalPlacement, offset }); const _onOpen = useStableCallback(() => { var _contentRef$current, _contentRef$current$m; onOpen === null || onOpen === void 0 || onOpen(); Keyboard.dismiss(); (_contentRef$current = contentRef.current) === null || _contentRef$current === void 0 || (_contentRef$current$m = _contentRef$current.measure) === null || _contentRef$current$m === void 0 || _contentRef$current$m.call(_contentRef$current, (x, y, width, height, pageX, pageY) => { setTargetContentLayoutState({ x, y, width, height, pageX, pageY }); }); }); const _onTooltipLayout = useCallback(e => { setTooltipContainerLayoutState(e.nativeEvent.layout); }, []); const _onTooltipContentLayout = useCallback(e => { setTooltipContentLayoutState(e.nativeEvent.layout); }, []); const _show = useCallback(() => { setVisibleState(true); }, []); const _hide = useCallback(() => { setVisibleState(false); }, []); const _onPress = useStableCallback(e => { _show(); onPress === null || onPress === void 0 || onPress(e); }); const _onLongPress = useStableCallback(e => { _show(); onLongPress === null || onLongPress === void 0 || onLongPress(e); }); const _getModalLayoutData = useCallback(data => { const { safeAreaInsets } = data; setSafeAreaInsetsState({ top: screenPadding + (safeAreaInsets.top || 0), bottom: screenPadding + (safeAreaInsets.bottom || 0), left: screenPadding + (safeAreaInsets.left || 0), right: screenPadding + (safeAreaInsets.right || 0) }); }, [screenPadding]); useEffect(() => { if (!expose) return; const handler = { show: _show, hide: _hide }; expose(handler); return () => { expose(undefined); }; }, [expose, _show, _hide]); useEffect(() => { bumpTick(); }, [extraData, tooltipPosition === null || tooltipPosition === void 0 ? void 0 : tooltipPosition.top, tooltipPosition === null || tooltipPosition === void 0 ? void 0 : tooltipPosition.bottom, tooltipPosition === null || tooltipPosition === void 0 ? void 0 : tooltipPosition.left, tooltipPosition === null || tooltipPosition === void 0 ? void 0 : tooltipPosition.right, caretPosition === null || caretPosition === void 0 ? void 0 : caretPosition.top, caretPosition === null || caretPosition === void 0 ? void 0 : caretPosition.bottom, caretPosition === null || caretPosition === void 0 ? void 0 : caretPosition.left, caretPosition === null || caretPosition === void 0 ? void 0 : caretPosition.right]); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Pressable, _extends({ ref: contentRef }, pressableProps, { onPress: actionType === 'onPress' ? _onPress : undefined, onLongPress: actionType === 'onLongPress' ? _onLongPress : undefined })), /*#__PURE__*/React.createElement(NestedModal, { autoPadding: false, bottomOffset: safeAreaInsetsState.bottom || 0, dimension: windowDimensions, visible: _visible, close: _hide, onOpen: _onOpen, onDidOpen: onDidOpen, onClose: onClose, getLayoutData: _getModalLayoutData, containerStyle: [lStyles.tooltipContainerStyle, wrapContainerStyles, modalContainerStyle], contentContainerStyle: [lStyles.shadow10, lStyles.wrapContentContainerStyle, containerStyle], backdropStyle: { backgroundColor: backdropColor }, onContainerLayout: _onTooltipLayout, onMainContentLayout: _onTooltipContentLayout, extraData: tick }, /*#__PURE__*/React.createElement(View, { style: [containerStyles] }, /*#__PURE__*/React.createElement(View, { style: lStyles.tooltipContent }, /*#__PURE__*/React.createElement(View, { style: [contentContainerStyles, contentContainerStyle, { backgroundColor }] }, content)), /*#__PURE__*/React.createElement(View, { style: [offsetViewStyles], pointerEvents: 'box-none' }, !!caretPosition && !!_caretSize && /*#__PURE__*/React.createElement(Caret, { backgroundColor: backgroundColor, size: _caretSize, style: [lStyles.positionCaret, lStyles.caret, caretPosition] }))))); } const lStyles = StyleSheet.create({ shadow10: { shadowColor: '#000000', shadowOffset: { width: 0, height: 5 }, shadowOpacity: 0.34, shadowRadius: 6.27, elevation: 10 }, wrapContentContainerStyle: { borderRadius: 0, backgroundColor: 'transparent', overflow: 'visible' }, tooltipContainerStyle: { maxHeight: '100%', height: -1, width: -1, overflow: 'visible', alignSelf: 'auto', position: 'absolute' }, positionCaret: { position: 'absolute' }, tooltipContent: { zIndex: 2, overflow: 'hidden' }, caret: { zIndex: 1 } }); export default Tooltip; //# sourceMappingURL=Tooltip.js.map