UNPKG

@nghinv/react-native-app-tour

Version:
422 lines (385 loc) 16.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactFastCompare = _interopRequireDefault(require("react-fast-compare")); var _reactNativeSvg = require("react-native-svg"); var _reactNativeAnimateableText = _interopRequireDefault(require("react-native-animateable-text")); var _reactNativeGestureHandler = require("react-native-gesture-handler"); var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated")); var _AppTourContext = require("./AppTourContext"); var _hook = require("./hook"); var _math = require("./math"); var _MenuButton = _interopRequireDefault(require("./MenuButton")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /** * Created by nghinv on Wed Jun 23 2021 * Copyright (c) 2021 nghinv@lumi.biz */ const RectAnimated = _reactNativeReanimated.default.createAnimatedComponent(_reactNativeSvg.Rect); const CircleAnimated = _reactNativeReanimated.default.createAnimatedComponent(_reactNativeSvg.Circle); const IS_IOS = _reactNative.Platform.OS === 'ios'; function MashView(props) { var _options$triangleHeig, _options$stepHeight, _options$pathAnimated, _options$backgroundCo, _options$borderRadius, _options$backgroundCo2, _options$stepBackgrou, _options$stepTitleCol; const { progress, currentStep, scene, onStop } = props; const { nodes, options } = (0, _react.useContext)(_AppTourContext.AppTourContext); const { emitEvent } = (0, _hook.useEvent)(); const defaultTarget = (0, _hook.useVectorLayout)(); const dimension = (0, _reactNative.useWindowDimensions)(); const contentHeight = (0, _reactNativeReanimated.useSharedValue)(0); const contentWidth = (0, _reactNativeReanimated.useSharedValue)(0); const activeNode = (0, _reactNativeReanimated.useSharedValue)(0); const TriangleHeight = (_options$triangleHeig = options === null || options === void 0 ? void 0 : options.triangleHeight) !== null && _options$triangleHeig !== void 0 ? _options$triangleHeig : 8; const StepHeight = (_options$stepHeight = options === null || options === void 0 ? void 0 : options.stepHeight) !== null && _options$stepHeight !== void 0 ? _options$stepHeight : 20; const pathAnimated = (_options$pathAnimated = options === null || options === void 0 ? void 0 : options.pathAnimated) !== null && _options$pathAnimated !== void 0 ? _options$pathAnimated : IS_IOS; const onNextStep = () => { const nextValue = currentStep.value + 1; const sceneLength = scene.length; if (nextValue <= sceneLength - 1) { const currentScene = scene[nextValue]; currentStep.value = nextValue; emitEvent('AppTourEvent', { name: 'onNext', step: nextValue, node: nodes.value.find(n => n.id === currentScene.id), scene: currentScene }); } else { onStop(); } }; const onPressNode = () => { const currentScene = scene[currentStep.value]; const node = nodes.value.find(n => n.id === currentScene.id); if (currentScene.enablePressNode) { var _node$onPress; node === null || node === void 0 ? void 0 : (_node$onPress = node.onPress) === null || _node$onPress === void 0 ? void 0 : _node$onPress.call(node); } if (currentScene.pressToNext) { emitEvent('AppTourEvent', { name: 'onPressNode', step: currentStep.value, node, scene: currentScene }); if (currentScene.nextDelay) { setTimeout(() => { onNextStep(); }, currentScene.nextDelay); } else { onNextStep(); } } }; const onGestureEventNode = (0, _reactNativeReanimated.useAnimatedGestureHandler)({ onActive: () => { (0, _reactNativeReanimated.runOnJS)(onPressNode)(); }, onStart: () => { const currentScene = scene[currentStep.value]; if (currentScene.enablePressNode) { activeNode.value = (0, _math.withAnimation)(1); } }, onFinish: () => { const currentScene = scene[currentStep.value]; if (currentScene.enablePressNode) { activeNode.value = (0, _math.withAnimation)(0); } } }); const onContentLayout = event => { contentHeight.value = event.nativeEvent.layout.height; contentWidth.value = event.nativeEvent.layout.width; }; const animatedPropsBackdrop = (0, _reactNativeReanimated.useAnimatedProps)(() => { var _options$backdropOpac; return { fill: (0, _reactNativeReanimated.interpolateColor)(progress.value, [0, 1], ['rgba(0, 0, 0, 0)', `rgba(0, 0, 0, ${(_options$backdropOpac = options === null || options === void 0 ? void 0 : options.backdropOpacity) !== null && _options$backdropOpac !== void 0 ? _options$backdropOpac : 0.8})`]) }; }); const animatedPropsMaskCircle = (0, _reactNativeReanimated.useAnimatedProps)(() => { const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { target, maskType } = node; return { cx: (0, _math.withAnimation)(target.x.value + target.width.value / 2, pathAnimated), cy: (0, _math.withAnimation)(target.y.value + target.height.value / 2, pathAnimated), r: maskType === 'circle' ? (0, _math.withAnimation)(Math.max(target.width.value, target.height.value) / 2, pathAnimated) : 0 }; }); const animatedPropsMaskRect = (0, _reactNativeReanimated.useAnimatedProps)(() => { const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { target, maskType } = node; return { x: (0, _math.withAnimation)(target.x.value, pathAnimated), y: (0, _math.withAnimation)(target.y.value, pathAnimated), width: maskType !== 'circle' ? (0, _math.withAnimation)(target.width.value, pathAnimated) : 0, height: maskType !== 'circle' ? (0, _math.withAnimation)(target.height.value, pathAnimated) : 0 }; }); const childrenStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { var _options$colorNodeOnP; const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { target } = node; return { width: target.width.value, height: target.height.value, borderRadius: target.height.value, backgroundColor: (0, _reactNativeReanimated.interpolateColor)(activeNode.value, [0, 1], ['transparent', (_options$colorNodeOnP = options === null || options === void 0 ? void 0 : options.colorNodeOnPress) !== null && _options$colorNodeOnP !== void 0 ? _options$colorNodeOnP : 'rgba(255, 255, 255, 0.8)']), transform: [{ translateX: target.x.value }, { translateY: target.y.value }, { scale: (0, _reactNativeReanimated.interpolate)(activeNode.value, [0, 1], [1, 1.2]) }] }; }); const contentStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { target } = node; const isTargetTopScreen = target.y.value + target.height.value < dimension.height / 2; const translateY = isTargetTopScreen ? (0, _math.withAnimation)(target.y.value + target.height.value + TriangleHeight) : (0, _math.withAnimation)(target.y.value - contentHeight.value - TriangleHeight); const isOverScreen = contentWidth.value + target.x.value > dimension.width - 32; const delta = (dimension.width - contentWidth.value) / 2; const translateX = isOverScreen ? (0, _math.withAnimation)(Math.max(0, delta)) : (0, _math.withAnimation)(target.x.value); return { opacity: (0, _reactNativeReanimated.interpolate)(progress.value, [0, 0.9, 1], [0, 0, 1]), transform: [{ translateX }, { translateY }, { scale: (0, _reactNativeReanimated.interpolate)(progress.value, [0, 1], [0.6, 1]) }] }; }); const triangleStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { target, maskType } = node; const isTargetTopScreen = target.y.value + target.height.value < dimension.height / 2; const isOverScreen = contentWidth.value + target.x.value > dimension.width - 32; const delta = (dimension.width - contentWidth.value) / 2; const originTranslateX = isOverScreen ? Math.max(0, delta) : target.x.value; const translateY = isTargetTopScreen ? -TriangleHeight : contentHeight.value; const translateX = maskType === 'circle' ? (0, _math.withAnimation)(target.x.value + target.width.value / 2 - originTranslateX - TriangleHeight) : (0, _math.withAnimation)(target.x.value - originTranslateX + 12); return { transform: [{ translateY }, { translateX }, { rotate: isTargetTopScreen ? '0deg' : '180deg' }] }; }); const stepStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { target } = node; const translateX = target.x.value < 32 ? target.x.value + target.width.value - StepHeight / 2 : target.x.value - StepHeight / 2; const translateY = target.y.value - StepHeight / 2; return { transform: [{ translateX }, { translateY }] }; }); const animatedPropsStep = (0, _reactNativeReanimated.useAnimatedProps)(() => { return { text: `${currentStep.value + 1}` }; }); const animatedPropsTitle = (0, _reactNativeReanimated.useAnimatedProps)(() => { const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { title } = node; return { text: title }; }); const animatedPropsDescribe = (0, _reactNativeReanimated.useAnimatedProps)(() => { const { node } = (0, _math.getCurrentNode)(nodes, scene, currentStep, defaultTarget); const { describe } = node; return { text: describe }; }); return /*#__PURE__*/_react.default.createElement(_reactNative.View, { pointerEvents: "box-none", style: styles.container }, /*#__PURE__*/_react.default.createElement(_reactNativeSvg.Svg, { height: "100%", width: "100%" }, /*#__PURE__*/_react.default.createElement(_reactNativeSvg.Defs, null, /*#__PURE__*/_react.default.createElement(_reactNativeSvg.Mask, { id: "mask", x: "0", y: "0", height: "100%", width: "100%" }, /*#__PURE__*/_react.default.createElement(_reactNativeSvg.Rect, { height: "100%", width: "100%", fill: "#fff" }), /*#__PURE__*/_react.default.createElement(CircleAnimated, { animatedProps: animatedPropsMaskCircle, fill: "black" }), /*#__PURE__*/_react.default.createElement(RectAnimated, { animatedProps: animatedPropsMaskRect, fill: "black" }))), /*#__PURE__*/_react.default.createElement(RectAnimated, { animatedProps: animatedPropsBackdrop, height: "100%", width: "100%", mask: "url(#mask)", "fill-opacity": "0" })), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [styles.content, { backgroundColor: (_options$backgroundCo = options === null || options === void 0 ? void 0 : options.backgroundColor) !== null && _options$backgroundCo !== void 0 ? _options$backgroundCo : 'white', borderRadius: (_options$borderRadius = options === null || options === void 0 ? void 0 : options.borderRadius) !== null && _options$borderRadius !== void 0 ? _options$borderRadius : 5 }, contentStyle], onLayout: onContentLayout }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [styles.triangle, { borderBottomColor: (_options$backgroundCo2 = options === null || options === void 0 ? void 0 : options.backgroundColor) !== null && _options$backgroundCo2 !== void 0 ? _options$backgroundCo2 : 'white', borderLeftWidth: TriangleHeight, borderRightWidth: TriangleHeight, borderBottomWidth: TriangleHeight }, triangleStyle] }), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.viewTitle }, (options === null || options === void 0 ? void 0 : options.titleShow) !== false && /*#__PURE__*/_react.default.createElement(_reactNativeAnimateableText.default, { style: [styles.txtTitle, options === null || options === void 0 ? void 0 : options.titleStyle], animatedProps: animatedPropsTitle }), /*#__PURE__*/_react.default.createElement(_reactNativeAnimateableText.default, { style: [styles.txtDescribe, options === null || options === void 0 ? void 0 : options.describeStyle], animatedProps: animatedPropsDescribe })), /*#__PURE__*/_react.default.createElement(_MenuButton.default, { currentStep: currentStep, onStop: onStop })), (options === null || options === void 0 ? void 0 : options.stepShow) !== false && /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [styles.stepView, { backgroundColor: (_options$stepBackgrou = options === null || options === void 0 ? void 0 : options.stepBackgroundColor) !== null && _options$stepBackgrou !== void 0 ? _options$stepBackgrou : 'green', height: StepHeight, minWidth: StepHeight, borderRadius: StepHeight / 2 }, stepStyle] }, /*#__PURE__*/_react.default.createElement(_reactNativeAnimateableText.default, { style: [styles.txtStep, { color: (_options$stepTitleCol = options === null || options === void 0 ? void 0 : options.stepTitleColor) !== null && _options$stepTitleCol !== void 0 ? _options$stepTitleCol : 'white' }], animatedProps: animatedPropsStep })), /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.TapGestureHandler, { onGestureEvent: onGestureEventNode, enabled: !(options !== null && options !== void 0 && options.nativeModal) }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [styles.children, childrenStyle] }, (options === null || options === void 0 ? void 0 : options.nativeModal) && /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, { onPress: onPressNode, style: styles.childrenButton })))); } const styles = _reactNative.StyleSheet.create({ container: { ..._reactNative.StyleSheet.absoluteFillObject }, children: { position: 'absolute', overflow: 'hidden' }, stepView: { position: 'absolute', justifyContent: 'center', alignItems: 'center', borderWidth: 1, borderColor: 'white', paddingHorizontal: 4 }, triangle: { position: 'absolute', width: 0, height: 0, zIndex: 0, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderStyle: 'solid' }, content: { position: 'absolute', minWidth: 180 }, viewTitle: { paddingHorizontal: 16, paddingTop: 12, paddingBottom: 4, zIndex: 1 }, txtTitle: { fontSize: 16, fontWeight: 'bold', marginBottom: 2 }, txtDescribe: { fontSize: 16 }, txtStep: { fontSize: 10, lineHeight: 12, fontWeight: '500' }, childrenButton: { flex: 1 } }); var _default = /*#__PURE__*/_react.default.memo(MashView, _reactFastCompare.default); exports.default = _default; //# sourceMappingURL=MashView.js.map