react-native-my-survey-sdk 2.2.6 → 2.2.8

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.6",
3
+ "version": "2.2.8",
4
4
  "description": "Xebo survey collection SDK for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -24,4 +24,4 @@
24
24
  "@types/react-native": "^0.73.0",
25
25
  "typescript": "^5.3.0"
26
26
  }
27
- }
27
+ }
@@ -13,7 +13,8 @@ export const XeboIntroView: React.FC<Props> = ({ introPage, onStart }) => {
13
13
 
14
14
  return (
15
15
  <View style={styles.container}>
16
- {/* Scrollable content area — button stays pinned below no matter how long the text */}
16
+ {/* Scrollable content — button is absolutely pinned at bottom so it's
17
+ always visible regardless of how the flex layout settles on first render */}
17
18
  <ScrollView
18
19
  style={styles.scroll}
19
20
  contentContainerStyle={styles.scrollContent}
@@ -46,9 +47,12 @@ const styles = StyleSheet.create({
46
47
  paddingTop: 16,
47
48
  paddingBottom: 8,
48
49
  },
50
+ // marginBottom leaves a fixed gap for the absolutely-positioned button below.
51
+ // 48 = button height (paddingVertical 14×2 + text ~20) + 12 gap = 60dp
49
52
  scroll: {
50
53
  flex: 1,
51
54
  minHeight: 0,
55
+ marginBottom: 60,
52
56
  },
53
57
  scrollContent: {
54
58
  paddingBottom: 8,
@@ -57,10 +61,15 @@ const styles = StyleSheet.create({
57
61
  fontSize: 16,
58
62
  lineHeight: 24,
59
63
  },
64
+ // Absolute positioning ensures this button is ALWAYS visible at the bottom,
65
+ // immune to first-render flex layout measurement issues on Android.
60
66
  button: {
67
+ position: 'absolute',
68
+ bottom: 0,
69
+ left: 0,
70
+ right: 0,
61
71
  paddingVertical: 14,
62
72
  alignItems: 'center',
63
- marginTop: 12,
64
73
  },
65
74
  buttonText: {
66
75
  color: '#FFFFFF',
@@ -41,8 +41,8 @@ const _androidNavBar = Platform.OS === 'android'
41
41
  : 0;
42
42
 
43
43
  function computeSheetHeight(question: XeboQuestion | null, screen: ModalScreen): number {
44
- if (screen === 'thankYou') return SCREEN_HEIGHT * 0.32;
45
- if (screen === 'intro') return SCREEN_HEIGHT * 0.42;
44
+ if (screen === 'thankYou') return SCREEN_HEIGHT * 0.35;
45
+ if (screen === 'intro') return SCREEN_HEIGHT * 0.55;
46
46
  if (!question) return SCREEN_HEIGHT * 0.48;
47
47
  switch (question.type) {
48
48
  case XeboQuestionType.multiNps:
@@ -57,16 +57,18 @@ function computeSheetHeight(question: XeboQuestion | null, screen: ModalScreen):
57
57
  case XeboQuestionType.rating:
58
58
  return question.followUpQuestion ? SCREEN_HEIGHT * 0.56 : SCREEN_HEIGHT * 0.38;
59
59
  case XeboQuestionType.singleTextBox:
60
- return SCREEN_HEIGHT * 0.44;
60
+ // title + 4-line input + button — no wasted space
61
+ return SCREEN_HEIGHT * 0.40;
61
62
  case XeboQuestionType.multipleTextBox: {
62
63
  const fieldCount = question.options?.length ?? 1;
63
- return Math.min(SCREEN_HEIGHT * 0.70, SCREEN_HEIGHT * (0.28 + fieldCount * 0.10));
64
+ return Math.min(SCREEN_HEIGHT * 0.72, SCREEN_HEIGHT * (0.30 + fieldCount * 0.12));
64
65
  }
65
66
  case XeboQuestionType.singleChoice:
66
67
  case XeboQuestionType.multipleChoice:
67
68
  case XeboQuestionType.dropdown: {
69
+ // each option row ≈ 58dp; base includes title + button; 0.085 per option is accurate
68
70
  const optCount = question.options?.length ?? 0;
69
- return Math.min(SCREEN_HEIGHT * 0.72, SCREEN_HEIGHT * (0.30 + optCount * 0.058));
71
+ return Math.min(SCREEN_HEIGHT * 0.80, SCREEN_HEIGHT * (0.28 + optCount * 0.085));
70
72
  }
71
73
  default:
72
74
  return SCREEN_HEIGHT * 0.48;
@@ -270,35 +272,38 @@ export const XeboSurveyModal: React.FC = () => {
270
272
  shiftAnim.setValue(0); // reset in case keyboard was open when modal closed
271
273
  }}
272
274
  >
273
- <Animated.View
274
- style={[
275
- styles.sheet,
276
- {
277
- backgroundColor: theme.backgroundColor,
278
- height: sheetHeight,
279
- transform: [{ translateY: shiftAnim }],
280
- },
281
- ]}
282
- >
283
- {/* Handle bar */}
284
- <View style={styles.handleWrap}>
285
- <View style={styles.handle} />
286
- </View>
287
-
288
- {/* Skip button — right aligned */}
289
- {screen !== 'thankYou' && (
290
- <View style={styles.skipRow}>
291
- <TouchableOpacity onPress={handleSkip} style={styles.skipButton} activeOpacity={0.7}>
292
- <Text style={[styles.skipText, { color: theme.textColor }]}>Skip</Text>
293
- </TouchableOpacity>
275
+ {/* Animated.View handles ONLY the keyboard shift (transform).
276
+ The inner View owns height/layout so flex children compute correctly. */}
277
+ <Animated.View style={{ transform: [{ translateY: shiftAnim }] }}>
278
+ <View
279
+ style={[
280
+ styles.sheet,
281
+ {
282
+ backgroundColor: theme.backgroundColor,
283
+ height: sheetHeight,
284
+ },
285
+ ]}
286
+ >
287
+ {/* Handle bar */}
288
+ <View style={styles.handleWrap}>
289
+ <View style={styles.handle} />
294
290
  </View>
295
- )}
296
291
 
297
- {/* Main content */}
298
- <View style={styles.content}>{renderContent()}</View>
292
+ {/* Skip button — right aligned */}
293
+ {screen !== 'thankYou' && (
294
+ <View style={styles.skipRow}>
295
+ <TouchableOpacity onPress={handleSkip} style={styles.skipButton} activeOpacity={0.7}>
296
+ <Text style={[styles.skipText, { color: theme.textColor }]}>Skip</Text>
297
+ </TouchableOpacity>
298
+ </View>
299
+ )}
299
300
 
300
- {/* Safe area bottom padding — home indicator on iOS, gesture nav on Android */}
301
- <View style={{ height: bottomInset }} />
301
+ {/* Main content */}
302
+ <View style={styles.content}>{renderContent()}</View>
303
+
304
+ {/* Safe area bottom padding — home indicator on iOS, gesture nav on Android */}
305
+ <View style={{ height: bottomInset }} />
306
+ </View>
302
307
  </Animated.View>
303
308
  </RNModal>
304
309
  );