@solucx/react-native-solucx-widget 0.1.3 → 0.1.5

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/README.intern.md CHANGED
@@ -85,7 +85,6 @@ export default function MyComponent() {
85
85
  param_REGIAO: "SUDESTE"
86
86
  }}
87
87
  options={{
88
- width: 380,
89
88
  height: 400
90
89
  }}
91
90
  />
@@ -145,8 +144,7 @@ interface WidgetData {
145
144
 
146
145
  ```typescript
147
146
  interface WidgetOptions {
148
- width?: number; // Largura do widget (padrão: 380)
149
- height?: number; // Altura do widget (padrão: 400)
147
+ height?: number; // Altura
150
148
  retry?: { // Configuração de retry
151
149
  attempts?: number; // Número de tentativas
152
150
  interval?: number; // Intervalo entre tentativas
@@ -277,7 +275,6 @@ Configurações centralizadas em [`webViewConstants.ts`](src/constants/webViewCo
277
275
  ```typescript
278
276
  export const BASE_URL = 'https://survey-link.solucx.com.br/link';
279
277
  export const STORAGE_KEY = '@solucxWidgetLog';
280
- export const DEFAULT_WIDTH = 380;
281
278
  export const MIN_HEIGHT = 200;
282
279
  export const FIXED_Z_INDEX = 9999;
283
280
  export const MODAL_Z_INDEX = 10000;
package/README.md CHANGED
@@ -54,8 +54,7 @@ export default function MyScreen() {
54
54
  store_id: "loja_01",
55
55
  amount: 150.00
56
56
  }}
57
- options={{
58
- width: 380,
57
+ options={{
59
58
  height: 400
60
59
  }}
61
60
  />
@@ -138,8 +137,7 @@ interface WidgetData {
138
137
 
139
138
  ```typescript
140
139
  interface WidgetOptions {
141
- width?: number; // Largura (padrão: 380)
142
- height?: number; // Altura (padrão: 400)
140
+ height?: number; // Altura
143
141
  retry?: {
144
142
  attempts?: number; // Tentativas (padrão: 3)
145
143
  interval?: number; // Intervalo em ms (padrão: 1000)
@@ -239,10 +237,9 @@ const handleMessage = (message: string) => {
239
237
 
240
238
  ```typescript
241
239
  // Ajustar dimensões para o dispositivo:
242
- const { width, height } = Dimensions.get('window');
240
+ const { height } = Dimensions.get('window');
243
241
 
244
242
  const options = {
245
- width: width * 0.9,
246
243
  height: Math.min(height * 0.6, 400)
247
244
  };
248
245
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solucx/react-native-solucx-widget",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "The React Native SDK for Solucx Widget",
5
5
  "main": "src/index",
6
6
  "author": " <> ()",
@@ -12,10 +12,11 @@
12
12
  ],
13
13
  "dependencies": {
14
14
  "@react-native-async-storage/async-storage": "^2.2.0",
15
- "react-native-webview": "^13.16.0"
15
+ "react-native-webview": "^13.16.0",
16
+ "react-native-reanimated": "~3.17.4"
16
17
  },
17
18
  "peerDependencies": {
18
19
  "react": ">=18.0.0",
19
20
  "react-native": ">=0.72.0"
20
21
  }
21
- }
22
+ }
@@ -36,13 +36,12 @@ export const SoluCXWidget: React.FC<SoluCXWidgetProps> = ({
36
36
  open,
37
37
  close,
38
38
  userId,
39
- } = useWidgetState(data, type);
39
+ } = useWidgetState(data, options, type);
40
40
 
41
41
  const eventService = new WidgetEventService(setIsWidgetVisible, resize, open, userId, options);
42
42
 
43
43
  const uri = buildWidgetURL(soluCXKey, data);
44
44
  const isForm = Boolean(data.form_id);
45
- const height = options.height ? Number(options.height) : undefined;
46
45
 
