@idonatedev/idonate-sdk 1.2.0-dev14 → 1.2.0-dev16

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.
Files changed (34) hide show
  1. package/dist/constants.js +1 -1
  2. package/dist/esm/constants.js +1 -1
  3. package/dist/esm/tokenize/CardConnectTokenizer.d.ts +6 -1
  4. package/dist/esm/tokenize/CardConnectTokenizer.js +184 -53
  5. package/dist/esm/tokenize/PayPalTokenizer.d.ts +1 -0
  6. package/dist/esm/tokenize/PayPalTokenizer.js +52 -16
  7. package/dist/esm/tokenize/SpreedlyTokenizer.d.ts +6 -0
  8. package/dist/esm/tokenize/SpreedlyTokenizer.js +113 -63
  9. package/dist/esm/tokenize/Tokenizer.d.ts +6 -2
  10. package/dist/esm/tokenize/Tokenizer.js +13 -3
  11. package/dist/esm/tokenize/gateway-utils.js +3 -2
  12. package/dist/esm/tokenize/index.d.ts +1 -1
  13. package/dist/esm/tokenize/spreedly-secure.js +6 -2
  14. package/dist/esm/tokenize/tokenizer-utils.d.ts +1 -1
  15. package/dist/esm/tokenize/tokenizer-utils.js +25 -4
  16. package/dist/esm/tokenize/types.d.ts +3 -2
  17. package/dist/esm/typeAdapters.js +6 -4
  18. package/dist/tokenize/CardConnectTokenizer.d.ts +6 -1
  19. package/dist/tokenize/CardConnectTokenizer.js +184 -56
  20. package/dist/tokenize/PayPalTokenizer.d.ts +1 -0
  21. package/dist/tokenize/PayPalTokenizer.js +52 -16
  22. package/dist/tokenize/SpreedlyTokenizer.d.ts +6 -0
  23. package/dist/tokenize/SpreedlyTokenizer.js +113 -63
  24. package/dist/tokenize/Tokenizer.d.ts +6 -2
  25. package/dist/tokenize/Tokenizer.js +13 -3
  26. package/dist/tokenize/gateway-utils.js +3 -2
  27. package/dist/tokenize/index.d.ts +1 -1
  28. package/dist/tokenize/spreedly-secure.js +6 -2
  29. package/dist/tokenize/tokenizer-utils.d.ts +1 -1
  30. package/dist/tokenize/tokenizer-utils.js +25 -4
  31. package/dist/tokenize/types.d.ts +3 -2
  32. package/dist/typeAdapters.js +6 -4
  33. package/package.json +1 -1
  34. package/umd/idonate-sdk.js +1 -1
@@ -66,7 +66,7 @@ export class SpreedlyTokenizer extends Tokenizer {
66
66
  }
