@gr4vy/secure-fields 0.5.2 → 0.5.4

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/CHANGELOG.md CHANGED
@@ -1,3 +1,34 @@
1
+ # v0.5.4 (Fri Sep 16 2022)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - fix: Ensure a field is only marked as invalid if it has been blurred [#46](https://github.com/gr4vy/secure-fields/pull/46) ([@cbetta](https://github.com/cbetta) [@luca-gr4vy](https://github.com/luca-gr4vy))
6
+
7
+ #### 🏠 Internal
8
+
9
+ - task: sdk updates [#49](https://github.com/gr4vy/secure-fields/pull/49) ([@luca-gr4vy](https://github.com/luca-gr4vy))
10
+ - task: rename expiration to expiry [#48](https://github.com/gr4vy/secure-fields/pull/48) ([@luca-gr4vy](https://github.com/luca-gr4vy))
11
+
12
+ #### Authors: 2
13
+
14
+ - Cristiano Betta ([@cbetta](https://github.com/cbetta))
15
+ - Luca Allievi ([@luca-gr4vy](https://github.com/luca-gr4vy))
16
+
17
+ ---
18
+
19
+ # v0.5.3 (Thu Sep 15 2022)
20
+
21
+ #### 🏠 Internal
22
+
23
+ - feat: update documentation [#37](https://github.com/gr4vy/secure-fields/pull/37) ([@luca-gr4vy](https://github.com/luca-gr4vy) [@cbetta](https://github.com/cbetta))
24
+
25
+ #### Authors: 2
26
+
27
+ - Cristiano Betta ([@cbetta](https://github.com/cbetta))
28
+ - Luca Allievi ([@luca-gr4vy](https://github.com/luca-gr4vy))
29
+
30
+ ---
31
+
1
32
  # v0.5.2 (Wed Sep 14 2022)
2
33
 
3
34
  #### 🐛 Bug Fix
package/README.md CHANGED
@@ -18,7 +18,7 @@ npm install @gr4vy/secure-fields --save-prod
18
18
 
19
19
  ## Get started
20
20
 
21
- To use Secure Fields, you first need a form with placeholder elements that will be replaced by secure fields (`iframe`s), each with a specific `id` attribute. Get a session id by making a request to the Session API, passing one or more accepted `targetOrigins` (urls that host your form).
21
+ To use Secure Fields, you first need a form with placeholder elements that will be replaced by secure fields (`iframe`s), each with a specific `id` attribute.
22
22
 
23
23
  ```html
24
24
  <form id="cc-form">
@@ -32,80 +32,97 @@ To use Secure Fields, you first need a form with placeholder elements that will
32
32
  <input id="cc-number" class="form-control" />
33
33
  <label for="cc-security-code">Security Code</label>
34
34
  <input id="cc-security-code" class="form-control" />
35
- <label for="cc-expiration-date">Expiration date</label>
36
- <input id="cc-expiration-date" class="form-control" />
35
+ <label for="cc-expiry-date">Expiry date</label>
36
+ <input id="cc-expiry-date" class="form-control" />
37
37
  <button id="pay-button">Pay now</button>
38
38
  </form>
39
39
  ```
40
40
 
41
- Import the library and call the class constructor to create an instance. Pass the session id returned by the Session API.
41
+ Generate a client token which is going to be used to make an authenticated call (you can use any of our [SDKs](https://gr4vy.com/docs/web-checkout/sdks)). Then, get a session id by making a request to the [Checkout Sessions API](https://gr4vy.com/docs/reference#tag/Checkout-Sessions), passing an `Authorization` header with the generated bearer token.
42
+
43
+ Import the library and call the class constructor to create an instance. Pass the session id returned by the Checkout Sessions API, an environment and your gr4vyId.
42
44
 
43
45
  ```js
44
46
  const { SecureFields } = require(`@gr4vy/secure-fields`)
45
- // import { SecureFields } from (`@gr4vy/secure-fields`)
46
47
 
47
- const secureFields = new SecureFields([SESSION_ID])
48
+ const secureFields = new SecureFields({
49
+ environment: 'sandbox',
50
+ gr4vyId: '[GR4VY_ID]'
51
+ sessionId: '[SESSION_ID]'
52
+ })
48
53
 
49
- > **Note**: Replace `[SESSION_ID]` with the session id.
54
+ > **Note**: Replace `[GR4VY_ID]` with your Gr4vy ID and `[SESSION_ID]` with the session id.
50
55
  ```
51
56
 
52
- Call methods to add fields, set flags, and attach event listeners. Call `submit` to capture the data and send it to Gr4vy, passing an optional callback to handle other UI interactions.
57
+ Call methods to add / update fields, set flags, and attach event listeners. Call `submit` to capture the data and send it to Gr4vy, passing an optional callback to handle other UI interactions.
53
58
 
54
59
  ```js
55
60
  secureFields.setDebug(true)
56
61
 
57
- const cardNumber = secureFields.addCardNumber('#cc-number', {
58
- placeholder: 'Enter card number',
59
- styles: {
60
- base: {
61
- color: 'black',
62
- fontSize: '18px',
63
- },
62
+ const styles = {
63
+ color: 'black',
64
+ fontSize: '18px',
65
+ ':focus': {
66
+ color: 'blue',
64
67
  },
68
+ }
69
+
70
+ const cardNumberField = secureFields.addCardNumberField('#cc-number', {
71
+ styles,
72
+ })
73
+ const expiryDateField = secureFields.addExpiryDateField('#cc-number', {
74
+ styles,
75
+ })
76
+ const securityCodeField = secureFields.addSecurityCodeField('#cc-number', {
77
+ styles,
65
78
  })
66
79
 
67
- secureFields.addEventListener(
68
- SecureFields.Events.CARD_VAULT_SUCCESS,
69
- (data) => {
70
- console.log(data) // data.card.number, data.card.type...
71
- }
72
- )
80
+ secureFields.addEventListener(SecureFields.Events.CARD_VAULT_SUCCESS, () => {
81
+ console.log('Card has been tokenized successfully!')
82
+ })
83
+
84
+ cardNumberField.addEventListener('input', (data) => {
85
+ console.warn('Input changed', data) // data.schema, data.codeLabel...
86
+ })
73
87
 
74
88
  const form = document.getElementById('cc-form')
75
89
  form.addEventListener('submit', (e) => {
76
90
  e.preventDefault()
77
- secureFields.submit((err, data) => {
78
- if (err) {
91
+ secureFields.submit((msg) => {
92
+ if (msg === 'Failed to update checkout session') {
79
93
  throw new Error(err)
80
94
  }
81
95
 
82
- console.log(`Got tokenized data`, data)
96
+ console.log('Data stored')
97
+ // create transaction using the Checkout Sessions API...
83
98
  })
84
99
  })
85
100
  ```
86
101
 
102
+ This will initialize Secure Fields and inject corresponding iframe elements into your form. On form submit, it will capture and store the payment method data securely via Gr4vy, so you can then create a transaction via the Checkout Sessions API.
103
+
87
104
  ### Styles
88
105
 
89
- The outer styling (any containers around fields, etc) is completely in the your control. SecureFields will also generate a set of so-called managed CSS classes and attach them to the outer iframe containers, so you can target them with your own CSS. Finally, an object of CSS rules can be passed to the `addField` options to style elements inside the iframe(s).
106
+ The outer styling (any containers around fields, etc) is completely in the your control. SecureFields will also generate classes along with a set of data attributes and attach them to the outer iframe containers, so you can target them with your own CSS. Finally, an object of CSS rules can be passed to the `addCardNumberField`, `addExpiryDateField` and `addSecurityCodeField` methods options to style elements inside the iframe(s).
90
107
 
91
108
  ```js
92
109
  const styles = {
93
- // Default styles
94
- base: { ... },
110
+ // Default styles (any of the supported CSS property)
111
+ color: ...,
95
112
  // Rules applied when the field has its value autofilled by a browser / extension
96
- autofill: { ... },
113
+ ':autofill': { ... },
97
114
  // Rules applied when the field is hovered
98
- hover: { ... },
115
+ ':hover': { ... },
99
116
  // Rules applied when the field is focused
100
- focus: { ... },
117
+ ':focus': { ... },
101
118
  // Rules applied when the field is disabled
102
- disabled: { ... },
119
+ ':disabled': { ... },
103
120
  // Rules applied when the field is valid
104
- valid: { ... },
121
+ ':valid': { ... },
105
122
  // Rules applied when the field is invalid
106
- invalid: { ... },
123
+ ':invalid': { ... },
107
124
  // Rules applied to the field placeholder
108
- placeholder: { ... },
125
+ '::placeholder': { ... },
109
126
  }
110
127
  ```
111
128
 
@@ -113,6 +130,7 @@ We only allow the following CSS properties:
113
130
 
114
131
  ```
115
132
  backgroundColor
133
+ boxShadow
116
134
  caretColor
117
135
  color
118
136
  colorScheme
@@ -136,6 +154,7 @@ fontWeight
136
154
  letterSpacing
137
155
  lineHeight
138
156
  opacity
157
+ padding
139
158
  textAlign
140
159
  textShadow
141
160
  textRendering
@@ -144,29 +163,26 @@ MozOsxFontSmoothing
144
163
  WebkitFontSmoothing
145
164
  ```
146
165
 
147
- Here are the managed classes generated by Secure Fields:
166
+ Here are the selectors you can use to style the outer frame containers:
148
167
 
149
168
  ```css
150
- /* Applied to the (form) container */
151
- .secure-fields {
152
- }
153
169
  /* Applied to each field */
154
- .secure-fields__field {
170
+ .secure-fields__input {
155
171
  }
156
- /* Applied to a disabled field */
157
- .secure-fields__field--disabled {
172
+ /* Applied to the card number field */
173
+ .secure-fields__input--number {
158
174
  }
159
- /* Applied to a focused field */
160
- .secure-fields__field--focused {
175
+ /* Applied to the expiry date field */
176
+ .secure-fields__input--expiry-date {
161
177
  }
162
- /* Applied to a valid field */
163
- .secure-fields__field--valid {
178
+ /* Applied to the security code field */
179
+ .secure-fields__input--security-code {
164
180
  }
165
- /* Applied to an invalid field */
166
- .secure-fields__field--invalid {
181
+ /* Applied to a focused field */
182
+ .secure-fields__input[data-secure-fields-focused] {
167
183
  }
168
- /* Applied to a autofilled field */
169
- .secure-fields__field--autofilled {
184
+ /* Applied to an invalid field */
185
+ .secure-fields__input[data-secure-fields-invalid] {
170
186
  }
171
187
  ```
172
188
 
@@ -174,13 +190,19 @@ Here are the managed classes generated by Secure Fields:
174
190
 
175
191
  You can call the `addEventListener` on a Secure Fields instance or on fields, passing one of the supported events and a callback. Here are the events you can listen to on an instance:
176
192
 
177
- | Name | Description |
178
- | -------------------- | --------------------------------------------------------------- |
179
- | `CARD_VAULT_SUCCESS` | Triggered when the card is successfully vaulted. |
180
- | `CARD_VAULT_FAILURE` | Triggered when the card vaulting fails. |
181
- | `READY` | Triggered when the SecureFields is loaded and ready to be used. |
193
+ | Name | Description | Example |
194
+ | -------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
195
+ | `CARD_VAULT_SUCCESS` | Triggered when the card is successfully vaulted. | `secureFields.addEventListener(SecureFields.Events.CARD_VAULT_SUCCESS, () => { console.log('Card has been tokenized successfully!') })` |
196
+ | `CARD_VAULT_FAILURE` | Triggered when the card vaulting fails. | `secureFields.addEventListener(SecureFields.Events.CARD_VAULT_FAILURE, () => { console.log('Couldn\'t tokenize the card') })` |
197
+ | `READY` | Triggered when the SecureFields is loaded and ready to be used. | `secureFields.addEventListener(SecureFields.READY, () => { console.log('Secure fields loaded') })` |
198
+
199
+ For actual fields (returned by the `addCardNumberField`, `addExpiryDateField` and `addSecurityCodeField` methods), you can subscribe to default events and have access to more useful data (bin, validation status, etc). For example, the input event on a card number field might include `{ schema: 'american-express', codeLabel: 'CID', valid: true, ... }`. You can expect to be able to listen to the following events:
182
200
 
183
- For actual fields, you can subscribe to default events and have access to more useful data (bin, validation status, etc). For example, the change event on a card number input might include `{ valid: true, complete: true, ... }`. You can expect to be able to listen to events such as `blur`, `focus`, `change`, `input`...
201
+ | Name | Description | Example |
202
+ | ------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
203
+ | `blur` | Triggered when the field loses focus. | `cardNumberField.addEventListener('blur', (data) => { console.log(data) /* { type: 'number' } */ })` |
204
+ | `focus` | Triggered when the field gains focus. | `cardNumberField.addEventListener('focus', (data) => { console.log(data) /* { type: 'number' } */ })` |
205
+ | `input` | Triggered when the field value has been changed. | `cardNumberField.addEventListener('input', (data) => { console.log(data) /* { type: 'number', schema: 'visa', codeLabel: 'CVV', valid: true } */` |
184
206
 
185
207
  ### API reference
186
208
 
@@ -193,14 +215,13 @@ For actual fields, you can subscribe to default events and have access to more u
193
215
 
194
216
  #### Methods
195
217
 
196
- | Name | Description |
197
- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
198
- | `constructor` | Instantiates SecureFields with a session id. <br /><br />`new SecureFields('...')` |
199
- | `addCardNumberField` | Injects a secure field of type `cardNumber`. <br /><br />`secureFields.addCardNumberField('#cc-number', { placeholder: 'Enter card number', ... })` |
200
- | `addSecurityCodeField` | Injects a secure field of type `securityCode`. <br /><br />`secureFields.addSecurityCodeField('#cc-security-code', { placeholder: 'Enter security code', ... })` |
201
- | `addExpirationDateField` | Injects a secure field of type `expirationDate`. <br /><br />`secureFields.addExpirationDateField('#cc-expiration-date', { placeholder: 'Enter expiration date', ... })` |
202
- | `addEventListener` | Attaches an event handler to the SecureFields instance or to a secure field in order to listen to specific events. Requires one of the events supported and a callback. <br /><br />`secureFields.addEventListener(SecureFields.Events.READY, (data) => { ... })` <br /><br />`cardNumber.element.addEventListener(SecureFields.Events.CHANGE, (data) => { ... })` |
203
- | `removeEventListener` | Removes a previously attached event handler. |
204
- | `submit` | Calls the Vault API to tokenize and store the card data. Returns an error with invalid fields or the tokenized data in case everything went fine. <br /><br />`secureFields.submit((err, data) => { ... }` |
205
- | `setDebug` | Enable / disable debug mode. When the debug mode is enabled, SecureFields logs information to the console. <br /><br />`secureFields.setDebug(true)` |
206
- | `isFormValid` | Return the state of the card form validation at any time. <br /><br />`secureFields.isFormValid()` |
218
+ | Name | Description |
219
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
220
+ | `constructor` | Instantiates SecureFields with a configuration object include `environment`, `gr4vyId` and a session id. <br /><br />`new SecureFields({...})` |
221
+ | `addCardNumberField` | Injects a secure field of type `number`. <br /><br />`secureFields.addCardNumberField('#cc-number', { placeholder: 'Enter card number', ... })` |
222
+ | `addSecurityCodeField` | Injects a secure field of type `securityCode`. <br /><br />`secureFields.addSecurityCodeField('#cc-security-code', { placeholder: 'Enter security code', ... })` |
223
+ | `addExpiryDateField` | Injects a secure field of type `expiryDate`. <br /><br />`secureFields.addExpiryDateField('#cc-expiry-date', { placeholder: 'Enter expiry date', ... })` |
224
+ | `addEventListener` | Attaches an event handler to the SecureFields instance or to a secure field in order to listen to specific events. Requires one of the events supported and a callback. <br /><br />`secureFields.addEventListener(SecureFields.Events.READY, (data) => { ... })` <br /><br />`cardNumberField.addEventListener('input', (data) => { ... })` |
225
+ | `removeEventListener` | Removes a previously attached event handler. |
226
+ | `submit` | Calls the Vault API to tokenize and store the card data. Returns an error with invalid fields or the tokenized data in case everything went fine. <br /><br />`secureFields.submit((msg) => { ... }` |
227
+ | `setDebug` | Enable / disable debug mode. When the debug mode is enabled, SecureFields logs information to the console. <br /><br />`secureFields.setDebug(true)` |
@@ -5,8 +5,6 @@ export declare enum Events {
5
5
  READY = "ready"
6
6
  }
7
7
  export declare enum FieldAttributes {
8
- AUTOFILLED = "data-secure-fields-autofilled",
9
- DISABLED = "data-secure-fields-disabled",
10
8
  FOCUSED = "data-secure-fields-focused",
11
9
  INVALID = "data-secure-fields-invalid"
12
10
  }
package/lib/index.d.ts CHANGED
@@ -26,9 +26,8 @@ declare class SecureFields {
26
26
  addExpiryDateField(element: string | HTMLElement, options?: Omit<Field, 'element' | 'type'>): SecureInput;
27
27
  addEventListener(event: CombinedEvents, callback: (...args: any[]) => void): void;
28
28
  removeEventListener(event: CombinedEvents, callback: (...args: any[]) => void): void;
29
- submit(callback: (error: string) => void): void;
29
+ submit(callback?: (error: string) => void): void;
30
30
  setDebug(debug: boolean): void;
31
- isFormValid(): void;
32
31
  }
33
32
  export { SecureFields };
34
- export type { Field, Styles, StylesTuple } from './types';
33
+ export type { Config, CombinedEvents, Field, FieldType, FieldEvent, Styles, StylesTuple, } from './types';
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r=e();for(var n in r)("object"==typeof exports?exports:t)[n]=r[n]}}(this,(()=>(()=>{"use strict";var t={d:(e,r)=>{for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{SecureFields:()=>U});var r,n,i="@gr4vy-secure-fields-debug";!function(t){t.CARD_VAULT_SUCCESS="card-vault-success",t.CARD_VAULT_FAILURE="card-vault-failure",t.READY="ready"}(r||(r={})),function(t){t.AUTOFILLED="data-secure-fields-autofilled",t.DISABLED="data-secure-fields-disabled",t.FOCUSED="data-secure-fields-focused",t.INVALID="data-secure-fields-invalid"}(n||(n={}));var o="secure-fields";function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function s(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,i,o=[],a=!0,s=!1;try{for(r=r.call(t);!(a=(n=r.next()).done)&&(o.push(n.value),!e||o.length!==e);a=!0);}catch(t){s=!0,i=t}finally{try{a||null==r.return||r.return()}finally{if(s)throw i}}return o}}(t,e)||function(t,e){if(t){if("string"==typeof t)return a(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(r):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?a(t,e):void 0}}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var c=new(function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.subscribers=[]}var e=t.prototype;return e.subscribe=function(t,e){this.subscribers.push([t,e])},e.unsubscribe=function(t,e){this.subscribers=this.subscribers.filter((function(r){var n=s(r,2),i=n[0],o=n[1];return i!==t||o.toString()!==e.toString()}))},e.publish=function(t,e){this.subscribers.forEach((function(r){var n=s(r,2),i=n[0],o=n[1];return setTimeout((function(){return i===t?o(e):null}),0)}))},t}()),u=function(t){return"[object Object]"===Object.prototype.toString.call(t)};function l(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var f={debug:!1,level:"log"},d=function(t,e,r){var n=function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},n=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),n.forEach((function(e){l(t,e,r[e])}))}return t}({},f,r),o=n.debug,a=n.level;(o||"true"===localStorage.getItem(i))&&console[a]("Gr4vy - Secure Fields - ".concat(t),e||{})},p=function(t){return t!=t.toLowerCase()&&(t=t.replace(/[A-Z]/g,(function(t){return"-"+t.toLowerCase()}))),t};function y(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function b(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,i,o=[],a=!0,s=!1;try{for(r=r.call(t);!(a=(n=r.next()).done)&&(o.push(n.value),!e||o.length!==e);a=!0);}catch(t){s=!0,i=t}finally{try{a||null==r.return||r.return()}finally{if(s)throw i}}return o}}(t,e)||m(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(t){return function(t){if(Array.isArray(t))return y(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||m(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function m(t,e){if(t){if("string"==typeof t)return y(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(r):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?y(t,e):void 0}}var v=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return Object.entries(t).reduce((function(n,i){var o,a=b(i,2),s=a[0],c=a[1];return u(c)?(o=n).push.apply(o,h(e(t[s],"".concat((r+s).match(/[a-zA-Z0-9]+/g).join("-"),"-")))):(s=p(s).replace(/^-/,""),n.push(["--".concat(r).concat(s),c])),n}),[])};return e(t)};function g(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function O(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},n=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),n.forEach((function(e){g(t,e,r[e])}))}return t}function w(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);r.push.apply(r,n)}return r}(Object(e)).forEach((function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r))})),t}var j=function(){function t(e){var r=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t);var n=e.frameUrl,i=e.parentOrigin,o=e.options.type,a=function(t,e){if(null==t)return{};var r,n,i=function(t,e){if(null==t)return{};var r,n,i={},o=Object.keys(t);for(n=0;n<o.length;n++)r=o[n],e.indexOf(r)>=0||(i[r]=t[r]);return i}(t,e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);for(n=0;n<o.length;n++)r=o[n],e.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(i[r]=t[r])}return i}(e.options,["type"]);this.frameUrl=n,this.parentOrigin=i,this.type=o,this.options=a;var s=v(a.styles);this.frame=document.createElement("iframe"),this.frame.id=o,this.frame.src="".concat(n,"/input.html?parentOrigin=").concat(i,"&type=").concat(this.type),this.frame.style.display="block",this.frame.style.height="100%",this.frame.style.border="none",this.frame.style.width="100%",this.frame.onload=function(){r._postMessage({type:"update",data:w(O({},r.options),{styles:s})}),d("Added field",r.options)}}var e=t.prototype;return e._postMessage=function(t){this.frame.contentWindow.postMessage(O({channel:o},t),this.frameUrl)},e.update=function(t){this.options=O({},this.options,t);var e=v(O({},this.options.styles,t.styles)),r=w(O({},this.options,t),{styles:e});this._postMessage({type:"update",data:w(O({},r),{styles:e})}),d("Updated field",this.options)},e.setPlaceholder=function(t){this.update({placeholder:t})},e.setStyles=function(t){this.update({styles:t})},t}();function S(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function A(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function E(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},n=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),n.forEach((function(e){A(t,e,r[e])}))}return t}function P(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);r.push.apply(r,n)}return r}(Object(e)).forEach((function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r))})),t}var U=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.config=E({environment:"production"},e);var i="sandbox"===this.config.environment?"sandbox.":"";this.frameUrl="https://secure-fields.".concat(i).concat(this.config.gr4vyId,".gr4vy.app"),this.parentOrigin=window.location.origin,this.controller=document.createElement("iframe"),this.controller.src="".concat(this.frameUrl,"/controller.html?parentOrigin=").concat(this.parentOrigin,"&sessionId=").concat(this.config.sessionId,"&gr4vyId=").concat(this.config.gr4vyId,"&environment=").concat(this.config.environment),this.controller.style.position="absolute",this.controller.style.left="-9999999px",document.body.appendChild(this.controller),window.onload=function(){c.publish(r.READY,E({version:t.version},n.config))},d("Initialized",P(E({},this.config),{frameUrl:this.frameUrl,parentOrigin:this.parentOrigin}))}var e,a,s=t.prototype;return s._addField=function(t,e){var r=this;if(!(t="string"==typeof t?document.querySelector(t):t))return e;var i=document.createElement("div");return i.classList.add("secure-fields__input","secure-fields__input--".concat(p(e.type))),i.appendChild(e.frame),t.parentNode.replaceChild(i,t),window.addEventListener("message",(function(t){var o;if(t.origin===r.frameUrl&&(null===(o=t.data.data)||void 0===o?void 0:o.id)===e.type)switch(t.data.type){case"blur":c.publish("".concat(e.type,":blur"),t.data.data),i.removeAttribute(n.FOCUSED),d("Field blurred",t.data.data);break;case"focus":c.publish("".concat(e.type,":focus"),t.data.data),i.setAttribute(n.FOCUSED,""),d("Field focused",t.data.data);break;case"input":c.publish("".concat(e.type,":input"),t.data.data),t.data.data.valid?i.removeAttribute(n.INVALID):i.setAttribute(n.INVALID,""),d("Field input changed",t.data.data)}})),e.addEventListener=this.addEventListener,e.removeEventListener=this.removeEventListener,e},s.addCardNumberField=function(t,e){return this.cardNumber||(this.cardNumber=new j({frameUrl:this.frameUrl,parentOrigin:this.parentOrigin,options:P(E({},e),{type:"number"})})),this._addField(t,this.cardNumber)},s.addSecurityCodeField=function(t,e){return this.securityCode||(this.securityCode=new j({frameUrl:this.frameUrl,parentOrigin:this.parentOrigin,options:P(E({},e),{type:"securityCode"})})),this._addField(t,this.securityCode)},s.addExpiryDateField=function(t,e){return this.expiryDate||(this.expiryDate=new j({frameUrl:this.frameUrl,parentOrigin:this.parentOrigin,options:P(E({},e),{type:"expiryDate"})})),this._addField(t,this.expiryDate)},s.addEventListener=function(t,e){var r=this.type,n="".concat(this.constructor===j?"".concat(r,":"):"").concat(t);c.subscribe(n,e)},s.removeEventListener=function(t,e){var r=this.type,n="".concat(this.constructor===j?"".concat(r,":"):"").concat(t);c.unsubscribe(n,e)},s.submit=function(t){var e=this,n=function(i){if(i.origin===e.frameUrl&&i.data.channel===o){switch(i.data.type){case"success":t("Checkout session updated"),c.publish(r.CARD_VAULT_SUCCESS),d("Payment method tokenized successfully");break;case"error":t("Failed to update checkout session"),c.publish(r.CARD_VAULT_FAILURE),d("Failed to update checkout session")}window.removeEventListener("message",n)}};window.addEventListener("message",n),this.controller.contentWindow.postMessage({type:"submit",channel:o},this.frameUrl)},s.setDebug=function(t){localStorage.setItem(i,String(t))},s.isFormValid=function(){},e=t,a=[{key:"Events",get:function(){return r}},{key:"version",get:function(){}}],null&&S(e.prototype,null),a&&S(e,a),t}();return e})()));
1
+ !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r=e();for(var n in r)("object"==typeof exports?exports:t)[n]=r[n]}}(this,(()=>(()=>{"use strict";var t={d:(e,r)=>{for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{SecureFields:()=>U});var r,n,o="@gr4vy-secure-fields-debug";!function(t){t.CARD_VAULT_SUCCESS="card-vault-success",t.CARD_VAULT_FAILURE="card-vault-failure",t.READY="ready"}(r||(r={})),function(t){t.FOCUSED="data-secure-fields-focused",t.INVALID="data-secure-fields-invalid"}(n||(n={}));var i="secure-fields";function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function c(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i=[],a=!0,c=!1;try{for(r=r.call(t);!(a=(n=r.next()).done)&&(i.push(n.value),!e||i.length!==e);a=!0);}catch(t){c=!0,o=t}finally{try{a||null==r.return||r.return()}finally{if(c)throw o}}return i}}(t,e)||function(t,e){if(t){if("string"==typeof t)return a(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(r):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?a(t,e):void 0}}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var s=new(function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.subscribers=[]}var e=t.prototype;return e.subscribe=function(t,e){this.subscribers.push([t,e])},e.unsubscribe=function(t,e){this.subscribers=this.subscribers.filter((function(r){var n=c(r,2),o=n[0],i=n[1];return o!==t||i.toString()!==e.toString()}))},e.publish=function(t,e){this.subscribers.forEach((function(r){var n=c(r,2),o=n[0],i=n[1];return setTimeout((function(){return o===t?i(e):null}),0)}))},t}()),u=function(t){return"[object Object]"===Object.prototype.toString.call(t)};function l(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var f={debug:!1,level:"log"},d=function(t,e,r){var n=function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},n=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),n.forEach((function(e){l(t,e,r[e])}))}return t}({},f,r),i=n.debug,a=n.level;(i||"true"===localStorage.getItem(o))&&console[a]("Gr4vy - Secure Fields - ".concat(t),e||{})},p=function(t){return t!=t.toLowerCase()&&(t=t.replace(/[A-Z]/g,(function(t){return"-"+t.toLowerCase()}))),t};function y(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function b(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i=[],a=!0,c=!1;try{for(r=r.call(t);!(a=(n=r.next()).done)&&(i.push(n.value),!e||i.length!==e);a=!0);}catch(t){c=!0,o=t}finally{try{a||null==r.return||r.return()}finally{if(c)throw o}}return i}}(t,e)||m(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(t){return function(t){if(Array.isArray(t))return y(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||m(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function m(t,e){if(t){if("string"==typeof t)return y(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(r):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?y(t,e):void 0}}var v=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return Object.entries(t).reduce((function(n,o){var i,a=b(o,2),c=a[0],s=a[1];return u(s)?(i=n).push.apply(i,h(e(t[c],"".concat((r+c).match(/[a-zA-Z0-9]+/g).join("-"),"-")))):(c=p(c).replace(/^-/,""),n.push(["--".concat(r).concat(c),s])),n}),[])};return e(t)};function g(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function O(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},n=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),n.forEach((function(e){g(t,e,r[e])}))}return t}function w(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);r.push.apply(r,n)}return r}(Object(e)).forEach((function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r))})),t}var j=function(){function t(e){var r=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t);var n=e.frameUrl,o=e.parentOrigin,i=e.options.type,a=function(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r,n,o={},i=Object.keys(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||(o[r]=t[r]);return o}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(e.options,["type"]);this.frameUrl=n,this.parentOrigin=o,this.type=i,this.options=a;var c=v(a.styles);this.frame=document.createElement("iframe"),this.frame.id=i,this.frame.src="".concat(n,"/input.html?parentOrigin=").concat(o,"&type=").concat(this.type),this.frame.style.display="block",this.frame.style.height="100%",this.frame.style.border="none",this.frame.style.width="100%",this.frame.onload=function(){r._postMessage({type:"update",data:w(O({},r.options),{styles:c})}),d("Added field",r.options)}}var e=t.prototype;return e._postMessage=function(t){this.frame.contentWindow.postMessage(O({channel:i},t),this.frameUrl)},e.update=function(t){this.options=O({},this.options,t);var e=v(O({},this.options.styles,t.styles)),r=w(O({},this.options,t),{styles:e});this._postMessage({type:"update",data:w(O({},r),{styles:e})}),d("Updated field",this.options)},e.setPlaceholder=function(t){this.update({placeholder:t})},e.setStyles=function(t){this.update({styles:t})},t}();function S(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function A(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function E(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},n=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),n.forEach((function(e){A(t,e,r[e])}))}return t}function P(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);r.push.apply(r,n)}return r}(Object(e)).forEach((function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r))})),t}var U=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.config=E({environment:"production"},e);var o="sandbox"===this.config.environment?"sandbox.":"";this.frameUrl="https://secure-fields.".concat(o).concat(this.config.gr4vyId,".gr4vy.app"),this.parentOrigin=window.location.origin,this.controller=document.createElement("iframe"),this.controller.src="".concat(this.frameUrl,"/controller.html?parentOrigin=").concat(this.parentOrigin,"&sessionId=").concat(this.config.sessionId,"&gr4vyId=").concat(this.config.gr4vyId,"&environment=").concat(this.config.environment),this.controller.style.position="absolute",this.controller.style.left="-9999999px",document.body.appendChild(this.controller),window.onload=function(){s.publish(r.READY,E({version:t.version},n.config))},d("Initialized",P(E({},this.config),{frameUrl:this.frameUrl,parentOrigin:this.parentOrigin}))}var e,a,c=t.prototype;return c._addField=function(t,e){var r=this;if(!(t="string"==typeof t?document.querySelector(t):t))return e;var o=document.createElement("div");return o.classList.add("secure-fields__input","secure-fields__input--".concat(p(e.type))),o.appendChild(e.frame),t.parentNode.replaceChild(o,t),window.addEventListener("message",(function(t){var i;if(t.origin===r.frameUrl&&(null===(i=t.data.data)||void 0===i?void 0:i.id)===e.type)switch(t.data.type){case"blur":s.publish("".concat(e.type,":blur"),t.data.data),o.removeAttribute(n.FOCUSED),d("Field blurred",t.data.data);break;case"focus":s.publish("".concat(e.type,":focus"),t.data.data),o.setAttribute(n.FOCUSED,""),d("Field focused",t.data.data);break;case"input":s.publish("".concat(e.type,":input"),t.data.data),t.data.data.valid?o.removeAttribute(n.INVALID):o.setAttribute(n.INVALID,""),d("Field input changed",t.data.data)}})),e.addEventListener=this.addEventListener,e.removeEventListener=this.removeEventListener,e},c.addCardNumberField=function(t,e){return this.cardNumber||(this.cardNumber=new j({frameUrl:this.frameUrl,parentOrigin:this.parentOrigin,options:P(E({},e),{type:"number"})})),this._addField(t,this.cardNumber)},c.addSecurityCodeField=function(t,e){return this.securityCode||(this.securityCode=new j({frameUrl:this.frameUrl,parentOrigin:this.parentOrigin,options:P(E({},e),{type:"securityCode"})})),this._addField(t,this.securityCode)},c.addExpiryDateField=function(t,e){return this.expiryDate||(this.expiryDate=new j({frameUrl:this.frameUrl,parentOrigin:this.parentOrigin,options:P(E({},e),{type:"expiryDate"})})),this._addField(t,this.expiryDate)},c.addEventListener=function(t,e){var r=this.type,n="".concat(this.constructor===j?"".concat(r,":"):"").concat(t);s.subscribe(n,e)},c.removeEventListener=function(t,e){var r=this.type,n="".concat(this.constructor===j?"".concat(r,":"):"").concat(t);s.unsubscribe(n,e)},c.submit=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},e=this,n=function(o){if(o.origin===e.frameUrl&&o.data.channel===i){switch(o.data.type){case"success":t("Checkout session updated"),s.publish(r.CARD_VAULT_SUCCESS),d("Payment method tokenized successfully");break;case"error":t("Failed to update checkout session"),s.publish(r.CARD_VAULT_FAILURE),d("Failed to update checkout session")}window.removeEventListener("message",n)}};window.addEventListener("message",n),this.controller.contentWindow.postMessage({type:"submit",channel:i},this.frameUrl)},c.setDebug=function(t){localStorage.setItem(o,String(t))},e=t,a=[{key:"Events",get:function(){return r}},{key:"version",get:function(){}}],null&&S(e.prototype,null),a&&S(e,a),t}();return e})()));
package/lib/input.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { Field, StylesTuple } from './types';
1
+ import { Field, FieldType, FieldEvent, StylesTuple } from './types';
2
2
  declare type Options = Omit<Field, 'element' | 'type'>;
