@basis-theory/web-elements 2.11.1 → 3.0.0-beta.2
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 +668 -2
- package/dist/.vite/manifest.json +27 -0
- package/dist/api-client/src/api-client.d.ts +11 -0
- package/dist/api-client/src/api-client.d.ts.map +1 -0
- package/dist/api-client/src/http-client.d.ts +24 -0
- package/dist/api-client/src/http-client.d.ts.map +1 -0
- package/dist/api-client/src/index.d.ts +9 -0
- package/dist/api-client/src/index.d.ts.map +1 -0
- package/dist/api-client/src/services/sessions.d.ts +19 -0
- package/dist/api-client/src/services/sessions.d.ts.map +1 -0
- package/dist/api-client/src/services/token-intents.d.ts +17 -0
- package/dist/api-client/src/services/token-intents.d.ts.map +1 -0
- package/dist/api-client/src/services/tokens.d.ts +19 -0
- package/dist/api-client/src/services/tokens.d.ts.map +1 -0
- package/dist/api-client/src/types.d.ts +313 -0
- package/dist/api-client/src/types.d.ts.map +1 -0
- package/dist/basis-theory-sdk.es.js +6 -0
- package/dist/basis-theory-sdk.es.js.map +1 -0
- package/dist/basis-theory-sdk.umd.js +1 -0
- package/dist/basis-theory-sdk.umd.js.map +1 -0
- package/dist/create-card-BuOvimjH.js +232 -0
- package/dist/create-card-BuOvimjH.js.map +1 -0
- package/dist/index-oREjBjga.js +2317 -0
- package/dist/index-oREjBjga.js.map +1 -0
- package/dist/loader/basis-theory.min.js +1 -0
- package/dist/postmessage/src/client.d.ts +7 -0
- package/dist/postmessage/src/client.d.ts.map +1 -0
- package/dist/postmessage/src/event-map.d.ts +135 -0
- package/dist/postmessage/src/event-map.d.ts.map +1 -0
- package/dist/postmessage/src/index.d.ts +9 -0
- package/dist/postmessage/src/index.d.ts.map +1 -0
- package/dist/postmessage/src/server.d.ts +11 -0
- package/dist/postmessage/src/server.d.ts.map +1 -0
- package/dist/postmessage/src/types.d.ts +71 -0
- package/dist/postmessage/src/types.d.ts.map +1 -0
- package/dist/shared/src/api-url-resolver.d.ts +22 -0
- package/dist/shared/src/api-url-resolver.d.ts.map +1 -0
- package/dist/shared/src/debug-logger.d.ts +16 -0
- package/dist/shared/src/debug-logger.d.ts.map +1 -0
- package/dist/shared/src/deep-sanitization.d.ts +24 -0
- package/dist/shared/src/deep-sanitization.d.ts.map +1 -0
- package/dist/shared/src/errors.d.ts +93 -0
- package/dist/shared/src/errors.d.ts.map +1 -0
- package/dist/shared/src/generate-id.d.ts +13 -0
- package/dist/shared/src/generate-id.d.ts.map +1 -0
- package/dist/shared/src/index.d.ts +13 -0
- package/dist/shared/src/index.d.ts.map +1 -0
- package/dist/shared/src/logger-context.d.ts +25 -0
- package/dist/shared/src/logger-context.d.ts.map +1 -0
- package/dist/sri.json +22 -0
- package/dist/stats.html +4949 -0
- package/dist/web-elements/src/BasisTheory.d.ts +47 -0
- package/dist/web-elements/src/BasisTheory.d.ts.map +1 -0
- package/dist/web-elements/src/basis-theory.d.ts +62 -0
- package/dist/web-elements/src/basis-theory.d.ts.map +1 -0
- package/dist/web-elements/src/elements/create-card-number.d.ts +14 -0
- package/dist/web-elements/src/elements/create-card-number.d.ts.map +1 -0
- package/dist/web-elements/src/elements/create-card.d.ts +37 -0
- package/dist/web-elements/src/elements/create-card.d.ts.map +1 -0
- package/dist/web-elements/src/elements/create-cvv.d.ts +10 -0
- package/dist/web-elements/src/elements/create-cvv.d.ts.map +1 -0
- package/dist/web-elements/src/elements/create-expiry.d.ts +10 -0
- package/dist/web-elements/src/elements/create-expiry.d.ts.map +1 -0
- package/dist/web-elements/src/elements/create-text.d.ts +13 -0
- package/dist/web-elements/src/elements/create-text.d.ts.map +1 -0
- package/dist/web-elements/src/index.d.ts +27 -0
- package/dist/web-elements/src/index.d.ts.map +1 -0
- package/dist/web-elements/src/mounter/create-mounter.d.ts +11 -0
- package/dist/web-elements/src/mounter/create-mounter.d.ts.map +1 -0
- package/dist/web-elements/src/theme/default-theme.d.ts +22 -0
- package/dist/web-elements/src/theme/default-theme.d.ts.map +1 -0
- package/dist/web-elements/src/theme/inject-theme-dark.d.ts +13 -0
- package/dist/web-elements/src/theme/inject-theme-dark.d.ts.map +1 -0
- package/dist/web-elements/src/theme/inject-theme.d.ts +20 -0
- package/dist/web-elements/src/theme/inject-theme.d.ts.map +1 -0
- package/dist/web-elements/src/types/events.d.ts +137 -0
- package/dist/web-elements/src/types/events.d.ts.map +1 -0
- package/dist/web-elements/src/types/theme.d.ts +91 -0
- package/dist/web-elements/src/types/theme.d.ts.map +1 -0
- package/dist/web-elements/src/types.d.ts +537 -0
- package/dist/web-elements/src/types.d.ts.map +1 -0
- package/dist/web-elements/src/utils/create-event-dispatcher.d.ts +47 -0
- package/dist/web-elements/src/utils/create-event-dispatcher.d.ts.map +1 -0
- package/dist/web-elements/src/utils/create-iframe.d.ts +10 -0
- package/dist/web-elements/src/utils/create-iframe.d.ts.map +1 -0
- package/dist/web-elements/src/utils/resolve-element-references.d.ts +20 -0
- package/dist/web-elements/src/utils/resolve-element-references.d.ts.map +1 -0
- package/dist/web-elements/src/utils/validate-element-options.d.ts +11 -0
- package/dist/web-elements/src/utils/validate-element-options.d.ts.map +1 -0
- package/dist/web-elements/src/utils/validate-sdk-config.d.ts +15 -0
- package/dist/web-elements/src/utils/validate-sdk-config.d.ts.map +1 -0
- package/dist/web-elements/src/utils/warn-unknown-keys.d.ts +15 -0
- package/dist/web-elements/src/utils/warn-unknown-keys.d.ts.map +1 -0
- package/dist/web-elements/src/version.d.ts +25 -0
- package/dist/web-elements/src/version.d.ts.map +1 -0
- package/package.json +53 -72
- package/LICENSE +0 -202
- package/dist/LICENSE +0 -202
- package/dist/README.md +0 -3
- package/dist/bundle/index.js +0 -1
- package/dist/main/index.js +0 -1160
- package/dist/module/module.js +0 -1158
- package/dist/package.json +0 -37
- package/dist/types/index.d.ts +0 -732
package/README.md
CHANGED
|
@@ -1,3 +1,669 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @basis-theory-elements/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Secure, PCI-compliant SDK for creating payment input elements in web applications.
|
|
4
|
+
|
|
5
|
+
Zero dependencies on RxJS · No dynamic script loading · Framework-agnostic · TypeScript-first
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🌍 **Platform Support**
|
|
10
|
+
|
|
11
|
+
✅ **Web Browsers Only** (v3.0)
|
|
12
|
+
|
|
13
|
+
- Chrome, Firefox, Safari, Edge (desktop)
|
|
14
|
+
- Chrome, Safari (mobile browsers)
|
|
15
|
+
- Standard `window.postMessage` API required
|
|
16
|
+
|
|
17
|
+
❌ **Not Yet Supported:**
|
|
18
|
+
|
|
19
|
+
- iOS/Android Native WebViews
|
|
20
|
+
- React Native WebView
|
|
21
|
+
- Electron (may work, untested)
|
|
22
|
+
|
|
23
|
+
**See [v3 Documentation](../../docs/README.md) for architecture and platform roadmap.**
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 📦 **Installation**
|
|
28
|
+
|
|
29
|
+
### **For Bundlers (webpack, vite, rollup)**
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @basis-theory-elements/sdk
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### **For Script Tags (no build step)**
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<!-- CDN-hosted UMD bundle -->
|
|
39
|
+
<script src="https://cdn.basistheory.com/elements/v3/index.umd.js"></script>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Requirements:**
|
|
43
|
+
|
|
44
|
+
- Modern browser with `iframe` and `postMessage` support
|
|
45
|
+
- TypeScript 4.5+ (optional but recommended for ESM)
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 🚀 **Quick Start**
|
|
50
|
+
|
|
51
|
+
### **ESM (bundlers)**
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import BasisTheory from '@basis-theory-elements/sdk';
|
|
55
|
+
|
|
56
|
+
// 1. Initialize SDK
|
|
57
|
+
const bt = BasisTheory('pk_test_YOUR_API_KEY');
|
|
58
|
+
|
|
59
|
+
// 2. Create elements
|
|
60
|
+
const cardNumber = bt.createElement('cardNumber', {
|
|
61
|
+
placeholder: '4111 1111 1111 1111',
|
|
62
|
+
style: {
|
|
63
|
+
base: {
|
|
64
|
+
color: '#000',
|
|
65
|
+
fontSize: '16px',
|
|
66
|
+
fontFamily: 'Arial, sans-serif',
|
|
67
|
+
},
|
|
68
|
+
invalid: {
|
|
69
|
+
color: '#EA4B97',
|
|
70
|
+
},
|
|
71
|
+
complete: {
|
|
72
|
+
color: '#1976d2',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const cvv = bt.createElement('cvv', {
|
|
78
|
+
placeholder: '123',
|
|
79
|
+
style: {
|
|
80
|
+
/* ... */
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const expiry = bt.createElement('expiry', {
|
|
85
|
+
placeholder: 'MM/YY',
|
|
86
|
+
style: {
|
|
87
|
+
/* ... */
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// 3. Mount elements to DOM
|
|
92
|
+
await cardNumber.mount('#card-number');
|
|
93
|
+
await cvv.mount('#cvv');
|
|
94
|
+
await expiry.mount('#expiry');
|
|
95
|
+
|
|
96
|
+
// 4. Listen for changes
|
|
97
|
+
cardNumber.on('change', (event) => {
|
|
98
|
+
console.log('Card Brand:', event.detail.cardBrand);
|
|
99
|
+
console.log('Is Valid:', event.detail.isValid);
|
|
100
|
+
console.log('Is Complete:', event.detail.isComplete);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
cardNumber.on('ready', () => {
|
|
104
|
+
console.log('Card number element is ready');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// 5. Tokenize
|
|
108
|
+
const token = await bt.tokenize({
|
|
109
|
+
number: cardNumber,
|
|
110
|
+
cvv: cvv,
|
|
111
|
+
expiry: expiry,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
console.log('Token ID:', token.id);
|
|
115
|
+
console.log('Masked Card:', token.mask);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### **UMD (script tags)**
|
|
119
|
+
|
|
120
|
+
```html
|
|
121
|
+
<!DOCTYPE html>
|
|
122
|
+
<html>
|
|
123
|
+
<head>
|
|
124
|
+
<!-- Load SDK from CDN -->
|
|
125
|
+
<script src="https://cdn.basistheory.com/elements/v3/index.umd.js"></script>
|
|
126
|
+
</head>
|
|
127
|
+
<body>
|
|
128
|
+
<div id="card-number"></div>
|
|
129
|
+
<div id="cvv"></div>
|
|
130
|
+
<div id="expiry"></div>
|
|
131
|
+
<button id="tokenize-btn">Tokenize</button>
|
|
132
|
+
|
|
133
|
+
<script>
|
|
134
|
+
// SDK is available globally as window.BasisTheory
|
|
135
|
+
const bt = window.BasisTheory('pk_test_YOUR_API_KEY');
|
|
136
|
+
|
|
137
|
+
// Create elements
|
|
138
|
+
const cardNumber = bt.createElement('cardNumber', {
|
|
139
|
+
placeholder: '4111 1111 1111 1111',
|
|
140
|
+
style: {
|
|
141
|
+
base: { color: '#000', fontSize: '16px' },
|
|
142
|
+
invalid: { color: '#EA4B97' },
|
|
143
|
+
complete: { color: '#1976d2' },
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const cvv = bt.createElement('cvv', { placeholder: '123' });
|
|
148
|
+
const expiry = bt.createElement('expiry', { placeholder: 'MM/YY' });
|
|
149
|
+
|
|
150
|
+
// Mount elements
|
|
151
|
+
cardNumber.mount('#card-number').then(() => {
|
|
152
|
+
console.log('Card number mounted');
|
|
153
|
+
});
|
|
154
|
+
cvv.mount('#cvv');
|
|
155
|
+
expiry.mount('#expiry');
|
|
156
|
+
|
|
157
|
+
// Tokenize on button click
|
|
158
|
+
document
|
|
159
|
+
.getElementById('tokenize-btn')
|
|
160
|
+
.addEventListener('click', async () => {
|
|
161
|
+
const token = await bt.tokenize({
|
|
162
|
+
number: cardNumber,
|
|
163
|
+
cvv: cvv,
|
|
164
|
+
expiry: expiry,
|
|
165
|
+
});
|
|
166
|
+
console.log('Token:', token);
|
|
167
|
+
});
|
|
168
|
+
</script>
|
|
169
|
+
</body>
|
|
170
|
+
</html>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 🎨 **Element Types**
|
|
176
|
+
|
|
177
|
+
### **Card Number**
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const cardNumber = bt.createElement('cardNumber', {
|
|
181
|
+
placeholder: '4111 1111 1111 1111',
|
|
182
|
+
style: {
|
|
183
|
+
/* ... */
|
|
184
|
+
},
|
|
185
|
+
ariaLabel: 'Card Number',
|
|
186
|
+
disabled: false,
|
|
187
|
+
readOnly: false,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Events
|
|
191
|
+
cardNumber.on('change', (event) => {
|
|
192
|
+
console.log(event.detail.cardBrand); // 'visa', 'mastercard', etc.
|
|
193
|
+
console.log(event.detail.isValid); // true/false
|
|
194
|
+
console.log(event.detail.isPotentiallyValid); // Could become valid?
|
|
195
|
+
console.log(event.detail.potentialBrands); // ['visa', 'mastercard']
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### **CVV**
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const cvv = bt.createElement('cvv', {
|
|
203
|
+
placeholder: '123',
|
|
204
|
+
style: {
|
|
205
|
+
/* ... */
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Events
|
|
210
|
+
cvv.on('change', (event) => {
|
|
211
|
+
console.log(event.detail.isValid);
|
|
212
|
+
console.log(event.detail.isComplete);
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### **Expiry Date**
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const expiry = bt.createElement('expiry', {
|
|
220
|
+
placeholder: 'MM/YY',
|
|
221
|
+
style: {
|
|
222
|
+
/* ... */
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Events
|
|
227
|
+
expiry.on('change', (event) => {
|
|
228
|
+
console.log(event.detail.isValid);
|
|
229
|
+
console.log(event.detail.isComplete);
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 📋 **Element Methods**
|
|
236
|
+
|
|
237
|
+
All elements support the following methods:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// Mount to DOM
|
|
241
|
+
await element.mount('#container');
|
|
242
|
+
await element.mount(document.querySelector('#container'));
|
|
243
|
+
|
|
244
|
+
// Unmount from DOM
|
|
245
|
+
element.unmount();
|
|
246
|
+
|
|
247
|
+
// Update configuration
|
|
248
|
+
await element.update({
|
|
249
|
+
placeholder: 'New placeholder',
|
|
250
|
+
style: { base: { color: '#333' } },
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Focus/blur input
|
|
254
|
+
element.focus();
|
|
255
|
+
element.blur();
|
|
256
|
+
|
|
257
|
+
// Clear input value
|
|
258
|
+
element.clear();
|
|
259
|
+
|
|
260
|
+
// Listen for events (returns unsubscribe function)
|
|
261
|
+
const unsubscribe = element.on('change', (event) => {
|
|
262
|
+
console.log(event.detail);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Cleanup
|
|
266
|
+
unsubscribe();
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 🎭 **Events**
|
|
272
|
+
|
|
273
|
+
### **change**
|
|
274
|
+
|
|
275
|
+
Fired when the input value changes.
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
element.on('change', (event) => {
|
|
279
|
+
console.log({
|
|
280
|
+
isValid: event.detail.isValid, // true/false
|
|
281
|
+
isEmpty: event.detail.isEmpty, // true/false
|
|
282
|
+
isComplete: event.detail.isComplete, // true/false
|
|
283
|
+
isPotentiallyValid: event.detail.isPotentiallyValid, // true/false (real-time UX)
|
|
284
|
+
cardBrand: event.detail.cardBrand, // 'visa' | 'mastercard' | ...
|
|
285
|
+
potentialBrands: event.detail.potentialBrands, // ['visa', 'mastercard']
|
|
286
|
+
error: event.detail.error, // { code, message }
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### **ready**
|
|
292
|
+
|
|
293
|
+
Fired when the element is fully initialized and ready for user input.
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
element.on('ready', (event) => {
|
|
297
|
+
console.log('Element ready:', event.detail.elementType);
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### **focus**
|
|
302
|
+
|
|
303
|
+
Fired when the input receives focus.
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
element.on('focus', (event) => {
|
|
307
|
+
console.log('Element focused:', event.detail.elementType);
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### **blur**
|
|
312
|
+
|
|
313
|
+
Fired when the input loses focus.
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
element.on('blur', (event) => {
|
|
317
|
+
console.log('Element blurred:', event.detail.elementType);
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### **error**
|
|
322
|
+
|
|
323
|
+
Fired when an error occurs (network failures, configuration errors, etc.).
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
element.on('error', (event) => {
|
|
327
|
+
console.error('Element error:', {
|
|
328
|
+
code: event.detail.code,
|
|
329
|
+
message: event.detail.message,
|
|
330
|
+
details: event.detail.details,
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 🔐 **Tokenization**
|
|
338
|
+
|
|
339
|
+
### **Single Element**
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
const token = await bt.tokenize({
|
|
343
|
+
cardNumber: cardNumber,
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### **Multiple Elements (Composite Token)**
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const token = await bt.tokenize({
|
|
351
|
+
number: cardNumber,
|
|
352
|
+
cvv: cvv,
|
|
353
|
+
expiry: expiry,
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### **TokenizeResult**
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
interface TokenizeResult {
|
|
361
|
+
id: string; // Token ID
|
|
362
|
+
type: 'card' | 'token'; // Token type
|
|
363
|
+
mask?: string; // Masked card (e.g., "411111******1111")
|
|
364
|
+
brand?: string; // Card brand (e.g., "visa")
|
|
365
|
+
expiry?: {
|
|
366
|
+
month: number;
|
|
367
|
+
year: number;
|
|
368
|
+
};
|
|
369
|
+
metadata?: Record<string, unknown>;
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 🎨 **Styling**
|
|
376
|
+
|
|
377
|
+
### **Style States**
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
interface ElementStyle {
|
|
381
|
+
base?: CSSProperties; // Default state
|
|
382
|
+
invalid?: CSSProperties; // When input is invalid
|
|
383
|
+
complete?: CSSProperties; // When input is valid and complete
|
|
384
|
+
empty?: CSSProperties; // When input is empty
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### **Supported CSS Properties**
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
interface CSSProperties {
|
|
392
|
+
color?: string;
|
|
393
|
+
backgroundColor?: string;
|
|
394
|
+
fontSize?: string;
|
|
395
|
+
fontFamily?: string;
|
|
396
|
+
fontWeight?: string;
|
|
397
|
+
lineHeight?: string;
|
|
398
|
+
letterSpacing?: string;
|
|
399
|
+
textAlign?: string;
|
|
400
|
+
padding?: string;
|
|
401
|
+
margin?: string;
|
|
402
|
+
border?: string;
|
|
403
|
+
borderRadius?: string;
|
|
404
|
+
boxShadow?: string;
|
|
405
|
+
// ... more (see API Reference section below for complete list)
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### **Example**
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
const cardNumber = bt.createElement('cardNumber', {
|
|
413
|
+
style: {
|
|
414
|
+
base: {
|
|
415
|
+
color: '#000',
|
|
416
|
+
fontSize: '16px',
|
|
417
|
+
fontFamily: 'Arial, sans-serif',
|
|
418
|
+
backgroundColor: '#fff',
|
|
419
|
+
padding: '12px',
|
|
420
|
+
border: '1px solid #ddd',
|
|
421
|
+
borderRadius: '4px',
|
|
422
|
+
},
|
|
423
|
+
invalid: {
|
|
424
|
+
color: '#EA4B97',
|
|
425
|
+
borderColor: '#EA4B97',
|
|
426
|
+
},
|
|
427
|
+
complete: {
|
|
428
|
+
color: '#1976d2',
|
|
429
|
+
borderColor: '#1976d2',
|
|
430
|
+
},
|
|
431
|
+
empty: {
|
|
432
|
+
color: '#999',
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## ⚙️ **Configuration**
|
|
441
|
+
|
|
442
|
+
### **SDK Options**
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
const bt = BasisTheory('pk_test_YOUR_API_KEY', {
|
|
446
|
+
elementsBaseUrl: 'https://js.basistheory.com/v3/elements', // Default (auto-configured)
|
|
447
|
+
debug: false, // Enable debug logging
|
|
448
|
+
measurePerformance: false, // Enable performance monitoring
|
|
449
|
+
timeoutMs: 30000, // PostMessage timeout (30s default)
|
|
450
|
+
retryConfig: {
|
|
451
|
+
maxRetries: 3,
|
|
452
|
+
delayMs: 1000,
|
|
453
|
+
backoffFactor: 2,
|
|
454
|
+
},
|
|
455
|
+
themeMode: 'auto', // 'light' | 'dark' | 'auto'
|
|
456
|
+
theme: { /* theme tokens */ },
|
|
457
|
+
darkTheme: { /* dark theme tokens */ },
|
|
458
|
+
});
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### **Element Options**
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
interface ElementOptions {
|
|
465
|
+
placeholder?: string; // Placeholder text
|
|
466
|
+
style?: ElementStyle; // Styling for different states
|
|
467
|
+
ariaLabel?: string; // ARIA label for accessibility
|
|
468
|
+
disabled?: boolean; // Disable input
|
|
469
|
+
readOnly?: boolean; // Make input read-only
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## 🧪 **Testing**
|
|
476
|
+
|
|
477
|
+
### **Unit Testing**
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
import { render } from '@testing-library/react';
|
|
481
|
+
import BasisTheory from '@basis-theory-elements/sdk';
|
|
482
|
+
|
|
483
|
+
test('should create and mount element', async () => {
|
|
484
|
+
const { container } = render(<div id="card-number" />);
|
|
485
|
+
|
|
486
|
+
const bt = BasisTheory('pk_test_123');
|
|
487
|
+
const cardNumber = bt.createElement('cardNumber');
|
|
488
|
+
|
|
489
|
+
await cardNumber.mount('#card-number');
|
|
490
|
+
|
|
491
|
+
expect(cardNumber.mounted).toBe(true);
|
|
492
|
+
expect(container.querySelector('iframe')).toBeInTheDocument();
|
|
493
|
+
});
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### **E2E Testing (Cypress)**
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
cy.visit('/payment-form.html');
|
|
500
|
+
|
|
501
|
+
cy.window().then((win) => {
|
|
502
|
+
const bt = win.BasisTheory('pk_test_123');
|
|
503
|
+
const cardNumber = bt.createElement('cardNumber');
|
|
504
|
+
|
|
505
|
+
return cardNumber.mount('#card-number');
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
cy.get('iframe').should('exist');
|
|
509
|
+
cy.iframe().find('input').type('4111111111111111');
|
|
510
|
+
cy.contains('Card Brand: visa');
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## 🔒 **Security**
|
|
516
|
+
|
|
517
|
+
### **PCI-DSS Compliance**
|
|
518
|
+
|
|
519
|
+
✅ **Stateless Elements** - No sensitive data persisted in SDK
|
|
520
|
+
✅ **Iframe Isolation** - Payment inputs sandboxed in secure iframes
|
|
521
|
+
✅ **Origin Validation** - PostMessage communication validates sender origin
|
|
522
|
+
✅ **No Direct PAN Access** - SDK never touches raw card numbers
|
|
523
|
+
✅ **Secure Tokenization** - Values retrieved ephemerally from iframe
|
|
524
|
+
|
|
525
|
+
### **Best Practices**
|
|
526
|
+
|
|
527
|
+
- ✅ **Use HTTPS** in production
|
|
528
|
+
- ✅ **Validate API key** is for correct environment (test vs production)
|
|
529
|
+
- ✅ **Don't log sensitive data** (card numbers, CVVs, etc.)
|
|
530
|
+
- ✅ **Implement CSP headers** to prevent XSS
|
|
531
|
+
- ✅ **Use subresource integrity** for CDN-hosted iframes
|
|
532
|
+
|
|
533
|
+
**See [Security Architecture](../../docs/user-guide/security.md) for detailed security measures.**
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## 🏗️ **Architecture**
|
|
538
|
+
|
|
539
|
+
The v3 SDK is built with **composition over inheritance**:
|
|
540
|
+
|
|
541
|
+
```
|
|
542
|
+
@basis-theory-elements/sdk # Public API
|
|
543
|
+
├── BasisTheory.ts # Main SDK factory
|
|
544
|
+
├── elements/
|
|
545
|
+
│ ├── CardNumberElement.ts # Card number element
|
|
546
|
+
│ ├── CVVElement.ts # CVV element
|
|
547
|
+
│ └── ExpiryElement.ts # Expiry date element
|
|
548
|
+
├── mounter/
|
|
549
|
+
│ └── ElementMounter.ts # DOM mounting logic
|
|
550
|
+
└── utils/
|
|
551
|
+
├── iframe.ts # Iframe creation utilities
|
|
552
|
+
└── config.ts # Configuration validation
|
|
553
|
+
|
|
554
|
+
@basis-theory-elements/postmessage # Communication layer
|
|
555
|
+
├── client.ts # PostMessage client (parent side)
|
|
556
|
+
├── server.ts # PostMessage server (iframe side)
|
|
557
|
+
└── types.ts # Message type definitions
|
|
558
|
+
|
|
559
|
+
@basis-theory-elements/validation # Validation logic
|
|
560
|
+
├── validators/
|
|
561
|
+
│ ├── card-number.ts # Card number validation
|
|
562
|
+
│ ├── cvv.ts # CVV validation
|
|
563
|
+
│ └── expiry.ts # Expiry date validation
|
|
564
|
+
└── types.ts # Validation type definitions
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
**Benefits:**
|
|
568
|
+
|
|
569
|
+
- ✅ **Single Responsibility** - Each module does one thing well
|
|
570
|
+
- ✅ **Independently Testable** - Test each module in isolation
|
|
571
|
+
- ✅ **Reusable** - Other applications can use `@postmessage` or `@validation` without SDK
|
|
572
|
+
- ✅ **Clear Dependencies** - No circular references, clean module boundaries
|
|
573
|
+
|
|
574
|
+
**See [Coordinator Architecture](../../docs/architecture/coordinator.md) for detailed implementation.**
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## 📚 **Documentation**
|
|
579
|
+
|
|
580
|
+
- [Quick Start](./README.md) - This document
|
|
581
|
+
- [v3 Documentation](../../docs/README.md) - Complete architecture and implementation details
|
|
582
|
+
- [v2 to v3 Migration](../../docs/user-guide/migration.md) - Migration guide and improvements
|
|
583
|
+
|
|
584
|
+
**Related Packages:**
|
|
585
|
+
|
|
586
|
+
- [PostMessage Module](../postmessage/README.md) - Cross-iframe communication
|
|
587
|
+
- [Validation Module](../validation/README.md) - Payment data validation
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## 🤔 **Why Not Use v2 SDK?**
|
|
592
|
+
|
|
593
|
+
The v2 SDK (`@basis-theory/basis-theory-js`) has **accidental complexity**:
|
|
594
|
+
|
|
595
|
+
1. ❌ **Dynamic script loading** - CDN dependency, hard to test
|
|
596
|
+
2. ❌ **Global namespace pollution** - `window.BasisTheoryElements`
|
|
597
|
+
3. ❌ **RxJS dependency** - 35KB+ for simple pub-sub
|
|
598
|
+
4. ❌ **1147-line god class** - `BaseElement` does everything
|
|
599
|
+
5. ❌ **DataElement anti-pattern** - Hidden coordinator iframe
|
|
600
|
+
6. ❌ **Complex initialization** - 10+ async steps to initialize
|
|
601
|
+
7. ❌ **Over-abstraction** - Too many layers for PostMessage
|
|
602
|
+
|
|
603
|
+
**v3 fixes all of these:**
|
|
604
|
+
|
|
605
|
+
- ✅ **Direct ESM import** - no dynamic loading
|
|
606
|
+
- ✅ **Zero global pollution** - standard module imports
|
|
607
|
+
- ✅ **Zero RxJS dependency** - native `EventTarget`
|
|
608
|
+
- ✅ **Composition over inheritance** - focused modules
|
|
609
|
+
- ✅ **No hidden iframes** - SDK client handles coordination
|
|
610
|
+
- ✅ **Simple initialization** - one-step, synchronous
|
|
611
|
+
- ✅ **Clear separation of concerns** - mounting, messaging, validation are independent
|
|
612
|
+
|
|
613
|
+
**See [v2 to v3 Migration](../../docs/user-guide/migration.md) for detailed comparison.**
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
## 🐛 **Troubleshooting**
|
|
618
|
+
|
|
619
|
+
### **Element Not Mounting**
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
// Check if container exists
|
|
623
|
+
const container = document.querySelector('#card-number');
|
|
624
|
+
if (!container) {
|
|
625
|
+
console.error('Container not found');
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Check iframe origin
|
|
629
|
+
const bt = BasisTheory('pk_test_123', {
|
|
630
|
+
iframeOrigin: 'https://elements.basistheory.com', // Must be correct
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
// Enable debug logging
|
|
634
|
+
const bt = BasisTheory('pk_test_123', {
|
|
635
|
+
debug: true, // See PostMessage logs in console
|
|
636
|
+
});
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### **PostMessage Timeout**
|
|
640
|
+
|
|
641
|
+
```typescript
|
|
642
|
+
// Increase timeout for slow networks
|
|
643
|
+
const bt = BasisTheory('pk_test_123', {
|
|
644
|
+
timeoutMs: 10000, // 10 seconds
|
|
645
|
+
});
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### **CORS Errors**
|
|
649
|
+
|
|
650
|
+
```typescript
|
|
651
|
+
// Ensure iframe origin matches server
|
|
652
|
+
const bt = BasisTheory('pk_test_123', {
|
|
653
|
+
iframeOrigin: 'https://elements.basistheory.com', // Must match server
|
|
654
|
+
});
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
## 📄 **License**
|
|
660
|
+
|
|
661
|
+
MIT License - see [LICENSE](../../LICENSE) for details
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## 🤝 **Support**
|
|
666
|
+
|
|
667
|
+
- 📖 **Documentation**: [v3 Docs](../../docs/README.md)
|
|
668
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/basis-theory/elements/issues)
|
|
669
|
+
- 💬 **Community**: [Slack](https://community.basistheory.com)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_index-oREjBjga.js": {
|
|
3
|
+
"file": "index-oREjBjga.js",
|
|
4
|
+
"name": "index",
|
|
5
|
+
"dynamicImports": [
|
|
6
|
+
"src/elements/create-card.ts"
|
|
7
|
+
],
|
|
8
|
+
"integrity": "sha384-cJIUUFQ6r3cxVoriFOcPwaoiNh3fZEDVQnIz5vHikpBYUCFQXdq9TOK7zWchlegN"
|
|
9
|
+
},
|
|
10
|
+
"src/elements/create-card.ts": {
|
|
11
|
+
"file": "create-card-BuOvimjH.js",
|
|
12
|
+
"name": "create-card",
|
|
13
|
+
"src": "src/elements/create-card.ts",
|
|
14
|
+
"isDynamicEntry": true,
|
|
15
|
+
"imports": [
|
|
16
|
+
"_index-oREjBjga.js"
|
|
17
|
+
],
|
|
18
|
+
"integrity": "sha384-arcYvaRuIygr99TSB9iejT6KwhxJ61qf7bks9W+lE9+jTK1EmDkAdvliMYj7AyPj"
|
|
19
|
+
},
|
|
20
|
+
"src/index.ts": {
|
|
21
|
+
"file": "basis-theory-sdk.umd.js",
|
|
22
|
+
"name": "index",
|
|
23
|
+
"src": "src/index.ts",
|
|
24
|
+
"isEntry": true,
|
|
25
|
+
"integrity": "sha384-DDUToQ7bLJ9x04+C8ghbk7ooaa7vb4OCMffjVypI3Hd7THv8C5dQ8jHOjVCNaEwe"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BasisTheory API Client
|
|
3
|
+
*
|
|
4
|
+
* Provides tokenization, BIN lookup, and proxy services
|
|
5
|
+
*/
|
|
6
|
+
import type { BasisTheoryClient, HttpClientConfig } from './types';
|
|
7
|
+
/**
|
|
8
|
+
* Create BasisTheory API client
|
|
9
|
+
*/
|
|
10
|
+
export declare const createBasisTheoryClient: (apiKey: string, options?: Partial<HttpClientConfig>) => BasisTheoryClient;
|
|
11
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../../api-client/src/api-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EACV,iBAAiB,EAEjB,gBAAgB,EAKjB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,EACd,UAAS,OAAO,CAAC,gBAAgB,CAAM,KACtC,iBA0KF,CAAC"}
|