67
67
  static create(gateway, container, config) {
68
68
  return __awaiter(this, void 0, void 0, function* () {
69
- var _a;
69
+ var _a, _b;
70
70
  if (container.mode !== 'bank_account') {
71
71
  yield SpreedlyTokenizer.ensureSpreedlyLoaded();
72
72
  }
@@ -75,9 +75,9 @@ export class SpreedlyTokenizer extends Tokenizer {
75
75
  environmentKey = config.clientConfig.spreedlyEnvironmentKey;
76
76
  }
77
77
  if (!environmentKey) {
78
- environmentKey = '';
78
+ throw new Error('Spreedly environment key is required. Provide it via gateway.config.environmentKey or client config.');
79
79
  }
80
- const tokenizer = new SpreedlyTokenizer(environmentKey, container.containerId, container.styling, container.mode || 'credit_card', container.bankCountry || 'US', container.enableTestMode || false, container.layout || 'single-line', container.responsiveBreakpoint || RESPONSIVE_BREAKPOINT);
80
+ const tokenizer = new SpreedlyTokenizer(environmentKey, container.containerId, container.styling, container.mode || 'credit_card', container.bankCountry || 'US', container.enableTestMode || false, container.layout || 'single-line', (_b = container.responsiveBreakpoint) !== null && _b !== void 0 ? _b : RESPONSIVE_BREAKPOINT);
81
81
  tokenizer.organizationId = config.organizationId;
82
82
  tokenizer.embedId = config.embedId;
83
83
  tokenizer.clientConfig = config.clientConfig;
@@ -158,8 +158,29 @@ export class SpreedlyTokenizer extends Tokenizer {
158
158
  this.emit('ready');
159
159
  resolve();
160
160
  });
161
+ this.spreedly.on('paymentMethod', (token, pmData) => {
162
+ const paymentToken = {
163
+ token,
164
+ lastFour: pmData.last_four_digits,
165
+ cardType: this.normalizeCardType(pmData.card_type),
166
+ paymentMethodType: 'credit_card',
167
+ provider: 'spreedly',
168
+ };
169
+ if (this.tokenizationResolve) {
170
+ const resolveTokenization = this.tokenizationResolve;
171
+ this.clearTokenizationState();
172
+ this.emit('tokenReady', paymentToken);
173
+ resolveTokenization(paymentToken);
174
+ }
175
+ });
161
176
  this.spreedly.on('errors', (errors) => {
162
- this.emit('error', new TokenizationError(errors));
177
+ const error = new TokenizationError(errors);
178
+ this.emit('error', error);
179
+ if (this.tokenizationReject) {
180
+ const rejectTokenization = this.tokenizationReject;
181
+ this.clearTokenizationState();
182
+ rejectTokenization(error);
183
+ }
163
184
  });
164
185
  this.spreedly.on('fieldEvent', (fieldName, eventType, activeEl, inputProperties) => {
165
186
  this.handleFieldEvent(fieldName, eventType, inputProperties);
@@ -185,6 +206,19 @@ export class SpreedlyTokenizer extends Tokenizer {
185
206
  });
186
207
  }
187
208
  tokenizeCardInternal(cardData) {
209
+ if (this.tokenizationPromise) {
210
+ return this.tokenizationPromise;
211
+ }
212
+ const expiry = this.parseExpiry(this.expiryEl);
213
+ if (!expiry) {
214
+ return Promise.reject(new TokenizationError('Expiration date is required', 'VALIDATION_ERROR'));
215
+ }
216
+ this.tokenizationPromise = this.executeCardTokenization(cardData, expiry).finally(() => {
217
+ this.tokenizationPromise = undefined;
218
+ });
219
+ return this.tokenizationPromise;
220
+ }
221
+ executeCardTokenization(cardData, expiry) {
188
222
  return __awaiter(this, void 0, void 0, function* () {
189
223
  var _a;
190
224
  let securityFields = {};
@@ -204,42 +238,13 @@ export class SpreedlyTokenizer extends Tokenizer {
204
238
  }
205
239
  return new Promise((resolve, reject) => {
206
240
  var _a, _b, _c, _d, _e, _f;
207
- const timeout = setTimeout(() => {
208
- if (this.spreedly && this.spreedly.removeHandlers) {
209
- this.spreedly.removeHandlers();
210
- }
241
+ this.tokenizationResolve = resolve;
242
+ this.tokenizationReject = reject;
243
+ this.tokenizationTimeout = setTimeout(() => {
244
+ this.clearTokenizationState();
211
245
  reject(new TokenizationError('Tokenization timeout', 'TIMEOUT'));
212
246
  }, TOKENIZE_TIMEOUT);
213
- const cleanup = () => {
214
- clearTimeout(timeout);
215
- if (this.spreedly && this.spreedly.removeHandlers) {
216
- this.spreedly.removeHandlers();
217
- }
218
- };
219
- this.spreedly.on('paymentMethod', (token, pmData) => {
220
- cleanup();
221
- const paymentToken = {
222
- token,
223
- lastFour: pmData.last_four_digits,
224
- cardType: this.normalizeCardType(pmData.card_type),
225
- provider: 'spreedly',
226
- };
227
- this.emit('tokenReady', paymentToken);
228
- resolve(paymentToken);
229
- });
230
- this.spreedly.on('errors', (errors) => {
231
- cleanup();
232
- reject(new TokenizationError(errors));
233
- });
234
- const expiry = this.parseExpiry(this.expiryEl);
235
- if (!expiry) {
236
- cleanup();
237
- reject(new TokenizationError('Expiration date is required', 'VALIDATION_ERROR'));
238
- return;
239
- }
240
- const expiryMonth = expiry.month;
241
- const expiryYear = expiry.year;
242
- this.spreedly.tokenizeCreditCard(Object.assign({ first_name: cardData.firstName, last_name: cardData.lastName, month: expiryMonth, year: expiryYear, email: cardData.email, phone_number: cardData.phone, address1: (_a = cardData.address) === null || _a === void 0 ? void 0 : _a.address1, address2: (_b = cardData.address) === null || _b === void 0 ? void 0 : _b.address2, city: (_c = cardData.address) === null || _c === void 0 ? void 0 : _c.city, state: (_d = cardData.address) === null || _d === void 0 ? void 0 : _d.state, zip: (_e = cardData.address) === null || _e === void 0 ? void 0 : _e.zip, country: (_f = cardData.address) === null || _f === void 0 ? void 0 : _f.country }, securityFields));
247
+ this.spreedly.tokenizeCreditCard(Object.assign({ first_name: cardData.firstName, last_name: cardData.lastName, month: expiry.month, year: expiry.year, email: cardData.email, phone_number: cardData.phone, address1: (_a = cardData.address) === null || _a === void 0 ? void 0 : _a.address1, address2: (_b = cardData.address) === null || _b === void 0 ? void 0 : _b.address2, city: (_c = cardData.address) === null || _c === void 0 ? void 0 : _c.city, state: (_d = cardData.address) === null || _d === void 0 ? void 0 : _d.state, zip: (_e = cardData.address) === null || _e === void 0 ? void 0 : _e.zip, country: (_f = cardData.address) === null || _f === void 0 ? void 0 : _f.country }, securityFields));
243
248
  });
244
249
  });
245
250
  }
@@ -432,17 +437,22 @@ export class SpreedlyTokenizer extends Tokenizer {
432
437
  accountHolderType: accountHolderType,
433
438
  },
434
439
  }, this.clientConfig, this.environmentKey);
435
- return {
440
+ const paymentToken = {
436
441
  token: result,
437
442
  lastFour: accountNumber.slice(-4),
438
443
  accountType: accountType,
439
444
  paymentMethodType: 'bank_account',
440
445
  provider: 'spreedly',
441
446
  };
447
+ this.emit('tokenReady', paymentToken);
448
+ return paymentToken;
442
449
  });
443
450
  }
