@idonatedev/idonate-sdk 1.2.0-dev7 → 1.2.0-dev9

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/dist/constants.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CLIENT_HEADERS = exports.CARD_CONNECT_DEFAULT_STYLE = exports.DEFAULT_APP_NAME = exports.DEFAULT_CF_TURNSTILE_CDN_EXPLICIT_URL = exports.FALLBACK_CF_TURNSTILE_SITE_KEY = exports.FALLBACK_PC_SCRIPT_ID = exports.FALLBACK_PC_SCRIPT_URL = exports.SANDBOX_APPLE_PAY_URL = exports.APPLE_PAY_URL = exports.SPREEDLY_TOKENIZER_URL = exports.SANDBOX_CARD_CONNECT_BASE_URL = exports.PRODUCTION_CARD_CONNECT_BASE_URL = exports.SANDBOX_BASE_URL = exports.PRODUCTION_BASE_URL = exports.SDK_VERSION = void 0;
4
- exports.SDK_VERSION = '1.2.0-dev7';
4
+ exports.SDK_VERSION = '1.2.0-dev9';
5
5
  exports.PRODUCTION_BASE_URL = 'https://secure-api.idonate.com';
6
6
  exports.SANDBOX_BASE_URL = 'https://api.qa-idonate.com';
7
7
  exports.PRODUCTION_CARD_CONNECT_BASE_URL = 'https://boltgw.cardconnect.com:8443';
@@ -1,4 +1,4 @@
1
- export const SDK_VERSION = '1.2.0-dev7';
1
+ export const SDK_VERSION = '1.2.0-dev9';
2
2
  export const PRODUCTION_BASE_URL = 'https://secure-api.idonate.com';
3
3
  export const SANDBOX_BASE_URL = 'https://api.qa-idonate.com';
4
4
  export const PRODUCTION_CARD_CONNECT_BASE_URL = 'https://boltgw.cardconnect.com:8443';
@@ -11,7 +11,7 @@ import { Tokenizer } from './Tokenizer';
11
11
  import { TokenizationError, } from './types';
12
12
  import ConfigHandler from '../config-handler';
13
13
  import { DEFAULT_UNIFIED_STYLES, mergeStyles, getContainerStylesForLayout, } from './styles';
14
- import { INIT_TIMEOUT, TOKENIZE_TIMEOUT, BANK_FIELD_FLEX, } from './tokenizer-constants';
14
+ import { INIT_TIMEOUT, TOKENIZE_TIMEOUT, BANK_FIELD_FLEX, RESPONSIVE_BREAKPOINT, } from './tokenizer-constants';
15
15
  import { createInputElement, validateRoutingNumber, validateAccountNumber, createAccountTypeSelect, } from './tokenizer-utils';
16
16
  export class CardConnectTokenizer extends Tokenizer {
17
17
  constructor(iframe, iframeUrl, containerId, mode = 'credit_card', enableTestMode = false, layout = 'single-line') {
@@ -38,13 +38,25 @@ export class CardConnectTokenizer extends Tokenizer {
38
38
  if (container.mode === 'bank_account' && container.bankCountry === 'CA') {
39
39
  throw new Error('CardConnect does not support Canadian bank accounts');
40
40
  }
41
+ let effectiveLayout = 'single-line';
42
+ if (container.layout === 'responsive') {
43
+ const containerEl = document.getElementById(container.containerId);
44
+ const containerWidth = (containerEl === null || containerEl === void 0 ? void 0 : containerEl.offsetWidth) || 0;
45
+ const breakpoint = container.responsiveBreakpoint || RESPONSIVE_BREAKPOINT;
46
+ effectiveLayout =
47
+ containerWidth < breakpoint ? 'two-line' : 'single-line';
48
+ }
49
+ else if (container.layout === 'two-line') {
50
+ effectiveLayout = 'two-line';
51
+ }
52
+ const resolvedContainer = Object.assign(Object.assign({}, container), { layout: effectiveLayout });
41
53
  let baseUrl = ((_a = gateway.config) === null || _a === void 0 ? void 0 : _a.base_url) || config.clientConfig.cardConnectBaseUrl;
42
54
  config.cardConnectBaseUrl = baseUrl;
43
55
  const mergedStyles = mergeStyles(DEFAULT_UNIFIED_STYLES, container.styling);
44
- const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, container);
56
+ const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, resolvedContainer);
45
57
  const iframe = CardConnectTokenizer.createIframe(iframeUrl, mergedStyles);
46
- const tokenizer = new CardConnectTokenizer(iframe, iframeUrl, container.containerId, container.mode || 'credit_card', container.enableTestMode || false, container.layout || 'single-line');
47
- tokenizer.createInternalElements(container);
58
+ const tokenizer = new CardConnectTokenizer(iframe, iframeUrl, container.containerId, container.mode || 'credit_card', container.enableTestMode || false, effectiveLayout);
59
+ tokenizer.createInternalElements(resolvedContainer);
48
60
  yield tokenizer.init();
49
61
  return tokenizer;
50
62
  });
