@umituz/react-native-subscription 2.24.12 → 2.24.14

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": "@umituz/react-native-subscription",
3
- "version": "2.24.12",
3
+ "version": "2.24.14",
4
4
  "description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -2,10 +2,11 @@
2
2
  * Paywall Hooks Index
3
3
  */
4
4
 
5
- export { usePaywall } from "./usePaywall";
6
- export { useSubscriptionModal } from "./useSubscriptionModal";
5
+ export { usePaywall } from './usePaywall';
6
+ export { useSubscriptionModal } from './useSubscriptionModal';
7
+ export { usePaywallActions } from './usePaywallActions';
7
8
  export {
8
9
  usePaywallTranslations,
9
10
  type UsePaywallTranslationsParams,
10
11
  type UsePaywallTranslationsResult,
11
- } from "./usePaywallTranslations";
12
+ } from './usePaywallTranslations';
@@ -12,7 +12,7 @@ import {
12
12
  TextInput,
13
13
  KeyboardAvoidingView,
14
14
  } from "react-native";
15
- import { AtomicText } from "@umituz/react-native-design-system";
15
+ import { AtomicText, BaseModal } from "@umituz/react-native-design-system";
16
16
  import { useAppDesignTokens } from "@umituz/react-native-design-system";
17
17
  import { useLocalization } from "@umituz/react-native-localization";
18
18
  import { usePaywallFeedback } from "../../hooks/feedback/usePaywallFeedback";
@@ -54,7 +54,7 @@ export const PaywallFeedbackModal: React.FC<PaywallFeedbackModalProps> = React.m
54
54
  setOtherText,
55
55
  selectReason,
56
56
  handleSubmit,
57
- handleSkip,
57
+ handleSkip, // BaseModal's onClose will handle skipping
58
58
  canSubmit,
59
59
  } = usePaywallFeedback({ onSubmit, onClose });
60
60
 
@@ -68,101 +68,111 @@ export const PaywallFeedbackModal: React.FC<PaywallFeedbackModalProps> = React.m
68
68
  const displaySubmitText = submitText || t("paywall.feedback.submit");
69
69
  const displayOtherPlaceholder = otherPlaceholder || t("paywall.feedback.otherPlaceholder");
70
70
 