444
451
  validate() {
445
452
  return __awaiter(this, void 0, void 0, function* () {
453
+ if (!this.isReady) {
454
+ throw new Error('Tokenizer not initialized');
455
+ }
446
456
  if (this.mode === 'bank_account') {
447
457
  return this.validateBankAccountInternal();
448
458
  }
@@ -630,13 +640,31 @@ export class SpreedlyTokenizer extends Tokenizer {
630
640
  this.accountNumberEl.value = '';
631
641
  if (this.accountTypeEl)
632
642
  this.accountTypeEl.selectedIndex = 0;
643
+ this.currentValidationState = {
644
+ isValid: false,
645
+ routingNumber: { isValid: false, isEmpty: true },
646
+ accountNumber: { isValid: false, isEmpty: true },
647
+ };
633
648
  }
634
649
  else {
635
650
  this.spreedly.reload();
636
651
  if (this.expiryEl) {
637
652
  this.expiryEl.value = '';
638
653
  }
654
+ this.currentValidationState = {
655
+ isValid: false,
656
+ cardNumber: { isValid: false, isEmpty: true },
657
+ cvv: { isValid: false, isEmpty: true },
658
+ expiry: { isValid: false, isEmpty: true },
659
+ };
660
+ }
661
+ if (this.tokenizationReject) {
662
+ const reject = this.tokenizationReject;
663
+ this.clearTokenizationState();
664
+ reject(new TokenizationError('Tokenizer cleared', 'CLEARED'));
639
665
  }
666
+ this.clearTokenizationState();
667
+ this.emit('validation', this.currentValidationState);
640
668
  }
641
669
  focus(field) {
642
670
  if (this.mode === 'bank_account') {
@@ -727,14 +755,29 @@ export class SpreedlyTokenizer extends Tokenizer {
727
755
  }
728
756
  }
729
757
  }
758
+ clearTokenizationState() {
759
+ if (this.tokenizationTimeout) {
760
+ clearTimeout(this.tokenizationTimeout);
761
+ this.tokenizationTimeout = undefined;
762
+ }
763
+ this.tokenizationResolve = undefined;
764
+ this.tokenizationReject = undefined;
765
+ }
730
766
  destroy() {
731
767
  var _a;
768
+ this.markDestroyed();
732
769
  (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
770
+ if (this.tokenizationReject) {
771
+ const reject = this.tokenizationReject;
772
+ this.clearTokenizationState();
773
+ reject(new TokenizationError('Tokenizer destroyed', 'DESTROYED'));
774
+ }
733
775
  if (this.spreedly && this.spreedly.removeHandlers) {
734
776
  this.spreedly.removeHandlers();
735
777
  }
736
778
  this.eventHandlers.clear();
737
- if (this.expiryEl) {
779
+ if (this.containerEl) {
780
+ this.containerEl.innerHTML = '';
738
781
  }
739
782
  }
740
783
  hasToken() {
@@ -781,15 +824,6 @@ export class SpreedlyTokenizer extends Tokenizer {
781
824
  }
782
825
  this.updateOverallValidation();
783
826
  }
784
- if (eventType === 'focus') {
785
- this.emit('focus', { field: fieldName });
786
- }
787
- else if (eventType === 'blur') {
788
- this.emit('blur', { field: fieldName });
789
- }
790
- else if (eventType === 'input') {
791
- this.emit('change', { field: fieldName });
792
- }
793
827
  }
794
828
  createInternalElements() {
795
829
  const container = document.getElementById(this.containerId);
@@ -835,6 +869,10 @@ export class SpreedlyTokenizer extends Tokenizer {
835
869
  };
836
870
  this.updateOverallValidation();
837
871
  });
872
+ this.expiryEl.addEventListener('blur', () => {
873
+ this.validateExpiry();
874
+ this.updateOverallValidation();
875
+ });
838
876
  container.appendChild(this.expiryEl);
839
877
  const cvvDiv = createFieldContainer(this.cvvEl, '1', FIELD_FLEX.cvv.minWidth);
840
878
  cvvDiv.style.height = this.mergedStyles.input.height;
@@ -862,6 +900,10 @@ export class SpreedlyTokenizer extends Tokenizer {
862
900
  };
863
901
  this.updateOverallValidation();
864
902
  });