3
- declare type EventListener = (event: keyof HTMLElementEventMap, callback: (...args: any[]) => void) => void;
3
+ declare type EventListener = (event: FieldEvent['type'], callback: (...args: any[]) => void) => void;
4
4
  declare class SecureInput {
5
5
  frameUrl: string;
6
6
  parentOrigin: string;
7
7
  frame: HTMLIFrameElement;
8
- type: 'number' | 'securityCode' | 'expiryDate';
8
+ type: FieldType;
9
9
  options: Options;
10
10
  addEventListener: EventListener;
11
11
  removeEventListener: EventListener;
package/lib/types.d.ts CHANGED
@@ -5,7 +5,7 @@ export declare type Config = {
5
5
  gr4vyId: string;
6
6
  sessionId: string;
7
7
  };
8
- export declare type FieldType = 'number' | 'securityCode' | 'expirationDate';
8
+ export declare type FieldType = 'number' | 'securityCode' | 'expiryDate';
9
9
  export declare type Field = {
10
10
  type: FieldType;
11
11
  placeholder?: string;
@@ -28,7 +28,3 @@ export declare type Styles = {
28
28
  [key in ':autofill' | ':hover' | ':focus' | ':disabled' | ':valid' | ':invalid' | '::placeholder']?: SupportedCSSProperties;
29
29
  } & SupportedCSSProperties;
30
30
  export declare type StylesTuple = [string, string][];
31
- export declare type VaultSessionResponse = {
32
- type: 'vault-session';
33
- id: string;
34
- };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gr4vy/secure-fields",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Gr4vy-hosted secure fields offering advanced theming, PCI compliance, event handling, and more.",
5
5
  "main": "lib/index",
6
6
  "types": "lib/index",
@@ -51,5 +51,5 @@
51
51
  "publishConfig": {
52
52
  "access": "public"
53
53
  },
54
- "gitHead": "75d5076d7ad7410cb8ad975d9c8b7da80f451701"
54
+ "gitHead": "160286f5462c6ee37f5566082aee130ca3710400"
55
55
  }