@propel-nsl/propel-react-native-sdk 1.1.5 → 1.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@propel-nsl/propel-react-native-sdk",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "Propel Mobile SDK - React Native Core",
5
5
  "files": [
6
6
  "src/",
@@ -270,19 +270,11 @@ const PaymentMethod: React.FC<{
270
270
  return;
271
271
  }
272
272
  const payload = {
273
- orderId: cartId,
274
273
  amount_cents: 0,
275
274
  client_id: '7b170ef2-c0a0-4968-a832-d308d54a8419',
276
275
  order_id: cartId,
277
- redeem_propel_points: true,
278
- redirect: '',
279
276
  payment_method: 'third_party_points',
280
- transactions: [
281
- {
282
- amount_cents: 0,
283
- payment_method: 'zaggleOption',
284
- },
285
- ],
277
+ transactions: [],
286
278
  skipAddress,
287
279
  };
288
280
  setShowLoader(true);
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useState } from 'react';
1
+ import React, { Component, useCallback, useEffect, useState } from 'react';
2
2
  import {
3
3
  View,
4
4
  Text,
@@ -145,6 +145,26 @@ const ChevronDownIcon: React.FC = () => (
145
145
  </Svg>
146
146
  );
147
147
 
148
+ class HTMLErrorBoundary extends Component<
149
+ { fallback?: React.ReactNode; children: React.ReactNode },
150
+ { hasError: boolean }
151
+ > {
152
+ state = { hasError: false };
153
+ static getDerivedStateFromError() {
154
+ return { hasError: true };
155
+ }
156
+ render() {
157
+ if (this.state.hasError) {
158
+ return this.props.fallback ?? (
159
+ <Text style={{ color: colors.onSurfaceVariant, fontSize: 13 }}>
160
+ Content could not be displayed.
161
+ </Text>
162
+ );
163
+ }
164
+ return this.props.children;
165
+ }
166
+ }
167
+
148
168
  const AccordionItem: React.FC<{
149
169
  title: string;
150
170
  content: string;
@@ -174,21 +194,23 @@ const AccordionItem: React.FC<{
174
194
  </TouchableOpacity>
175
195
  {isExpanded && (
176
196
  <View style={styles.accordionContent}>
177
- <RenderHTML
178
- contentWidth={width}
179
- source={{
180
- html: sanitizeHtmlContent(content ?? ''),
181
- }}
182
- tagsStyles={{
183
- ol: styles.ol,
184
- ul: styles.ul,
185
- li: styles.li,
186
- p: styles.p,
187
- div: styles.div,
188
- }}
189
- renderers={renderers}
190
- ignoredDomTags={IGNORED_DOM_TAGS}
191
- />
197
+ <HTMLErrorBoundary>
198
+ <RenderHTML
199
+ contentWidth={width}
200
+ source={{
201
+ html: sanitizeHtmlContent(content ?? ''),
202
+ }}
203
+ tagsStyles={{
204
+ ol: styles.ol,
205
+ ul: styles.ul,
206
+ li: styles.li,
207
+ p: styles.p,
208
+ div: styles.div,
209
+ }}
210
+ renderers={renderers}
211
+ ignoredDomTags={IGNORED_DOM_TAGS}
212
+ />
213
+ </HTMLErrorBoundary>
192
214
  </View>
193
215
  )}
194
216
  </View>
@@ -271,50 +293,69 @@ const ProductDetail: React.FC = () => {
271
293
  }, [dispatch]);
272
294
 
273
295
  const sanitizeHtmlContent = (html: string): string => {
274
- if (!html) return '';
275
-
276
- const cleaned = html
277
- .replace(HTML_SANITIZATION_PATTERNS.STYLE_TAGS, '')
278
- .replace(HTML_SANITIZATION_PATTERNS.SPAN_OPEN, '')
279
- .replace(HTML_SANITIZATION_PATTERNS.SPAN_CLOSE, '')
280
- .replace(HTML_SANITIZATION_PATTERNS.MSO_NORMAL_CLASS, '')
281
- .replace(HTML_SANITIZATION_PATTERNS.O_P_TAG, '')
282
- .replace(HTML_SANITIZATION_PATTERNS.SUP_TAG, '')
283
- .replace(HTML_SANITIZATION_PATTERNS.SUB_TAG, '')
284
- .replace(HTML_SANITIZATION_PATTERNS.EMPTY_P, '')
285
- .replace(HTML_SANITIZATION_PATTERNS.FONT_OPEN, '')
286
- .replace(HTML_SANITIZATION_PATTERNS.FONT_CLOSE, '')
287
-
288
- .replace(HTML_SANITIZATION_PATTERNS.TABLE_OPEN, '<div>')
289
- .replace(HTML_SANITIZATION_PATTERNS.TABLE_CLOSE, '</div>')
290
- .replace(HTML_SANITIZATION_PATTERNS.TR_OPEN, '<div>')
291
- .replace(HTML_SANITIZATION_PATTERNS.TR_CLOSE, '</div>')
292
- .replace(HTML_SANITIZATION_PATTERNS.TD_OPEN, '<div>')
293
- .replace(HTML_SANITIZATION_PATTERNS.TD_CLOSE, '</div>')
294
- .replace(HTML_SANITIZATION_PATTERNS.TBODY_OPEN, '<div>')
295
- .replace(HTML_SANITIZATION_PATTERNS.TBODY_CLOSE, '</div>')
296
- .replace(HTML_SANITIZATION_PATTERNS.P_OPEN, '<div>')
297
- .replace(HTML_SANITIZATION_PATTERNS.P_CLOSE, '</div>')
298
-
299
- .replace(HTML_SANITIZATION_PATTERNS.DIV_BR, '</div><div>')
300
- .replace(HTML_SANITIZATION_PATTERNS.BR, '</div><div>')
301
- .replace(HTML_SANITIZATION_PATTERNS.EMPTY_DIV, '')
302
- .replace(HTML_SANITIZATION_PATTERNS.SUP_INLINE, '')
303
-
304
- .replace(HTML_SANITIZATION_PATTERNS.STYLE_ATTRIBUTES, '')
305
- .replace(HTML_SANITIZATION_PATTERNS.ID_ATTRIBUTES, '')
306
- .replace(HTML_SANITIZATION_PATTERNS.CLASS_ATTRIBUTES, '')
307
- .replace(HTML_SANITIZATION_PATTERNS.TITLE_ATTRIBUTES, '')
308
-
309
- .replace(HTML_SANITIZATION_PATTERNS.NBSP, ' ')
310
- .replace(HTML_SANITIZATION_PATTERNS.MULTI_SPACE, ' ')
311
-
312
- .replace(HTML_SANITIZATION_PATTERNS.DIV_OPEN, '<p>')
313
- .replace(HTML_SANITIZATION_PATTERNS.DIV_CLOSE, '</p>')
314
-
315
- .trim();
316
-
317
- return `<div>${cleaned}</div>`;
296
+ if (!html) return '<div></div>';
297
+
298
+ try {
299
+ const cleaned = html
300
+ .replace(/\r\n?/g, '\n')
301
+ .replace(/<!--[\s\S]*?-->/g, '')
302
+ .replace(/<!DOCTYPE[^>]*>/gi, '')
303
+ .replace(/<!(?!--)[\s\S]*?>/g, '')
304
+
305
+ .replace(HTML_SANITIZATION_PATTERNS.STYLE_TAGS, '')
306
+ .replace(HTML_SANITIZATION_PATTERNS.SPAN_OPEN, '')
307
+ .replace(HTML_SANITIZATION_PATTERNS.SPAN_CLOSE, '')
308
+ .replace(HTML_SANITIZATION_PATTERNS.MSO_NORMAL_CLASS, '')
309
+ .replace(HTML_SANITIZATION_PATTERNS.O_P_TAG, '')
310
+ .replace(HTML_SANITIZATION_PATTERNS.SUP_TAG, '')
311
+ .replace(HTML_SANITIZATION_PATTERNS.SUB_TAG, '')
312
+ .replace(HTML_SANITIZATION_PATTERNS.EMPTY_P, '')
313
+ .replace(HTML_SANITIZATION_PATTERNS.FONT_OPEN, '')
314
+ .replace(HTML_SANITIZATION_PATTERNS.FONT_CLOSE, '')
315
+
316
+ .replace(HTML_SANITIZATION_PATTERNS.TABLE_OPEN, '<div>')
317
+ .replace(HTML_SANITIZATION_PATTERNS.TABLE_CLOSE, '</div>')
318
+ .replace(HTML_SANITIZATION_PATTERNS.TR_OPEN, '<div>')
319
+ .replace(HTML_SANITIZATION_PATTERNS.TR_CLOSE, '</div>')
320
+ .replace(HTML_SANITIZATION_PATTERNS.TD_OPEN, '<div>')
321
+ .replace(HTML_SANITIZATION_PATTERNS.TD_CLOSE, '</div>')
322
+ .replace(HTML_SANITIZATION_PATTERNS.TBODY_OPEN, '<div>')
323
+ .replace(HTML_SANITIZATION_PATTERNS.TBODY_CLOSE, '</div>')
324
+ .replace(HTML_SANITIZATION_PATTERNS.P_OPEN, '<div>')
325
+ .replace(HTML_SANITIZATION_PATTERNS.P_CLOSE, '</div>')
326
+
327
+ .replace(HTML_SANITIZATION_PATTERNS.DIV_BR, '</div><div>')
328
+ .replace(HTML_SANITIZATION_PATTERNS.BR, '</div><div>')
329
+ .replace(HTML_SANITIZATION_PATTERNS.EMPTY_DIV, '')
330
+ .replace(HTML_SANITIZATION_PATTERNS.SUP_INLINE, '')
331
+
332
+ .replace(HTML_SANITIZATION_PATTERNS.STYLE_ATTRIBUTES, '')
333
+ .replace(HTML_SANITIZATION_PATTERNS.ID_ATTRIBUTES, '')
334
+ .replace(HTML_SANITIZATION_PATTERNS.CLASS_ATTRIBUTES, '')
335
+ .replace(HTML_SANITIZATION_PATTERNS.TITLE_ATTRIBUTES, '')
336
+
337
+ .replace(HTML_SANITIZATION_PATTERNS.NBSP, ' ')
338
+ .replace(/&amp;/gi, 'and')
339
+ .replace(/&lt;/gi, '<')
340
+ .replace(/&gt;/gi, '>')
341
+ .replace(/&quot;/gi, '"')
342
+ .replace(/&apos;/gi, "'")
343
+ .replace(/&#0?39;/g, "'")
344
+ .replace(/&#\d+;/g, '')
345
+ .replace(/&#x[0-9a-fA-F]+;/g, '')
346
+ .replace(/&[a-zA-Z]+;/g, ' ')
347
+ .replace(/&/g, ' ')
348
+ .replace(HTML_SANITIZATION_PATTERNS.MULTI_SPACE, ' ')
349
+
350
+ .replace(HTML_SANITIZATION_PATTERNS.DIV_OPEN, '<p>')
351
+ .replace(HTML_SANITIZATION_PATTERNS.DIV_CLOSE, '</p>')
352
+
353
+ .trim();
354
+
355
+ return `<div>${cleaned || ''}</div>`;
356
+ } catch {
357
+ return '<div></div>';
358
+ }
318
359
  };
319
360
 
320
361
  const normalize = (v: any) => String(v ?? '').trim().toLowerCase();
@@ -68,6 +68,10 @@ const getStatusIcon = (status: string) => {
68
68
  return (
69
69
  <CustomImage source={Images?.pendingIcon} imgStyle={[styles.icon]} />
70
70
  );
71
+ case 'cancelled':
72
+ return (
73
+ <CustomImage source={Images?.crossIcon} imgStyle={[styles.icon]} />
74
+ );
71
75
  default:
72
76
  return null;
73
77
  }
@@ -83,6 +87,8 @@ const getStatusColor = (status: string) => {
83
87
  return colors.orange;
84
88
  case 'partial':
85
89
  return colors.orange;
90
+ case 'cancelled':
91
+ return colors.red;
86
92
  case 'complete':
87
93
  case 'confirmed':
88
94
  return colors.green;
@@ -100,8 +106,9 @@ const getStatusText = (status: string) => {
100
106
  case 'pending':
101
107
  return 'Pending';
102
108
  case 'partial':
103
- case 'cancelled':
104
109
  return 'Partial';
110
+ case 'cancelled':
111
+ return 'Cancelled';
105
112
  case 'complete':
106
113
  return 'Complete';
107
114
  case 'confirmed':