71
+ // BaseModal from design system handles animations, safe areas, keyboard avoiding, and overlay backdrop
71
72
  return (
72
- <Modal
73
+ <BaseModal
73
74
  visible={visible}
74
- transparent
75
- animationType="none"
76
- onRequestClose={handleSkip}
75
+ onClose={handleSkip}
76
+ title={displayTitle}
77
+ swipeToClose={true}
77
78
  >
78
- <Pressable onPress={handleSkip} style={styles.overlay}>
79
- <KeyboardAvoidingView
80
- behavior="padding"
81
- style={styles.keyboardView}
82
- >
83
- <Pressable onPress={(e) => e.stopPropagation()}>
84
- <View style={styles.container}>
85
- <View style={styles.header}>
86
- <AtomicText type="headlineMedium" style={styles.title}>
87
- {displayTitle}
88
- </AtomicText>
89
- <AtomicText type="bodyMedium" style={styles.subtitle}>
90
- {displaySubtitle}
91
- </AtomicText>
92
- </View>
93
-
94
- <View style={styles.optionsContainer}>
95
- {FEEDBACK_OPTION_IDS.map((optionId, index) => {
96
- const isSelected = selectedReason === optionId;
97
- const isLast = index === FEEDBACK_OPTION_IDS.length - 1;
98
- const displayText = t(`paywall.feedback.reasons.${optionId}`);
99
-
100
- return (
101
- <View key={optionId}>
102
- <TouchableOpacity
103
- style={[
104
- styles.optionRow,
105
- isLast && styles.optionRowLast,
106
- ]}
107
- onPress={() => selectReason(optionId)}
108
- activeOpacity={0.7}
109
- >
110
- <AtomicText
111
- type="bodyMedium"
112
- style={[
113
- styles.optionText,
114
- isSelected && styles.optionTextSelected,
115
- ]}
116
- >
117
- {displayText}
118
- </AtomicText>
79
+ <View style={{ paddingBottom: tokens.spacing.lg }}>
80
+ <AtomicText type="bodyMedium" style={[styles.subtitle, { marginBottom: tokens.spacing.md }]}>
81
+ {displaySubtitle}
82
+ </AtomicText>
119
83
 
120
- <View
121
- style={[
122
- styles.radioButton,
123
- isSelected && styles.radioButtonSelected,
124
- ]}
125
- >
126
- {isSelected && (
127
- <View style={styles.radioButtonInner} />
128
- )}
129
- </View>
130
- </TouchableOpacity>
131
-
132
- {isSelected && optionId === "other" && (
133
- <View style={styles.inputContainer}>
134
- <TextInput
135
- style={styles.textInput}
136
- placeholder={displayOtherPlaceholder}
137
- placeholderTextColor={tokens.colors.textTertiary}
138
- multiline
139
- maxLength={200}
140
- value={otherText}
141
- onChangeText={setOtherText}
142
- autoFocus
143
- />
144
- </View>
145
- )}
146
- </View>
147
- );
148
- })}
149
- </View>
84
+ <View style={[styles.optionsContainer, { backgroundColor: 'transparent', padding: 0 }]}>
85
+ {FEEDBACK_OPTION_IDS.map((optionId, index) => {
86
+ const isSelected = selectedReason === optionId;
87
+ const isOther = optionId === "other";
88
+ const showInput = isSelected && isOther;
89
+ const displayText = t(`paywall.feedback.reasons.${optionId}`);
90
+
91
+ // Dynamic styles for the container
92
+ const containerStyle = {
93
+ marginBottom: tokens.spacing.sm,
94
+ backgroundColor: tokens.colors.surfaceVariant,
95
+ borderRadius: tokens.borderRadius.md,
96
+ overflow: 'hidden' as const, // Ensure children don't bleed out
97
+ };
150
98
 
99
+ return (
100
+ <View key={optionId} style={containerStyle}>
151
101
  <TouchableOpacity
152
- style={styles.submitButton}
153
- onPress={handleSubmit}
154
- disabled={!canSubmit}
155
- activeOpacity={0.8}
102
+ style={{
103
+ borderBottomWidth: showInput ? 1 : 0,
104
+ borderBottomColor: tokens.colors.surface, // Subtle separator
105
+ paddingVertical: tokens.spacing.md,
106
+ paddingHorizontal: tokens.spacing.md,
107
+ flexDirection: 'row',
108
+ alignItems: 'center',
109
+ justifyContent: 'space-between',
110
+ }}
111
+ onPress={() => selectReason(optionId)}
112
+ activeOpacity={0.7}
156
113
  >
157
- <AtomicText type="labelLarge" style={styles.submitText}>
158
- {displaySubmitText}
114
+ <AtomicText
115
+ type="bodyMedium"
116
+ style={[
117
+ styles.optionText,
118
+ isSelected && { color: tokens.colors.primary, fontWeight: '600' },
119
+ ]}
120
+ >
121
+ {displayText}
159
122
  </AtomicText>
123
+
124
+ <View
125
+ style={[
126
+ styles.radioButton,
127
+ isSelected && styles.radioButtonSelected,
128
+ ]}
129
+ >
130
+ {isSelected && (
131
+ <View style={styles.radioButtonInner} />
132
+ )}
133
+ </View>
160
134
  </TouchableOpacity>
161
- </View>
162
- </Pressable>
163
- </KeyboardAvoidingView>
164
- </Pressable>
165
- </Modal>
135
+
136
+ {showInput && (
137
+ <View style={[styles.inputContainer, { backgroundColor: 'transparent', marginTop: 0, padding: tokens.spacing.sm }]}>
138
+ <TextInput
139
+ style={[
140
+ styles.textInput,
141
+ {
142
+ minHeight: 80,
143
+ textAlignVertical: 'top',
144
+ backgroundColor: tokens.colors.surface, // Slightly different background for input
145
+ borderRadius: tokens.borderRadius.sm,
146
+ padding: tokens.spacing.sm,
147
+ }
148
+ ]}
149
+ placeholder={displayOtherPlaceholder}
150
+ placeholderTextColor={tokens.colors.textTertiary}
151
+ multiline
152
+ maxLength={200}
153
+ value={otherText}
154
+ onChangeText={setOtherText}
155
+ autoFocus
156
+ />
157
+ </View>
158
+ )}
159
+ </View>
160
+ );
161
+ })}
162
+ </View>
163
+
164
+ <TouchableOpacity
165
+ style={[styles.submitButton, { marginTop: tokens.spacing.lg }]}
166
+ onPress={handleSubmit}
167
+ disabled={!canSubmit}
168
+ activeOpacity={0.8}
169
+ >
170
+ <AtomicText type="labelLarge" style={styles.submitText}>
171
+ {displaySubmitText}
172
+ </AtomicText>
173
+ </TouchableOpacity>
174
+ </View>
175
+ </BaseModal>
166
176
  );
167
177
  });
168
178