react-native-my-survey-sdk 2.2.2 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-my-survey-sdk",
3
- "version": "2.2.2",
3
+ "version": "2.2.4",
4
4
  "description": "Xebo survey collection SDK for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -28,8 +28,15 @@ import { XeboMultiNPSView } from './XeboMultiNPSView';
28
28
  import { XeboRatingView } from './XeboRatingView';
29
29
  import { XeboMultiRatingView } from './XeboMultiRatingView';
30
30
 
31
- // 'screen' includes the Android system navigation bar; 'window' excludes it.
32
- const SCREEN_HEIGHT = Dimensions.get('screen').height;
31
+ // 'window' excludes the Android navigation bar; 'screen' includes it.
32
+ // Using window height so sheets are sized relative to the usable area.
33
+ const SCREEN_HEIGHT = Dimensions.get('window').height;
34
+
35
+ // Android navigation bar height = difference between screen and window.
36
+ // Used as bottomInset so content isn't hidden behind the nav bar.
37
+ const _androidNavBar = Platform.OS === 'android'
38
+ ? Math.max(0, Dimensions.get('screen').height - Dimensions.get('window').height)
39
+ : 0;
33
40
 
34
41
  function computeSheetHeight(question: XeboQuestion | null, screen: ModalScreen): number {
35
42
  if (screen === 'thankYou') return SCREEN_HEIGHT * 0.32;
@@ -68,8 +75,8 @@ type ModalScreen = 'intro' | 'question' | 'thankYou';
68
75
 
69
76
  export const XeboSurveyModal: React.FC = () => {
70
77
  const theme = getTheme();
71
- // Static bottom inset no SafeAreaProvider needed
72
- const bottomInset = Platform.OS === 'ios' ? 34 : 16;
78
+ // Bottom inset: iOS home indicator (34) or Android nav bar height (min 16)
79
+ const bottomInset = Platform.OS === 'ios' ? 34 : Math.max(16, _androidNavBar);
73
80
 
74
81
  const [visible, setVisible] = useState(false);
75
82
  const [survey, setSurvey] = useState<XeboSurvey | null>(null);
@@ -217,7 +224,6 @@ export const XeboSurveyModal: React.FC = () => {
217
224
  hideModalContentWhileAnimating={true}
218
225
  coverScreen={true}
219
226
  propagateSwipe={false}
220
- avoidKeyboard={true}
221
227
  onModalHide={() => setSurvey(null)}
222
228
  >
223
229
  <View
@@ -1,4 +1,4 @@
1
- import React, { useRef, useState } from 'react';
1
+ import React, { useRef, useState, useEffect } from 'react';
2
2
  import {
3
3
  View,
4
4
  Text,
@@ -7,6 +7,8 @@ import {
7
7
  StyleSheet,
8
8
  ScrollView,
9
9
  Animated,
10
+ Keyboard,
11
+ Platform,
10
12
  } from 'react-native';
11
13
  import { XeboQuestion, XeboAnswer, XeboQuestionType } from '../models/XeboModels';
12
14
  import { getTheme } from '../theme/XeboTheme';
@@ -24,7 +26,27 @@ export const XeboTextBoxView: React.FC<Props> = ({ question, isLastQuestion, onA
24
26
 
25
27
  const [values, setValues] = useState<Record<string, string>>({});
26
28
  const [error, setError] = useState('');
29
+ const [keyboardHeight, setKeyboardHeight] = useState(0);
27
30
  const shakeAnim = useRef(new Animated.Value(0)).current;
31
+ const scrollRef = useRef<ScrollView>(null);
32
+
33
+ // Track keyboard height so the outer container can push button above keyboard.
34
+ // KAV does not work reliably inside react-native-modal on Android — this is the
35
+ // proven alternative: increase paddingBottom by keyboard height so content shifts up.
36
+ useEffect(() => {
37
+ const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
38
+ const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
39
+ const showSub = Keyboard.addListener(showEvent, (e: { endCoordinates: { height: number } }) => setKeyboardHeight(e.endCoordinates.height));
40
+ const hideSub = Keyboard.addListener(hideEvent, () => setKeyboardHeight(0));
41
+ return () => { showSub.remove(); hideSub.remove(); };
42
+ }, []);
43
+
44
+ // Scroll so the focused field is visible above the button when keyboard is up
45
+ const handleFocus = (idx: number) => {
46
+ setTimeout(() => {
47
+ scrollRef.current?.scrollTo({ y: idx * 80, animated: true });
48
+ }, 150);
49
+ };
28
50
 
29
51
  const shake = () => {
30
52
  Animated.sequence([
@@ -59,10 +81,11 @@ export const XeboTextBoxView: React.FC<Props> = ({ question, isLastQuestion, onA
59
81
  };
60
82
 
61
83
  return (
62
- // Outer view fills modal content area; button pinned at bottom outside ScrollView.
63
- // react-native-modal's avoidKeyboard=true moves the whole modal up no KAV needed.
64
- <View style={styles.outer}>
84
+ // paddingBottom grows to keyboard height so the button is always above the keyboard.
85
+ // The ScrollView above it shrinks accordingly; onFocus scrolls the active field into view.
86
+ <View style={[styles.outer, { paddingBottom: keyboardHeight > 0 ? keyboardHeight + 8 : 16 }]}>
65
87
  <ScrollView
88
+ ref={scrollRef}
66
89
  style={styles.scroll}
67
90
  contentContainerStyle={styles.scrollContent}
68
91
  keyboardShouldPersistTaps="handled"
@@ -98,6 +121,7 @@ export const XeboTextBoxView: React.FC<Props> = ({ question, isLastQuestion, onA
98
121
  placeholderTextColor="#9CA3AF"
99
122
  value={values[field.id] ?? ''}
100
123
  onChangeText={text => handleChange(field.id, text)}
124
+ onFocus={() => handleFocus(idx)}
101
125
  multiline={!isMulti}
102
126
  numberOfLines={isMulti ? 1 : 4}
103
127
  textAlignVertical={isMulti ? 'center' : 'top'}