diff --git a/.github/workflows/deploy-preview.yml b/.github/workflows/deploy-preview.yml index 57c68030..a93cf1a8 100644 --- a/.github/workflows/deploy-preview.yml +++ b/.github/workflows/deploy-preview.yml @@ -2,8 +2,6 @@ name: deploy-preview on: workflow_call: pull_request: - branches: - - main types: - opened - synchronize diff --git a/package-lock.json b/package-lock.json index 662003ff..21e2537b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2620,6 +2620,10 @@ "resolved": "packages/smart-camera-web", "link": true }, + "node_modules/@smileid/components": { + "resolved": "packages/components", + "link": true + }, "node_modules/@smileid/embed": { "resolved": "packages/embed", "link": true @@ -10433,11 +10437,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/components": { + "name": "@smileid/components", + "version": "1.0.0" + }, "packages/embed": { "name": "@smileid/embed", "version": "v1.2.3", "dependencies": { "@smile_identity/smart-camera-web": "file:../smart-camera-web", + "@smileid/components": "file:../components", "jszip": "^3.10.1", "validate.js": "^0.13.1" }, diff --git a/packages/embed/src/js/components/Combobox.js b/packages/components/combobox/src/Combobox.js similarity index 94% rename from packages/embed/src/js/components/Combobox.js rename to packages/components/combobox/src/Combobox.js index 5660d0d7..36acaf2f 100644 --- a/packages/embed/src/js/components/Combobox.js +++ b/packages/components/combobox/src/Combobox.js @@ -106,15 +106,15 @@ class ComboboxTrigger extends HTMLElement { this.innerHTML = `${ this.type === "text" ? ` -
- + - -
- ` + + + ` : `` @@ -335,10 +335,10 @@ class ComboboxListbox extends HTMLElement { get emptyState() { return ` -

- ${this.emptyLabel || "No items"} -

- `; +

+ ${this.emptyLabel || "No items"} +

+ `; } connectedCallback() { @@ -571,9 +571,21 @@ class ComboboxOption extends HTMLElement { } } -export default { - Root: ComboboxRoot, - Trigger: ComboboxTrigger, - List: ComboboxListbox, - Option: ComboboxOption, +const Root = ComboboxRoot; +const Trigger = ComboboxTrigger; +const List = ComboboxListbox; +const Option = ComboboxOption; + +if ("customElements" in window) { + window.customElements.define('smileid-combobox', Root); + window.customElements.define('smileid-combobox-trigger', Trigger); + window.customElements.define('smileid-combobox-listbox', List); + window.customElements.define('smileid-combobox-option', Option); +} + +export { + Root, + Trigger, + List, + Option, }; diff --git a/packages/components/combobox/src/index.js b/packages/components/combobox/src/index.js new file mode 100644 index 00000000..403fcff4 --- /dev/null +++ b/packages/components/combobox/src/index.js @@ -0,0 +1,6 @@ +export { + Root, + Trigger, + List, + Option, +} from './Combobox'; diff --git a/packages/components/end-user-consent/src/EndUserConsent.js b/packages/components/end-user-consent/src/EndUserConsent.js new file mode 100644 index 00000000..5e75cf7a --- /dev/null +++ b/packages/components/end-user-consent/src/EndUserConsent.js @@ -0,0 +1,858 @@ +"use strict"; + +function templateString() { + return ` + + + + + + + + `; +} + +class EndUserConsent extends HTMLElement { + constructor() { + super(); + + this.idRequiresTotpConsent = ["BVN_MFA"]; + this.templateString = templateString.bind(this); + this.render = () => { + return this.templateString(); + }; + + this.attachShadow({ mode: "open" }); + } + + connectedCallback() { + this.pages = []; + const template = document.createElement("template"); + template.innerHTML = this.render(); + + this.shadowRoot.appendChild(template.content.cloneNode(true)); + + this.consentScreen = this.shadowRoot.querySelector("#consent-screen"); + this.totpConsentApp = this.shadowRoot.querySelector("totp-consent-app"); + this.consentRejectedScreen = this.shadowRoot.querySelector( + "#consent-rejected-screen", + ); + + this.allowButton = this.shadowRoot.querySelector("#allow"); + this.rejectButton = this.shadowRoot.querySelector("#cancel"); + this.backToConsentButton = + this.shadowRoot.querySelector("#back-to-consent"); + this.confirmConsentRejectionButton = this.shadowRoot.querySelector( + "#confirm-consent-rejection", + ); + this.backButton = this.shadowRoot.querySelector("#back-button"); + const CloseIframeButtons = + this.shadowRoot.querySelectorAll(".close-iframe"); + + this.allowButton.addEventListener("click", (e) => + this.handleConsentGrant(e), + ); + this.rejectButton.addEventListener("click", (e) => + this.handleConsentGrant(e), + ); + + this.backToConsentButton.addEventListener("click", () => + this.setActiveScreen(this.consentScreen), + ); + this.confirmConsentRejectionButton.addEventListener("click", (e) => + this.handleConsentRejection(e), + ); + + this.totpConsentApp.addEventListener( + "SmileIdentity::ConsentDenied::TOTP::ContactMethodsOutdated", + (e) => this.handleTotpConsentEvents(e), + ); + this.totpConsentApp.addEventListener( + "SmileIdentity::ConsentGranted::TOTP", + (e) => this.handleTotpConsentEvents(e), + ); + this.totpConsentApp.addEventListener( + "SmileIdentity::ConsentDenied::Back", + (e) => this.handleBackEvents(e), + ); + + this.backButton.addEventListener("click", (e) => { + this.handleBackEvents(e); + }); + + CloseIframeButtons.forEach((button) => { + button.addEventListener( + "click", + () => { + this.closeWindow(); + }, + false, + ); + }); + + this.activeScreen = this.consentScreen; + } + + setActiveScreen(screen) { + this.activeScreen.hidden = true; + screen.hidden = false; + this.activeScreen = screen; + } + + get baseUrl() { + return this.getAttribute("base-url"); + } + + get country() { + return this.getAttribute("country"); + } + + get demoMode() { + return !!this.hasAttribute("demo-mode"); + } + + get hideBack() { + return this.hasAttribute("hide-back-to-host"); + } + + get idHint() { + return this.getAttribute("id-hint") || "Your BVN should be 11 digits long"; + } + + get idRegex() { + return this.getAttribute("id-regex"); + } + + get idType() { + return this.getAttribute("id-type"); + } + + get idTypeLabel() { + return this.getAttribute("id-type-label"); + } + + get partnerId() { + return this.getAttribute("partner-id"); + } + + get partnerName() { + return this.getAttribute("partner-name"); + } + + get partnerLogoURL() { + return this.getAttribute("partner-logo"); + } + + get partnerPolicyURL() { + return this.getAttribute("policy-url"); + } + + get themeColor() { + return this.getAttribute("theme-color") || "#043C93"; + } + + get token() { + return this.getAttribute("token"); + } + + handleConsentGrant(e) { + const granted = e.target === this.allowButton; + + if (granted) { + if (this.idRequiresTotpConsent.includes(this.idType)) { + this.setActiveScreen(this.totpConsentApp); + this.pages.push(this.consentScreen); + } else { + this.dispatchEvent( + new CustomEvent("SmileIdentity::ConsentGranted", { + detail: { + consented: { + personal_details: granted, + contact_information: granted, + document_information: granted, + }, + }, + }), + ); + } + } else { + this.setActiveScreen(this.consentRejectedScreen); + } + } + + handleConsentRejection() { + this.dispatchEvent(new CustomEvent("SmileIdentity::ConsentDenied")); + } + + handleTotpConsentEvents(e) { + const customEvent = new CustomEvent(e.type, { + detail: { + ...e.detail, + }, + }); + this.dispatchEvent(customEvent); + } + + handleBackEvents() { + const page = this.pages.pop(); + if (page) { + this.setActiveScreen(page); + } else { + this.dispatchEvent(new CustomEvent("SmileIdentity::Exit")); + } + } + + closeWindow() { + const referenceWindow = window.parent; + referenceWindow.postMessage("SmileIdentity::Close", "*"); + } +} + +if ("customElements" in window) { + window.customElements.define('end-user-consent', EndUserConsent); +} + +export { + EndUserConsent +}; diff --git a/packages/components/end-user-consent/src/index.js b/packages/components/end-user-consent/src/index.js new file mode 100644 index 00000000..562c109d --- /dev/null +++ b/packages/components/end-user-consent/src/index.js @@ -0,0 +1,3 @@ +export { + EndUserConsent +} from './EndUserConsent'; diff --git a/packages/components/package.json b/packages/components/package.json new file mode 100644 index 00000000..5a753846 --- /dev/null +++ b/packages/components/package.json @@ -0,0 +1,13 @@ +{ + "name": "@smileid/components", + "version": "1.0.0", + "private": "true", + "exports": { + ".": "./index.js", + "./combobox": "./combobox/src/index.js", + "./end-user-consent": "./end-user-consent/src/index.js" + }, + "description": "A collection of Web Components used by SmileID", + "keywords": [ "Web Components" ], + "author": "SmileID (https://usesmileid.com)" +} diff --git a/packages/embed/package.json b/packages/embed/package.json index c1091f1f..5411e387 100644 --- a/packages/embed/package.json +++ b/packages/embed/package.json @@ -28,6 +28,7 @@ "homepage": "https://github.com/smileidentity/hosted-web-integration#readme", "dependencies": { "@smile_identity/smart-camera-web": "file:../smart-camera-web", + "@smileid/components": "file:../components", "jszip": "^3.10.1", "validate.js": "^0.13.1" }, diff --git a/packages/embed/src/js/basic-kyc.js b/packages/embed/src/js/basic-kyc.js index 2fd64862..d8e9260f 100644 --- a/packages/embed/src/js/basic-kyc.js +++ b/packages/embed/src/js/basic-kyc.js @@ -1,7 +1,7 @@ import validate from "validate.js"; -import ConsentScreen from "./components/ConsentScreen"; +import "@smileid/components/combobox"; +import "@smileid/components/end-user-consent"; import TotpBasedConsent from "./components/TotpConsentApp"; -import Combobox from "./components/Combobox"; import { version as sdkVersion } from "../../package.json"; (function basicKyc() { @@ -19,14 +19,8 @@ import { version as sdkVersion } from "../../package.json"; const referenceWindow = window.parent; referenceWindow.postMessage("SmileIdentity::ChildPageReady", "*"); - window.customElements.define("end-user-consent", ConsentScreen); window.customElements.define("totp-consent-app", TotpBasedConsent); - window.customElements.define("smileid-combobox", Combobox.Root); - window.customElements.define("smileid-combobox-trigger", Combobox.Trigger); - window.customElements.define("smileid-combobox-listbox", Combobox.List); - window.customElements.define("smileid-combobox-option", Combobox.Option); - const pages = []; let activeScreen; let config; diff --git a/packages/embed/src/js/biometric-kyc.js b/packages/embed/src/js/biometric-kyc.js index 7089757d..eb3258eb 100644 --- a/packages/embed/src/js/biometric-kyc.js +++ b/packages/embed/src/js/biometric-kyc.js @@ -1,7 +1,7 @@ import JSZip from "jszip"; import validate from "validate.js"; import "@smile_identity/smart-camera-web"; -import ConsentScreen from "./components/ConsentScreen"; +import "@smileid/components/end-user-consent"; import TotpBasedConsent from "./components/TotpConsentApp"; import { version as sdkVersion } from "../../package.json"; @@ -20,7 +20,6 @@ import { version as sdkVersion } from "../../package.json"; const referenceWindow = window.parent; referenceWindow.postMessage("SmileIdentity::ChildPageReady", "*"); - window.customElements.define("end-user-consent", ConsentScreen); window.customElements.define("totp-consent-app", TotpBasedConsent); const pages = []; diff --git a/packages/embed/src/js/components/ConsentScreen.js b/packages/embed/src/js/components/ConsentScreen.js deleted file mode 100644 index 2e56d442..00000000 --- a/packages/embed/src/js/components/ConsentScreen.js +++ /dev/null @@ -1,852 +0,0 @@ -"use strict"; - -function templateString() { - return ` - - - - - - - - `; -} - -class EndUserConsent extends HTMLElement { - constructor() { - super(); - - this.idRequiresTotpConsent = ["BVN_MFA"]; - this.templateString = templateString.bind(this); - this.render = () => { - return this.templateString(); - }; - - this.attachShadow({ mode: "open" }); - } - - connectedCallback() { - this.pages = []; - const template = document.createElement("template"); - template.innerHTML = this.render(); - - this.shadowRoot.appendChild(template.content.cloneNode(true)); - - this.consentScreen = this.shadowRoot.querySelector("#consent-screen"); - this.totpConsentApp = this.shadowRoot.querySelector("totp-consent-app"); - this.consentRejectedScreen = this.shadowRoot.querySelector( - "#consent-rejected-screen", - ); - - this.allowButton = this.shadowRoot.querySelector("#allow"); - this.rejectButton = this.shadowRoot.querySelector("#cancel"); - this.backToConsentButton = - this.shadowRoot.querySelector("#back-to-consent"); - this.confirmConsentRejectionButton = this.shadowRoot.querySelector( - "#confirm-consent-rejection", - ); - this.backButton = this.shadowRoot.querySelector("#back-button"); - const CloseIframeButtons = - this.shadowRoot.querySelectorAll(".close-iframe"); - - this.allowButton.addEventListener("click", (e) => - this.handleConsentGrant(e), - ); - this.rejectButton.addEventListener("click", (e) => - this.handleConsentGrant(e), - ); - - this.backToConsentButton.addEventListener("click", () => - this.setActiveScreen(this.consentScreen), - ); - this.confirmConsentRejectionButton.addEventListener("click", (e) => - this.handleConsentRejection(e), - ); - - this.totpConsentApp.addEventListener( - "SmileIdentity::ConsentDenied::TOTP::ContactMethodsOutdated", - (e) => this.handleTotpConsentEvents(e), - ); - this.totpConsentApp.addEventListener( - "SmileIdentity::ConsentGranted::TOTP", - (e) => this.handleTotpConsentEvents(e), - ); - this.totpConsentApp.addEventListener( - "SmileIdentity::ConsentDenied::Back", - (e) => this.handleBackEvents(e), - ); - - this.backButton.addEventListener("click", (e) => { - this.handleBackEvents(e); - }); - - CloseIframeButtons.forEach((button) => { - button.addEventListener( - "click", - () => { - this.closeWindow(); - }, - false, - ); - }); - - this.activeScreen = this.consentScreen; - } - - setActiveScreen(screen) { - this.activeScreen.hidden = true; - screen.hidden = false; - this.activeScreen = screen; - } - - get baseUrl() { - return this.getAttribute("base-url"); - } - - get country() { - return this.getAttribute("country"); - } - - get demoMode() { - return !!this.hasAttribute("demo-mode"); - } - - get hideBack() { - return this.hasAttribute("hide-back-to-host"); - } - - get idHint() { - return this.getAttribute("id-hint") || "Your BVN should be 11 digits long"; - } - - get idRegex() { - return this.getAttribute("id-regex"); - } - - get idType() { - return this.getAttribute("id-type"); - } - - get idTypeLabel() { - return this.getAttribute("id-type-label"); - } - - get partnerId() { - return this.getAttribute("partner-id"); - } - - get partnerName() { - return this.getAttribute("partner-name"); - } - - get partnerLogoURL() { - return this.getAttribute("partner-logo"); - } - - get partnerPolicyURL() { - return this.getAttribute("policy-url"); - } - - get themeColor() { - return this.getAttribute("theme-color") || "#043C93"; - } - - get token() { - return this.getAttribute("token"); - } - - handleConsentGrant(e) { - const granted = e.target === this.allowButton; - - if (granted) { - if (this.idRequiresTotpConsent.includes(this.idType)) { - this.setActiveScreen(this.totpConsentApp); - this.pages.push(this.consentScreen); - } else { - this.dispatchEvent( - new CustomEvent("SmileIdentity::ConsentGranted", { - detail: { - consented: { - personal_details: granted, - contact_information: granted, - document_information: granted, - }, - }, - }), - ); - } - } else { - this.setActiveScreen(this.consentRejectedScreen); - } - } - - handleConsentRejection() { - this.dispatchEvent(new CustomEvent("SmileIdentity::ConsentDenied")); - } - - handleTotpConsentEvents(e) { - const customEvent = new CustomEvent(e.type, { - detail: { - ...e.detail, - }, - }); - this.dispatchEvent(customEvent); - } - - handleBackEvents() { - const page = this.pages.pop(); - if (page) { - this.setActiveScreen(page); - } else { - this.dispatchEvent(new CustomEvent("SmileIdentity::Exit")); - } - } - - closeWindow() { - const referenceWindow = window.parent; - referenceWindow.postMessage("SmileIdentity::Close", "*"); - } -} - -export default EndUserConsent; diff --git a/packages/embed/src/js/doc-verification.js b/packages/embed/src/js/doc-verification.js index b0460f7d..7aa804f4 100644 --- a/packages/embed/src/js/doc-verification.js +++ b/packages/embed/src/js/doc-verification.js @@ -1,7 +1,7 @@ import "@smile_identity/smart-camera-web"; +import "@smileid/components/combobox"; import JSZip from "jszip"; import { version as sdkVersion } from "../../package.json"; -import Combobox from "./components/Combobox"; (function documentVerification() { "use strict"; @@ -17,11 +17,6 @@ import Combobox from "./components/Combobox"; const referenceWindow = window.parent; referenceWindow.postMessage("SmileIdentity::ChildPageReady", "*"); - window.customElements.define("smileid-combobox", Combobox.Root); - window.customElements.define("smileid-combobox-trigger", Combobox.Trigger); - window.customElements.define("smileid-combobox-listbox", Combobox.List); - window.customElements.define("smileid-combobox-option", Combobox.Option); - let config; let activeScreen; let id_info; diff --git a/packages/embed/src/js/ekyc.js b/packages/embed/src/js/ekyc.js index 1743b2e8..f75597b1 100644 --- a/packages/embed/src/js/ekyc.js +++ b/packages/embed/src/js/ekyc.js @@ -1,7 +1,7 @@ import validate from "validate.js"; -import ConsentScreen from "./components/ConsentScreen"; +import "@smileid/components/combobox"; +import "@smileid/components/end-user-consent"; import TotpBasedConsent from "./components/TotpConsentApp"; -import Combobox from "./components/Combobox"; import { version as sdkVersion } from "../../package.json"; (function eKYC() { @@ -18,14 +18,8 @@ import { version as sdkVersion } from "../../package.json"; const referenceWindow = window.parent; referenceWindow.postMessage("SmileIdentity::ChildPageReady", "*"); - window.customElements.define("end-user-consent", ConsentScreen); window.customElements.define("totp-consent-app", TotpBasedConsent); - window.customElements.define("smileid-combobox", Combobox.Root); - window.customElements.define("smileid-combobox-trigger", Combobox.Trigger); - window.customElements.define("smileid-combobox-listbox", Combobox.List); - window.customElements.define("smileid-combobox-option", Combobox.Option); - const pages = []; let activeScreen; let config;