@parafin/react 6.4.1 → 7.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/out/index.d.ts CHANGED
@@ -1,58 +1,3 @@
1
+ import { LinkOpenedMetadata, WidgetProps, WidgetEvent, WidgetEventMetadata } from '@parafin/core';
1
2
  declare const ParafinWidget: (props: WidgetProps) => import("react/jsx-runtime").JSX.Element;
2
- export { ParafinWidget };
3
- export type WidgetEvent = 'opted_in' | 'opted_out';
4
- export type LinkOpenedMetadata = {
5
- type: 'auth' | 'document' | 'webpage' | 'phone' | 'email';
6
- };
7
- export type WidgetProps = {
8
- token: string;
9
- product: 'capital' | 'spend_card' | 'cash_account';
10
- externalBusinessId?: string;
11
- onEvent?: (eventType: WidgetEvent) => Promise<void> | void;
12
- onExit?: () => void;
13
- /** @deprecated Use onEvent with 'opted_in' event type instead */
14
- onOptIn?: () => Promise<OptInFields>;
15
- openInNewTab?: boolean;
16
- onLinkOpened?: (url: string, metadata: LinkOpenedMetadata) => void;
17
- inWebView?: boolean;
18
- };
19
- type USStates = 'AL' | 'AK' | 'AZ' | 'AR' | 'CA' | 'CO' | 'CT' | 'DE' | 'DC' | 'FL' | 'GA' | 'HI' | 'ID' | 'IL' | 'IN' | 'IA' | 'KS' | 'KY' | 'LA' | 'ME' | 'MD' | 'MA' | 'MI' | 'MN' | 'MS' | 'MO' | 'MT' | 'NE' | 'NV' | 'NH' | 'NJ' | 'NM' | 'NY' | 'NC' | 'ND' | 'OH' | 'OK' | 'OR' | 'PA' | 'RI' | 'SC' | 'SD' | 'TN' | 'TX' | 'UT' | 'VT' | 'VA' | 'WA' | 'WV' | 'WI' | 'WY';
20
- type USTerritories = 'AS' | 'GU' | 'MP' | 'PR' | 'VI';
21
- type CanadianProvinces = 'AB' | 'BC' | 'MB' | 'NB' | 'NL' | 'NS' | 'QC' | 'ON' | 'PE' | 'SK';
22
- type CanadianTerritories = 'NT' | 'NU' | 'YT';
23
- type Address = {
24
- addressLine1: string;
25
- addressLine2?: string;
26
- city: string;
27
- state: USStates | USTerritories | CanadianProvinces | CanadianTerritories;
28
- postalCode: string;
29
- country: 'US' | 'CA';
30
- };
31
- export type OptInFields = {
32
- businessExternalId: string;
33
- accountManagers?: {
34
- name: string;
35
- email: string;
36
- }[];
37
- owner: {
38
- firstName: string;
39
- lastName: string;
40
- email: string;
41
- phoneNumber?: string;
42
- /** yyyy-mm-dd */
43
- dateOfBirth?: string;
44
- address?: Address;
45
- };
46
- business: {
47
- legalName: string;
48
- dbaName?: string;
49
- address?: Address;
50
- /** yyyy-mm-dd */
51
- dateEstablished?: string;
52
- };
53
- bank?: {
54
- routingNumber?: string;
55
- accountNumberLastFour?: string;
56
- currencyCode?: 'USD' | 'CAD';
57
- };
58
- };
3
+ export { ParafinWidget, type WidgetEvent, type WidgetEventMetadata, type WidgetProps, type LinkOpenedMetadata, };
package/out/index.js CHANGED
@@ -7,33 +7,41 @@ const openParafinDashboard = (props) => {
7
7
  // @ts-ignore
8
8
  props.dashboardUrlOverride ?? 'https://app.parafin.com');
9
9
  const route = 'route' in props ? props.route : '/';
