@createlex/onetapforms-sdk 1.0.0 → 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 +100 -1
- package/dist/index.esm.js +129 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +129 -0
- package/dist/index.js.map +1 -1
- package/dist/onetapforms.d.ts +22 -0
- package/dist/types.d.ts +2 -0
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
OneTapForms SDK for secure, biometric-authenticated form completion. This SDK enables websites to offer instant form completion through Face ID/Touch ID authentication on iOS devices.
|
|
4
4
|
|
|
5
|
+
## 🆓 Free for Developers
|
|
6
|
+
|
|
7
|
+
**The SDK is completely free to use!** There are no fees, usage limits, or restrictions for developers integrating OneTapForms into their websites.
|
|
8
|
+
|
|
9
|
+
### Why Developers Love OneTapForms
|
|
10
|
+
|
|
11
|
+
Integrating OneTapForms benefits your business directly:
|
|
12
|
+
|
|
13
|
+
- ⚡ **Faster Form Completion** - Users fill forms in seconds instead of minutes
|
|
14
|
+
- 📈 **Higher Conversion Rates** - Reduce form abandonment with one-tap completion
|
|
15
|
+
- 🎯 **Better User Experience** - Eliminate typing errors and friction
|
|
16
|
+
- 🔒 **Verified Data** - Receive pre-verified, accurate user information
|
|
17
|
+
- 💰 **No Cost to You** - Free SDK, zero integration fees
|
|
18
|
+
|
|
19
|
+
**Encourage your users to download the OneTapForms app** - it helps them complete your forms faster, which means more completed applications, signups, and conversions for you!
|
|
20
|
+
|
|
21
|
+
Revenue comes from end users who subscribe to the OneTapForms service ($9-29/month) to securely store their profile data. Your users pay for the convenience, not you.
|
|
22
|
+
|
|
5
23
|
## Installation
|
|
6
24
|
|
|
7
25
|
```bash
|
|
@@ -49,6 +67,25 @@ await onetapforms.request({
|
|
|
49
67
|
});
|
|
50
68
|
```
|
|
51
69
|
|
|
70
|
+
### 2.5. Encourage App Downloads (Optional but Recommended)
|
|
71
|
+
|
|
72
|
+
Help users discover OneTapForms to get faster form completion:
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// Show download prompt if user doesn't have the app
|
|
76
|
+
if (!onetapforms.isAppLikelyInstalled()) {
|
|
77
|
+
onetapforms.showDownloadPrompt({
|
|
78
|
+
title: 'Complete Forms Faster!',
|
|
79
|
+
message: 'Download OneTapForms to fill this form in seconds with Face ID/Touch ID.',
|
|
80
|
+
buttonText: 'Download App'
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Or add a download button to your UI
|
|
85
|
+
const downloadUrl = onetapforms.getAppDownloadUrl();
|
|
86
|
+
// <a href={downloadUrl}>Download OneTapForms App</a>
|
|
87
|
+
```
|
|
88
|
+
|
|
52
89
|
### 3. Handle Mobile Redirect Callback
|
|
53
90
|
|
|
54
91
|
If using redirect mode on mobile, handle the callback:
|
|
@@ -134,6 +171,39 @@ Exchanges token for user data. **Note:** This should be called server-side, not
|
|
|
134
171
|
|
|
135
172
|
**Returns:** `Promise<any>` - User data object
|
|
136
173
|
|
|
174
|
+
### `getAppDownloadUrl()`
|
|
175
|
+
|
|
176
|
+
Returns the App Store URL for downloading the OneTapForms app. Use this to encourage users to download the app.
|
|
177
|
+
|
|
178
|
+
**Returns:** `string` - App Store URL
|
|
179
|
+
|
|
180
|
+
### `showDownloadPrompt(options?)`
|
|
181
|
+
|
|
182
|
+
Shows a modal prompt encouraging users to download the OneTapForms app. This helps developers get faster form completion and better conversion rates.
|
|
183
|
+
|
|
184
|
+
**Parameters:**
|
|
185
|
+
- `options.title` (string, optional): Custom title for the prompt
|
|
186
|
+
- `options.message` (string, optional): Custom message
|
|
187
|
+
- `options.buttonText` (string, optional): Custom button text
|
|
188
|
+
- `options.onDismiss` (function, optional): Callback when user dismisses the prompt
|
|
189
|
+
|
|
190
|
+
**Example:**
|
|
191
|
+
```javascript
|
|
192
|
+
// Show download prompt to encourage app downloads
|
|
193
|
+
onetapforms.showDownloadPrompt({
|
|
194
|
+
title: 'Complete Forms Faster!',
|
|
195
|
+
message: 'Download OneTapForms to fill forms in seconds with Face ID.',
|
|
196
|
+
buttonText: 'Download Now',
|
|
197
|
+
onDismiss: () => console.log('User dismissed prompt')
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `isAppLikelyInstalled()`
|
|
202
|
+
|
|
203
|
+
Checks if the user likely has the OneTapForms app installed (iOS device detection).
|
|
204
|
+
|
|
205
|
+
**Returns:** `boolean` - True if on iOS device
|
|
206
|
+
|
|
137
207
|
## Request Modes
|
|
138
208
|
|
|
139
209
|
### Auto Mode (Default)
|
|
@@ -155,9 +225,38 @@ Before using the SDK, you must register as a client:
|
|
|
155
225
|
2. Provide your company name and allowed callback URLs
|
|
156
226
|
3. Receive your `clientId` and `clientSecret` credentials
|
|
157
227
|
|
|
228
|
+
**Note:** Client registration is free and only required for security and callback URL validation. There are no fees for developers.
|
|
229
|
+
|
|
230
|
+
## Pricing Model
|
|
231
|
+
|
|
232
|
+
- ✅ **SDK is free** - No cost to integrate or use
|
|
233
|
+
- ✅ **No usage limits** - Use as much as you need
|
|
234
|
+
- ✅ **No developer fees** - Zero cost for website owners
|
|
235
|
+
- 💰 **End users pay** - Your users subscribe to OneTapForms service ($9-29/month) to store their data securely
|
|
236
|
+
|
|
237
|
+
### Win-Win Model
|
|
238
|
+
|
|
239
|
+
**For Developers:**
|
|
240
|
+
- Free integration with no ongoing costs
|
|
241
|
+
- Faster form completion = more conversions
|
|
242
|
+
- Better UX = happier users
|
|
243
|
+
- Verified data = less errors
|
|
244
|
+
|
|
245
|
+
**For End Users:**
|
|
246
|
+
- One-tap form completion
|
|
247
|
+
- Secure biometric authentication
|
|
248
|
+
- Pre-filled verified data
|
|
249
|
+
- Works across all OneTapForms-enabled sites
|
|
250
|
+
|
|
251
|
+
**For OneTapForms:**
|
|
252
|
+
- Revenue from user subscriptions
|
|
253
|
+
- Network effects as more sites integrate
|
|
254
|
+
|
|
255
|
+
This model creates genuine value for everyone - developers get better results, users get convenience, and OneTapForms grows sustainably.
|
|
256
|
+
|
|
158
257
|
## License
|
|
159
258
|
|
|
160
|
-
MIT
|
|
259
|
+
MIT - Free to use, modify, and distribute
|
|
161
260
|
|
|
162
261
|
## Support
|
|
163
262
|
|
package/dist/index.esm.js
CHANGED
|
@@ -52,6 +52,135 @@ class OneTapForms {
|
|
|
52
52
|
async exchangeToken(token) {
|
|
53
53
|
return this.instance.exchangeToken(token);
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the App Store URL for downloading OneTapForms app
|
|
57
|
+
* Use this to encourage users to download the app for faster form completion
|
|
58
|
+
*/
|
|
59
|
+
getAppDownloadUrl() {
|
|
60
|
+
return 'https://apps.apple.com/app/onetapforms';
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Show a prompt encouraging users to download the OneTapForms app
|
|
64
|
+
* This helps developers get faster form completion and better conversion rates
|
|
65
|
+
*
|
|
66
|
+
* @param options Customization options for the prompt
|
|
67
|
+
*/
|
|
68
|
+
showDownloadPrompt(options) {
|
|
69
|
+
if (typeof window === 'undefined') {
|
|
70
|
+
return; // Server-side, do nothing
|
|
71
|
+
}
|
|
72
|
+
const title = options?.title || 'Download OneTapForms for Faster Form Completion';
|
|
73
|
+
const message = options?.message ||
|
|
74
|
+
'Complete forms in seconds with one tap! Download the OneTapForms app to instantly fill forms using Face ID/Touch ID.';
|
|
75
|
+
const buttonText = options?.buttonText || 'Download App';
|
|
76
|
+
const appUrl = this.getAppDownloadUrl();
|
|
77
|
+
// Create a simple modal/prompt
|
|
78
|
+
const modal = document.createElement('div');
|
|
79
|
+
modal.style.cssText = `
|
|
80
|
+
position: fixed;
|
|
81
|
+
top: 0;
|
|
82
|
+
left: 0;
|
|
83
|
+
right: 0;
|
|
84
|
+
bottom: 0;
|
|
85
|
+
background: rgba(0, 0, 0, 0.5);
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
justify-content: center;
|
|
89
|
+
z-index: 10000;
|
|
90
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
91
|
+
`;
|
|
92
|
+
const content = document.createElement('div');
|
|
93
|
+
content.style.cssText = `
|
|
94
|
+
background: white;
|
|
95
|
+
padding: 24px;
|
|
96
|
+
border-radius: 12px;
|
|
97
|
+
max-width: 400px;
|
|
98
|
+
margin: 20px;
|
|
99
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
100
|
+
`;
|
|
101
|
+
const titleEl = document.createElement('h3');
|
|
102
|
+
titleEl.textContent = title;
|
|
103
|
+
titleEl.style.cssText = `
|
|
104
|
+
margin: 0 0 12px 0;
|
|
105
|
+
font-size: 20px;
|
|
106
|
+
font-weight: 600;
|
|
107
|
+
color: #1a1a1a;
|
|
108
|
+
`;
|
|
109
|
+
const messageEl = document.createElement('p');
|
|
110
|
+
messageEl.textContent = message;
|
|
111
|
+
messageEl.style.cssText = `
|
|
112
|
+
margin: 0 0 20px 0;
|
|
113
|
+
font-size: 14px;
|
|
114
|
+
color: #666;
|
|
115
|
+
line-height: 1.5;
|
|
116
|
+
`;
|
|
117
|
+
const buttonContainer = document.createElement('div');
|
|
118
|
+
buttonContainer.style.cssText = `
|
|
119
|
+
display: flex;
|
|
120
|
+
gap: 12px;
|
|
121
|
+
justify-content: flex-end;
|
|
122
|
+
`;
|
|
123
|
+
const dismissBtn = document.createElement('button');
|
|
124
|
+
dismissBtn.textContent = 'Maybe Later';
|
|
125
|
+
dismissBtn.style.cssText = `
|
|
126
|
+
padding: 10px 20px;
|
|
127
|
+
border: 1px solid #ddd;
|
|
128
|
+
background: white;
|
|
129
|
+
border-radius: 6px;
|
|
130
|
+
cursor: pointer;
|
|
131
|
+
font-size: 14px;
|
|
132
|
+
color: #666;
|
|
133
|
+
`;
|
|
134
|
+
dismissBtn.onclick = () => {
|
|
135
|
+
document.body.removeChild(modal);
|
|
136
|
+
if (options?.onDismiss) {
|
|
137
|
+
options.onDismiss();
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const downloadBtn = document.createElement('button');
|
|
141
|
+
downloadBtn.textContent = buttonText;
|
|
142
|
+
downloadBtn.style.cssText = `
|
|
143
|
+
padding: 10px 20px;
|
|
144
|
+
border: none;
|
|
145
|
+
background: #007AFF;
|
|
146
|
+
color: white;
|
|
147
|
+
border-radius: 6px;
|
|
148
|
+
cursor: pointer;
|
|
149
|
+
font-size: 14px;
|
|
150
|
+
font-weight: 500;
|
|
151
|
+
`;
|
|
152
|
+
downloadBtn.onclick = () => {
|
|
153
|
+
window.open(appUrl, '_blank');
|
|
154
|
+
document.body.removeChild(modal);
|
|
155
|
+
};
|
|
156
|
+
buttonContainer.appendChild(dismissBtn);
|
|
157
|
+
buttonContainer.appendChild(downloadBtn);
|
|
158
|
+
content.appendChild(titleEl);
|
|
159
|
+
content.appendChild(messageEl);
|
|
160
|
+
content.appendChild(buttonContainer);
|
|
161
|
+
modal.appendChild(content);
|
|
162
|
+
// Close on background click
|
|
163
|
+
modal.onclick = (e) => {
|
|
164
|
+
if (e.target === modal) {
|
|
165
|
+
document.body.removeChild(modal);
|
|
166
|
+
if (options?.onDismiss) {
|
|
167
|
+
options.onDismiss();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
document.body.appendChild(modal);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if the user likely has the OneTapForms app installed
|
|
175
|
+
* Returns true if on iOS and Universal Links are supported
|
|
176
|
+
*/
|
|
177
|
+
isAppLikelyInstalled() {
|
|
178
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const userAgent = navigator.userAgent || '';
|
|
182
|
+
return /iPhone|iPad|iPod/i.test(userAgent);
|
|
183
|
+
}
|
|
55
184
|
}
|
|
56
185
|
|
|
57
186
|
export { OneTapForms, OneTapForms as default };
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/onetapforms.ts"],"sourcesContent":["import type { OneTapFormsConfig, RequestOptions, CompletionResult } from './types';\n\n// We'll use a dynamic import approach that works in both browser and Node\nlet OneTapFormsJS: any;\n\n// Lazy load the JS implementation\nfunction getOneTapFormsClass() {\n if (!OneTapFormsJS) {\n // In browser/build environment, this will be resolved at build time\n // The bundled JS file exports OneTapForms as a class\n if (typeof window !== 'undefined') {\n // Browser environment - use global or import\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n } else {\n // Node environment\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n }\n }\n return OneTapFormsJS;\n}\n\n/**\n * OneTapForms SDK class for secure, biometric-authenticated form completion\n */\nexport class OneTapForms {\n private instance: any;\n\n constructor(config: OneTapFormsConfig) {\n const OneTapFormsClass = getOneTapFormsClass();\n this.instance = new OneTapFormsClass(config);\n }\n\n /**\n * Create a form completion request\n */\n async request(options: RequestOptions): Promise<void> {\n return this.instance.request(options);\n }\n\n /**\n * Cancel active polling (useful for cleanup)\n */\n cancelPolling(): void {\n return this.instance.cancelPolling();\n }\n\n /**\n * Handle callback from redirect flow\n * Call this when user returns to your site with token in URL\n */\n handleCallback(): CompletionResult | null {\n return this.instance.handleCallback();\n }\n\n /**\n * Exchange token for user data (server-side only!)\n * This should be called from your backend, not the browser\n */\n async exchangeToken(token: string): Promise<any> {\n return this.instance.exchangeToken(token);\n }\n}\n\nexport default OneTapForms;\n"],"names":[],"mappings":"AAEA;AACA,IAAI,aAAkB;AAEtB;AACA,SAAS,mBAAmB,GAAA;IAC1B,IAAI,CAAC,aAAa,EAAE;;;AAGlB,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;;AAEjC,YAAA,MAAM,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAC1C,aAAa,GAAG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,OAAO;QACtD;aAAO;;AAEL,YAAA,MAAM,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAC1C,aAAa,GAAG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,OAAO;QACtD;IACF;AACA,IAAA,OAAO,aAAa;AACtB;AAEA;;AAEG;MACU,WAAW,CAAA;AAGtB,IAAA,WAAA,CAAY,MAAyB,EAAA;AACnC,QAAA,MAAM,gBAAgB,GAAG,mBAAmB,EAAE;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAC9C;AAEA;;AAEG;IACH,MAAM,OAAO,CAAC,OAAuB,EAAA;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;IACvC;AAEA;;AAEG;IACH,aAAa,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE;IACtC;AAEA;;;AAGG;IACH,cAAc,GAAA;AACZ,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE;IACvC;AAEA;;;AAGG;IACH,MAAM,aAAa,CAAC,KAAa,EAAA;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;IAC3C;AACD;;;;"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/onetapforms.ts"],"sourcesContent":["import type { OneTapFormsConfig, RequestOptions, CompletionResult } from './types';\n\n// We'll use a dynamic import approach that works in both browser and Node\nlet OneTapFormsJS: any;\n\n// Lazy load the JS implementation\nfunction getOneTapFormsClass() {\n if (!OneTapFormsJS) {\n // In browser/build environment, this will be resolved at build time\n // The bundled JS file exports OneTapForms as a class\n if (typeof window !== 'undefined') {\n // Browser environment - use global or import\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n } else {\n // Node environment\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n }\n }\n return OneTapFormsJS;\n}\n\n/**\n * OneTapForms SDK class for secure, biometric-authenticated form completion\n */\nexport class OneTapForms {\n private instance: any;\n\n constructor(config: OneTapFormsConfig) {\n const OneTapFormsClass = getOneTapFormsClass();\n this.instance = new OneTapFormsClass(config);\n }\n\n /**\n * Create a form completion request\n */\n async request(options: RequestOptions): Promise<void> {\n return this.instance.request(options);\n }\n\n /**\n * Cancel active polling (useful for cleanup)\n */\n cancelPolling(): void {\n return this.instance.cancelPolling();\n }\n\n /**\n * Handle callback from redirect flow\n * Call this when user returns to your site with token in URL\n */\n handleCallback(): CompletionResult | null {\n return this.instance.handleCallback();\n }\n\n /**\n * Exchange token for user data (server-side only!)\n * This should be called from your backend, not the browser\n */\n async exchangeToken(token: string): Promise<any> {\n return this.instance.exchangeToken(token);\n }\n\n /**\n * Get the App Store URL for downloading OneTapForms app\n * Use this to encourage users to download the app for faster form completion\n */\n getAppDownloadUrl(): string {\n return 'https://apps.apple.com/app/onetapforms';\n }\n\n /**\n * Show a prompt encouraging users to download the OneTapForms app\n * This helps developers get faster form completion and better conversion rates\n * \n * @param options Customization options for the prompt\n */\n showDownloadPrompt(options?: {\n title?: string;\n message?: string;\n buttonText?: string;\n onDismiss?: () => void;\n }): void {\n if (typeof window === 'undefined') {\n return; // Server-side, do nothing\n }\n\n const title = options?.title || 'Download OneTapForms for Faster Form Completion';\n const message = options?.message || \n 'Complete forms in seconds with one tap! Download the OneTapForms app to instantly fill forms using Face ID/Touch ID.';\n const buttonText = options?.buttonText || 'Download App';\n const appUrl = this.getAppDownloadUrl();\n\n // Create a simple modal/prompt\n const modal = document.createElement('div');\n modal.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n `;\n\n const content = document.createElement('div');\n content.style.cssText = `\n background: white;\n padding: 24px;\n border-radius: 12px;\n max-width: 400px;\n margin: 20px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n `;\n\n const titleEl = document.createElement('h3');\n titleEl.textContent = title;\n titleEl.style.cssText = `\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #1a1a1a;\n `;\n\n const messageEl = document.createElement('p');\n messageEl.textContent = message;\n messageEl.style.cssText = `\n margin: 0 0 20px 0;\n font-size: 14px;\n color: #666;\n line-height: 1.5;\n `;\n\n const buttonContainer = document.createElement('div');\n buttonContainer.style.cssText = `\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n `;\n\n const dismissBtn = document.createElement('button');\n dismissBtn.textContent = 'Maybe Later';\n dismissBtn.style.cssText = `\n padding: 10px 20px;\n border: 1px solid #ddd;\n background: white;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n color: #666;\n `;\n dismissBtn.onclick = () => {\n document.body.removeChild(modal);\n if (options?.onDismiss) {\n options.onDismiss();\n }\n };\n\n const downloadBtn = document.createElement('button');\n downloadBtn.textContent = buttonText;\n downloadBtn.style.cssText = `\n padding: 10px 20px;\n border: none;\n background: #007AFF;\n color: white;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n `;\n downloadBtn.onclick = () => {\n window.open(appUrl, '_blank');\n document.body.removeChild(modal);\n };\n\n buttonContainer.appendChild(dismissBtn);\n buttonContainer.appendChild(downloadBtn);\n\n content.appendChild(titleEl);\n content.appendChild(messageEl);\n content.appendChild(buttonContainer);\n modal.appendChild(content);\n\n // Close on background click\n modal.onclick = (e) => {\n if (e.target === modal) {\n document.body.removeChild(modal);\n if (options?.onDismiss) {\n options.onDismiss();\n }\n }\n };\n\n document.body.appendChild(modal);\n }\n\n /**\n * Check if the user likely has the OneTapForms app installed\n * Returns true if on iOS and Universal Links are supported\n */\n isAppLikelyInstalled(): boolean {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return false;\n }\n const userAgent = navigator.userAgent || '';\n return /iPhone|iPad|iPod/i.test(userAgent);\n }\n}\n\nexport default OneTapForms;\n"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -56,6 +56,135 @@ class OneTapForms {
|
|
|
56
56
|
async exchangeToken(token) {
|
|
57
57
|
return this.instance.exchangeToken(token);
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Get the App Store URL for downloading OneTapForms app
|
|
61
|
+
* Use this to encourage users to download the app for faster form completion
|
|
62
|
+
*/
|
|
63
|
+
getAppDownloadUrl() {
|
|
64
|
+
return 'https://apps.apple.com/app/onetapforms';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Show a prompt encouraging users to download the OneTapForms app
|
|
68
|
+
* This helps developers get faster form completion and better conversion rates
|
|
69
|
+
*
|
|
70
|
+
* @param options Customization options for the prompt
|
|
71
|
+
*/
|
|
72
|
+
showDownloadPrompt(options) {
|
|
73
|
+
if (typeof window === 'undefined') {
|
|
74
|
+
return; // Server-side, do nothing
|
|
75
|
+
}
|
|
76
|
+
const title = options?.title || 'Download OneTapForms for Faster Form Completion';
|
|
77
|
+
const message = options?.message ||
|
|
78
|
+
'Complete forms in seconds with one tap! Download the OneTapForms app to instantly fill forms using Face ID/Touch ID.';
|
|
79
|
+
const buttonText = options?.buttonText || 'Download App';
|
|
80
|
+
const appUrl = this.getAppDownloadUrl();
|
|
81
|
+
// Create a simple modal/prompt
|
|
82
|
+
const modal = document.createElement('div');
|
|
83
|
+
modal.style.cssText = `
|
|
84
|
+
position: fixed;
|
|
85
|
+
top: 0;
|
|
86
|
+
left: 0;
|
|
87
|
+
right: 0;
|
|
88
|
+
bottom: 0;
|
|
89
|
+
background: rgba(0, 0, 0, 0.5);
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
z-index: 10000;
|
|
94
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
95
|
+
`;
|
|
96
|
+
const content = document.createElement('div');
|
|
97
|
+
content.style.cssText = `
|
|
98
|
+
background: white;
|
|
99
|
+
padding: 24px;
|
|
100
|
+
border-radius: 12px;
|
|
101
|
+
max-width: 400px;
|
|
102
|
+
margin: 20px;
|
|
103
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
104
|
+
`;
|
|
105
|
+
const titleEl = document.createElement('h3');
|
|
106
|
+
titleEl.textContent = title;
|
|
107
|
+
titleEl.style.cssText = `
|
|
108
|
+
margin: 0 0 12px 0;
|
|
109
|
+
font-size: 20px;
|
|
110
|
+
font-weight: 600;
|
|
111
|
+
color: #1a1a1a;
|
|
112
|
+
`;
|
|
113
|
+
const messageEl = document.createElement('p');
|
|
114
|
+
messageEl.textContent = message;
|
|
115
|
+
messageEl.style.cssText = `
|
|
116
|
+
margin: 0 0 20px 0;
|
|
117
|
+
font-size: 14px;
|
|
118
|
+
color: #666;
|
|
119
|
+
line-height: 1.5;
|
|
120
|
+
`;
|
|
121
|
+
const buttonContainer = document.createElement('div');
|
|
122
|
+
buttonContainer.style.cssText = `
|
|
123
|
+
display: flex;
|
|
124
|
+
gap: 12px;
|
|
125
|
+
justify-content: flex-end;
|
|
126
|
+
`;
|
|
127
|
+
const dismissBtn = document.createElement('button');
|
|
128
|
+
dismissBtn.textContent = 'Maybe Later';
|
|
129
|
+
dismissBtn.style.cssText = `
|
|
130
|
+
padding: 10px 20px;
|
|
131
|
+
border: 1px solid #ddd;
|
|
132
|
+
background: white;
|
|
133
|
+
border-radius: 6px;
|
|
134
|
+
cursor: pointer;
|
|
135
|
+
font-size: 14px;
|
|
136
|
+
color: #666;
|
|
137
|
+
`;
|
|
138
|
+
dismissBtn.onclick = () => {
|
|
139
|
+
document.body.removeChild(modal);
|
|
140
|
+
if (options?.onDismiss) {
|
|
141
|
+
options.onDismiss();
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const downloadBtn = document.createElement('button');
|
|
145
|
+
downloadBtn.textContent = buttonText;
|
|
146
|
+
downloadBtn.style.cssText = `
|
|
147
|
+
padding: 10px 20px;
|
|
148
|
+
border: none;
|
|
149
|
+
background: #007AFF;
|
|
150
|
+
color: white;
|
|
151
|
+
border-radius: 6px;
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
font-size: 14px;
|
|
154
|
+
font-weight: 500;
|
|
155
|
+
`;
|
|
156
|
+
downloadBtn.onclick = () => {
|
|
157
|
+
window.open(appUrl, '_blank');
|
|
158
|
+
document.body.removeChild(modal);
|
|
159
|
+
};
|
|
160
|
+
buttonContainer.appendChild(dismissBtn);
|
|
161
|
+
buttonContainer.appendChild(downloadBtn);
|
|
162
|
+
content.appendChild(titleEl);
|
|
163
|
+
content.appendChild(messageEl);
|
|
164
|
+
content.appendChild(buttonContainer);
|
|
165
|
+
modal.appendChild(content);
|
|
166
|
+
// Close on background click
|
|
167
|
+
modal.onclick = (e) => {
|
|
168
|
+
if (e.target === modal) {
|
|
169
|
+
document.body.removeChild(modal);
|
|
170
|
+
if (options?.onDismiss) {
|
|
171
|
+
options.onDismiss();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
document.body.appendChild(modal);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Check if the user likely has the OneTapForms app installed
|
|
179
|
+
* Returns true if on iOS and Universal Links are supported
|
|
180
|
+
*/
|
|
181
|
+
isAppLikelyInstalled() {
|
|
182
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
const userAgent = navigator.userAgent || '';
|
|
186
|
+
return /iPhone|iPad|iPod/i.test(userAgent);
|
|
187
|
+
}
|
|
59
188
|
}
|
|
60
189
|
|
|
61
190
|
exports.OneTapForms = OneTapForms;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/onetapforms.ts"],"sourcesContent":["import type { OneTapFormsConfig, RequestOptions, CompletionResult } from './types';\n\n// We'll use a dynamic import approach that works in both browser and Node\nlet OneTapFormsJS: any;\n\n// Lazy load the JS implementation\nfunction getOneTapFormsClass() {\n if (!OneTapFormsJS) {\n // In browser/build environment, this will be resolved at build time\n // The bundled JS file exports OneTapForms as a class\n if (typeof window !== 'undefined') {\n // Browser environment - use global or import\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n } else {\n // Node environment\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n }\n }\n return OneTapFormsJS;\n}\n\n/**\n * OneTapForms SDK class for secure, biometric-authenticated form completion\n */\nexport class OneTapForms {\n private instance: any;\n\n constructor(config: OneTapFormsConfig) {\n const OneTapFormsClass = getOneTapFormsClass();\n this.instance = new OneTapFormsClass(config);\n }\n\n /**\n * Create a form completion request\n */\n async request(options: RequestOptions): Promise<void> {\n return this.instance.request(options);\n }\n\n /**\n * Cancel active polling (useful for cleanup)\n */\n cancelPolling(): void {\n return this.instance.cancelPolling();\n }\n\n /**\n * Handle callback from redirect flow\n * Call this when user returns to your site with token in URL\n */\n handleCallback(): CompletionResult | null {\n return this.instance.handleCallback();\n }\n\n /**\n * Exchange token for user data (server-side only!)\n * This should be called from your backend, not the browser\n */\n async exchangeToken(token: string): Promise<any> {\n return this.instance.exchangeToken(token);\n }\n}\n\nexport default OneTapForms;\n"],"names":[],"mappings":";;;;AAEA;AACA,IAAI,aAAkB;AAEtB;AACA,SAAS,mBAAmB,GAAA;IAC1B,IAAI,CAAC,aAAa,EAAE;;;AAGlB,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;;AAEjC,YAAA,MAAM,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAC1C,aAAa,GAAG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,OAAO;QACtD;aAAO;;AAEL,YAAA,MAAM,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAC1C,aAAa,GAAG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,OAAO;QACtD;IACF;AACA,IAAA,OAAO,aAAa;AACtB;AAEA;;AAEG;MACU,WAAW,CAAA;AAGtB,IAAA,WAAA,CAAY,MAAyB,EAAA;AACnC,QAAA,MAAM,gBAAgB,GAAG,mBAAmB,EAAE;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAC9C;AAEA;;AAEG;IACH,MAAM,OAAO,CAAC,OAAuB,EAAA;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;IACvC;AAEA;;AAEG;IACH,aAAa,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE;IACtC;AAEA;;;AAGG;IACH,cAAc,GAAA;AACZ,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE;IACvC;AAEA;;;AAGG;IACH,MAAM,aAAa,CAAC,KAAa,EAAA;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;IAC3C;AACD;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/onetapforms.ts"],"sourcesContent":["import type { OneTapFormsConfig, RequestOptions, CompletionResult } from './types';\n\n// We'll use a dynamic import approach that works in both browser and Node\nlet OneTapFormsJS: any;\n\n// Lazy load the JS implementation\nfunction getOneTapFormsClass() {\n if (!OneTapFormsJS) {\n // In browser/build environment, this will be resolved at build time\n // The bundled JS file exports OneTapForms as a class\n if (typeof window !== 'undefined') {\n // Browser environment - use global or import\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n } else {\n // Node environment\n const module = require('./onetapforms.js');\n OneTapFormsJS = module.OneTapForms || module.default;\n }\n }\n return OneTapFormsJS;\n}\n\n/**\n * OneTapForms SDK class for secure, biometric-authenticated form completion\n */\nexport class OneTapForms {\n private instance: any;\n\n constructor(config: OneTapFormsConfig) {\n const OneTapFormsClass = getOneTapFormsClass();\n this.instance = new OneTapFormsClass(config);\n }\n\n /**\n * Create a form completion request\n */\n async request(options: RequestOptions): Promise<void> {\n return this.instance.request(options);\n }\n\n /**\n * Cancel active polling (useful for cleanup)\n */\n cancelPolling(): void {\n return this.instance.cancelPolling();\n }\n\n /**\n * Handle callback from redirect flow\n * Call this when user returns to your site with token in URL\n */\n handleCallback(): CompletionResult | null {\n return this.instance.handleCallback();\n }\n\n /**\n * Exchange token for user data (server-side only!)\n * This should be called from your backend, not the browser\n */\n async exchangeToken(token: string): Promise<any> {\n return this.instance.exchangeToken(token);\n }\n\n /**\n * Get the App Store URL for downloading OneTapForms app\n * Use this to encourage users to download the app for faster form completion\n */\n getAppDownloadUrl(): string {\n return 'https://apps.apple.com/app/onetapforms';\n }\n\n /**\n * Show a prompt encouraging users to download the OneTapForms app\n * This helps developers get faster form completion and better conversion rates\n * \n * @param options Customization options for the prompt\n */\n showDownloadPrompt(options?: {\n title?: string;\n message?: string;\n buttonText?: string;\n onDismiss?: () => void;\n }): void {\n if (typeof window === 'undefined') {\n return; // Server-side, do nothing\n }\n\n const title = options?.title || 'Download OneTapForms for Faster Form Completion';\n const message = options?.message || \n 'Complete forms in seconds with one tap! Download the OneTapForms app to instantly fill forms using Face ID/Touch ID.';\n const buttonText = options?.buttonText || 'Download App';\n const appUrl = this.getAppDownloadUrl();\n\n // Create a simple modal/prompt\n const modal = document.createElement('div');\n modal.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n `;\n\n const content = document.createElement('div');\n content.style.cssText = `\n background: white;\n padding: 24px;\n border-radius: 12px;\n max-width: 400px;\n margin: 20px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n `;\n\n const titleEl = document.createElement('h3');\n titleEl.textContent = title;\n titleEl.style.cssText = `\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #1a1a1a;\n `;\n\n const messageEl = document.createElement('p');\n messageEl.textContent = message;\n messageEl.style.cssText = `\n margin: 0 0 20px 0;\n font-size: 14px;\n color: #666;\n line-height: 1.5;\n `;\n\n const buttonContainer = document.createElement('div');\n buttonContainer.style.cssText = `\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n `;\n\n const dismissBtn = document.createElement('button');\n dismissBtn.textContent = 'Maybe Later';\n dismissBtn.style.cssText = `\n padding: 10px 20px;\n border: 1px solid #ddd;\n background: white;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n color: #666;\n `;\n dismissBtn.onclick = () => {\n document.body.removeChild(modal);\n if (options?.onDismiss) {\n options.onDismiss();\n }\n };\n\n const downloadBtn = document.createElement('button');\n downloadBtn.textContent = buttonText;\n downloadBtn.style.cssText = `\n padding: 10px 20px;\n border: none;\n background: #007AFF;\n color: white;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n `;\n downloadBtn.onclick = () => {\n window.open(appUrl, '_blank');\n document.body.removeChild(modal);\n };\n\n buttonContainer.appendChild(dismissBtn);\n buttonContainer.appendChild(downloadBtn);\n\n content.appendChild(titleEl);\n content.appendChild(messageEl);\n content.appendChild(buttonContainer);\n modal.appendChild(content);\n\n // Close on background click\n modal.onclick = (e) => {\n if (e.target === modal) {\n document.body.removeChild(modal);\n if (options?.onDismiss) {\n options.onDismiss();\n }\n }\n };\n\n document.body.appendChild(modal);\n }\n\n /**\n * Check if the user likely has the OneTapForms app installed\n * Returns true if on iOS and Universal Links are supported\n */\n isAppLikelyInstalled(): boolean {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return false;\n }\n const userAgent = navigator.userAgent || '';\n return /iPhone|iPad|iPod/i.test(userAgent);\n }\n}\n\nexport default OneTapForms;\n"],"names":[],"mappings":"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"}
|
package/dist/onetapforms.d.ts
CHANGED
|
@@ -23,5 +23,27 @@ export declare class OneTapForms {
|
|
|
23
23
|
* This should be called from your backend, not the browser
|
|
24
24
|
*/
|
|
25
25
|
exchangeToken(token: string): Promise<any>;
|
|
26
|
+
/**
|
|
27
|
+
* Get the App Store URL for downloading OneTapForms app
|
|
28
|
+
* Use this to encourage users to download the app for faster form completion
|
|
29
|
+
*/
|
|
30
|
+
getAppDownloadUrl(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Show a prompt encouraging users to download the OneTapForms app
|
|
33
|
+
* This helps developers get faster form completion and better conversion rates
|
|
34
|
+
*
|
|
35
|
+
* @param options Customization options for the prompt
|
|
36
|
+
*/
|
|
37
|
+
showDownloadPrompt(options?: {
|
|
38
|
+
title?: string;
|
|
39
|
+
message?: string;
|
|
40
|
+
buttonText?: string;
|
|
41
|
+
onDismiss?: () => void;
|
|
42
|
+
}): void;
|
|
43
|
+
/**
|
|
44
|
+
* Check if the user likely has the OneTapForms app installed
|
|
45
|
+
* Returns true if on iOS and Universal Links are supported
|
|
46
|
+
*/
|
|
47
|
+
isAppLikelyInstalled(): boolean;
|
|
26
48
|
}
|
|
27
49
|
export default OneTapForms;
|
package/dist/types.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export interface RequestOptions {
|
|
|
40
40
|
onError?: (error: Error) => void;
|
|
41
41
|
/** Callback when QR code is ready (desktop flow) */
|
|
42
42
|
onQRReady?: (qrDataUrl: string) => void;
|
|
43
|
+
/** Show download prompt if user doesn't have the app (defaults to true) */
|
|
44
|
+
showDownloadPrompt?: boolean;
|
|
43
45
|
}
|
|
44
46
|
/**
|
|
45
47
|
* Result returned when a form completion request is approved
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@createlex/onetapforms-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Free SDK for instant form completion. Faster conversions, better UX, verified data - zero cost for developers. Users pay for convenience.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.esm.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
@@ -46,9 +46,7 @@
|
|
|
46
46
|
"rollup": "^4.9.0",
|
|
47
47
|
"typescript": "^5.7.2"
|
|
48
48
|
},
|
|
49
|
-
"peerDependencies": {},
|
|
50
49
|
"publishConfig": {
|
|
51
50
|
"access": "public"
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
|
-
|