UNPKG

react-native-xenon

Version:

A powerful in-app debugging tool for React Native.

124 lines (123 loc) 3.78 kB
"use strict"; import { useContext, useMemo, useRef, useState } from 'react'; import { Animated, PanResponder, StyleSheet, View } from 'react-native'; import { MainContext } from "../../../contexts/index.js"; import refs, { DebuggerVisibility } from "../../../core/refs.js"; import { clamp, getVerticalSafeMargin } from "../../../core/utils.js"; import colors from "../../../theme/colors.js"; import icons from "../../../theme/icons.js"; import Icon from "../common/Icon.js"; import { jsx as _jsx } from "react/jsx-runtime"; export default function Bubble({ bubbleSize, idleBubbleOpacity, style, ...props }) { const { dimensions: { width: screenWidth, height: screenHeight } } = useContext(MainContext); const [idleOpacity, setIdleOpacity] = useState(idleBubbleOpacity); const pan = useRef(new Animated.ValueXY({ x: 0, y: getVerticalSafeMargin(screenHeight) })); const opacityTimer = useRef(null); const panResponder = useMemo(() => { const clearTimer = () => { if (opacityTimer.current) clearTimeout(opacityTimer.current); opacityTimer.current = null; }; const blur = () => { opacityTimer.current = setTimeout(() => { setIdleOpacity(idleBubbleOpacity); clearTimer(); }, 1000); }; return PanResponder.create({ onStartShouldSetPanResponder: () => true, onMoveShouldSetPanResponder: () => true, onPanResponderGrant: () => { pan.current.setOffset({ // @ts-ignore x: pan.current.x._value, // @ts-ignore y: pan.current.y._value }); pan.current.setValue({ x: 0, y: 0 }); clearTimer(); setIdleOpacity(1); }, onPanResponderMove: Animated.event([null, { dx: pan.current.x, dy: pan.current.y }], { useNativeDriver: false }), onPanResponderRelease: (_, gesture) => { pan.current.flattenOffset(); const isTapGesture = gesture.dx > -10 && gesture.dx < 10 && gesture.dy > -10 && gesture.dy < 10; if (isTapGesture) { refs.debugger.current?.setCurrentIndex(DebuggerVisibility.Panel); } if (gesture.moveX === 0 && gesture.moveY === 0) { blur(); return; } const finalX = gesture.moveX < (screenWidth - bubbleSize) / 2 ? 0 : screenWidth - bubbleSize; const verticalSafeMargin = getVerticalSafeMargin(screenHeight); const finalY = clamp(verticalSafeMargin, screenHeight - verticalSafeMargin - bubbleSize, gesture.moveY); Animated.spring(pan.current, { toValue: { x: finalX, y: finalY }, useNativeDriver: false }).start(({ finished }) => { if (!finished) return; blur(); }); } }); }, [bubbleSize, idleBubbleOpacity, screenHeight, screenWidth]); return /*#__PURE__*/_jsx(View, { style: [styles.bubbleBackdrop, style], ...props, children: /*#__PURE__*/_jsx(Animated.View, { ...panResponder.panHandlers, style: [styles.bubble, { width: bubbleSize, height: bubbleSize, borderRadius: bubbleSize / 2, transform: pan.current.getTranslateTransform(), opacity: idleOpacity }], children: /*#__PURE__*/_jsx(Icon, { source: icons.bug, size: bubbleSize * 0.65 }) }) }); } const styles = StyleSheet.create({ bubbleBackdrop: { flex: 1, ...StyleSheet.absoluteFillObject, pointerEvents: 'box-none' }, bubble: { backgroundColor: colors.lightGray, position: 'absolute', justifyContent: 'center', alignItems: 'center' } }); //# sourceMappingURL=Bubble.js.map