@@ -67,7 +79,7 @@ export class CardConnectTokenizer extends Tokenizer {
67
79
  }
68
80
  createCreditCardFields(containerEl, mergedStyles) {
69
81
  this.iframe.style.width = '100%';
70
- if (this.layout === 'two-line') {
82
+ if (this.layout === 'two-line' || this.layout === 'responsive') {
71
83
  const inputHeight = mergedStyles.input.height || '40px';
72
84
  this.iframe.style.height = `calc((${inputHeight}) * 2 + 10px)`;
73
85
  }
@@ -578,7 +590,12 @@ export class CardConnectTokenizer extends Tokenizer {
578
590
  params.set('placeholderyear', 'YYYY');
579
591
  }
580
592
  const mergedStyles = mergeStyles(DEFAULT_UNIFIED_STYLES, container.styling);
581
- const cssString = CardConnectTokenizer.generateCardConnectCss(mergedStyles, container.layout || 'single-line');
593
+ const isDesktopSafari = typeof navigator !== 'undefined' &&
594
+ /Safari/.test(navigator.userAgent) &&
595
+ /Apple Computer/.test(navigator.vendor) &&
596
+ !/Chrome/.test(navigator.userAgent) &&
597
+ !/Mobile/.test(navigator.userAgent);
598
+ const cssString = CardConnectTokenizer.generateCardConnectCss(mergedStyles, (container.layout || 'single-line'), isDesktopSafari);
582
599
  const queryPairs = [];
583
600
  params.forEach((value, key) => {
584
601
  queryPairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
@@ -611,8 +628,8 @@ export class CardConnectTokenizer extends Tokenizer {
611
628
  iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms');
612
629
  return iframe;
613
630
  }
614
- static generateCardConnectCss(styles, layout = 'single-line') {
615
- var _a, _b, _c, _d;
631
+ static generateCardConnectCss(styles, layout = 'single-line', isDesktopSafari = false) {
632
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
616
633
  const css = [];
617
634
  if (layout === 'two-line') {
618
635
  css.push('html,form,body{margin:0;padding:0;}');
@@ -646,14 +663,22 @@ export class CardConnectTokenizer extends Tokenizer {
646
663
  commonStyles.push('box-sizing:border-box');
647
664
  const baseStyles = commonStyles.join(';');
648
665
  css.push(`input{${baseStyles};}`);
649
- css.push(`select{${baseStyles};}`);
666
+ if (isDesktopSafari) {
667
+ css.push(`select{${baseStyles};-webkit-appearance:none;appearance:none;}`);
668
+ }
669
+ else {
670
+ css.push(`select{${baseStyles};}`);
671
+ }
650
672
  }
651
673
  if (layout === 'two-line') {
652
674
  css.push('input#ccnumfield{width:100%;display:block;margin-bottom:8px;}');
653
- css.push('input#ccexpiryfieldmonth{width:20%;}');
654
- css.push('input#ccexpiryfieldyear{width:24%;}');
655
- css.push('input#cccvvfield{width:calc(56% - 20px);}');
656
- if ((_a = styles.input) === null || _a === void 0 ? void 0 : _a.borderRadius) {
675
+ const twoLinePadding = ((_a = styles.twoLine) === null || _a === void 0 ? void 0 : _a.padding) || ((_b = styles.input) === null || _b === void 0 ? void 0 : _b.padding) || '10px';
676
+ const twoLineFontSize = ((_c = styles.twoLine) === null || _c === void 0 ? void 0 : _c.fontSize) || ((_d = styles.input) === null || _d === void 0 ? void 0 : _d.fontSize) || '14px';
677
+ const twoLineTextAlign = ((_e = styles.twoLine) === null || _e === void 0 ? void 0 : _e.textAlign) || 'left';
678
+ css.push(`input#ccexpiryfieldmonth{width:25%;padding:${twoLinePadding};font-size:${twoLineFontSize};text-align:${twoLineTextAlign};}`);
679
+ css.push(`input#ccexpiryfieldyear{width:35%;padding:${twoLinePadding};font-size:${twoLineFontSize};text-align:${twoLineTextAlign};}`);
680
+ css.push(`input#cccvvfield{width:calc(40% - 16px);padding:${twoLinePadding};font-size:${twoLineFontSize};text-align:${twoLineTextAlign};margin-left:-4px;}`);
681
+ if ((_f = styles.input) === null || _f === void 0 ? void 0 : _f.borderRadius) {
657
682
  css.push(`input{border-radius:${styles.input.borderRadius};}`);
658
683
  }
659
684
  }
@@ -662,7 +687,7 @@ export class CardConnectTokenizer extends Tokenizer {
662
687
  css.push('select#ccexpirymonth{width:16%;margin:0;margin-right:-12px;}');
663
688
  css.push('select#ccexpiryyear{width:20%;}');
664
689
  css.push('input#cccvvfield{width:20%;margin:0;margin-left:-12px;}');
665
- if ((_b = styles.input) === null || _b === void 0 ? void 0 : _b.borderRadius) {
690
+ if ((_g = styles.input) === null || _g === void 0 ? void 0 : _g.borderRadius) {
666
691
  css.push(`input#ccnumfield{border-radius:${styles.input.borderRadius} 0 0 ${styles.input.borderRadius};border-right:none;}`);
667
692
  css.push('select#ccexpirymonth{border-radius:0;border-right:none;}');
668
693
  css.push('select#ccexpiryyear{border-radius:0;border-right:none;}');
@@ -680,7 +705,7 @@ export class CardConnectTokenizer extends Tokenizer {
680
705
  css.push(`select#ccexpirymonth{width:15%;margin-right:${marginRight};}`);
681
706
  css.push(`select#ccexpiryyear{width:20%;margin-right:${marginRight};}`);
682
707
  css.push('input#cccvvfield{width:15%;}');
683
- if ((_c = styles.input) === null || _c === void 0 ? void 0 : _c.borderRadius) {
708
+ if ((_h = styles.input) === null || _h === void 0 ? void 0 : _h.borderRadius) {
684
709
  css.push(`input,select{border-radius:${styles.input.borderRadius};}`);
685
710
  }
686
711
  }
@@ -696,7 +721,7 @@ export class CardConnectTokenizer extends Tokenizer {
696
721
  if (focusStyles.length > 0) {
697
722
  css.push(`input:focus{${focusStyles.join(';')};}`);
698
723
  css.push(`select:focus{${focusStyles.join(';')};}`);
699
- if (isConnected && ((_d = styles.input) === null || _d === void 0 ? void 0 : _d.border)) {
724
+ if (isConnected && ((_j = styles.input) === null || _j === void 0 ? void 0 : _j.border)) {
700
725
  css.push(`input#ccnumfield:focus{border:${styles.input.border};${focusStyles.join(';')};}`);
701
726
  css.push(`select#ccexpirymonth:focus{border:${styles.input.border};${focusStyles.join(';')};}`);
702
727
  css.push(`select#ccexpiryyear:focus{border:${styles.input.border};${focusStyles.join(';')};}`);
@@ -24,6 +24,11 @@ export declare class SpreedlyTokenizer extends Tokenizer {
24
24
  private institutionNumberEl?;
25
25
  private transitNumberEl?;
26
26
  private enableTestMode;
27
+ private resizeObserver?;
28
+ private effectiveLayout;
29
+ private cardNumberDiv?;
30
+ private cvvDiv?;
31
+ private responsiveBreakpoint;
27
32
  private constructor();
28
33
  static create(gateway: PaymentGateway, container: TokenizerContainer, config: {
29
34
  organizationId: string;
@@ -42,6 +47,9 @@ export declare class SpreedlyTokenizer extends Tokenizer {
42
47
  private stylesToCssString;
43
48
  clear(): void;
44
49
  focus(field: 'cardNumber' | 'cvv' | 'expiry' | 'routingNumber' | 'accountNumber'): void;
50
+ private determineLayout;
51
+ private setupResizeObserver;
52
+ private applyLayoutStyles;
45
53
  destroy(): void;
46
54
  hasToken(): boolean;
47
55
  getToken(): PaymentToken | null;
@@ -13,21 +13,24 @@ import { SPREEDLY_TOKENIZER_URL } from '../constants';
13
13
  import { extractSpreedlyToken, unpackSpreedlyResponse } from '../typeAdapters';
14
14
  import { fetchSpreedlySecurityArgs, } from './spreedly-secure';
15
15
  import { DEFAULT_UNIFIED_STYLES, mergeStyles, getContainerStylesForLayout, } from './styles';
16
- import { INIT_TIMEOUT, TOKENIZE_TIMEOUT, FIELD_FLEX, BANK_FIELD_FLEX, CANADIAN_BANK_FIELD_FLEX, PLACEHOLDERS, FIELD_CONSTRAINTS, } from './tokenizer-constants';
16
+ import { INIT_TIMEOUT, TOKENIZE_TIMEOUT, FIELD_FLEX, BANK_FIELD_FLEX, CANADIAN_BANK_FIELD_FLEX, PLACEHOLDERS, FIELD_CONSTRAINTS, RESPONSIVE_BREAKPOINT, } from './tokenizer-constants';
17
17
  import { createFieldContainer, createInputElement, validateRoutingNumber, validateAccountNumber, createAccountTypeSelect, validateInstitutionNumber, validateTransitNumber, validateCanadianAccountNumber, formatCanadianRoutingNumber, } from './tokenizer-utils';
18
18
  const SPREEDLY_SCRIPT_URL = 'https://core.spreedly.com/iframe/iframe-v1.min.js';
19
19
  const SPREEDLY_SCRIPT_ID = 'spreedly-iframe-script';
20
20
  export class SpreedlyTokenizer extends Tokenizer {
21
- constructor(environmentKey, containerId, styles, mode = 'credit_card', bankCountry = 'US', enableTestMode = false, layout = 'single-line') {
21
+ constructor(environmentKey, containerId, styles, mode = 'credit_card', bankCountry = 'US', enableTestMode = false, layout = 'single-line', responsiveBreakpoint = RESPONSIVE_BREAKPOINT) {
22
22
  super();
23
23
  this.environmentKey = environmentKey;
24
24
  this.containerId = containerId;
25
25
  this.layout = layout;
26
26
  this.bankCountry = 'US';
27
27
  this.enableTestMode = false;
28
+ this.effectiveLayout = 'single-line';
29
+ this.responsiveBreakpoint = RESPONSIVE_BREAKPOINT;
28
30
  this.mode = mode;
29
31
  this.bankCountry = bankCountry;
30
32
  this.enableTestMode = enableTestMode;
33
+ this.responsiveBreakpoint = responsiveBreakpoint;
31
34
  if (mode === 'credit_card') {
32
35
  const SpreedlyFrame = window.SpreedlyPaymentFrame;
33
36
  if (SpreedlyFrame) {
@@ -74,7 +77,7 @@ export class SpreedlyTokenizer extends Tokenizer {
74
77
  if (!environmentKey) {
75
78
  environmentKey = '';
76
79
  }
77
- const tokenizer = new SpreedlyTokenizer(environmentKey, container.containerId, container.styling, container.mode || 'credit_card', container.bankCountry || 'US', container.enableTestMode || false, container.layout || 'single-line');
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);
78
81
  tokenizer.organizationId = config.organizationId;
79
82
  tokenizer.embedId = config.embedId;
80
83
  tokenizer.clientConfig = config.clientConfig;
@@ -680,7 +683,64 @@ export class SpreedlyTokenizer extends Tokenizer {
680
683
  element === null || element === void 0 ? void 0 : element.focus();
681
684
  }
682
685
  }
686
+ determineLayout(width) {
687
+ return width < this.responsiveBreakpoint ? 'two-line' : 'single-line';
688
+ }
689
+ setupResizeObserver() {
690
+ if (this.layout !== 'responsive')
691
+ return;
692
+ const container = document.getElementById(this.containerId);
693
+ if (!container)
694
+ return;
695
+ let debounceTimer;
696
+ this.resizeObserver = new ResizeObserver((entries) => {
697
+ clearTimeout(debounceTimer);
698
+ debounceTimer = setTimeout(() => {
699
+ const newWidth = entries[0].contentRect.width;
700
+ const newLayout = this.determineLayout(newWidth);
701
+ if (newLayout !== this.effectiveLayout) {
702
+ this.applyLayoutStyles(newLayout);
703
+ }
704
+ }, 100);
705
+ });
706
+ this.resizeObserver.observe(container);
707
+ }
708
+ applyLayoutStyles(newLayout) {
709
+ this.effectiveLayout = newLayout;
710
+ const container = document.getElementById(this.containerId);
711
+ if (!container)
712
+ return;
713
+ if (newLayout === 'two-line') {
714
+ container.style.flexWrap = 'wrap';
715
+ if (this.cardNumberDiv) {
716
+ this.cardNumberDiv.style.flex = '1';
717
+ this.cardNumberDiv.style.flexBasis = '100%';
718
+ }
719
+ if (this.expiryEl) {
720
+ this.expiryEl.style.flex = '1';
721
+ this.expiryEl.style.flexBasis = 'auto';
722
+ }
723
+ if (this.cvvDiv) {
724
+ this.cvvDiv.style.flex = '1';
725
+ this.cvvDiv.style.flexBasis = 'auto';
726
+ }
727
+ }
728
+ else {
729
+ container.style.flexWrap = 'nowrap';
730
+ if (this.cardNumberDiv) {
731
+ this.cardNumberDiv.style.flex = FIELD_FLEX.cardNumber.flex;
732
+ }
733
+ if (this.expiryEl) {
734
+ this.expiryEl.style.flex = FIELD_FLEX.expiry.flex;
735
+ }
736
+ if (this.cvvDiv) {
737
+ this.cvvDiv.style.flex = FIELD_FLEX.cvv.flex;
738
+ }
739
+ }
740
+ }
683
741
  destroy() {
742
+ var _a;
743
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
684
744
  if (this.spreedly && this.spreedly.removeHandlers) {
685
745
  this.spreedly.removeHandlers();
686
746
  }
@@ -757,10 +817,18 @@ export class SpreedlyTokenizer extends Tokenizer {
757
817
  }
758
818
  }
759
819
  createCreditCardFields(container) {
760
- if (this.layout === 'two-line') {
820
+ if (this.layout === 'responsive') {
821
+ this.effectiveLayout = this.determineLayout(container.offsetWidth);
822
+ }
823
+ else {
824
+ this.effectiveLayout =
825
+ this.layout === 'two-line' ? 'two-line' : 'single-line';
826
+ }
827
+ if (this.effectiveLayout === 'two-line' && this.layout !== 'responsive') {
761
828
  const cardNumberDiv = createFieldContainer(this.numberEl, '1', FIELD_FLEX.cardNumber.minWidth);
762
829
  cardNumberDiv.style.height = this.mergedStyles.input.height;
763
830
  cardNumberDiv.style.flexBasis = '100%';
831
+ this.cardNumberDiv = cardNumberDiv;
764
832
  container.appendChild(cardNumberDiv);
765
833
  this.expiryEl = createInputElement(this.expiryId, 'text', PLACEHOLDERS.expiry, FIELD_CONSTRAINTS.expiry.maxLength);
766
834
  Object.assign(this.expiryEl.style, {
@@ -781,11 +849,13 @@ export class SpreedlyTokenizer extends Tokenizer {
781
849
  container.appendChild(this.expiryEl);
782
850
  const cvvDiv = createFieldContainer(this.cvvEl, '1', FIELD_FLEX.cvv.minWidth);
783
851
  cvvDiv.style.height = this.mergedStyles.input.height;
852
+ this.cvvDiv = cvvDiv;
784
853
  container.appendChild(cvvDiv);
785
854
  }
786
855
  else {
787
856
  const cardNumberDiv = createFieldContainer(this.numberEl, FIELD_FLEX.cardNumber.flex, FIELD_FLEX.cardNumber.minWidth);
788
857
  cardNumberDiv.style.height = this.mergedStyles.input.height;
858
+ this.cardNumberDiv = cardNumberDiv;
789
859
  container.appendChild(cardNumberDiv);
790
860
  this.expiryEl = createInputElement(this.expiryId, 'text', PLACEHOLDERS.expiry, FIELD_CONSTRAINTS.expiry.maxLength);
791
861
  Object.assign(this.expiryEl.style, {
@@ -806,7 +876,12 @@ export class SpreedlyTokenizer extends Tokenizer {
806
876
  container.appendChild(this.expiryEl);
807
877
  const cvvDiv = createFieldContainer(this.cvvEl, FIELD_FLEX.cvv.flex, FIELD_FLEX.cvv.minWidth);
808
878
  cvvDiv.style.height = this.mergedStyles.input.height;
879
+ this.cvvDiv = cvvDiv;
809
880
  container.appendChild(cvvDiv);
881
+ if (this.layout === 'responsive') {
882
+ this.applyLayoutStyles(this.effectiveLayout);
883
+ this.setupResizeObserver();
884
+ }
810
885
  }
811
886
  }
812
887
  createBankAccountFields(container) {
@@ -1,4 +1,4 @@
1
1
  import { TokenizerStyling, TokenizerStylingComplete } from './types';
2
2
  export declare const DEFAULT_UNIFIED_STYLES: TokenizerStylingComplete;
3
3
  export declare function mergeStyles(defaults: TokenizerStylingComplete, userStyles?: TokenizerStyling): TokenizerStylingComplete;
4
- export declare function getContainerStylesForLayout(baseStyles: TokenizerStylingComplete, layout?: 'single-line' | 'two-line'): TokenizerStylingComplete;
4
+ export declare function getContainerStylesForLayout(baseStyles: TokenizerStylingComplete, layout?: 'single-line' | 'two-line' | 'responsive'): TokenizerStylingComplete;
@@ -27,6 +27,11 @@ export const DEFAULT_UNIFIED_STYLES = {
27
27
  flexWrap: 'nowrap',
28
28
  rowGap: '1rem',
29
29
  },
30
+ twoLine: {
31
+ padding: '',
32
+ fontSize: '',
33
+ textAlign: '',
34
+ },
30
35
  };
31
36
  export function mergeStyles(defaults, userStyles) {
32
37
  if (!userStyles)
@@ -36,6 +41,7 @@ export function mergeStyles(defaults, userStyles) {
36
41
  focus: Object.assign(Object.assign({}, defaults.focus), userStyles.focus),
37
42
  error: Object.assign(Object.assign({}, defaults.error), userStyles.error),
38
43
  container: Object.assign(Object.assign({}, defaults.container), userStyles.container),
44
+ twoLine: Object.assign(Object.assign({}, defaults.twoLine), userStyles.twoLine),
39
45
  };
40
46
  }
41
47
  export function getContainerStylesForLayout(baseStyles, layout = 'single-line') {
@@ -60,3 +60,4 @@ export declare const FIELD_CONSTRAINTS: {
60
60
  readonly maxLength: 4;
61
61
  };
62
62
  };
63
+ export declare const RESPONSIVE_BREAKPOINT = 400;
@@ -60,3 +60,4 @@ export const FIELD_CONSTRAINTS = {
60
60
  maxLength: 4,
61
61
  },
62
62
  };
63
+ export const RESPONSIVE_BREAKPOINT = 400;
@@ -18,7 +18,8 @@ export interface TokenizerContainer {
18
18
  mode?: PaymentMethodMode;
19
19
  bankCountry?: 'US' | 'CA';
20
20
  enableTestMode?: boolean;
21
- layout?: 'single-line' | 'two-line';
21
+ layout?: 'single-line' | 'two-line' | 'responsive';
22
+ responsiveBreakpoint?: number;
22
23
  }
23
24
  export interface TokenizerStylingComplete {
24
25
  input: {
@@ -52,6 +53,11 @@ export interface TokenizerStylingComplete {
52
53
  flexWrap?: string;
53
54
  rowGap?: string;
54
55
  };
56
+ twoLine: {
57
+ padding: string;
58
+ fontSize: string;
59
+ textAlign: string;
60
+ };
55
61
  }
56
62
  type DeepPartial<T> = T extends object ? {
57
63
  [P in keyof T]?: DeepPartial<T[P]>;
@@ -44,13 +44,25 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
44
44
  if (container.mode === 'bank_account' && container.bankCountry === 'CA') {
45
45
  throw new Error('CardConnect does not support Canadian bank accounts');
46
46
  }
47
+ let effectiveLayout = 'single-line';
48
+ if (container.layout === 'responsive') {
49
+ const containerEl = document.getElementById(container.containerId);
50
+ const containerWidth = (containerEl === null || containerEl === void 0 ? void 0 : containerEl.offsetWidth) || 0;
51
+ const breakpoint = container.responsiveBreakpoint || tokenizer_constants_1.RESPONSIVE_BREAKPOINT;
52
+ effectiveLayout =
53
+ containerWidth < breakpoint ? 'two-line' : 'single-line';
54
+ }
55
+ else if (container.layout === 'two-line') {
56
+ effectiveLayout = 'two-line';
57
+ }
58
+ const resolvedContainer = Object.assign(Object.assign({}, container), { layout: effectiveLayout });
47
59
  let baseUrl = ((_a = gateway.config) === null || _a === void 0 ? void 0 : _a.base_url) || config.clientConfig.cardConnectBaseUrl;
48
60
  config.cardConnectBaseUrl = baseUrl;
49
61
  const mergedStyles = (0, styles_1.mergeStyles)(styles_1.DEFAULT_UNIFIED_STYLES, container.styling);
50
- const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, container);
62
+ const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, resolvedContainer);
51
63
  const iframe = CardConnectTokenizer.createIframe(iframeUrl, mergedStyles);
52
- const tokenizer = new CardConnectTokenizer(iframe, iframeUrl, container.containerId, container.mode || 'credit_card', container.enableTestMode || false, container.layout || 'single-line');
53
- tokenizer.createInternalElements(container);
64
+ const tokenizer = new CardConnectTokenizer(iframe, iframeUrl, container.containerId, container.mode || 'credit_card', container.enableTestMode || false, effectiveLayout);
65
+ tokenizer.createInternalElements(resolvedContainer);
54
66
  yield tokenizer.init();
55
67
  return tokenizer;
56
68
  });
@@ -73,7 +85,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
73
85
  }
74
86
  createCreditCardFields(containerEl, mergedStyles) {
75
87
  this.iframe.style.width = '100%';
76
- if (this.layout === 'two-line') {
88
+ if (this.layout === 'two-line' || this.layout === 'responsive') {
77
89
  const inputHeight = mergedStyles.input.height || '40px';
78
90
  this.iframe.style.height = `calc((${inputHeight}) * 2 + 10px)`;
79
91
  }
@@ -584,7 +596,12 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
584
596
  params.set('placeholderyear', 'YYYY');
585
597
  }
586
598
  const mergedStyles = (0, styles_1.mergeStyles)(styles_1.DEFAULT_UNIFIED_STYLES, container.styling);
587
- const cssString = CardConnectTokenizer.generateCardConnectCss(mergedStyles, container.layout || 'single-line');
599
+ const isDesktopSafari = typeof navigator !== 'undefined' &&
600
+ /Safari/.test(navigator.userAgent) &&
601
+ /Apple Computer/.test(navigator.vendor) &&
602
+ !/Chrome/.test(navigator.userAgent) &&
603
+ !/Mobile/.test(navigator.userAgent);
604
+ const cssString = CardConnectTokenizer.generateCardConnectCss(mergedStyles, (container.layout || 'single-line'), isDesktopSafari);
588
605
  const queryPairs = [];
589
606
  params.forEach((value, key) => {
590
607
  queryPairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
@@ -617,8 +634,8 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
617
634
  iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms');
618
635
  return iframe;
619
636
  }
620
- static generateCardConnectCss(styles, layout = 'single-line') {
621
- var _a, _b, _c, _d;
637
+ static generateCardConnectCss(styles, layout = 'single-line', isDesktopSafari = false) {
638
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
622
639
  const css = [];
623
640
  if (layout === 'two-line') {
624
641
  css.push('html,form,body{margin:0;padding:0;}');
@@ -652,14 +669,22 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
652
669
  commonStyles.push('box-sizing:border-box');
653
670
  const baseStyles = commonStyles.join(';');
654
671
  css.push(`input{${baseStyles};}`);
655
- css.push(`select{${baseStyles};}`);
672
+ if (isDesktopSafari) {
673
+ css.push(`select{${baseStyles};-webkit-appearance:none;appearance:none;}`);
674
+ }
675
+ else {
676
+ css.push(`select{${baseStyles};}`);
677
+ }
656
678
  }
657
679
  if (layout === 'two-line') {
658
680
  css.push('input#ccnumfield{width:100%;display:block;margin-bottom:8px;}');
659
- css.push('input#ccexpiryfieldmonth{width:20%;}');
660
- css.push('input#ccexpiryfieldyear{width:24%;}');
661
- css.push('input#cccvvfield{width:calc(56% - 20px);}');
662
- if ((_a = styles.input) === null || _a === void 0 ? void 0 : _a.borderRadius) {
681
+ const twoLinePadding = ((_a = styles.twoLine) === null || _a === void 0 ? void 0 : _a.padding) || ((_b = styles.input) === null || _b === void 0 ? void 0 : _b.padding) || '10px';
682
+ const twoLineFontSize = ((_c = styles.twoLine) === null || _c === void 0 ? void 0 : _c.fontSize) || ((_d = styles.input) === null || _d === void 0 ? void 0 : _d.fontSize) || '14px';
683
+ const twoLineTextAlign = ((_e = styles.twoLine) === null || _e === void 0 ? void 0 : _e.textAlign) || 'left';
684
+ css.push(`input#ccexpiryfieldmonth{width:25%;padding:${twoLinePadding};font-size:${twoLineFontSize};text-align:${twoLineTextAlign};}`);
685
+ css.push(`input#ccexpiryfieldyear{width:35%;padding:${twoLinePadding};font-size:${twoLineFontSize};text-align:${twoLineTextAlign};}`);
686
+ css.push(`input#cccvvfield{width:calc(40% - 16px);padding:${twoLinePadding};font-size:${twoLineFontSize};text-align:${twoLineTextAlign};margin-left:-4px;}`);
687
+ if ((_f = styles.input) === null || _f === void 0 ? void 0 : _f.borderRadius) {
663
688
  css.push(`input{border-radius:${styles.input.borderRadius};}`);
664
689
  }
665
690
  }
@@ -668,7 +693,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
668
693
  css.push('select#ccexpirymonth{width:16%;margin:0;margin-right:-12px;}');
669
694
  css.push('select#ccexpiryyear{width:20%;}');
670
695
  css.push('input#cccvvfield{width:20%;margin:0;margin-left:-12px;}');
671
- if ((_b = styles.input) === null || _b === void 0 ? void 0 : _b.borderRadius) {
696
+ if ((_g = styles.input) === null || _g === void 0 ? void 0 : _g.borderRadius) {
672
697
  css.push(`input#ccnumfield{border-radius:${styles.input.borderRadius} 0 0 ${styles.input.borderRadius};border-right:none;}`);
673
698
  css.push('select#ccexpirymonth{border-radius:0;border-right:none;}');
674
699
  css.push('select#ccexpiryyear{border-radius:0;border-right:none;}');
@@ -686,7 +711,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
686
711
  css.push(`select#ccexpirymonth{width:15%;margin-right:${marginRight};}`);
687
712
  css.push(`select#ccexpiryyear{width:20%;margin-right:${marginRight};}`);
688
713
  css.push('input#cccvvfield{width:15%;}');
689
- if ((_c = styles.input) === null || _c === void 0 ? void 0 : _c.borderRadius) {
714
+ if ((_h = styles.input) === null || _h === void 0 ? void 0 : _h.borderRadius) {
690
715
  css.push(`input,select{border-radius:${styles.input.borderRadius};}`);
691
716
  }
692
717
  }
@@ -702,7 +727,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
702
727
  if (focusStyles.length > 0) {
703
728
  css.push(`input:focus{${focusStyles.join(';')};}`);
704
729
  css.push(`select:focus{${focusStyles.join(';')};}`);
705
- if (isConnected && ((_d = styles.input) === null || _d === void 0 ? void 0 : _d.border)) {
730
+ if (isConnected && ((_j = styles.input) === null || _j === void 0 ? void 0 : _j.border)) {
706
731
  css.push(`input#ccnumfield:focus{border:${styles.input.border};${focusStyles.join(';')};}`);
707
732
  css.push(`select#ccexpirymonth:focus{border:${styles.input.border};${focusStyles.join(';')};}`);
708
733
  css.push(`select#ccexpiryyear:focus{border:${styles.input.border};${focusStyles.join(';')};}`);
@@ -24,6 +24,11 @@ export declare class SpreedlyTokenizer extends Tokenizer {
24
24
  private institutionNumberEl?;
25
25
  private transitNumberEl?;
26
26
  private enableTestMode;
27
+ private resizeObserver?;
28
+ private effectiveLayout;
29
+ private cardNumberDiv?;
30
+ private cvvDiv?;
31
+ private responsiveBreakpoint;
27
32
  private constructor();
28
33
  static create(gateway: PaymentGateway, container: TokenizerContainer, config: {
29
34
  organizationId: string;
@@ -42,6 +47,9 @@ export declare class SpreedlyTokenizer extends Tokenizer {
42
47
  private stylesToCssString;
43
48
  clear(): void;
44
49
  focus(field: 'cardNumber' | 'cvv' | 'expiry' | 'routingNumber' | 'accountNumber'): void;
50
+ private determineLayout;
51
+ private setupResizeObserver;
52
+ private applyLayoutStyles;
45
53
  destroy(): void;
46
54
  hasToken(): boolean;
47
55
  getToken(): PaymentToken | null;