10
- const addPropIfExists = (key) => {
11
- if (key in props && props[key] !== undefined && props[key] !== null) {
12
- return { [key]: props[key] };
13
- }
14
- else {
15
- return {};
16
- }
17
- };
18
10
  const query = {
19
11
  product: props.product,
20
12
  referrer: 'partner',
21
- ...addPropIfExists('token'),
22
- ...addPropIfExists('partner'),
23
- ...addPropIfExists('externalBusinessId'),
24
- ...addPropIfExists('orderId'),
25
- ...addPropIfExists('lineOfCreditApplicationId'),
26
- ...addPropIfExists('inWebView'),
13
+ ...('token' in props &&
14
+ props.token !== undefined &&
15
+ props.token !== null && { token: props.token }),
16
+ ...('partner' in props &&
17
+ props.partner !== undefined &&
18
+ props.partner !== null && { partner: props.partner }),
19
+ ...('externalBusinessId' in props &&
20
+ props.externalBusinessId !== undefined &&
21
+ props.externalBusinessId !== null && {
22
+ externalBusinessId: props.externalBusinessId,
23
+ }),
24
+ ...('orderId' in props &&
25
+ props.orderId !== undefined &&
26
+ props.orderId !== null && { orderId: props.orderId }),
27
+ ...('lineOfCreditApplicationId' in props &&
28
+ props.lineOfCreditApplicationId !== undefined &&
29
+ props.lineOfCreditApplicationId !== null && {
30
+ lineOfCreditApplicationId: props.lineOfCreditApplicationId,
31
+ }),
32
+ ...('inWebView' in props &&
33
+ props.inWebView !== undefined &&
34
+ props.inWebView !== null && { inWebView: props.inWebView.toString() }),
27
35
  ...Object.fromEntries(searchParams),
28
36
  };
29
37
  const url = `${origin}${route}?${new URLSearchParams(query).toString()}`;
30
38
  if ('openInNewTab' in props && props.openInNewTab) {
31
39
  window.open(url, '_blank');
32
- return;
40
+ return () => { }; // noop
33
41
  }
34
42
  if ('mode' in props && props.mode === 'redirect') {
35
43
  window.location.href = url;
36
- return;
44
+ return () => { }; // noop
37
45
  }
38
46
  const existingParafinDashboard = document.getElementById('parafin-dashboard');
39
47
  if (existingParafinDashboard) {
@@ -72,17 +80,25 @@ const openParafinDashboard = (props) => {
72
80
  props.onExit?.();
73
81
  }
74
82
  };