47
46
  useEffect(() => {
48
47
  loadSavedData();
@@ -77,7 +76,7 @@ export const SoluCXWidget: React.FC<SoluCXWidgetProps> = ({
77
76
 
78
77
  if (type === 'modal') {
79
78
  return (
80
- <ModalWidget visible={isWidgetVisible} onClose={handleClose}>
79
+ <ModalWidget visible={isWidgetVisible} height={widgetHeight} onClose={handleClose}>
81
80
  <WebView
82
81
  ref={webviewRef}
83
82
  style={webViewStyle}
@@ -91,7 +90,7 @@ export const SoluCXWidget: React.FC<SoluCXWidgetProps> = ({
91
90
 
92
91
  if (type === 'inline') {
93
92
  return (
94
- <InlineWidget visible={isWidgetVisible} onClose={handleClose}>
93
+ <InlineWidget visible={isWidgetVisible} height={widgetHeight} onClose={handleClose}>
95
94
  <WebView
96
95
  ref={webviewRef}
97
96
  style={webViewStyle}
@@ -1,25 +1,32 @@
1
- import React from 'react';
1
+ import React, { useEffect } from 'react';
2
2
  import { View } from 'react-native';
3
- import { styles, getWidgetVisibility } from '../styles/widgetStyles';
3
+ import { styles, getWidgetVisibility, useHeightAnimation } from '../styles/widgetStyles';
4
4
  import { CloseButton } from './CloseButton';
5
+ import Animated from 'react-native-reanimated';
5
6
 
6
7
  interface InlineWidgetProps {
7
8
  visible: boolean;
9
+ height: number;
8
10
  children?: React.ReactNode;
9
11
  onClose?: () => void;
10
12
  }
11
13
 
12
- export const InlineWidget: React.FC<InlineWidgetProps> = ({ visible, children, onClose }) => {
14
+ export const InlineWidget: React.FC<InlineWidgetProps> = ({ visible, height, children, onClose }) => {
15
+ const { animatedHeightStyle, updateHeight } = useHeightAnimation(height);
16
+
17
+ useEffect(() => {
18
+ updateHeight(height);
19
+ }, [height, updateHeight]);
13
20
 
14
21
  return (
15
- <View style={[styles.wrapper, getWidgetVisibility(visible)]}>
16
- <View style={[styles.inline, getWidgetVisibility(visible)]}>
22
+ <View style={[styles.inlineWrapper, getWidgetVisibility(visible)]}>
23
+ <Animated.View style={[styles.inline, animatedHeightStyle, getWidgetVisibility(visible)]}>
17
24
  {children}
18
25
  <CloseButton
19
26
  visible={visible}
20
27
  onPress={onClose || (() => { })}
21
28
  />
22
- </View>
29
+ </Animated.View>
23
30
  </View>
24
31
  );
25
32
  };
@@ -1,22 +1,30 @@
1
- import React, { useState } from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  import { Modal, SafeAreaView, View } from 'react-native';
3
- import { styles, getWidgetVisibility } from '../styles/widgetStyles';
3
+ import { styles, getWidgetVisibility, useHeightAnimation } from '../styles/widgetStyles';
4
4
  import { CloseButton } from './CloseButton';
5
+ import Animated from 'react-native-reanimated';
5
6
 
6
7
  interface ModalWidgetProps {
7
8
  visible: boolean;
9
+ height: number;
8
10
  children?: React.ReactNode;
9
11
  onClose?: () => void;
10
12
  }
11
13
 
12
- export const ModalWidget: React.FC<ModalWidgetProps> = ({ visible, children, onClose }) => {
14
+ export const ModalWidget: React.FC<ModalWidgetProps> = ({ visible, height, children, onClose }) => {
13
15
  const [isWidgetVisible, setIsWidgetVisible] = useState<boolean>(true);
14
16
 
17
+ const { animatedHeightStyle, updateHeight } = useHeightAnimation(height);
18
+
19
+ useEffect(() => {
20
+ updateHeight(height);
21
+ }, [height, updateHeight]);
22
+
15
23
  return (
16
24
  <SafeAreaView>
17
- <Modal transparent visible={isWidgetVisible} animationType="fade" hardwareAccelerated>
25
+ <Modal transparent visible={isWidgetVisible} animationType="slide" hardwareAccelerated>
18
26
  <View style={[styles.modalOverlay, getWidgetVisibility(visible)]}>
19
- <View style={[styles.modalContent, getWidgetVisibility(visible)]}>
27
+ <Animated.View style={[styles.modalContent, getWidgetVisibility(visible), animatedHeightStyle]}>
20
28
  {children}
21
29
  <CloseButton
22
30
  visible={visible}
@@ -27,7 +35,7 @@ export const ModalWidget: React.FC<ModalWidgetProps> = ({ visible, children, onC
27
35
  }
28
36
  }}
29
37
  />
30
- </View>
38
+ </Animated.View>
31
39
  </View>
32
40
  </Modal>
33
41
  </SafeAreaView>
@@ -1,9 +1,10 @@
1
- import React, { useState } from 'react';
2
- import { View, ViewStyle, Modal, SafeAreaView } from 'react-native';
1
+ import React, { useState, useEffect } from 'react';
2
+ import { View, ViewStyle } from 'react-native';
3
3
  import { initialWindowMetrics } from 'react-native-safe-area-context';
4
- import { getWidgetStyles, getWidgetVisibility } from '../styles/widgetStyles';
4
+ import { getWidgetStyles, getWidgetVisibility, useHeightAnimation } from '../styles/widgetStyles';
5
5
  import { FIXED_Z_INDEX } from '../constants/webViewConstants';
6
6
  import { CloseButton } from './CloseButton';
7
+ import Animated from 'react-native-reanimated';
7
8
 
8
9
  interface OverlayWidgetProps {
9
10
  visible: boolean;
@@ -14,10 +15,23 @@ interface OverlayWidgetProps {
14
15
  onClose?: () => void;
15
16
  }
16
17
 
17
- export const OverlayWidget: React.FC<OverlayWidgetProps> = ({ visible, width, height, position, children, onClose }) => {
18
+ export const OverlayWidget: React.FC<OverlayWidgetProps> = ({
19
+ visible,
20
+ width,
21
+ height,
22
+ position,
23
+ children,
24
+ onClose,
25
+ }) => {
18
26
  const insets = initialWindowMetrics?.insets ?? { top: 0, bottom: 0, left: 0, right: 0 };
19
27
  const [isWidgetVisible, setIsWidgetVisible] = useState<boolean>(true);
20
28
 
29
+ const { animatedHeightStyle, updateHeight } = useHeightAnimation(height);
30
+
31
+ useEffect(() => {
32
+ updateHeight(height);
33
+ }, [height, updateHeight]);
34
+
21
35
  const containerStyle: ViewStyle = {
22
36
  position: 'absolute',
23
37
  top: 0,
@@ -27,14 +41,14 @@ export const OverlayWidget: React.FC<OverlayWidgetProps> = ({ visible, width, he
27
41
  width: '100%',
28
42
  height: '100%',
29
43
  zIndex: FIXED_Z_INDEX,
30
- backgroundColor: 'transparent',
44
+ pointerEvents: 'box-none'
31
45
  }
32
46
 
33
47
  const contentStyle = [
34
48
  getWidgetStyles(position).content,
35
49
  {
36
50
  width,
37
- height,
51
+ pointerEvents: 'auto' as const,
38
52
  ...(position === 'top' && {
39
53
  top: insets.top,
40
54
  }),
@@ -45,15 +59,10 @@ export const OverlayWidget: React.FC<OverlayWidgetProps> = ({ visible, width, he
45
59
  ];
46
60
 
47
61
  return (
48
- <SafeAreaView>
49
- <Modal
50
- transparent
51
- visible={isWidgetVisible}
52
- animationType="fade"
53
- hardwareAccelerated
54
- >
62
+ <>
63
+ {isWidgetVisible && (
55
64
  <View style={[containerStyle, getWidgetVisibility(visible)]}>
56
- <View style={[contentStyle, getWidgetVisibility(visible)]}>
65
+ <Animated.View style={[contentStyle, animatedHeightStyle, getWidgetVisibility(visible)]}>
57
66
  {children}
58
67
  <CloseButton
59
68
  visible={visible}
@@ -64,9 +73,9 @@ export const OverlayWidget: React.FC<OverlayWidgetProps> = ({ visible, width, he
64
73
  }
65
74
  }}
66
75
  />
67
- </View>
76
+ </Animated.View>
68
77
  </View>
69
- </Modal>
70
- </SafeAreaView>
78
+ )}
79
+ </>
71
80
  );
72
81
  };
@@ -2,12 +2,13 @@ import { useState, useCallback } from 'react';
2
2
  import { Dimensions } from 'react-native';
3
3
  import { WidgetSamplerLog, WidgetData, WidgetType } from '../interfaces';
4
4
  import { StorageService } from '../services/storage';
5
+ import { WidgetOptions } from '@solucx/react-native-solucx-widget';
5
6
 
6
7
  function getUserId(widgetData: WidgetData): string {
7
8
  return widgetData.customer_id ?? widgetData.document ?? widgetData.email ?? "";
8
9
  }
9
10
 
10
- export const useWidgetState = (data: WidgetData, type?: WidgetType) => {
11
+ export const useWidgetState = (data: WidgetData, options?: WidgetOptions, type?: WidgetType) => {
11
12
  const [savedData, setSavedData] = useState<WidgetSamplerLog | null>(null);
12
13
  const [widgetHeight, setWidgetHeight] = useState<number>(0);
13
14
  const [isWidgetVisible, setIsWidgetVisible] = useState<boolean>(false);
@@ -15,6 +16,7 @@ export const useWidgetState = (data: WidgetData, type?: WidgetType) => {
15
16
  const userId = getUserId(data);
16
17
  const storageService = new StorageService(userId);
17
18
  const screenHeight = Dimensions.get('screen').height;
19
+ const height = options?.height ? Number(options.height) : undefined;
18
20
 
19
21
  const loadSavedData = useCallback(async () => {
20
22
  try {
@@ -53,6 +55,10 @@ export const useWidgetState = (data: WidgetData, type?: WidgetType) => {
53
55
 
54
56
  const resize = useCallback((value: string) => {
55
57
  const receivedHeight = Number(value);
58
+ if (height && receivedHeight > height) {
59
+ setWidgetHeight(height);
60
+ return;
61
+ }
56
62
  setWidgetHeight(receivedHeight);
57
63
  }, [screenHeight]);
58
64
 
@@ -1,5 +1,4 @@
1
1
  export interface WidgetOptions {
2
- width?: number;
3
2
  height?: number;
4
3
  retry?: {
5
4
  attempts?: number;
@@ -1,5 +1,30 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
  import { WidgetType } from '../interfaces';
3
+ import {
4
+ useSharedValue,
5
+ withTiming,
6
+ useAnimatedStyle,
7
+ Easing,
8
+ } from 'react-native-reanimated';
9
+
10
+ export const useHeightAnimation = (height: number) => {
11
+ const animatedHeight = useSharedValue(height);
12
+
13
+ const animatedHeightStyle = useAnimatedStyle(() => {
14
+ return {
15
+ height: animatedHeight.value,
16
+ };
17
+ });
18
+
19
+ const updateHeight = (newHeight: number) => {
20
+ animatedHeight.value = withTiming(newHeight, {
21
+ duration: 300,
22
+ easing: Easing.bezier(0.25, 0.1, 0.25, 1),
23
+ });
24
+ };
25
+
26
+ return { animatedHeightStyle, updateHeight };
27
+ };
3
28
 
4
29
  export const styles = StyleSheet.create({
5
30
  wrapper: {