@originallyus/feedback-rn-sdk 4.0.0-beta.6 → 4.0.0-beta.7

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.

Potentially problematic release.


This version of @originallyus/feedback-rn-sdk might be problematic. Click here for more details.

@@ -1,267 +0,0 @@
1
- import React from 'react'
2
- import {Image, Text, View} from 'react-native'
3
- import {feedbackStyles as styles} from './AIAFeedbackStyles'
4
- import ErrorIcon from './assets/ErrorIcon'
5
- import ButtonSubmit from './component/ButtonSubmit'
6
- import MultiSelectButtons from './component/MultiSelectButtons'
7
- import Rating from './component/Rating'
8
- import RatingNumber from './component/RatingNumber'
9
- import Textarea from './component/Textarea'
10
- import YesNoButtons from './component/YesNoButtons'
11
- import * as f from './utils/common'
12
- import {ERROR_COLOR} from './utils/constants'
13
-
14
- interface Props {
15
- formData: any
16
- rating: number
17
- freeText: string
18
- selectedOptions: string[]
19
- step: 'PROMPT' | 'FORM'
20
- isNPSFlow: boolean
21
- showSecondary: boolean
22
- isSubmitting: boolean
23
- submissionError: string | null
24
- autoHeight?: boolean
25
- onRate: (value: number) => void
26
- onChangeFreeText: (value: string) => void
27
- onChangeSelectedOptions: (value: string[]) => void
28
- onSubmit: () => void
29
- getThemeColor: (key: string, fallback: string) => string
30
- onPromptSelect: (value: 'yes' | 'no') => void
31
- }
32
-
33
- const AIAFeedbackForm: React.FC<Props> = ({
34
- formData,
35
- rating,
36
- freeText,
37
- selectedOptions,
38
- step,
39
- isNPSFlow,
40
- showSecondary,
41
- isSubmitting,
42
- submissionError,
43
- onRate,
44
- onChangeFreeText,
45
- onChangeSelectedOptions,
46
- onSubmit,
47
- getThemeColor,
48
- onPromptSelect,
49
- autoHeight,
50
- }) => {
51
- if (!formData) return null
52
-
53
- const appWidth = f.getAppWidth(true)
54
- const align: any = formData.alignment === 'left' ? 'flex-start' : 'center'
55
- const textAlign: any = formData.alignment === 'left' ? 'left' : 'center'
56
- const titleFont = getThemeColor('title_font', '')
57
- const questionFont = getThemeColor('question_font', '')
58
- const textareaFont = getThemeColor('textarea_font', '')
59
-
60
- const renderPrompt = () => (
61
- <YesNoButtons
62
- question={formData.question}
63
- value={null}
64
- yesLabel={formData.positive_feedback_button || 'Yes'}
65
- noLabel={formData.negative_feedback_button || 'No'}
66
- onSelect={onPromptSelect}
67
- appWidth={appWidth}
68
- selectedVariant="secondary"
69
- questionStyle={{
70
- color: getThemeColor('question_color', '#14181C'),
71
- textAlign,
72
- fontFamily: questionFont || undefined,
73
- }}
74
- />
75
- )
76
-
77
- const renderSatisfaction = () => (
78
- <Rating
79
- title={formData.title}
80
- question={formData.question}
81
- value={rating}
82
- onRate={onRate}
83
- rating_max={formData.rating_max || 5}
84
- titleStyle={{
85
- color: getThemeColor('title_color', '#14181C'),
86
- textAlign,
87
- fontFamily: titleFont || undefined,
88
- }}
89
- questionStyle={{
90
- color: getThemeColor('question_color', '#14181C'),
91
- textAlign,
92
- fontFamily: questionFont || undefined,
93
- }}
94
- normalStarColor={getThemeColor('normal_star_color', '#D0D0D0')}
95
- selectedStarColor={getThemeColor('selected_star_color', '#F7C926')}
96
- style={styles.satisfactionRating}
97
- />
98
- )
99
-
100
- const renderNPS = () => (
101
- <View style={[styles.section, {alignItems: align}]}>
102
- <Text
103
- style={[
104
- styles.title,
105
- // {color: getThemeColor('title_color', '#082065'), textAlign, fontFamily: titleFont},
106
- ]}
107
- >
108
- {formData.title}
109
- </Text>
110
- <RatingNumber
111
- numStar={rating}
112
- handlePressRating={onRate}
113
- rating_min={formData.rating_min || 0}
114
- rating_max={formData.rating_max || 10}
115
- scale_label_left={formData.scale_label_left}
116
- scale_label_right={formData.scale_label_right}
117
- scale_label_color={getThemeColor('scale_label_color', '#858B91')}
118
- scale_label_font={getThemeColor('scale_label_font', '')}
119
- appWidth={appWidth}
120
- compact={false}
121
- label={formData.question}
122
- />
123
- </View>
124
- )
125
-
126
- const renderPoll = () => (
127
- <View style={styles.section}>
128
- <Text style={[styles.title, {color: getThemeColor('title_color', '#14181C'), fontFamily: titleFont}]}>
129
- {formData.title}
130
- </Text>
131
-
132
- {formData.type === 'poll' && formData.options && (
133
- <MultiSelectButtons
134
- question={formData.instruction}
135
- options={formData.options.map((o: any) => ({
136
- label: o.title || o.label || String(o),
137
- value: o.slug || o.value || String(o),
138
- }))}
139
- value={selectedOptions}
140
- onSelect={onChangeSelectedOptions}
141
- appWidth={appWidth}
142
- />
143
- )}
144
- {(formData.type === 'comment' || (formData.type === 'poll' && formData.show_comment)) && (
145
- <Textarea
146
- value={freeText}
147
- onChangeText={onChangeFreeText}
148
- placeholder={formData.comment_placeholder}
149
- label={formData.question}
150
- appWidth={appWidth}
151
- maxLength={formData.comment_max_length || 150}
152
- fontFamily={textareaFont}
153
- style={formData.type === 'poll' ? styles.mt16 : undefined}
154
- note={formData.fineprint}
155
- />
156
- )}
157
- </View>
158
- )
159
-
160
- const renderExternal = () => (
161
- <View style={[styles.section, {alignItems: align}]}>
162
- {formData.image_file_url && (
163
- <Image source={{uri: formData.image_file_url}} style={styles.externalIcon} resizeMode="contain" />
164
- )}
165
- <Text
166
- style={[
167
- styles.title,
168
- {color: getThemeColor('title_color', '#14181C'), textAlign, fontFamily: titleFont},
169
- ]}
170
- >
171
- {formData.title}
172
- </Text>
173
- </View>
174
- )
175
-
176
- const renderSecondary = () => {
177
- if (!showSecondary) return null
178
-
179
- return (
180
- <View style={[styles.secondarySection, autoHeight && styles.autoHeightReset, {alignItems: align}]}>
181
- {formData.type === 'satisfaction' && formData.options && formData.options.length > 0 && (
182
- <>
183
- <View style={styles.divider} />
184
-
185
- <MultiSelectButtons
186
- question={rating === 5 ? formData.instruction_5_star : formData.instruction}
187
- options={formData.options.map((o: any) => ({
188
- label: o.title || o.label || String(o),
189
- value: o.slug || o.value || String(o),
190
- }))}
191
- value={selectedOptions}
192
- onSelect={onChangeSelectedOptions}
193
- appWidth={appWidth}
194
- />
195
- </>
196
- )}
197
-
198
- <Textarea
199
- value={freeText}
200
- onChangeText={onChangeFreeText}
201
- placeholder={
202
- formData.type === 'satisfaction' && rating === 5
203
- ? formData.comment_placeholder_5_star
204
- : formData.comment_placeholder
205
- }
206
- label={formData.secondary_question || formData.comment_label || ''}
207
- appWidth={appWidth}
208
- maxLength={formData.comment_max_length || 150}
209
- fontFamily={textareaFont}
210
- style={styles.mt16}
211
- note={formData.fineprint}
212
- />
213
- </View>
214
- )
215
- }
216
-
217
- return (
218
- <View style={[styles.formRoot, autoHeight && styles.autoHeightFlexReset]}>
219
- <View
220
- style={[
221
- styles.formContent,
222
- autoHeight && styles.autoHeightReset,
223
- !showSecondary && formData.type !== 'poll' && styles.centeredContent,
224
- ]}
225
- >
226
- {step === 'PROMPT' && renderPrompt()}
227
-
228
- {step === 'FORM' && (
229
- <>
230
- {formData.type === 'satisfaction' && renderSatisfaction()}
231
- {isNPSFlow && renderNPS()}
232
- {(formData.type === 'poll' || formData.type === 'comment') && renderPoll()}
233
- {formData.type === 'external' && renderExternal()}
234
- {renderSecondary()}
235
- </>
236
- )}
237
- </View>
238
-
239
- <View style={[styles.submitSection, autoHeight && styles.autoHeightMargin]}>
240
- {submissionError && (
241
- <View style={[styles.errorWrap, styles.mb12]}>
242
- <ErrorIcon size={20} color={ERROR_COLOR} />
243
- <Text style={[styles.error, {color: ERROR_COLOR}]}>{submissionError}</Text>
244
- </View>
245
- )}
246
-
247
- {(rating > 0 ||
248
- formData.type === 'comment' ||
249
- formData.type === 'external' ||
250
- (formData.type === 'poll' && selectedOptions.length > 0)) && (
251
- <ButtonSubmit
252
- title={formData.button_text || 'Submit'}
253
- onPress={onSubmit}
254
- loading={isSubmitting}
255
- appWidth={appWidth}
256
- containerStyle={styles.mt24}
257
- backgroundColor={getThemeColor('button_bg_color', '#D31145')}
258
- textColor={getThemeColor('button_text_color', '#FFF')}
259
- fontFamily={getThemeColor('button_font', '')}
260
- />
261
- )}
262
- </View>
263
- </View>
264
- )
265
- }
266
-
267
- export default AIAFeedbackForm
@@ -1,49 +0,0 @@
1
- import React from 'react'
2
- import {Text, TouchableOpacity, View} from 'react-native'
3
- import ButtonSubmit from './component/ButtonSubmit'
4
- import * as f from './utils/common'
5
- import {feedbackStyles as styles} from './AIAFeedbackStyles'
6
-
7
- interface Props {
8
- formData: any
9
- getThemeColor: (key: string, fallback: string) => string
10
- onSkip: () => void
11
- onProceed: () => void
12
- }
13
-
14
- const AIAFeedbackSplash: React.FC<Props> = ({formData, getThemeColor, onSkip, onProceed}) => {
15
- if (!formData) return null
16
-
17
- const textAlign: any = formData.alignment === 'left' ? 'left' : 'center'
18
- const btnBg = getThemeColor('button_bg_color', '#D31145')
19
- const btnText = getThemeColor('button_text_color', '#FFFFFF')
20
- const titleColor = getThemeColor('title_color', '#082065')
21
- const questionColor = getThemeColor('question_color', '#082065')
22
- const titleFont = getThemeColor('title_font', '')
23
- const questionFont = getThemeColor('question_font', '')
24
-
25
- return (
26
- <View style={styles.splashContainer}>
27
- <Text style={[styles.splashTitle, {color: titleColor, textAlign, fontFamily: titleFont}]}>
28
- {formData.splash_screen_title}
29
- </Text>
30
- <Text style={[styles.splashQuestion, {color: questionColor, textAlign, fontFamily: questionFont}]}>
31
- {formData.splash_screen_question}
32
- </Text>
33
-
34
- <ButtonSubmit
35
- title={formData.splash_screen_button_proceed || "Yes, Let's go!"}
36
- onPress={onProceed}
37
- appWidth={f.getAppWidth(true)}
38
- backgroundColor={btnBg}
39
- textColor={btnText}
40
- containerStyle={styles.mt24}
41
- />
42
- <TouchableOpacity onPress={onSkip} style={styles.skipBtn}>
43
- <Text style={styles.skipBtnText}>{formData.splash_screen_button_skip || 'Another time'}</Text>
44
- </TouchableOpacity>
45
- </View>
46
- )
47
- }
48
-
49
- export default AIAFeedbackSplash
@@ -1,311 +0,0 @@
1
- import {Platform, StyleSheet} from 'react-native'
2
- import * as f from './utils/common'
3
-
4
- export const feedbackStyles = StyleSheet.create({
5
- overlay: {
6
- flex: 1,
7
- backgroundColor: 'rgba(20, 24, 28, 0.5)',
8
- justifyContent: 'flex-end',
9
- },
10
- nonBlockingOverlay: {
11
- backgroundColor: 'transparent',
12
- },
13
- splashOverlay: {
14
- justifyContent: 'center',
15
- alignItems: 'center',
16
- paddingHorizontal: 6,
17
- },
18
- intrusiveOverlay: {
19
- backgroundColor: '#FFF',
20
- justifyContent: 'flex-start',
21
- },
22
- dismissArea: {
23
- flex: 1,
24
- },
25
- modalContent: {
26
- backgroundColor: '#FFF',
27
- borderTopLeftRadius: 16,
28
- borderTopRightRadius: 16,
29
- width: '100%',
30
- maxHeight: '90%',
31
- minHeight: 180,
32
- overflow: 'hidden',
33
- },
34
- splashContent: {
35
- ...Platform.select({
36
- ios: {
37
- shadowColor: '#000',
38
- shadowOffset: {width: 0, height: 10},
39
- shadowOpacity: 0.2,
40
- shadowRadius: 20,
41
- },
42
- android: {
43
- elevation: 10,
44
- },
45
- }),
46
- borderTopLeftRadius: 16,
47
- borderTopRightRadius: 16,
48
- borderBottomLeftRadius: 16,
49
- borderBottomRightRadius: 16,
50
- },
51
- splashTabletContent: {
52
- width: '90%',
53
- maxWidth: 350,
54
- borderRadius: 16,
55
- maxHeight: '80%',
56
- minHeight: 0,
57
- },
58
- splashInner: {
59
- paddingTop: 20,
60
- },
61
- intrusiveContent: {
62
- flex: 1,
63
- maxHeight: '100%',
64
- minHeight: '100%',
65
- borderTopLeftRadius: 0,
66
- borderTopRightRadius: 0,
67
- },
68
- safeArea: {
69
- flexShrink: 1,
70
- flexGrow: 1,
71
- flexDirection: 'column',
72
- },
73
- flex1: {
74
- flex: 1,
75
- },
76
- header: {
77
- alignItems: 'center',
78
- justifyContent: 'flex-start',
79
- position: 'relative',
80
- },
81
- headerRow: {
82
- height: 30,
83
- width: '100%',
84
- alignItems: 'center',
85
- justifyContent: 'center',
86
- position: 'relative',
87
- },
88
- handle: {
89
- width: 40,
90
- height: 4,
91
- backgroundColor: '#E0E0E0',
92
- borderRadius: 2,
93
- },
94
- closeBtn: {
95
- position: 'absolute',
96
- right: 16,
97
- padding: 8,
98
- zIndex: 10,
99
- },
100
- intrusiveCloseBtn: {
101
- top: 0,
102
- },
103
- closeText: {
104
- fontSize: 18,
105
- color: '#999',
106
- },
107
- scrollContent: {
108
- flexGrow: 1,
109
- paddingHorizontal: f.isTablet ? 20 : 12,
110
- paddingBottom: 30,
111
- },
112
- scrollContentInner: {
113
- flex: 1,
114
- minHeight: 1,
115
- },
116
- center: {
117
- height: 200,
118
- justifyContent: 'center',
119
- alignItems: 'center',
120
- },
121
- mtAuto: {
122
- marginTop: 'auto',
123
- },
124
- w100: {
125
- width: '100%',
126
- },
127
- section: {
128
- marginBottom: 20,
129
- gap: 24,
130
- alignSelf: 'stretch',
131
- width: '100%',
132
- },
133
- secondarySection: {
134
- flexGrow: 1,
135
- alignItems: 'center',
136
- gap: 24,
137
- },
138
- satisfactionRating: {
139
- alignItems: 'center',
140
- marginBottom: 16,
141
- },
142
- title: {
143
- fontSize: 24,
144
- fontWeight: '500',
145
- color: '#14181C',
146
- marginBottom: 8,
147
- },
148
- externalIcon: {
149
- width: 140,
150
- height: 140,
151
- marginBottom: 10,
152
- },
153
- question: {
154
- fontSize: 16,
155
- color: '#082065',
156
- marginBottom: 16,
157
- fontWeight: '600',
158
- },
159
- successContainer: {
160
- padding: 24,
161
- alignItems: 'center',
162
- },
163
- successTitle: {
164
- fontSize: 20,
165
- fontWeight: '700',
166
- color: '#082065',
167
- marginBottom: 12,
168
- textAlign: 'center',
169
- },
170
- successDesc: {
171
- fontSize: 16,
172
- color: '#444',
173
- marginBottom: 24,
174
- textAlign: 'center',
175
- lineHeight: 22,
176
- },
177
- mt16: {
178
- marginTop: 16,
179
- },
180
- mt24: {
181
- marginTop: 24,
182
- },
183
- splashContainer: {
184
- padding: 16,
185
- alignItems: 'center',
186
- },
187
- splashTitle: {
188
- fontSize: 24,
189
- fontWeight: '700',
190
- textAlign: 'center',
191
- marginBottom: 16,
192
- },
193
- splashQuestion: {
194
- fontSize: 16,
195
- textAlign: 'center',
196
- marginBottom: 24,
197
- lineHeight: 22,
198
- },
199
- skipBtn: {
200
- marginTop: 16,
201
- padding: 8,
202
- },
203
- skipBtnText: {
204
- fontSize: 14,
205
- textDecorationLine: 'underline',
206
- fontWeight: '700',
207
- },
208
- successIcon: {
209
- width: 80,
210
- height: 80,
211
- marginBottom: 20,
212
- },
213
- fineprint: {
214
- fontSize: 12,
215
- marginTop: 16,
216
- textAlign: 'center',
217
- opacity: 0.8,
218
- },
219
- centeredScrollContent: {
220
- flexGrow: 1,
221
- justifyContent: 'center',
222
- },
223
- formRoot: {
224
- flex: 1,
225
- justifyContent: 'space-between',
226
- },
227
- formContent: {
228
- flexGrow: 1,
229
- },
230
- submitSection: {
231
- width: '100%',
232
- marginTop: 'auto',
233
- },
234
- successRoot: {
235
- flex: 1,
236
- justifyContent: 'space-between',
237
- },
238
- successContentCenter: {
239
- flex: 1,
240
- justifyContent: 'center',
241
- },
242
- tabletOverlay: {
243
- justifyContent: 'center',
244
- alignItems: 'center',
245
- },
246
- tabletIntrusive: {
247
- width: '90%',
248
- maxWidth: 850,
249
- height: 'auto',
250
- maxHeight: '90%',
251
- borderRadius: 16,
252
- overflow: 'hidden',
253
- ...Platform.select({
254
- ios: {
255
- shadowColor: '#000',
256
- shadowOffset: {width: 0, height: 10},
257
- shadowOpacity: 0.2,
258
- shadowRadius: 20,
259
- },
260
- android: {
261
- elevation: 10,
262
- },
263
- }),
264
- },
265
- tabletNonIntrusive: {
266
- position: 'absolute',
267
- bottom: 30,
268
- right: 30,
269
- width: 400,
270
- maxHeight: '70%',
271
- borderRadius: 16,
272
- overflow: 'hidden',
273
- ...Platform.select({
274
- ios: {
275
- shadowColor: '#000',
276
- shadowOffset: {width: 0, height: 10},
277
- shadowOpacity: 0.2,
278
- shadowRadius: 20,
279
- },
280
- android: {
281
- elevation: 10,
282
- },
283
- }),
284
- },
285
-
286
- errorWrap: {
287
- flexDirection: 'row',
288
- alignItems: 'center',
289
- gap: 6,
290
- },
291
- error: {
292
- fontSize: 14,
293
- lineHeight: 20,
294
- flex: 1,
295
- fontWeight: '400',
296
- },
297
- mb12: {
298
- marginBottom: 12,
299
- },
300
- divider: {
301
- width: '100%',
302
- height: 1,
303
- backgroundColor: '#E5E5E5',
304
- marginTop: 12,
305
- },
306
-
307
- centeredContent: {justifyContent: 'center', alignItems: 'center'},
308
- autoHeightReset: {flexGrow: 0},
309
- autoHeightFlexReset: {flex: 0},
310
- autoHeightMargin: {marginTop: 16},
311
- })
@@ -1,67 +0,0 @@
1
- import React from 'react'
2
- import {Image, Text, View} from 'react-native'
3
- import ButtonSubmit from './component/ButtonSubmit'
4
- import * as f from './utils/common'
5
- import {feedbackStyles as styles} from './AIAFeedbackStyles'
6
-
7
- interface Props {
8
- submitRes: any
9
- shouldCenter: boolean
10
- getThemeColor: (key: string, fallback: string) => string
11
- onClose: () => void
12
- autoHeight?: boolean
13
- }
14
-
15
- const AIAFeedbackSuccess: React.FC<Props> = ({submitRes, shouldCenter, getThemeColor, onClose, autoHeight}) => {
16
- if (!submitRes) return null
17
-
18
- const align: any = submitRes.alignment === 'left' ? 'flex-start' : 'center'
19
- const textAlign: any = submitRes.alignment === 'left' ? 'left' : 'center'
20
- const btnBg = getThemeColor('button_bg_color', '#D31145')
21
- const btnText = getThemeColor('button_text_color', '#FFFFFF')
22
- const titleColor = getThemeColor('title_color', '#333D47')
23
- const instructionColor = getThemeColor('instruction_color', '#444')
24
- const titleFont = getThemeColor('title_font', '')
25
- const instructionFont = getThemeColor('instruction_font', '')
26
-
27
- return (
28
- <View style={[styles.successRoot, autoHeight && styles.autoHeightFlexReset]}>
29
- <View
30
- style={[
31
- styles.successContentCenter,
32
- autoHeight && styles.autoHeightFlexReset,
33
- shouldCenter && styles.centeredScrollContent,
34
- ]}
35
- >
36
- <View style={[styles.w100, {alignItems: align}]}>
37
- {submitRes.image_file_url && (
38
- <Image
39
- source={{uri: submitRes.image_file_url}}
40
- style={styles.successIcon}
41
- resizeMode="contain"
42
- />
43
- )}
44
- <Text style={[styles.successTitle, {color: titleColor, textAlign, fontFamily: titleFont}]}>
45
- {submitRes.title || 'Thank You!'}
46
- </Text>
47
- <Text
48
- style={[styles.successDesc, {color: instructionColor, textAlign, fontFamily: instructionFont}]}
49
- >
50
- {submitRes.instruction || 'Your feedback has been submitted successfully.'}
51
- </Text>
52
- </View>
53
- </View>
54
- <View style={[styles.submitSection, autoHeight && styles.autoHeightMargin]}>
55
- <ButtonSubmit
56
- title={submitRes.button_text || 'Close'}
57
- onPress={onClose}
58
- appWidth={f.getAppWidth(true)}
59
- backgroundColor={btnBg}
60
- textColor={btnText}
61
- />
62
- </View>
63
- </View>
64
- )
65
- }
66
-
67
- export default AIAFeedbackSuccess
@@ -1,18 +0,0 @@
1
- import {memo} from 'react'
2
- import Svg, {Path} from 'react-native-svg'
3
-
4
- const CHECK_PATH =
5
- 'M13.66 0.390759C14.181 -0.130253 15.0257 -0.130253 15.5467 0.390759C16.0678 0.911771 16.0678 1.7565 15.5467 2.27751L6.60443 11.2198C6.08342 11.7408 5.23869 11.7408 4.71768 11.2198L0.390759 6.89289C-0.130253 6.37188 -0.130253 5.52716 0.390759 5.00614C0.911771 4.48513 1.7565 4.48513 2.27751 5.00614L5.66106 8.38969L13.66 0.390759Z'
6
-
7
- interface CheckIconProps {
8
- size?: number
9
- color?: string
10
- }
11
-
12
- const CheckIcon = memo(({size = 16, color = '#082065'}: CheckIconProps) => (
13
- <Svg width={size} height={size * (12 / 16)} viewBox="0 0 16 12" fill="none">
14
- <Path d={CHECK_PATH} fill={color} />
15
- </Svg>
16
- ))
17
-
18
- export default CheckIcon