83
+ let cleanedUp = false;
84
+ const cleanup = ({ withOnExit }) => {
85
+ if (cleanedUp)
86
+ return; // noop
87
+ cleanedUp = true;
88
+ window.removeEventListener('message', messageListener);
89
+ frame.style.opacity = '0';
90
+ setTimeout(() => {
91
+ if (withOnExit)
92
+ onExit();
93
+ dashboardTargetElement.removeChild(frame);
94
+ document.body.style.removeProperty('overflow');
95
+ }, 200);
96
+ };
75
97
  const messageListener = async (event) => {
76
98
  if (event.origin === origin) {
77
99
  switch (event.data?.message) {
78
100
  case 'close-dashboard':
79
- window.removeEventListener('message', messageListener);
80
- frame.style.opacity = '0';
81
- setTimeout(() => {
82
- onExit();
83
- dashboardTargetElement.removeChild(frame);
84
- document.body.style.removeProperty('overflow');
85
- }, 200);
101
+ cleanup({ withOnExit: true });
86
102
  break;
87
103
  case 'link-opened':
88
104
  if (props.onLinkOpened && event.data?.url && event.data?.metadata) {
@@ -97,20 +113,33 @@ const openParafinDashboard = (props) => {
97
113
  setTimeout(() => {
98
114
  frame.style.opacity = '1';
99
115
  document.body.style.overflow = 'hidden';
100
- }, 1);
116
+ }, 0);
117
+ return () => cleanup({ withOnExit: false });
101
118
  }
102
119
  catch (error) {
103
120
  console.error('Error loading Parafin dashboard', error);
121
+ return () => { }; // noop
104
122
  }
105
123
  };
106
-
107
- const initializeWidget = (iframe, props) => {
124
+ const defaultWidgetStyles = {
125
+ width: '100%',
126
+ height: '258px',
127
+ backgroundColor: '#fff',
128
+ border: '1px solid #E8E8E8',
129
+ borderRadius: '16px',
130
+ transition: 'border 0.2s, border-radius 0.2s',
131
+ boxSizing: 'border-box',
132
+ };
133
+ const emptyMetadata = {
134
+ timeToLoadInMs: null,
135
+ };
136
+ const initializeParafinWidget = (iframe, props) => {
137
+ const initStartTime = Date.now();
108
138
  // @ts-ignore
109
139
  const url = new URL(props.widgetUrlOverride ?? 'https://widget.parafin.com');
110
140
  const query = {
111
141
  token: props.token,
112
142
  product: props.product,
113
- hasOptIn: props.onOptIn ? 'true' : 'false',
114
143
  host: window.location.origin,
115
144
  externalBusinessId: props.externalBusinessId ?? '',
116
145
  ...Object.fromEntries(url.searchParams),
@@ -133,6 +162,9 @@ const initializeWidget = (iframe, props) => {
133
162
  }
134
163
  break;
135
164
  case 'open-dashboard':
165
+ if (props.onEvent) {
166
+ props.onEvent('dashboard_opened', emptyMetadata);
167
+ }
136
168
  openParafinDashboard({
137
169
  ...props,
138
170
  route: data?.route,
@@ -142,24 +174,10 @@ const initializeWidget = (iframe, props) => {
142
174
  },
143
175
  });
144
176
  break;
145
- case 'opt-in':
146
- if (props.onOptIn) {
147
- try {
148
- const optInFields = await props.onOptIn();
149
- sendMessage({ message: 'opt-in', optInFields });
150
- }
151
- catch {
152
- sendMessage({ message: 'opt-in', optInFields: undefined });
153
- }
154
- }
155
- else {
156
- sendMessage({ message: 'opt-in', optInFields: undefined });
157
- }
158
- break;
159
177
  case 'person-opt-in':
160
178
  if (props.onEvent) {
161
179
  try {
162
- await props.onEvent('opted_in');
180
+ await props.onEvent('opted_in', emptyMetadata);
163
181
  sendMessage({ message: 'person-opt-in', state: 'success' });
164
182
  }
165
183
  catch {
@@ -173,7 +191,7 @@ const initializeWidget = (iframe, props) => {
173
191
  case 'person-opt-out':
174
192
  if (props.onEvent) {
175
193
  try {
176
- await props.onEvent('opted_out');
194
+ await props.onEvent('opted_out', emptyMetadata);
177
195
  sendMessage({ message: 'person-opt-out', state: 'success' });
178
196
  }
179
197
  catch {
@@ -189,27 +207,29 @@ const initializeWidget = (iframe, props) => {
189
207
  iframe.style.height = data.height;
190
208
  }
191
209
  break;
210
+ case 'widget-error':
211
+ if (props.onEvent) {
212
+ props.onEvent('widget_error', emptyMetadata);
213
+ }
214
+ break;
215
+ case 'widget-load-complete':
216
+ if (props.onEvent) {
217
+ const timeToLoadInMs = Date.now() - initStartTime;
218
+ props.onEvent('widget_loaded', { timeToLoadInMs });
219
+ }
220
+ break;
192
221
  }
193
222
  }
194
223
  };
195
224
  window.addEventListener('message', messageListener);
196
225
  return () => window.removeEventListener('message', messageListener);
197
226
  };
198
- const defaultWidgetStyles = {
199
- width: '100%',
200
- height: '258px',
201
- backgroundColor: '#fff',
202
- border: '1px solid #E8E8E8',
203
- borderRadius: '16px',
204
- transition: 'border 0.2s, border-radius 0.2s',
205
- boxSizing: 'border-box',
206
- };
207
227
 
208
228
  const ParafinWidget = (props) => {
209
229
  const frameRef = useRef(null);
210
230
  useEffect(() => {
211
231
  if (frameRef.current) {
212
- const cleanup = initializeWidget(frameRef.current, props);
232
+ const cleanup = initializeParafinWidget(frameRef.current, props);
213
233
  return cleanup;
214
234
  }
215
235
  }, [props]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parafin/react",
3
- "version": "6.4.1",
3
+ "version": "7.1.0",
4
4
  "description": "Parafin React widget",
5
5
  "author": "Parafin (https://www.parafin.com)",
6
6
  "module": "out/index.js",
@@ -23,8 +23,9 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/react": ">=16.8.0",
26
- "typescript": "^4.9.5",
27
- "@parafin/widget": "*"
26
+ "typescript": "^4.9.5"
28
27
  },
29
- "dependencies": {}
28
+ "dependencies": {
29
+ "@parafin/core": "^3.1.0"
30
+ }
30
31
  }