diff --git a/.eslintrc.js b/.eslintrc.js index b35e55a4..d3dda9dc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,33 +1,34 @@ /* @flow */ module.exports = { - 'extends': './node_modules/@krakenjs/grumbler-scripts/config/.eslintrc-browser.js', + extends: + "./node_modules/@krakenjs/grumbler-scripts/config/.eslintrc-browser.js", - 'globals': { - 'Promise': false, - '__PAYPAL_CHECKOUT__': true, - '__paypal_checkout__': true, - '__sdk__': true, - '__LOCALE__': true, - '__CLIENT_ID__': true, - '__MERCHANT_ID__': true, - '__INTENT__': true, - '__COMMIT__': true, - '__VAULT__': true, - '__PORT__': true, - '__STAGE_HOST__': true, - '__HOST__': true, - '__PATH__': true, - '__COMPONENTS__': true - }, + globals: { + Promise: false, + __PAYPAL_CHECKOUT__: true, + __paypal_checkout__: true, + __sdk__: true, + __LOCALE__: true, + __CLIENT_ID__: true, + __MERCHANT_ID__: true, + __INTENT__: true, + __COMMIT__: true, + __VAULT__: true, + __PORT__: true, + __STAGE_HOST__: true, + __HOST__: true, + __PATH__: true, + __COMPONENTS__: true, + }, - 'rules': { - 'complexity': 'off', - 'max-nested-callbacks': [ 'error', 5 ], - 'react/prop-types': 'off', - 'react/style-prop-object': 'off', - 'react/display-name': 'off', - 'react/require-default-props': 'off', - 'react/forbid-component-props': 'off' - } -}; \ No newline at end of file + rules: { + complexity: "off", + "max-nested-callbacks": ["error", 5], + "react/prop-types": "off", + "react/style-prop-object": "off", + "react/display-name": "off", + "react/require-default-props": "off", + "react/forbid-component-props": "off", + }, +}; diff --git a/.github/renovate.json b/.github/renovate.json index e0e2f74c..c433a8a5 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,8 +1,5 @@ { - "extends": [ - "config:base", - ":preserveSemverRanges" - ], + "extends": ["config:base", ":preserveSemverRanges"], "prCreation": "immediate", "prHourlyLimit": 0, "rangeStrategy": "status-success", @@ -10,9 +7,7 @@ "semanticCommits": true, "timezone": "America/Los_Angeles", "rebaseStalePrs": true, - "labels": [ - ":christmas_tree: dependencies" - ], + "labels": [":christmas_tree: dependencies"], "packageRules": [ { "packagePatterns": "^babel", diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0edec367..153653c6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ jobs: - name: ⎔ Setup node uses: actions/setup-node@v2 with: - node-version: '14' + node-version: "14" - name: 📥 Download deps uses: bahmutov/npm-install@v1 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 09ee307a..c2bd385b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,8 +15,8 @@ jobs: # sets up the .npmrc file to publish to npm uses: actions/setup-node@v2 with: - node-version: '14' - registry-url: 'https://registry.npmjs.org' + node-version: "14" + registry-url: "https://registry.npmjs.org" - name: 📥 Download deps uses: bahmutov/npm-install@v1 diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..d24fdfc6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..b7edac54 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +build +dist +coverage +flow-typed +CHANGELOG.md diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1 @@ +{} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d5ab84f3..0b6816c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,9 @@ Feel free to raise a pull request to us. Our team would review your proposed mod your changes into our code. Ideas and other comments are also welcome. ## Getting Started + 1. Create your own [fork](https://help.github.com/articles/fork-a-repo) of this [repository](../../fork). + ```bash # Clone it $ git clone git@github.com:me/paypal-checkout.git @@ -28,10 +30,12 @@ $ npm test ``` ## Making Changes + 1. Make sure that your changes adhere to the current coding conventions used throughout the project, indentation, accurate comments, etc. 2. Ensure existing tests pass (`$ npm test`) and include test cases which fail without your change and succeed with it. ## Submitting Changes + 1. Ensure that no errors are generated by ESLint (run during `$ npm test`). 2. Commit your changes in logical chunks, i.e. keep your changes small per single commit. 3. Locally merge (or rebase) the upstream branch into your topic branch: `$ git pull upstream && git merge`. diff --git a/README.md b/README.md index 54060128..bd15845a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -PayPal Common Components ------------------------- +## PayPal Common Components [![build status][build-badge]][build] [![code coverage][coverage-badge]][coverage] @@ -42,13 +41,14 @@ npm run dev ``` ## Test Tasks + ``` npm test ``` -| Flags | Description | -| ------------- | ------------- | -| --clear-cache | Clear Babel Loader and PhantomJS cache | -| --debug | Debug mode. PhantomJS, Karma, and CheckoutJS | -| --quick | Fastest testing. Minimal output, no coverage | -| --browser | Choose Browser | +| Flags | Description | +| ------------- | -------------------------------------------- | +| --clear-cache | Clear Babel Loader and PhantomJS cache | +| --debug | Debug mode. PhantomJS, Karma, and CheckoutJS | +| --quick | Fastest testing. Minimal output, no coverage | +| --browser | Choose Browser | diff --git a/__sdk__.js b/__sdk__.js index c0db2dea..322bed38 100644 --- a/__sdk__.js +++ b/__sdk__.js @@ -1,12 +1,12 @@ /* @flow */ /* eslint unicorn/filename-case: 0, import/unambiguous: 0, import/no-commonjs: 0 */ -const globals = require('./globals'); +const globals = require("./globals"); module.exports = { - common: { - automatic: true, - entry: './src/interface', - globals - } + common: { + automatic: true, + entry: "./src/interface", + globals, + }, }; diff --git a/babel.config.json b/babel.config.json index 92ad6f61..2d3a6b31 100644 --- a/babel.config.json +++ b/babel.config.json @@ -1,3 +1,3 @@ { "extends": "@krakenjs/grumbler-scripts/config/.babelrc-node" -} \ No newline at end of file +} diff --git a/globals.js b/globals.js index 9e6b2bd6..ea045576 100644 --- a/globals.js +++ b/globals.js @@ -1,23 +1,22 @@ /* eslint import/no-commonjs: off, flowtype/require-valid-file-annotation: off, flowtype/require-return-type: off */ -const postRobotGlobals = require('@krakenjs/post-robot/globals'); -const zoidGlobals = require('@krakenjs/zoid/globals'); +const postRobotGlobals = require("@krakenjs/post-robot/globals"); +const zoidGlobals = require("@krakenjs/zoid/globals"); module.exports = { + __ZOID__: { + ...zoidGlobals.__ZOID__, + __DEFAULT_CONTAINER__: true, + __DEFAULT_PRERENDER__: true, + __FRAMEWORK_SUPPORT__: true, + }, - __ZOID__: { - ...zoidGlobals.__ZOID__, - __DEFAULT_CONTAINER__: true, - __DEFAULT_PRERENDER__: true, - __FRAMEWORK_SUPPORT__: true - }, + __POST_ROBOT__: { + ...postRobotGlobals.__POST_ROBOT__, + __IE_POPUP_SUPPORT__: false, + }, - __POST_ROBOT__: { - ...postRobotGlobals.__POST_ROBOT__, - __IE_POPUP_SUPPORT__: false - }, - - __PAYPAL_CHECKOUT__: { - __REMEMBERED_FUNDING__: [] - } + __PAYPAL_CHECKOUT__: { + __REMEMBERED_FUNDING__: [], + }, }; diff --git a/jest.config.js b/jest.config.js index 168c2f82..47c21f85 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,3 @@ /* eslint import/no-commonjs: off, flowtype/require-valid-file-annotation: off */ -module.exports = { - -}; +module.exports = {}; diff --git a/karma.conf.js b/karma.conf.js index 56548cdb..5e60ba35 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,44 +1,43 @@ /* @flow */ /* eslint import/no-default-export: off */ -import { getKarmaConfig } from '@krakenjs/grumbler-scripts/config/karma.conf'; - -import { WEBPACK_CONFIG_TEST } from './webpack.config'; - -export default function configKarma(karma : Object) { - - const karmaConfig = getKarmaConfig(karma, { - basePath: __dirname, - testDir: 'test', - windowDir: 'test/integration/windows', - entry: 'test/integration/index.js', - webpack: WEBPACK_CONFIG_TEST - }); - - karma.set({ - ...karmaConfig, - - files: [ - { - pattern: 'test/integration/globals.js', - included: true, - served: true - }, - - { - pattern: 'test/paypal.js', - included: true, - served: true - }, - - ...karmaConfig.files - ], - - preprocessors: { - ...karmaConfig.preprocessors, - - 'src/index.js': [ 'webpack', 'sourcemap' ], - 'src/**/*.js': [ 'sourcemap' ] - } - }); +import { getKarmaConfig } from "@krakenjs/grumbler-scripts/config/karma.conf"; + +import { WEBPACK_CONFIG_TEST } from "./webpack.config"; + +export default function configKarma(karma: Object) { + const karmaConfig = getKarmaConfig(karma, { + basePath: __dirname, + testDir: "test", + windowDir: "test/integration/windows", + entry: "test/integration/index.js", + webpack: WEBPACK_CONFIG_TEST, + }); + + karma.set({ + ...karmaConfig, + + files: [ + { + pattern: "test/integration/globals.js", + included: true, + served: true, + }, + + { + pattern: "test/paypal.js", + included: true, + served: true, + }, + + ...karmaConfig.files, + ], + + preprocessors: { + ...karmaConfig.preprocessors, + + "src/index.js": ["webpack", "sourcemap"], + "src/**/*.js": ["sourcemap"], + }, + }); } diff --git a/package.json b/package.json index 3b777a92..11da3086 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "flow-typed": "rm -rf flow-typed && flow-typed install", "flow": "flow", "karma": "cross-env NODE_ENV=test babel-node $(npm bin)/karma start", - "test": "npm run lint && npm run flow-typed && npm run flow && npm run karma", + "format": "prettier --write --ignore-unknown .", + "format:check": "prettier --check .", + "test": "npm run format:check && npm run lint && npm run flow-typed && npm run flow && npm run karma", "build": "npm run test && npm run webpack", "release": "./scripts/publish.sh", "release:patch": "./scripts/publish.sh patch", @@ -21,7 +23,8 @@ "reinstall": "rimraf flow-typed && rimraf node_modules && npm install && flow-typed install", "debug": "cross-env NODE_ENV=debug", "webpack": "babel-node --plugins=transform-es2015-modules-commonjs ./node_modules/.bin/webpack --progress", - "eslint-find-rules": "eslint-find-rules --current .eslintrc.js --unused --plugin" + "eslint-find-rules": "eslint-find-rules --current .eslintrc.js --unused --plugin", + "prepare": "husky install" }, "files": [ "src/", @@ -52,19 +55,22 @@ "license": "Apache-2.0", "readmeFilename": "README.md", "devDependencies": { - "@krakenjs/grumbler-scripts": "^6.0.2", + "@krakenjs/grumbler-scripts": "^7.0.0", "@krakenjs/sync-browser-mocks": "^3.0.0", "babel-core": "^7.0.0-bridge.0", "conventional-changelog-cli": "^2.0.11", "flow-bin": "0.135.0", "fs-extra": "^4.0.2", + "husky": "^8.0.1", "imagemagick": "^0.1.3", "imgur": "^0.2.1", + "lint-staged": "^13.0.3", "memory-fs": "^0.4.1", "mocha": "^4", "mocketeer": "^0.3.0", "pixelmatch": "^4.0.2", "pngjs": "^3.3.0", + "prettier": "2.7.1", "serve": "^10.1.2" }, "dependencies": { @@ -76,5 +82,8 @@ "@krakenjs/post-robot": "^11.0.0", "@krakenjs/zalgo-promise": "^2.0.0", "@krakenjs/zoid": "^10.0.0" + }, + "lint-staged": { + "**/*": "prettier --write --ignore-unknown" } } diff --git a/src/config.js b/src/config.js index 33a4525f..b73b60af 100644 --- a/src/config.js +++ b/src/config.js @@ -1,17 +1,15 @@ /* @flow */ -import { getPayPalDomain } from '@paypal/sdk-client/src'; +import { getPayPalDomain } from "@paypal/sdk-client/src"; const URI = __TEST__ - - ? { - THREEDOMAINSECURE: `/base/test/integration/windows/helios/index.htm` + ? { + THREEDOMAINSECURE: `/base/test/integration/windows/helios/index.htm`, } - - : { - THREEDOMAINSECURE: `/webapps/helios` + : { + THREEDOMAINSECURE: `/webapps/helios`, }; -export function getThreeDomainSecureUrl() : string { - return `${ getPayPalDomain() }${ URI.THREEDOMAINSECURE }`; +export function getThreeDomainSecureUrl(): string { + return `${getPayPalDomain()}${URI.THREEDOMAINSECURE}`; } diff --git a/src/declarations.js b/src/declarations.js index 4ae2203b..19e62bc6 100644 --- a/src/declarations.js +++ b/src/declarations.js @@ -1,9 +1,8 @@ /* @flow */ /* eslint import/unambiguous: 0 */ -import { FUNDING } from '@paypal/sdk-constants/src'; +import { FUNDING } from "@paypal/sdk-constants/src"; -declare var __PAYPAL_CHECKOUT__ : {| - __REMEMBERED_FUNDING__ : Array<$Values> // eslint-disable-line flowtype/no-mutable-array +declare var __PAYPAL_CHECKOUT__: {| + __REMEMBERED_FUNDING__: Array<$Values>, // eslint-disable-line flowtype/no-mutable-array |}; - diff --git a/src/globals.js b/src/globals.js index da4ba64e..1c4712ce 100644 --- a/src/globals.js +++ b/src/globals.js @@ -1,7 +1,8 @@ /* @flow */ -import { FUNDING } from '@paypal/sdk-constants/src'; +import { FUNDING } from "@paypal/sdk-constants/src"; -export function getRememberedFunding() : Array<$Values> { // eslint-disable-line flowtype/no-mutable-array - return __PAYPAL_CHECKOUT__.__REMEMBERED_FUNDING__; +// eslint-disable-next-line flowtype/no-mutable-array +export function getRememberedFunding(): Array<$Values> { + return __PAYPAL_CHECKOUT__.__REMEMBERED_FUNDING__; } diff --git a/src/index.js b/src/index.js index e212a8f6..d4d80d5e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ /* @flow */ -export * from './three-domain-secure'; -export * from './overlay'; -export * from './ui'; +export * from "./three-domain-secure"; +export * from "./overlay"; +export * from "./ui"; diff --git a/src/interface.js b/src/interface.js index e384c562..ebe8788d 100644 --- a/src/interface.js +++ b/src/interface.js @@ -1,29 +1,32 @@ /* @flow */ -import { isPayPalDomain } from '@paypal/sdk-client/src'; +import { isPayPalDomain } from "@paypal/sdk-client/src"; // eslint-disable-next-line import/no-namespace -import * as postRobotModule from '@krakenjs/post-robot/src'; +import * as postRobotModule from "@krakenjs/post-robot/src"; -import { getThreeDomainSecureComponent, type TDSComponent } from './three-domain-secure'; +import { + getThreeDomainSecureComponent, + type TDSComponent, +} from "./three-domain-secure"; export type LazyExport = {| - __get__ : () => T + __get__: () => T, |}; export type LazyProtectedExport = {| - __get__ : () => ?T + __get__: () => ?T, |}; -function protectedExport(xport : T) : ?T { - if (isPayPalDomain()) { - return xport; - } +function protectedExport(xport: T): ?T { + if (isPayPalDomain()) { + return xport; + } } -export const ThreeDomainSecure : LazyProtectedExport = { - __get__: () => protectedExport(getThreeDomainSecureComponent()) +export const ThreeDomainSecure: LazyProtectedExport = { + __get__: () => protectedExport(getThreeDomainSecureComponent()), }; -export const postRobot : LazyProtectedExport = { - __get__: () => protectedExport(postRobotModule) +export const postRobot: LazyProtectedExport = { + __get__: () => protectedExport(postRobotModule), }; diff --git a/src/overlay/index.js b/src/overlay/index.js index 591f30f2..7a209740 100644 --- a/src/overlay/index.js +++ b/src/overlay/index.js @@ -1,3 +1,3 @@ /* @flow */ -export * from './template'; +export * from "./template"; diff --git a/src/overlay/style.js b/src/overlay/style.js index 19f333d5..6a8d99e8 100644 --- a/src/overlay/style.js +++ b/src/overlay/style.js @@ -1,18 +1,18 @@ /* @flow */ -import { CONTEXT } from '@krakenjs/zoid/src'; +import { CONTEXT } from "@krakenjs/zoid/src"; export const CLASS = { - OUTLET: 'outlet', - VISIBLE: 'visible', - INVISIBLE: 'invisible', - COMPONENT_FRAME: 'component-frame', - PRERENDER_FRAME: 'prerender-frame' + OUTLET: "outlet", + VISIBLE: "visible", + INVISIBLE: "invisible", + COMPONENT_FRAME: "component-frame", + PRERENDER_FRAME: "prerender-frame", }; -export function getSandboxStyle({ uid } : {| uid : string |}) : string { - return ` - #${ uid }.paypal-checkout-sandbox { +export function getSandboxStyle({ uid }: {| uid: string |}): string { + return ` + #${uid}.paypal-checkout-sandbox { display: block; position: fixed; top: 0; @@ -35,7 +35,7 @@ export function getSandboxStyle({ uid } : {| uid : string |}) : string { opacity: 0; } - #${ uid }.paypal-checkout-sandbox .paypal-checkout-sandbox-iframe { + #${uid}.paypal-checkout-sandbox .paypal-checkout-sandbox-iframe { display: block; position: absolute; top: 0; @@ -44,7 +44,7 @@ export function getSandboxStyle({ uid } : {| uid : string |}) : string { height: 100%; } - #${ uid }.paypal-checkout-sandbox .paypal-checkout-sandbox-iframe-full { + #${uid}.paypal-checkout-sandbox .paypal-checkout-sandbox-iframe-full { border: 0; height: 100%; width: 100vw; @@ -76,9 +76,9 @@ export function getSandboxStyle({ uid } : {| uid : string |}) : string { `; } -export function getContainerStyle({ uid } : {| uid : string |}) : string { - return ` - #${ uid } { +export function getContainerStyle({ uid }: {| uid: string |}): string { + return ` + #${uid} { position: absolute; z-index: 2147483647; top: 0; @@ -95,24 +95,24 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { color: #fff; } - #${ uid } a { + #${uid} a { color: #fff; } - #${ uid } .paypal-checkout-close:before, - #${ uid } .paypal-checkout-close:after { + #${uid} .paypal-checkout-close:before, + #${uid} .paypal-checkout-close:after { background-color: #fff; } - #${ uid }.paypal-overlay-context-${ CONTEXT.POPUP } { + #${uid}.paypal-overlay-context-${CONTEXT.POPUP} { cursor: pointer; } - #${ uid } a { + #${uid} a { text-decoration: none; } - #${ uid } .paypal-checkout-modal { + #${uid} .paypal-checkout-modal { font-family: "HelveticaNeue", "HelveticaNeue-Light", "Helvetica Neue Light", helvetica, arial, sans-serif; font-size: 14px; text-align: center; @@ -127,7 +127,7 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { text-align: center; } - #${ uid }.paypal-overlay-loading .paypal-checkout-message, #${ uid }.paypal-overlay-loading .paypal-checkout-continue { + #${uid}.paypal-overlay-loading .paypal-checkout-message, #${uid}.paypal-overlay-loading .paypal-checkout-continue { display: none; } @@ -135,46 +135,46 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { display: none; } - #${ uid }.paypal-overlay-loading .paypal-checkout-loader { + #${uid}.paypal-overlay-loading .paypal-checkout-loader { display: block; } - #${ uid } .paypal-checkout-modal .paypal-checkout-logo { + #${uid} .paypal-checkout-modal .paypal-checkout-logo { cursor: pointer; margin-bottom: 30px; display: inline-block; } - #${ uid } .paypal-checkout-modal .paypal-checkout-logo img { + #${uid} .paypal-checkout-modal .paypal-checkout-logo img { height: 36px; } - #${ uid } .paypal-checkout-modal .paypal-checkout-logo img.paypal-checkout-logo-pp { + #${uid} .paypal-checkout-modal .paypal-checkout-logo img.paypal-checkout-logo-pp { margin-right: 10px; } - #${ uid } .paypal-checkout-modal .paypal-checkout-message { + #${uid} .paypal-checkout-modal .paypal-checkout-message { font-size: 15px; line-height: 1.5; padding: 10px 0; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-message, #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-continue { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-message, #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-continue { display: none; } - #${ uid } .paypal-checkout-modal .paypal-checkout-continue { + #${uid} .paypal-checkout-modal .paypal-checkout-continue { font-size: 15px; line-height: 1.35; padding: 10px 0; font-weight: bold; } - #${ uid } .paypal-checkout-modal .paypal-checkout-continue a { + #${uid} .paypal-checkout-modal .paypal-checkout-continue a { border-bottom: 1px solid white; } - #${ uid } .paypal-checkout-close { + #${uid} .paypal-checkout-close { position: absolute; right: 16px; top: 16px; @@ -183,15 +183,15 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { opacity: 0.6; } - #${ uid }.paypal-overlay-loading .paypal-checkout-close { + #${uid}.paypal-overlay-loading .paypal-checkout-close { display: none; } - #${ uid } .paypal-checkout-close:hover { + #${uid} .paypal-checkout-close:hover { opacity: 1; } - #${ uid } .paypal-checkout-close:before, .paypal-checkout-close:after { + #${uid} .paypal-checkout-close:before, .paypal-checkout-close:after { position: absolute; left: 8px; content: ' '; @@ -199,47 +199,47 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { width: 2px; } - #${ uid } .paypal-checkout-close:before { + #${uid} .paypal-checkout-close:before { transform: rotate(45deg); } - #${ uid } .paypal-checkout-close:after { + #${uid} .paypal-checkout-close:after { transform: rotate(-45deg); } - #${ uid } .paypal-checkout-iframe-container { + #${uid} .paypal-checkout-iframe-container { display: none; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container > .${ CLASS.OUTLET }, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container > .${ CLASS.OUTLET } > iframe { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container > .${CLASS.OUTLET}, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container > .${CLASS.OUTLET} > iframe { max-height: 95vh; max-width: 95vw; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container-full, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container-full > .${ CLASS.OUTLET }, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container-full > .${ CLASS.OUTLET } > iframe { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container-full, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container-full > .${CLASS.OUTLET}, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container-full > .${CLASS.OUTLET} > iframe { height: 100vh; max-width: 100vw; width: 100vw; } @media screen and (max-width: 470px) { - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container > .${ CLASS.OUTLET }, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container > .${ CLASS.OUTLET } > iframe { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container > .${CLASS.OUTLET}, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container > .${CLASS.OUTLET} > iframe { max-height: 85vh; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container-full, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container-full > .${ CLASS.OUTLET }, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container-full > .${ CLASS.OUTLET } > iframe { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container-full, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container-full > .${CLASS.OUTLET}, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container-full > .${CLASS.OUTLET} > iframe { height: 100vh; } } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container { display: block; @@ -257,7 +257,7 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { overflow: hidden; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} { position: relative; @@ -280,35 +280,35 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { -webkit-overflow-scrolling: touch; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } > iframe { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} > iframe { position: absolute; top: 0; left: 0; transition: opacity .4s ease-in-out; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } > iframe.${ CLASS.COMPONENT_FRAME } { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} > iframe.${CLASS.COMPONENT_FRAME} { z-index: 100; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } > iframe.${ CLASS.PRERENDER_FRAME } { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} > iframe.${CLASS.PRERENDER_FRAME} { z-index: 200; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } > iframe.${ CLASS.VISIBLE } { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} > iframe.${CLASS.VISIBLE} { opacity: 1; z-index: 200; } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } > iframe.${ CLASS.INVISIBLE } { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} > iframe.${CLASS.INVISIBLE} { opacity: 0; z-index: 100; } @media screen and (max-width: 470px) { - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .paypal-checkout-iframe-container, - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .paypal-checkout-iframe-container, + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} { min-width: 100%; min-width: calc(100% - 20px); @@ -317,7 +317,7 @@ export function getContainerStyle({ uid } : {| uid : string |}) : string { } } - #${ uid }.paypal-overlay-context-${ CONTEXT.IFRAME } .${ CLASS.OUTLET } iframe { + #${uid}.paypal-overlay-context-${CONTEXT.IFRAME} .${CLASS.OUTLET} iframe { width: 1px; min-width: 100%; height: 100%; diff --git a/src/overlay/template.jsx b/src/overlay/template.jsx index 5fb4a91b..a435fd2e 100644 --- a/src/overlay/template.jsx +++ b/src/overlay/template.jsx @@ -2,151 +2,207 @@ /** @jsx node */ /* eslint max-lines: off, react/jsx-max-depth: off */ -import { isIos, isFirefox, animate, noop, destroyElement, uniqueID, supportsPopups, type EventEmitterType, toCSS } from '@krakenjs/belter/src'; -import { EVENT, CONTEXT } from '@krakenjs/zoid/src'; -import { node, type ElementNode } from '@krakenjs/jsx-pragmatic/src'; -import { LOGO_COLOR, PPLogo, PayPalLogo } from '@paypal/sdk-logos/src'; -import type { ZalgoPromise } from '@krakenjs/zalgo-promise/src'; - -import { getContainerStyle, getSandboxStyle, CLASS } from './style'; +import { + isIos, + isFirefox, + animate, + noop, + destroyElement, + uniqueID, + supportsPopups, + type EventEmitterType, + toCSS, +} from "@krakenjs/belter/src"; +import { EVENT, CONTEXT } from "@krakenjs/zoid/src"; +import { node, type ElementNode } from "@krakenjs/jsx-pragmatic/src"; +import { LOGO_COLOR, PPLogo, PayPalLogo } from "@paypal/sdk-logos/src"; +import type { ZalgoPromise } from "@krakenjs/zalgo-promise/src"; + +import { getContainerStyle, getSandboxStyle, CLASS } from "./style"; export type OverlayProps = {| - context : $Values, - close : () => ZalgoPromise, - focus : () => ZalgoPromise, - event : EventEmitterType, - frame : ?HTMLElement, - prerenderFrame : ?HTMLElement, - content? : void | {| - windowMessage? : string, - continueMessage? : string - |}, - autoResize? : boolean, - hideCloseButton? : boolean, - nonce : string, - fullScreen? : boolean + context: $Values, + close: () => ZalgoPromise, + focus: () => ZalgoPromise, + event: EventEmitterType, + frame: ?HTMLElement, + prerenderFrame: ?HTMLElement, + content?: void | {| + windowMessage?: string, + continueMessage?: string, + |}, + autoResize?: boolean, + hideCloseButton?: boolean, + nonce: string, + fullScreen?: boolean, |}; -export function Overlay({ context, close, focus, event, frame, prerenderFrame, content = {}, autoResize, hideCloseButton, nonce, fullScreen = false } : OverlayProps) : ElementNode { - const uid = `paypal-overlay-${ uniqueID() }`; - - function closeCheckout(e) { - e.preventDefault(); - e.stopPropagation(); - close(); +export function Overlay({ + context, + close, + focus, + event, + frame, + prerenderFrame, + content = {}, + autoResize, + hideCloseButton, + nonce, + fullScreen = false, +}: OverlayProps): ElementNode { + const uid = `paypal-overlay-${uniqueID()}`; + + function closeCheckout(e) { + e.preventDefault(); + e.stopPropagation(); + close(); + } + + function focusCheckout(e) { + e.preventDefault(); + e.stopPropagation(); + + if (!supportsPopups()) { + return; } - function focusCheckout(e) { - e.preventDefault(); - e.stopPropagation(); - - if (!supportsPopups()) { - return; - } - - if (isIos()) { - // eslint-disable-next-line no-alert - window.alert('Please switch tabs to reactivate the PayPal window'); - } else if (isFirefox()) { - // eslint-disable-next-line no-alert - window.alert('Don\'t see the popup window?\n\nSelect "Window" in your toolbar to find "Log in to your PayPal account"'); - } else { - focus(); - } + if (isIos()) { + // eslint-disable-next-line no-alert + window.alert("Please switch tabs to reactivate the PayPal window"); + } else if (isFirefox()) { + // eslint-disable-next-line no-alert + window.alert( + 'Don\'t see the popup window?\n\nSelect "Window" in your toolbar to find "Log in to your PayPal account"' + ); + } else { + focus(); } - - const setupAnimations = (name) => { - return (el) => { - const showContainer = () => animate(el, `show-${ name }`, noop); - const hideContainer = () => animate(el, `hide-${ name }`, noop); - event.on(EVENT.DISPLAY, showContainer); - event.on(EVENT.CLOSE, hideContainer); - }; + } + + const setupAnimations = (name) => { + return (el) => { + const showContainer = () => animate(el, `show-${name}`, noop); + const hideContainer = () => animate(el, `hide-${name}`, noop); + event.on(EVENT.DISPLAY, showContainer); + event.on(EVENT.CLOSE, hideContainer); }; + }; + + const setupAutoResize = (el) => { + event.on(EVENT.RESIZE, ({ width: newWidth, height: newHeight }) => { + if (typeof newWidth === "number") { + el.style.width = toCSS(newWidth); + } + + if (typeof newHeight === "number") { + el.style.height = toCSS(newHeight); + } + }); + }; + + const outletOnRender = (el) => { + setupAnimations("component")(el); + if (autoResize) { + setupAutoResize(el); + } + }; - const setupAutoResize = (el) => { - event.on(EVENT.RESIZE, ({ width: newWidth, height: newHeight }) => { - if (typeof newWidth === 'number') { - el.style.width = toCSS(newWidth); - } + let outlet; - if (typeof newHeight === 'number') { - el.style.height = toCSS(newHeight); - } - }); - }; - - const outletOnRender = (el) => { - setupAnimations('component')(el); - if (autoResize) { - setupAutoResize(el); - } - }; + if (frame && prerenderFrame) { + frame.classList.add(CLASS.COMPONENT_FRAME); + prerenderFrame.classList.add(CLASS.PRERENDER_FRAME); - let outlet; - - if (frame && prerenderFrame) { - frame.classList.add(CLASS.COMPONENT_FRAME); - prerenderFrame.classList.add(CLASS.PRERENDER_FRAME); - - prerenderFrame.classList.add(CLASS.VISIBLE); - frame.classList.add(CLASS.INVISIBLE); - - event.on(EVENT.RENDERED, () => { - prerenderFrame.classList.remove(CLASS.VISIBLE); - prerenderFrame.classList.add(CLASS.INVISIBLE); - - frame.classList.remove(CLASS.INVISIBLE); - frame.classList.add(CLASS.VISIBLE); - - setTimeout(() => { - destroyElement(prerenderFrame); - }, 1); - }); - - outlet = ( -
- - -
- ); - } + prerenderFrame.classList.add(CLASS.VISIBLE); + frame.classList.add(CLASS.INVISIBLE); + + event.on(EVENT.RENDERED, () => { + prerenderFrame.classList.remove(CLASS.VISIBLE); + prerenderFrame.classList.add(CLASS.INVISIBLE); - return ( -
- - -
+ frame.classList.remove(CLASS.INVISIBLE); + frame.classList.add(CLASS.VISIBLE); + + setTimeout(() => { + destroyElement(prerenderFrame); + }, 1); + }); + + outlet = ( +
+ + +
); + } + + return ( +
+ + +
+ ); } diff --git a/src/three-domain-secure/component.jsx b/src/three-domain-secure/component.jsx index c3ef2602..bbab8cd4 100644 --- a/src/three-domain-secure/component.jsx +++ b/src/three-domain-secure/component.jsx @@ -2,139 +2,145 @@ /** @jsx node */ /* eslint max-lines: 0 */ -import { node, dom } from '@krakenjs/jsx-pragmatic/src'; -import { create, type ZoidComponent } from '@krakenjs/zoid/src'; -import { inlineMemoize, noop } from '@krakenjs/belter/src'; -import { getSDKMeta, getClientID, getCSPNonce } from '@paypal/sdk-client/src'; -import { ZalgoPromise } from '@krakenjs/zalgo-promise/src'; +import { node, dom } from "@krakenjs/jsx-pragmatic/src"; +import { create, type ZoidComponent } from "@krakenjs/zoid/src"; +import { inlineMemoize, noop } from "@krakenjs/belter/src"; +import { getSDKMeta, getClientID, getCSPNonce } from "@paypal/sdk-client/src"; +import { ZalgoPromise } from "@krakenjs/zalgo-promise/src"; -import { Overlay } from '../overlay'; -import { getThreeDomainSecureUrl } from '../config'; +import { Overlay } from "../overlay"; +import { getThreeDomainSecureUrl } from "../config"; -export type TDSResult = {| - -|}; +export type TDSResult = {||}; export const USER_TYPE = { - BRANDED_GUEST: ('BRANDED_GUEST' : 'BRANDED_GUEST'), // inline guest flow - UNBRANDED_GUEST: ('UNBRANDED_GUEST' : 'UNBRANDED_GUEST'), // UCC - MEMBER: ('MEMBER' : 'MEMBER') + BRANDED_GUEST: ("BRANDED_GUEST": "BRANDED_GUEST"), // inline guest flow + UNBRANDED_GUEST: ("UNBRANDED_GUEST": "UNBRANDED_GUEST"), // UCC + MEMBER: ("MEMBER": "MEMBER"), }; export type TDSProps = {| - action : string, - xcomponent : string, - flow : string, - orderID : string, - onSuccess : (TDSResult) => void, - onError : (mixed) => void, - sdkMeta : string, - content? : void | {| - windowMessage? : string, - continueMessage? : string - |}, - userType : ?$Values, - nonce : string + action: string, + xcomponent: string, + flow: string, + orderID: string, + onSuccess: (TDSResult) => void, + onError: (mixed) => void, + sdkMeta: string, + content?: void | {| + windowMessage?: string, + continueMessage?: string, + |}, + userType: ?$Values, + nonce: string, |}; export type TDSComponent = ZoidComponent; -export function getThreeDomainSecureComponent() : TDSComponent { - return inlineMemoize(getThreeDomainSecureComponent, () => { - const component = create({ - tag: 'three-domain-secure', - url: getThreeDomainSecureUrl, - - attributes: { - iframe: { - scrolling: 'no' - } - }, - - containerTemplate: ({ context, focus, close, frame, prerenderFrame, doc, event, props }) => { - return ( - - ).render(dom({ doc })); - }, +export function getThreeDomainSecureComponent(): TDSComponent { + return inlineMemoize(getThreeDomainSecureComponent, () => { + const component = create({ + tag: "three-domain-secure", + url: getThreeDomainSecureUrl, - props: { - action: { - type: 'string', - queryParam: true, - value: () => 'verify' - }, - xcomponent: { - type: 'string', - queryParam: true, - value: () => '1' - }, - flow: { - type: 'string', - queryParam: true, - value: () => '3ds' - }, - createOrder: { - type: 'function', - queryParam: 'cart_id', - // $FlowFixMe - queryValue: ({ value }) => ZalgoPromise.try(value) - }, - clientID: { - type: 'string', - value: getClientID, - queryParam: true - }, - onSuccess: { - type: 'function', - alias: 'onContingencyResult', - decorate: ({ value, onError }) => { - return (err, result) => { - if (err || (result && !result.success)) { - return onError(err); - } + attributes: { + iframe: { + scrolling: "no", + }, + }, - return value(true); - }; - } - }, - sdkMeta: { - type: 'string', - queryParam: true, - sendToChild: false, - value: getSDKMeta - }, - content: { - type: 'object', - required: false - }, - userType: { - type: 'string', - required: false - }, - nonce: { - type: 'string', - default: getCSPNonce + containerTemplate: ({ + context, + focus, + close, + frame, + prerenderFrame, + doc, + event, + props, + }) => { + return ( + + ).render(dom({ doc })); + }, - } - } - }); + props: { + action: { + type: "string", + queryParam: true, + value: () => "verify", + }, + xcomponent: { + type: "string", + queryParam: true, + value: () => "1", + }, + flow: { + type: "string", + queryParam: true, + value: () => "3ds", + }, + createOrder: { + type: "function", + queryParam: "cart_id", + // $FlowFixMe + queryValue: ({ value }) => ZalgoPromise.try(value), + }, + clientID: { + type: "string", + value: getClientID, + queryParam: true, + }, + onSuccess: { + type: "function", + alias: "onContingencyResult", + decorate: ({ value, onError }) => { + return (err, result) => { + if (err || (result && !result.success)) { + return onError(err); + } - if (component.isChild()) { - window.xchild = { - props: component.xprops, - close: noop + return value(true); }; - } - - return component; + }, + }, + sdkMeta: { + type: "string", + queryParam: true, + sendToChild: false, + value: getSDKMeta, + }, + content: { + type: "object", + required: false, + }, + userType: { + type: "string", + required: false, + }, + nonce: { + type: "string", + default: getCSPNonce, + }, + }, }); + + if (component.isChild()) { + window.xchild = { + props: component.xprops, + close: noop, + }; + } + + return component; + }); } diff --git a/src/three-domain-secure/index.js b/src/three-domain-secure/index.js index eb1eb2ed..c35c42e0 100644 --- a/src/three-domain-secure/index.js +++ b/src/three-domain-secure/index.js @@ -1,3 +1,3 @@ /* @flow */ -export * from './component'; +export * from "./component"; diff --git a/src/types.js b/src/types.js index 638ae406..7ce31f77 100644 --- a/src/types.js +++ b/src/types.js @@ -3,6 +3,6 @@ export const TYPES = true; export type DimensionsType = {| - width : number, - height : number + width: number, + height: number, |}; diff --git a/src/ui/index.js b/src/ui/index.js index a28eb86a..91813e2b 100644 --- a/src/ui/index.js +++ b/src/ui/index.js @@ -1,4 +1,4 @@ /* @flow */ -export * from './spinner'; -export * from './venmoSpinner'; +export * from "./spinner"; +export * from "./venmoSpinner"; diff --git a/src/ui/spinner.jsx b/src/ui/spinner.jsx index 4d496a6d..9ceac07c 100644 --- a/src/ui/spinner.jsx +++ b/src/ui/spinner.jsx @@ -1,7 +1,11 @@ /* @flow */ /** @jsx node */ -import { node, type ElementNode, type ChildrenType } from '@krakenjs/jsx-pragmatic/src'; +import { + node, + type ElementNode, + type ChildrenType, +} from "@krakenjs/jsx-pragmatic/src"; const spinnerStyle = ` @@ -69,30 +73,33 @@ const spinnerStyle = ` } `; -export function Spinner({ nonce } : {| nonce : ?string |}) : ElementNode { - return ( -
-