903
+ this.expiryEl.addEventListener('blur', () => {
904
+ this.validateExpiry();
905
+ this.updateOverallValidation();
906
+ });
865
907
  container.appendChild(this.expiryEl);
866
908
  const cvvDiv = createFieldContainer(this.cvvEl, FIELD_FLEX.cvv.flex, FIELD_FLEX.cvv.minWidth);
867
909
  cvvDiv.style.height = this.mergedStyles.input.height;
@@ -1024,23 +1066,31 @@ export class SpreedlyTokenizer extends Tokenizer {
1024
1066
  if (!this.expiryEl)
1025
1067
  return;
1026
1068
  const expiry = this.parseExpiry(this.expiryEl);
1069
+ const isEmpty = !this.expiryEl.value;
1070
+ let isValid = false;
1027
1071
  if (!expiry) {
1028
- this.applyErrorStyles(this.expiryEl);
1029
- return;
1030
- }
1031
- const month = parseInt(expiry.month, 10);
1032
- const year = parseInt(expiry.year, 10);
1033
- if (month < 1 || month > 12) {
1034
- this.applyErrorStyles(this.expiryEl);
1035
- return;
1072
+ if (!isEmpty)
1073
+ this.applyErrorStyles(this.expiryEl);
1036
1074
  }
1037
- const now = new Date();
1038
- const expiryDate = new Date(year, month - 1);
1039
- if (expiryDate < now) {
1040
- this.applyErrorStyles(this.expiryEl);
1041
- return;
1075
+ else {
1076
+ const month = parseInt(expiry.month, 10);
1077
+ const year = parseInt(expiry.year, 10);
1078
+ if (month < 1 || month > 12) {
1079
+ this.applyErrorStyles(this.expiryEl);
1080
+ }
1081
+ else {
1082
+ const now = new Date();
1083
+ const expiryEndDate = new Date(year, month);
1084
+ if (expiryEndDate <= now) {
1085
+ this.applyErrorStyles(this.expiryEl);
1086
+ }
1087
+ else {
1088
+ isValid = true;
1089
+ this.applyInputStyles(this.expiryEl, this.mergedStyles, 'middle');
1090
+ }
1091
+ }
1042
1092
  }
1043
- this.applyInputStyles(this.expiryEl, this.mergedStyles, 'middle');
1093
+ this.currentValidationState.expiry = { isValid, isEmpty };
1044
1094
  }
1045
1095
  applyErrorStyles(element) {
1046
1096
  if (this.mergedStyles.error) {
@@ -2,9 +2,13 @@ import { CardData, BankAccountData, PaymentData, PaymentToken, ValidationResult,
2
2
  import ConfigHandler from '../config-handler';
3
3
  export declare abstract class Tokenizer {
4
4
  protected mode: PaymentMethodMode;
5
- protected eventHandlers: Map<TokenizerEvent, Set<(data?: any) => void>>;
5
+ protected eventHandlers: Map<string, Set<(data?: any) => void>>;
6
+ private focusHandlerElements;
6
7
  private _isReady;
8
+ private _isDestroyed;
7
9
  get isReady(): boolean;
10
+ get isDestroyed(): boolean;
11
+ protected markDestroyed(): void;
8
12
  abstract tokenize(paymentData: PaymentData): Promise<PaymentToken>;
9
13
  abstract validate(): Promise<ValidationResult>;
10
14
  abstract clear(): void;
@@ -16,7 +20,7 @@ export declare abstract class Tokenizer {
16
20
  getMode(): PaymentMethodMode;
17
21
  on(event: TokenizerEvent, handler: (data?: any) => void): void;
18
22
  off(event: TokenizerEvent, handler: (data?: any) => void): void;
19
- protected emit(event: TokenizerEvent, data?: any): void;
23
+ protected emit(event: string, data?: any): void;
20
24
  protected isCardData(data: PaymentData): data is CardData;
21
25
  protected isBankAccountData(data: PaymentData): data is BankAccountData;
22
26
  protected normalizeCardType(providerCardType: string): CardType;
@@ -13,10 +13,18 @@ export class Tokenizer {
13
13
  constructor() {
14
14
  this.mode = 'credit_card';
15
15
  this.eventHandlers = new Map();
16
+ this.focusHandlerElements = new WeakSet();
16
17
  this._isReady = false;
18
+ this._isDestroyed = false;
17
19
  }
18
20
  get isReady() {
19
- return this._isReady;
21
+ return this._isReady && !this._isDestroyed;
22
+ }
23
+ get isDestroyed() {
24
+ return this._isDestroyed;
25
+ }
26
+ markDestroyed() {
27
+ this._isDestroyed = true;
20
28
  }
21
29
  getMode() {
22
30
  return this.mode;
@@ -82,7 +90,6 @@ export class Tokenizer {
82
90
  expiryEl.addEventListener('input', (e) => {
83
91
  const target = e.target;
84
92
  target.value = formatExpiryInput(target.value);
85
- this.emit('change', { field: 'expiry' });
86
93
  });
87
94
  expiryEl.addEventListener('keypress', (e) => {
88
95
  const char = String.fromCharCode(e.which);
@@ -133,7 +140,10 @@ export class Tokenizer {
133
140
  element.style.border = inputStyles.border;
134
141
  element.style.borderRadius = inputStyles.borderRadius;
135
142
  }
136
- addFocusHandlers(element, styles);
143
+ if (!this.focusHandlerElements.has(element)) {
144
+ addFocusHandlers(element, styles, position);
145
+ this.focusHandlerElements.add(element);
146
+ }
137
147
  }
138
148
  generateFieldIds(containerId) {
139
149
  return {
@@ -10,8 +10,9 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  export function normalizeGateway(input) {
13
- if (!input)
14
- return input;
13
+ if (!input) {
14
+ throw new Error('Gateway is required but received ' + String(input));
15
+ }
15
16
  if (input.backendName !== undefined)
16
17
  return input;
17
18
  const _a = input.config || {}, { environment_key, base_url, merchant_id } = _a, extraConfigKeys = __rest(_a, ["environment_key", "base_url", "merchant_id"]);
@@ -3,6 +3,6 @@ export { Tokenizer } from './Tokenizer';
3
3
  export { SpreedlyTokenizer } from './SpreedlyTokenizer';
4
4
  export { CardConnectTokenizer } from './CardConnectTokenizer';
5
5
  export { PayPalTokenizer, PayPalCreateOrderData } from './PayPalTokenizer';
6
- export { PaymentMethodType, PaymentGateway, TokenizerContainer, TokenizerStyling, CardData, PaymentData, PaymentToken, CardType, TokenizerEvent, ValidationState, ValidationResult, ValidationError, TokenizationError, } from './types';
6
+ export { PaymentMethodType, PaymentMethodMode, PaymentGateway, TokenizerContainer, TokenizerStyling, CardData, BankAccountData, PaymentData, PaymentToken, CardType, TokenizerEvent, ValidationState, ValidationResult, ValidationError, TokenizationError, } from './types';
7
7
  export { normalizeGateway } from './gateway-utils';
8
8
  export { iats };
@@ -13,6 +13,7 @@ export function fetchSpreedlySecurityArgs(config, organizationId, embedId) {
13
13
  throw new Error('Secure tokenization is not enabled');
14
14
  }
15
15
  const makeRequest = () => __awaiter(this, void 0, void 0, function* () {
16
+ var _a;
16
17
  const response = yield fetch(`${config.embedApiBaseUrl}/spreedly/security-args`, {
17
18
  method: 'POST',
18
19
  headers: { 'Content-Type': 'application/json' },
@@ -24,13 +25,16 @@ export function fetchSpreedlySecurityArgs(config, organizationId, embedId) {
24
25
  if (!response.ok) {
25
26
  throw new Error(`Security args request failed: ${response.status}`);
26
27
  }
27
- return response.json();
28
+ const data = yield response.json();
29
+ return (_a = data.result) !== null && _a !== void 0 ? _a : data;
28
30
  });
29
31
  try {
30
32
  return yield makeRequest();
31
33
  }
32
34
  catch (error) {
33
- if (error instanceof TypeError && error.message.includes('fetch')) {
35
+ const isNetworkError = error instanceof TypeError && error.message.includes('fetch');
36
+ const isServerError = error instanceof Error && error.message.includes('failed: 5');
37
+ if (isNetworkError || isServerError) {
34
38
  yield new Promise((resolve) => setTimeout(resolve, 1000));
35
39
  return makeRequest();
36
40
  }
@@ -6,7 +6,7 @@ export declare function parseExpiryDate(value: string): {
6
6
  export declare function formatExpiryInput(value: string): string;
7
7
  export declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string): Promise<T>;
8
8
  export declare function getConnectedBorderRadius(baseRadius: string, position: 'left' | 'middle' | 'right', isConnected: boolean): string;
9
- export declare function addFocusHandlers(element: HTMLElement, styles: TokenizerStylingComplete, onFocus?: () => void, onBlur?: () => void): void;
9
+ export declare function addFocusHandlers(element: HTMLElement, styles: TokenizerStylingComplete, position?: 'left' | 'middle' | 'right', onFocus?: () => void, onBlur?: () => void): void;
10
10
  export declare function createFieldContainer(id: string, flex: string, minWidth?: string, maxWidth?: string): HTMLDivElement;
11
11
  export declare function createInputElement(id: string, type: string, placeholder: string, maxLength?: number): HTMLInputElement;
12
12
  export declare function validateRoutingNumber(routingNumber: string): boolean;
@@ -39,7 +39,7 @@ export function getConnectedBorderRadius(baseRadius, position, isConnected) {
39
39
  return baseRadius;
40
40
  }
41
41
  }
42
- export function addFocusHandlers(element, styles, onFocus, onBlur) {
42
+ export function addFocusHandlers(element, styles, position, onFocus, onBlur) {
43
43
  element.addEventListener('focus', () => {
44
44
  if (styles.focus) {
45
45
  Object.assign(element.style, styles.focus);
@@ -47,9 +47,30 @@ export function addFocusHandlers(element, styles, onFocus, onBlur) {
47
47
  onFocus === null || onFocus === void 0 ? void 0 : onFocus();
48
48
  });
49
49
  element.addEventListener('blur', () => {
50
- element.style.border = styles.input.border;
51
- element.style.outline = 'none';
52
- element.style.boxShadow = 'none';
50
+ const isConnected = styles.container.gap === '0';
51
+ if (isConnected && position) {
52
+ element.style.borderTop = styles.input.border;
53
+ element.style.borderBottom = styles.input.border;
54
+ switch (position) {
55
+ case 'left':
56
+ element.style.borderLeft = styles.input.border;
57
+ element.style.borderRight = 'none';
58
+ break;
59
+ case 'middle':
60
+ element.style.borderLeft = styles.input.border;
61
+ element.style.borderRight = 'none';
62
+ break;
63
+ case 'right':
64
+ element.style.borderLeft = styles.input.border;
65
+ element.style.borderRight = styles.input.border;
66
+ break;
67
+ }
68
+ }
69
+ else {
70
+ element.style.border = styles.input.border;
71
+ }
72
+ element.style.outline = '';
73
+ element.style.boxShadow = '';
53
74
  onBlur === null || onBlur === void 0 ? void 0 : onBlur();
54
75
  });
55
76
  }
@@ -1,5 +1,5 @@
1
1
  export type PaymentMethodType = 'credit_card' | 'bank_account' | 'paypal' | 'apple_pay' | 'google_pay';
2
- export type PaymentMethodMode = 'credit_card' | 'bank_account';
2
+ export type PaymentMethodMode = 'credit_card' | 'bank_account' | 'paypal';
3
3
  export interface PaymentGateway {
4
4
  id: string;
5
5
  backendName: string;
@@ -106,9 +106,10 @@ export interface PaymentToken {
106
106
  paymentTransactionId?: string;
107
107
  }
108
108
  export type CardType = 'visa' | 'mastercard' | 'amex' | 'discover' | 'diners' | 'jcb' | 'unknown';
109
- export type TokenizerEvent = 'ready' | 'focus' | 'blur' | 'change' | 'validation' | 'cardTypeChange' | 'error' | 'tokenization' | 'tokenReady';
109
+ export type TokenizerEvent = 'ready' | 'validation' | 'cardTypeChange' | 'error' | 'tokenReady';
110
110
  export interface ValidationState {
111
111
  isValid: boolean;
112
+ hasToken?: boolean;
112
113
  cardNumber?: {
113
114
  isValid: boolean;
114
115
  isEmpty: boolean;
@@ -102,16 +102,18 @@ export function buildCashPaymentPayload(organizationId, input) {
102
102
  utmFields.utm_term = input.utm.term;
103
103
  }
104
104
  }
105
+ let remainingMeta = input.customerMeta
106
+ ? Object.assign({}, input.customerMeta) : {};
105
107
  if (input.customerMeta) {
106
108
  [1, 2, 3, 4, 5].forEach((customNoteIndex) => {
107
109
  const key = `custom_note_${customNoteIndex}`;
108
- if (input.customerMeta[key]) {
109
- donationOptions[key] = input.customerMeta[key];
110
- delete input.customerMeta[key];
110
+ if (remainingMeta[key]) {
111
+ donationOptions[key] = remainingMeta[key];
112
+ delete remainingMeta[key];
111
113
  }
112
114
  });
113
115
  }
114
- return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, donationOptions), billingAddress), billingContact), payment), utmFields), { customer_meta: input.customerMeta || {}, recaptcha_token: input.recaptchaToken, recaptcha_type: input.recaptchaType });
116
+ return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, donationOptions), billingAddress), billingContact), payment), utmFields), { customer_meta: remainingMeta, recaptcha_token: input.recaptchaToken, recaptcha_type: input.recaptchaType });
115
117
  }
116
118
  export function buildDonationResult(response) {
117
119
  let campaign;
@@ -16,10 +16,13 @@ export declare class CardConnectTokenizer extends Tokenizer {
16
16
  private accountTypeEl?;
17
17
  private enableTestMode;
18
18
  private cachedTokenResult?;
19
+ private acceptAutoToken;
19
20
  private tokenizationPromise?;
20
21
  private tokenizationResolve?;
21
22
  private tokenizationReject?;
22
23
  private currentCardType?;
24
+ private tokenizationTimeout?;
25
+ private mergedStyles?;
23
26
  private constructor();
24
27
  static create(gateway: PaymentGateway, container: TokenizerContainer, config: {
25
28
  organizationId: string;
@@ -29,6 +32,8 @@ export declare class CardConnectTokenizer extends Tokenizer {
29
32
  private createInternalElements;
30
33
  private createCreditCardFields;
31
34
  private createBankAccountFields;
35
+ private addBankAccountValidationListeners;
36
+ private updateBankAccountValidation;
32
37
  private init;
33
38
  tokenize(paymentData: PaymentData): Promise<PaymentToken>;
34
39
  private tokenizeCardInternal;
@@ -47,5 +52,5 @@ export declare class CardConnectTokenizer extends Tokenizer {
47
52
  private static generateIframeUrl;
48
53
  private static createIframe;
49
54
  private static generateCardConnectCss;
50
- static tokenizeBankAccount(routingNumber: string, accountNumber: string, config: ConfigHandler): Promise<TokenizeCardConnectBankAccountResult>;
55
+ static tokenizeBankAccount(routingNumber: string, accountNumber: string, configOrBaseUrl: ConfigHandler | string): Promise<TokenizeCardConnectBankAccountResult>;
51
56
  }