@thanksjs/react-native-webview 0.0.1-beta.1 → 1.1.0

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.md CHANGED
@@ -1,9 +1,10 @@
1
- Thanks JS react native adapter
2
- ===
3
- [ThanksJS React-Native](https://www.npmjs.com/package/@thanksjs/react-native-webview)
4
- | [ThanksJS React](https://www.npmjs.com/package/@thanksjs/react)
5
- | [ThanksJS Web](https://www.npmjs.com/package/@thanksjs/web)
6
- | [Integration Examples](https://github.com/thanksad/Thanks-examples)
1
+ # Thanks JS react native adapter
2
+
3
+ [ThanksJS React-Native](https://www.npmjs.com/package/@thanksjs/react-native-webview) |
4
+ [ThanksJS React](https://www.npmjs.com/package/@thanksjs/react) |
5
+ [ThanksJS Web](https://www.npmjs.com/package/@thanksjs/web) |
6
+ [Integration Examples](https://github.com/thanksad/Thanks-examples)
7
+
7
8
  ## Installation
8
9
 
9
10
  ```bash
@@ -16,16 +17,22 @@ yarn add @thanksjs/react-native-webview
16
17
  import { ThanksWidget } from '@thanksjs/react-native-webview';
17
18
 
18
19
  /// somewhere in your code
19
- <ThanksWidget
20
- partnerId="{your partner id}"
21
- // other available props, see Thanks Configuration section
22
- />
20
+ <ThanksWidget partnerId="{your partner id}" />;
23
21
  ```
22
+
24
23
  It's all comes with TypeScript support, dont worry.
25
24
 
25
+ ## Parameters
26
+
27
+ Refer to the full
28
+ [Thanks API configuration documentation for more](https://partners.thanks.co/docs/types/configuration).
29
+
26
30
  ### Advanced usage
31
+
27
32
  The important parts are:
28
- - providing a customer `email`. Strictly sha256 hash will be transferred during the widget lifecycle. No sensitive information leaves your application without your permission.
33
+
34
+ - providing a customer `email`. Strictly sha256 hash will be transferred during the widget lifecycle. No sensitive
35
+ information leaves your application without your permission.
29
36
  - giving permission to send Personal Information to improve efficiency of communications
30
37
  - `subject` and `info` can be used to decide what information to send
31
38
  - `subject` can be `notification` or `autofill` of visible UI elements
@@ -33,11 +40,12 @@ The important parts are:
33
40
  - `keywords`, `category` and `items` are used to fine-tune ads to display
34
41
 
35
42
  Example
43
+
36
44
  ```tsx
37
45
  <ThanksWidget
38
- partnerId='{your partner id}'
46
+ partnerId="{your partner id}"
39
47
  // information for the first scren
40
- statusText='Your order has been confirmed'
48
+ statusText="Your order has been confirmed"
41
49
  emailHash={{ sha256: customersEmailHash }}
42
50
  // or
43
51
  email={customerEmail}
@@ -47,70 +55,98 @@ Example
47
55
  firstName: 'TestUser',
48
56
  };
49
57
  }}
50
-
51
58
  onDisplay={() => {
52
59
  console.log('widget displayed');
53
60
  }}
54
61
  onClose={() => {
55
62
  console.log('widget closed');
56
63
  }}
57
-
58
- keywords={[
59
- 'violet',
60
- 'roses',
61
- 'blueberry',
62
- ]}
64
+ keywords={['violet', 'roses', 'blueberry']}
63
65
  items={[
64
66
  {
65
- 'name': 'Flatwhite',
66
- 'value': 4.00,
67
- 'currency': 'AUD',
68
- 'quantity': 2,
69
- 'type': 'coffee',
70
- 'category': 'drinks',
71
- 'subcategory': 'australian-coffee',
67
+ name: 'Flatwhite',
68
+ value: 4.0,
69
+ currency: 'AUD',
70
+ quantity: 2,
71
+ type: 'coffee',
72
+ category: 'drinks',
73
+ subcategory: 'australian-coffee',
72
74
  },
73
75
  ]}
74
- categories={[
75
- 'lifestyle',
76
- ]}
77
- />;
76
+ categories={['lifestyle']}
77
+ />
78
78
  ```
79
79
 
80
+ ## Indirect usage
81
+ Sometimes an event-based solution is easier to manage, in thie case we handle some state management for you.
82
+ ```tsx
83
+ import { ThanksWidgetController, thanksWidget } from '@thanksjs/react-native';
84
+
85
+ const YourApplication = () => (
86
+ <>
87
+ {someCode}
88
+ // put AFTER all other views, so it will be displayed on top
89
+ <ThanksWidgetController partnerId="your-id"/>
90
+ </>
91
+ )
92
+
93
+ const YourThanksPage = () => {
94
+ useEffect(() => {
95
+ // ThanksWidgetController will render Widget instantly
96
+ // if ThanksWidgetController is not present this will throw an error
97
+ thanksWidget.open(thanksConfiguration);
98
+
99
+ // and hide when you navigate away from the page
100
+ return () => thanksWidget.close();
101
+ }, [
102
+ // important to keep dependencies free to prevent re-rendering widget
103
+ // as customer's journey will be reset
104
+ ]);
105
+
106
+ return pageCode;
107
+ }
108
+
80
109
  ## Managing Personal Information
81
- By default, Thanks Widget does not send any personal information.
82
- The `email` specified in configuration is always converted into sha256 `emailHash` before being sent to server.
83
- All other extended information provided is used only to improve the efficiency of the widget and is not stored unless user performs an action.
84
- In such case the information will kept until the action is settled, but no longer than 60 days.
110
+
111
+ By default, Thanks Widget does not send any personal information. The `email` specified in configuration is always
112
+ converted into sha256 `emailHash` before being sent to server. All other extended information provided is used only to
113
+ improve the efficiency of the widget and is not stored unless user performs an action. In such case the information will
114
+ kept until the action is settled, but no longer than 60 days.
85
115
 
86
116
  However, there are situations when we need Partner to provide Personal Information:
117
+
87
118
  - to improve our communications and send email notification to the user following their actions
88
119
  - prefill a form with user's data to ease their interactions
89
120
 
90
- In both case we are going to call `onPersonalInformationRequest` function with `subject` and `info` arguments.
91
- Depending on request you may decide to return some information, or return nothing.
121
+ In both case we are going to call `onPersonalInformationRequest` function with `subject` and `info` arguments. Depending
122
+ on request you may decide to return some information, or return nothing.
123
+
92
124
  ```tsx
93
- onPersonalInformationRequest: (subject:'notification' | 'autofill', info) => {
125
+ onPersonalInformationRequest: (subject: 'notification' | 'autofill', info) => {
94
126
  return {
95
127
  email,
96
128
  firstName: 'TestUser',
97
129
  };
98
- }
130
+ };
99
131
  ```
100
- - subject of type `notification` will be used to send email notification to the user about the action just taken, for example coupon code they just claimed
101
- - subject of type `autofill` will be used to prefill a form with user's data, making the subscription process friction less
102
132
 
103
- In case of `onPersonalInformationRequest` is not defined, but `email` is provided as a part of configuraiton - nothing will happen.
104
- The process of capturing PII information is always in the Partners hands.
133
+ - subject of type `notification` will be used to send email notification to the user about the action just taken, for
134
+ example coupon code they just claimed
135
+ - subject of type `autofill` will be used to prefill a form with user's data, making the subscription process friction
136
+ less
105
137
 
106
- 💡It's not always known upfront if PII is required, so `onPersonalInformationRequest` will be called more often than PII information is being "consumed".
107
- In case it was not required, the information will be discarded.
138
+ In case of `onPersonalInformationRequest` is not defined, but `email` is provided as a part of configuraiton - nothing
139
+ will happen. The process of capturing PII information is always in the Partners hands.
140
+
141
+ 💡It's not always known upfront if PII is required, so `onPersonalInformationRequest` will be called more often than PII
142
+ information is being "consumed". In case it was not required, the information will be discarded.
108
143
 
109
144
  ### Using PII information for Promotions
110
- While not every Ad requires PII, some Ads can have a "Promotion" attached to them,
111
- for example "Subscribe to XYZ newsletter to enter the draw".
112
- In case of user action PII information might not be used by a particular Ad, but will be used by Promotion to keep track of participation.
113
- The information will be redacted after the Promotion ends.
145
+
146
+ While not every Ad requires PII, some Ads can have a "Promotion" attached to them, for example "Subscribe to XYZ
147
+ newsletter to enter the draw". In case of user action PII information might not be used by a particular Ad, but will be
148
+ used by Promotion to keep track of participation. The information will be redacted after the Promotion ends.
114
149
 
115
150
  # License
151
+
116
152
  MIT
package/dist/esm/index.js CHANGED
@@ -1,3 +1,28 @@
1
- var W="INIT_TUNNEL",k="TUNNEL_READY",E="rocket-seed";var w=e=>typeof e=="object"&&"seed"in e&&e.seed===E&&"cmd"in e?e:{error:!0},D=(e,r)=>({cmd:e,payload:r,seed:E}),M=(e,r,t)=>{(e[r]||[]).forEach(o=>o(t))};var v=(e,r)=>{let t={},o=!1,c=n=>{let{cmd:i,payload:a,error:d}=w(n);d?console.log("error decoding event",n,d):M(t,i,a)};return{on(n,i){(t[n]=t[n]||[]).push(i)},isReady(){return o},pushMessage:n=>{let{cmd:i,payload:a,error:d}=w(n);if(o){c(n);return}!d&&i===W&&a===e&&(o=!0,M(t,k,void 0))},send(n,i){if(!o)throw new Error("trying to `send` into non initialized tunnel");r(D(n,i))}}};var U=e=>{let r=Object.entries(e).filter(([t,o])=>!!o);return Object.fromEntries(r)},_=(e,r={})=>{let t={...r};return t.__forceAd=e.__forceAd,t.impressionId=e.impressionId,new URLSearchParams(U(t)).toString()},A=(e="production")=>e==="development"?"http://localhost:8081/":e==="staging"?"https://thanksad.dev/":"https://thanks.is/";var R={xs:360,sm:768,md:1024,lg:1200,xl:1350};var V=()=>typeof window>"u"||window.innerWidth>=R.sm?"desktop":"mobile";var j=e=>Array.from(new Uint8Array(e)).map(r=>r.toString(16).padStart(2,"0")).join("");var N=async e=>{if(!e)return;let r=new TextEncoder().encode(e);return j(await crypto.subtle.digest("SHA-256",r))};var B=async(e,r)=>{let t=e?await(typeof e=="function"?e({encode:N}):N(e)):"";return Object.assign({sha256:t},r)};var G=async e=>{let{partnerId:r,email:t,userId:o,traceId:c=o,keywords:p,items:n,flags:i={},style:a}=e,{switches:d,...x}=i,l=(await B(t,e.emailHash)).sha256;return _(x,{partnerId:r,emailHash:l,traceId:c,deviceMode:V(),keywords:p?p.join(","):void 0,items:JSON.stringify(n),embedTheme:a?.embed?.theme})},S=async(e,r)=>`${A(r)}?${await G(e)}`;import"react";import{useCallback as C,useEffect as I,useRef as xe,useState as b}from"react";import{Modal as Ce,Linking as be}from"react-native";import{WebView as Ee}from"react-native-webview";import{View as K,Modal as Z}from"react-native";import Te from"react-native-webview";import"react";import{Text as J,View as Y,TouchableOpacity as Q}from"react-native";var O=({onBack:e})=><Y style={{height:150,justifyContent:"center",alignItems:"flex-end",backgroundColor:"#000",width:"100%"}}><Q onPress={e}><J style={{color:"#FFF"}}>Close</J></Q></Y>;import{Component as X}from"react";var T=class extends X{state={error:null};static getDerivedStateFromError(r){return{error:r}}componentDidCatch(r,t){this.props.onError(r,t.componentStack)}render(){return this.state.error?null:this.props.children}};var L=({uri:e,onClose:r})=><T onError={r}><Z animationType="slide"onRequestClose={r}><K style={{flex:1,justifyContent:"center",alignItems:"center",display:"flex",flexDirection:"column"}}><O onBack={r}/><Te source={{uri:e}}onError={t=>{console.error("visible page error",t),r()}}onContentProcessDidTerminate={t=>{console.error("visible page terminate",t),r()}}onRenderProcessGone={t=>{console.error("visible render gone",t),r()}}style={{flex:1}}/><O onBack={r}/></K></Z></T>;var we=`
1
+ var D="INIT_TUNNEL",w="TUNNEL_READY",v="rocket-seed";var M=e=>typeof e=="object"&&"seed"in e&&e.seed===v&&"cmd"in e?e:{error:!0},_=(e,n)=>({cmd:e,payload:n,seed:v}),P=(e,n,r)=>{(e[n]||[]).forEach(t=>t(r))};var S=(e,n)=>{let r={},t=!1,c=o=>{let{cmd:i,payload:d,error:s}=M(o);s?console.log("error decoding event",o,s):P(r,i,d)};return{on(o,i){(r[o]=r[o]||[]).push(i)},isReady(){return t},pushMessage:o=>{let{cmd:i,payload:d,error:s}=M(o);if(t){c(o);return}!s&&i===D&&d===e&&(t=!0,P(r,w,void 0))},send(o,i){if(!t)throw new Error("trying to `send` into non initialized tunnel");n(_(o,i))}}};var R={xs:360,sm:768,md:1024,lg:1200,xl:1350};var A=()=>typeof window>"u"||window.innerWidth>=R.sm?"desktop":"mobile";var V=(e="production")=>e==="development"?"http://localhost:8081/":e==="staging"?"https://thanksad.dev/":"https://thanks.is/";var L=e=>e?e.join(",").toLowerCase():void 0;var $=e=>Array.from(new Uint8Array(e)).map(n=>n.toString(16).padStart(2,"0")).join("");var N=async e=>{if(!e)return;let n=new TextEncoder().encode(e);return $(await crypto.subtle.digest("SHA-256",n))};var j=async(e,n)=>{let r=e?await(typeof e=="function"?e({encode:N}):N(e)):"";return Object.assign({sha256:r},n)};var J=e=>{let n=Object.entries(e).filter(([r,t])=>!!t);return Object.fromEntries(n)},B=(e,n={})=>{let r={...n};return r.__forceAd=e.__forceAd,r.impressionId=e.impressionId,new URLSearchParams(J(r))};var K=async e=>{let{partnerId:n,email:r,userId:t,traceId:c=t,keywords:l,items:o,flags:i={},style:d}=e,{switches:s,...x}=i,m=(await j(r,e.emailHash)).sha256;return B(x,{partnerId:n,emailHash:m,traceId:c,deviceMode:A(),keywords:L(l),items:JSON.stringify(o),embedTheme:d?.embed?.theme,source:i.taint||"popup"})},I=async(e,n)=>`${V(n)}?${await K(e)}`;import"react";import{useCallback as C,useEffect as E,useRef as ke,useState as b}from"react";import{Modal as Ee,Linking as ve}from"react-native";import{WebView as Me}from"react-native-webview";import{View as Z,Modal as Te}from"react-native";import{WebView as Ce}from"react-native-webview";import"react";import{Text as Y,View as Q,TouchableOpacity as X}from"react-native";var O=({onBack:e})=><Q style={{height:150,justifyContent:"center",alignItems:"flex-end",backgroundColor:"#000",width:"100%"}}>
2
+ <X onPress={e}>
3
+ <Y style={{color:"#FFF"}}>Close</Y>
4
+ </X>
5
+ </Q>;import{Component as z}from"react";var T=class extends z{state={error:null};static getDerivedStateFromError(n){return{error:n}}componentDidCatch(n,r){this.props.onError(n,r.componentStack)}render(){return this.state.error?null:this.props.children}};var F=({uri:e,onClose:n})=><T onError={n}>
6
+ <Te animationType="slide"onRequestClose={n}>
7
+ <Z style={{flex:1,justifyContent:"center",alignItems:"center",display:"flex",flexDirection:"column"}}>
8
+ <O onBack={n}/>
9
+
10
+ <Ce source={{uri:e}}onError={r=>{console.error("visible page error",r),n()}}onContentProcessDidTerminate={r=>{console.error("visible page terminate",r),n()}}onRenderProcessGone={r=>{console.error("visible render gone",r),n()}}style={{flex:1}}/>
11
+
12
+ <O onBack={n}/>
13
+ </Z>
14
+ </Te>
15
+ </T>;var Pe=`
2
16
  window.onerror = (e) => { console.error(e); window.ReactNativeWebView.postMessage({cmd: 'error', payload: e.message});}
3
- `,Me=({uri:e,animationType:r="slide",thanks:t,onClose:o,onLinkClick:c,children:p})=>{let n=xe(),i=C(s=>{n.current=s},[]),[a,d]=b("idle"),x=C(()=>{d("closed")},[]),l=C(()=>{d("complete")},[]),[m]=b(()=>v("rocket",$=>{n.current?.injectJavaScript(`window.messageToThanks(${JSON.stringify($)});`)})),F=C(s=>{m.pushMessage(JSON.parse(s.nativeEvent.data))},[]),[P,H]=b();return I(()=>(m.on(k,()=>{m.send("init",{mode:"mobile",topOffset:t.offsetTop?.(),statusText:t.statusText,referral:"react-native"}),d("active"),t.onDisplay?.()}),m.on("close",()=>{x()}),m.on("terminate",()=>{l()}),m.on("click",s=>{(!c||c(s))&&be.openURL(s)}),()=>{m.isReady()&&m.send("close"),t.onClose?.()}),[]),I(()=>{a==="complete"&&o()},[a]),a==="complete"?null:<T onError={x}><Ce onRequestClose={x}animationType={r}transparent><Ee ref={i}source={{uri:e,headers:{referer:"https://react-native","x-thanksjs-integration-mode":"react-native"}}}onMessage={F}onError={s=>{console.error("page error",s),l()}}onContentProcessDidTerminate={s=>{console.error("page terminate",s),l()}}onRenderProcessGone={s=>{console.error("render gone",s),l()}}onLoad={s=>{}}style={{flex:1,backgroundColor:"transparent"}}webviewDebuggingEnabled injectedJavaScript={we}/>{P?<L uri={P}onClose={()=>H(void 0)}/>:null}{p}</Ce></T>},br=({onLinkClick:e,onClose:r,env:t="production",animationType:o,children:c,...p})=>{let[n,i]=b();I(()=>{S(p,t).then(d=>{i(d)})},[]);let a=C(()=>{i(void 0),r?.()},[]);return n?<Me uri={n}thanks={p}onClose={a}onLinkClick={e}animationType={o}>{c}</Me>:null};export{br as ThanksWidget};
17
+ // if you ever need a debug
18
+ // window.console.error = (...args) => { alert(...args);}
19
+ `,Se=({uri:e,animationType:n="slide",thanks:r,onClose:t,onLinkClick:c,children:l})=>{let o=ke(),i=C(a=>{o.current=a},[]),[d,s]=b("idle"),x=C(()=>{s("closed")},[]),m=C(()=>{s("complete")},[]),[p]=b(()=>S("rocket",G=>{o.current?.injectJavaScript(`window.messageToThanks(${JSON.stringify(G)});`)})),H=C(a=>{p.pushMessage(JSON.parse(a.nativeEvent.data))},[]),[W,U]=b();return E(()=>(p.on(w,()=>{p.send("init",{mode:"mobile",topOffset:r.offsetTop?.(),statusText:r.statusText,referral:"react-native"}),s("active"),r.onDisplay?.()}),p.on("close",()=>{x()}),p.on("terminate",()=>{m()}),p.on("click",a=>{(!c||c(a))&&ve.openURL(a)}),()=>{p.isReady()&&p.send("close"),r.onClose?.()}),[]),E(()=>{d==="complete"&&t()},[d]),d==="complete"?null:<T onError={x}>
20
+ <Ee onRequestClose={x}animationType={n}transparent>
21
+ <Me ref={i}source={{uri:e,headers:{referer:"https://react-native","x-thanksjs-integration-mode":"react-native"}}}onMessage={H}onError={a=>{console.error("page error",a),m()}}onContentProcessDidTerminate={a=>{console.error("page terminate",a),m()}}onRenderProcessGone={a=>{console.error("render gone",a),m()}}onLoad={a=>{}}style={{flex:1,backgroundColor:"transparent"}}webviewDebuggingEnabled injectedJavaScript={Pe}/>
22
+
23
+ {W?<F uri={W}onClose={()=>U(void 0)}/>:null}
24
+ {l}
25
+ </Ee>
26
+ </T>},Re=({onLinkClick:e,onClose:n,env:r="production",animationType:t,children:c,...l})=>{let[o,i]=b();E(()=>{I(l,r).then(s=>{i(s)}).catch(s=>{throw console.error(s),s})},[]);let d=C(()=>{i(void 0),n?.()},[]);return o?<Se uri={o}thanks={l}onClose={d}onLinkClick={e}animationType={t}>
27
+ {c}
28
+ </Se>:null},k,In={open:(e={})=>{if(!k)throw new Error("ThanksWidgetController not found on the page");k(e)},close:()=>{if(!k)throw new Error("ThanksWidgetController not found on the page");k(void 0)}},On=e=>{let[n,r]=b(void 0);k=r;let t={...e,...n};E(()=>()=>{k=void 0},[]);let c=C(()=>{t.onClose?.(),r(void 0)},[t.onClose]);return n?<Re{...t}onClose={c}/>:null};export{Re as ThanksWidget,On as ThanksWidgetController,In as thanksWidget};
@@ -75,7 +75,11 @@ declare type ThanksEmbedConfiguration = ThanksSharedConfiguration & {
75
75
  * specifies an element for embedded widget
76
76
  * this option will suppress automatic widget Display
77
77
  */
78
- embeddedInto: HTMLElement;
78
+ embeddedInto:
79
+ | HTMLElement
80
+ | HTMLElement[]
81
+ | (() => HTMLElement | HTMLElement[]);
82
+ slot?: string | undefined;
79
83
  };
80
84
 
81
85
  declare type ThanksLocation = {
@@ -83,6 +87,8 @@ declare type ThanksLocation = {
83
87
  postcode?: string;
84
88
  };
85
89
 
90
+ declare type ThanksProps = Omit<ThanksConfiguration, 'partnerId'> & Pick<Required<ThanksConfiguration>, 'partnerId'> & ThanksCallbacks & ThanksStyleProps;
91
+
86
92
  /**
87
93
  * A configuration options for the Thanks widget
88
94
  * @public
@@ -202,6 +208,17 @@ declare type ThanksSharedConfiguration = {
202
208
  */
203
209
  closeWidget?(): void;
204
210
 
211
+ /**
212
+ * a command available to the user.
213
+ * opens Widget using current _thanks settings
214
+ */
215
+ openWidget?(): void;
216
+
217
+ /**
218
+ * callback on thanksAPI ready
219
+ */
220
+ onReady?(api: ThanksSharedConfiguration): void;
221
+
205
222
 
206
223
  };
207
224
 
@@ -221,8 +238,47 @@ export declare type ThanksStyleProps = {
221
238
  *
222
239
  * @public ThanksWidget itself
223
240
  */
224
- export declare const ThanksWidget: FC<Omit<ThanksConfiguration, 'partnerId'> & Pick<Required<ThanksConfiguration>, 'partnerId'> & ThanksCallbacks & ThanksStyleProps & PropsWithChildren>;
241
+ export declare const ThanksWidget: FC<ThanksProps & PropsWithChildren>;
242
+
243
+ /**
244
+ * To be used only with {@link ThanksWidgetController}.
245
+ *
246
+ * Provides external control over ThanksWidget.
247
+ * Both ThanksWidgetController and thanksWidget.open can take settings with thanksWidget overriding values provided to ThanksWidgetController
248
+ * @public Indirect API for ThanksAd
249
+ * @example
250
+ * ```tsx
251
+ * // in some place
252
+ * <ThanksWidgetController partnerId="id" {...props}/>
253
+ *
254
+ * // in some other place
255
+ * thanksWidget.open({...propsOverride})
256
+ * thanksWidget.open()
257
+ * ```
258
+ */
259
+ export declare const thanksWidget: {
260
+ open: (configuration?: Partial<ThanksProps>) => void;
261
+ close: () => void;
262
+ };
225
263
 
226
264
  declare type ThanksWidgetConfiguration = ThanksSharedConfiguration;
227
265
 
266
+ /**
267
+ * To be used only with {@link thanksWidget}.
268
+ *
269
+ * Provides external control over ThanksWidget.
270
+ * Both ThanksWidgetController and thanksWidget.open can take settings with thanksWidget overriding values provided to ThanksWidgetController
271
+ * @public Indirect API for ThanksAd
272
+ * @example
273
+ * ```tsx
274
+ * // in some place
275
+ * <ThanksWidgetController partnerId="id" {...props}/>
276
+ *
277
+ * // in some other place
278
+ * thanksWidget.open({...propsOverride})
279
+ * thanksWidget.open()
280
+ * ```
281
+ */
282
+ export declare const ThanksWidgetController: FC<ThanksProps>;
283
+
228
284
  export { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thanksjs/react-native-webview",
3
- "version": "0.0.1-beta.1",
3
+ "version": "1.1.0",
4
4
  "description": "ThanksJS React Native WebView",
5
5
  "homepage": "https://thanks.co/",
6
6
  "license": "MIT",