Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@paypal/checkout-components

Package Overview
Dependencies
Maintainers
23
Versions
507
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@paypal/checkout-components - npm Package Compare versions

Comparing version 5.0.306 to 5.0.307-alpha-de2b1cd.0

src/ui/buttons/message.jsx

1

globals.js

@@ -35,4 +35,5 @@ /* eslint import/no-commonjs: off, flowtype/require-valid-file-annotation: off, flowtype/require-return-type: off */

__PAYMENT_FIELDS__: "/altpayfields",
__MESSAGE_MODAL__: "https://www.paypalobjects.com/upstream/bizcomponents/js/modal.js",
},
},
};

2

package.json
{
"name": "@paypal/checkout-components",
"version": "5.0.306",
"version": "5.0.307-alpha-de2b1cd.0",
"description": "PayPal Checkout components, for integrating checkout products.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -66,1 +66,22 @@ /* @flow */

};
export const MESSAGE_OFFER = {
PAY_LATER_LONG_TERM: ("pay_later_long_term": "pay_later_long_term"),
PAY_LATER_SHORT_TERM: ("pay_later_short_term": "pay_later_short_term"),
};
export const MESSAGE_COLOR = {
BLACK: ("black": "black"),
WHITE: ("white": "white"),
};
export const MESSAGE_POSITION = {
TOP: ("top": "top"),
BOTTOM: ("bottom": "bottom"),
};
export const MESSAGE_ALIGN = {
CENTER: ("center": "center"),
LEFT: ("left": "left"),
RIGHT: ("right": "right"),
};

@@ -45,2 +45,7 @@ /* @flow */

IMMEDIATE: ("immediate": "immediate"),
BUTTON_MESSAGE: ("paypal-button-message": "paypal-button-message"),
BUTTON_MESSAGE_RESERVE:
("paypal-button-message-reserved": "paypal-button-message-reserved"),
};

@@ -21,2 +21,3 @@ /* @flow */

__PAYMENT_FIELDS__: string,
__MESSAGE_MODAL__: string,
|},

@@ -23,0 +24,0 @@ |};

@@ -75,22 +75,2 @@ /* @flow */

export type DesignExperimentLabelOptions = {|
i: number,
logo: ChildType,
label: ?$Values<typeof BUTTON_LABEL>,
locale: LocaleType,
logoColor: $Values<typeof LOGO_COLOR>,
multiple: boolean,
period?: number,
fundingEligibility: FundingEligibilityType,
optional?: boolean,
onClick: (event: Event, ...args: $ReadOnlyArray<mixed>) => void,
onKeyPress?: (event: KeyboardEvent, ...args: $ReadOnlyArray<mixed>) => void,
layout: $Values<typeof BUTTON_LAYOUT>,
personalization: ?Personalization,
nonce: ?string,
tagline: ?boolean,
content: ?ContentType,
buttonDesignComponent: ?ChildType,
|};
export type WalletLabelOptions = {|

@@ -119,3 +99,6 @@ locale: LocaleType,

shippingChange?: boolean,
requires?: ({| experiment?: ?Experiment, platform?: $Values<typeof PLATFORM> |}) => Requires,
requires?: ({|
experiment?: ?Experiment,
platform?: $Values<typeof PLATFORM>,
|}) => Requires,
platforms: $ReadOnlyArray<$Values<typeof PLATFORM>>,

@@ -122,0 +105,0 @@ layouts: $ReadOnlyArray<$Values<typeof BUTTON_LAYOUT>>,

@@ -32,3 +32,2 @@ /* @flow */

type LabelOptions,
type DesignExperimentLabelOptions,
type WalletLabelOptions,

@@ -221,17 +220,2 @@ type TagOptions,

export function DesignExperimentLabel(
opts: DesignExperimentLabelOptions
): ChildType {
const { buttonDesignComponent, ...updatedOpts } = opts;
const basicLabel = <BasicLabel {...updatedOpts} />;
const buttonPersonalization = <ButtonPersonalization {...updatedOpts} />;
return (
<Fragment>
{basicLabel}
{buttonDesignComponent}
{buttonPersonalization}
</Fragment>
);
}
export function WalletLabelOld(opts: WalletLabelOptions): ?ChildType {

@@ -238,0 +222,0 @@ const { logoColor, instrument, locale, content, commit } = opts;

@@ -30,5 +30,3 @@ /* @flow */

import { getFundingConfig } from "../../funding";
import { DesignExperimentLabel } from "../../funding/paypal/template";
import { getButtonDesign } from "./buttonDesigns";
import type {

@@ -203,32 +201,2 @@ ButtonStyle,

// Only apply animation to the paypal button
const buttonDesign =
fundingSource === FUNDING.PAYPAL ? getButtonDesign(personalization) : {};
const { buttonDesignContainerClass = "", buttonDesignComponent = null } =
buttonDesign;
if (buttonDesignComponent) {
labelNode = (
<DesignExperimentLabel
i={i}
logo={logoNode}
label={label}
nonce={nonce}
locale={locale}
logoColor={logoColor}
period={period}
layout={layout}
multiple={multiple}
fundingEligibility={fundingEligibility}
onClick={clickHandler}
onKeyPress={keypressHandler}
personalization={personalization}
tagline={tagline}
content={content}
buttonDesignComponent={buttonDesignComponent}
/>
);
}
let isWallet = false;

@@ -286,3 +254,2 @@

`${shouldShowWalletMenu ? CLASS.WALLET_MENU : ""}`,
`${buttonDesignContainerClass}`,
`${borderRadiusClass}`,

@@ -289,0 +256,0 @@ ].join(" ")}

@@ -18,2 +18,3 @@ /* @flow */

BUTTON_FLOW,
MESSAGE_POSITION,
} from "../../constants";

@@ -26,4 +27,2 @@ import {

import { getButtonDesign } from "./buttonDesigns";
import { ButtonDesignExperimentScriptWrapper } from "./buttonDesigns/script";
import {

@@ -41,2 +40,4 @@ normalizeButtonProps,

import { PoweredByPayPal } from "./poweredBy";
import { Message } from "./message";
import { calculateShowPoweredBy } from "./util";

@@ -185,2 +186,4 @@ type GetWalletInstrumentOptions = {|

displayOnly,
message,
messageMarkup,
} = normalizeButtonProps(props);

@@ -242,3 +245,2 @@ const { layout, shape, tagline } = style;

const { buttonDesignScript = "" } = getButtonDesign(personalization);
const index = (i) => {

@@ -248,2 +250,10 @@ return i;

const showTagline =
tagline &&
layout === BUTTON_LAYOUT.HORIZONTAL &&
!fundingSource &&
!message;
const showPoweredBy = calculateShowPoweredBy(layout, fundingSources);
return (

@@ -268,2 +278,6 @@ <div

{message && message.position === MESSAGE_POSITION.TOP ? (
<Message markup={messageMarkup} position={message.position} />
) : null}
{fundingSources.map((source, i) => (

@@ -298,3 +312,3 @@ <Button

{tagline && layout === BUTTON_LAYOUT.HORIZONTAL && !fundingSource ? (
{showTagline ? (
<TagLine

@@ -321,15 +335,9 @@ fundingSource={fundingSources[0]}

{layout === BUTTON_LAYOUT.VERTICAL &&
fundingSources.indexOf(FUNDING.CARD) !== -1 ? (
<PoweredByPayPal locale={locale} nonce={nonce} />
{showPoweredBy ? <PoweredByPayPal locale={locale} nonce={nonce} /> : null}
{message && message.position === MESSAGE_POSITION.BOTTOM ? (
<Message markup={messageMarkup} position={message.position} />
) : null}
{buttonDesignScript ? (
<ButtonDesignExperimentScriptWrapper
nonce={nonce}
buttonDesignScript={buttonDesignScript}
/>
) : (
<Script nonce={nonce} />
)}
<Script nonce={nonce} />
</div>

@@ -336,0 +344,0 @@ );

@@ -43,2 +43,6 @@ /* eslint-disable eslint-comments/disable-enable-pair */

MENU_PLACEMENT,
MESSAGE_OFFER,
MESSAGE_COLOR,
MESSAGE_POSITION,
MESSAGE_ALIGN,
} from "../../constants";

@@ -48,3 +52,3 @@ import { getFundingConfig, isFundingEligible } from "../../funding";

import { BUTTON_SIZE_STYLE } from "./config";
import { isBorderRadiusNumber } from "./util";
import { isBorderRadiusNumber, calculateMessagePosition } from "./util";

@@ -362,10 +366,2 @@ export type CreateOrderData = {||} | {||};

|},
buttonDesign?: {|
id: string,
text: string,
tracking: {|
impression: string,
click: string,
|},
|},
|};

@@ -438,2 +434,18 @@

export type ButtonMessage = {|
amount?: number,
offer?: $ReadOnlyArray<$Values<typeof MESSAGE_OFFER>>,
color: $Values<typeof MESSAGE_COLOR>,
position: $Values<typeof MESSAGE_POSITION>,
align: $Values<typeof MESSAGE_ALIGN>,
|};
export type ButtonMessageInputs = {|
amount?: number | void,
offer?: $ReadOnlyArray<$Values<typeof MESSAGE_OFFER>> | void,
color?: $Values<typeof MESSAGE_COLOR> | void,
position?: $Values<typeof MESSAGE_POSITION> | void,
align?: $Values<typeof MESSAGE_ALIGN> | void,
|};
export type RenderButtonProps = {|

@@ -473,2 +485,4 @@ style: ButtonStyle,

displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
message?: ButtonMessage,
messageMarkup?: string,
|};

@@ -533,2 +547,4 @@

hostedButtonId?: string,
message?: ButtonMessage,
messageMarkup?: string,
|};

@@ -576,2 +592,5 @@

displayOnly: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
message?: ButtonMessageInputs | void,
messageMarkup?: string | void,
renderedButtons: $ReadOnlyArray<$Values<typeof FUNDING>>,
};

@@ -725,2 +744,68 @@

export function normalizeButtonMessage(
message: ButtonMessageInputs,
layout: $Values<typeof BUTTON_LAYOUT>,
fundingSources: $ReadOnlyArray<$Values<typeof FUNDING>>
): ButtonMessage {
const {
amount,
offer,
color = MESSAGE_COLOR.BLACK,
position,
align = MESSAGE_ALIGN.CENTER,
} = message;
if (typeof amount !== "undefined") {
if (typeof amount !== "number") {
throw new TypeError(
`Expected message.amount to be a number, got: ${amount}`
);
}
if (amount < 0) {
throw new Error(
`Expected message.amount to be a positive number, got: ${amount}`
);
}
}
if (typeof offer !== "undefined") {
if (!Array.isArray(offer)) {
throw new TypeError(
`Expected message.offer to be an array of strings, got: ${String(
offer
)}`
);
}
const invalidOffers = offer.filter(
(o) => !values(MESSAGE_OFFER).includes(o)
);
if (invalidOffers.length > 0) {
throw new Error(`Invalid offer(s): ${invalidOffers.join(",")}`);
}
}
if (typeof color !== "undefined" && !values(MESSAGE_COLOR).includes(color)) {
throw new Error(`Invalid color: ${color}`);
}
if (
typeof position !== "undefined" &&
!values(MESSAGE_POSITION).includes(position)
) {
throw new Error(`Invalid position: ${position}`);
}
if (typeof align !== "undefined" && !values(MESSAGE_ALIGN).includes(align)) {
throw new Error(`Invalid align: ${align}`);
}
return {
amount,
offer,
color,
position: calculateMessagePosition(fundingSources, layout, position),
align,
};
}
const COUNTRIES = values(COUNTRY);

@@ -780,2 +865,5 @@ const FUNDING_SOURCES = values(FUNDING);

displayOnly = [],
message,
messageMarkup,
renderedButtons,
} = props;

@@ -839,3 +927,8 @@

style = normalizeButtonStyle(props, style);
const { layout } = style;
message = message
? normalizeButtonMessage(message, layout, renderedButtons)
: undefined;
return {

@@ -873,3 +966,5 @@ clientID,

displayOnly,
message,
messageMarkup,
};
}
/* @flow */
import { FUNDING } from "@paypal/sdk-constants/src";
import { BUTTON_LAYOUT, MESSAGE_POSITION } from "../../constants";
import { ValidationError } from "../../lib";
export function isBorderRadiusNumber(borderRadius?: number): boolean {
return typeof borderRadius === "number";
}
export function calculateShowPoweredBy(
layout: $Values<typeof BUTTON_LAYOUT>,
fundingSources: $ReadOnlyArray<$Values<typeof FUNDING>>
): boolean {
return (
layout === BUTTON_LAYOUT.VERTICAL && fundingSources.includes(FUNDING.CARD)
);
}
export function calculateMessagePosition(
fundingSources: $ReadOnlyArray<$Values<typeof FUNDING>>,
layout: $Values<typeof BUTTON_LAYOUT>,
position?: $Values<typeof MESSAGE_POSITION>
): $Values<typeof MESSAGE_POSITION> {
const showPoweredBy = calculateShowPoweredBy(layout, fundingSources);
if (showPoweredBy && position === MESSAGE_POSITION.BOTTOM) {
throw new ValidationError(
"Message position must be 'top' when Debit and/or Credit Card button is present"
);
}
if (
showPoweredBy ||
position === MESSAGE_POSITION.TOP ||
(layout === BUTTON_LAYOUT.VERTICAL && !position)
) {
return MESSAGE_POSITION.TOP;
}
return MESSAGE_POSITION.BOTTOM;
}

@@ -76,3 +76,7 @@ /* @flow */

} from "../../lib";
import { normalizeButtonStyle, type ButtonProps } from "../../ui/buttons/props";
import {
normalizeButtonStyle,
normalizeButtonMessage,
type ButtonProps,
} from "../../ui/buttons/props";
import { isFundingEligible } from "../../funding";

@@ -90,2 +94,3 @@

getButtonExperiments,
getModal,
} from "./util";

@@ -640,2 +645,20 @@

message: {
type: "object",
queryParam: true,
required: false,
decorate: ({ props, value }) => {
const {
style: { layout },
renderedButtons: fundingSources,
} = props;
return normalizeButtonMessage(
// $FlowFixMe
value,
layout,
fundingSources
);
},
},
nonce: {

@@ -690,2 +713,97 @@ type: "string",

onMessageClick: {
type: "function",
required: false,
value: ({ props }) => {
return async ({
offerType,
messageType,
offerCountryCode,
creditProductIdentifier,
}) => {
const { message, clientID, merchantID, currency, buttonSessionID } =
props;
const amount = message?.amount;
getLogger()
.info("button_message_click")
.track({
[FPTI_KEY.TRANSITION]: "button_message_click",
[FPTI_KEY.STATE]: "BUTTON_MESSAGE",
[FPTI_KEY.CONTEXT_ID]: buttonSessionID,
[FPTI_KEY.CONTEXT_TYPE]: "button_session_id",
[FPTI_KEY.EVENT_NAME]: "message_click",
// adding temp string here for our sdk constants
button_message_offer_type: offerType,
button_message_credit_product_identifier:
creditProductIdentifier,
button_message_type: messageType,
button_message_position: message?.position,
button_message_align: message?.align,
button_message_color: message?.color,
button_message_offer_country: offerCountryCode,
button_message_amount: amount,
[FPTI_KEY.BUTTON_SESSION_UID]: buttonSessionID,
});
const modalInstance = await getModal(clientID, merchantID);
return modalInstance?.show({
amount,
offer: offerType,
currency,
});
};
},
},
onMessageHover: {
type: "function",
required: false,
value: ({ props }) => {
return () => {
// offerType, messageType, offerCountryCode, and creditProductIdentifier are passed in and may be used in an upcoming message hover logging feature
// lazy loads the modal, to be memoized and executed onMessageClick
const { clientID, merchantID } = props;
return getModal(clientID, merchantID);
};
},
},
onMessageReady: {
type: "function",
required: false,
value: ({ props }) => {
return ({
offerType,
messageType,
offerCountryCode,
creditProductIdentifier,
}) => {
const { message, buttonSessionID } = props;
getLogger()
.info("button_message_render")
.track({
[FPTI_KEY.TRANSITION]: "button_message_render",
[FPTI_KEY.STATE]: "BUTTON_MESSAGE",
[FPTI_KEY.CONTEXT_ID]: buttonSessionID,
[FPTI_KEY.CONTEXT_TYPE]: "button_session_id",
[FPTI_KEY.EVENT_NAME]: "message_render",
// adding temp string here for our sdk constants
button_message_offer_type: offerType,
button_message_credit_product_identifier:
creditProductIdentifier,
button_message_type: messageType,
button_message_posiiton: message?.position,
button_message_align: message?.align,
button_message_color: message?.color,
button_message_offer_country: offerCountryCode,
button_message_amount: message?.amount,
[FPTI_KEY.BUTTON_SESSION_UID]: buttonSessionID,
});
};
},
},
onShippingAddressChange: {

@@ -692,0 +810,0 @@ type: "function",

@@ -16,2 +16,3 @@ /* @flow */

once,
memoize,
} from "@krakenjs/belter/src";

@@ -26,2 +27,4 @@ import { FUNDING } from "@paypal/sdk-constants/src";

getComponents,
getEnv,
getNamespace,
} from "@paypal/sdk-client/src";

@@ -362,1 +365,51 @@ import { getRefinedFundingEligibility } from "@paypal/funding-components/src";

}
function buildModalBundleUrl(): string {
let url = __PAYPAL_CHECKOUT__.__URI__.__MESSAGE_MODAL__;
if (getEnv() === "sandbox") {
url = url.replace("/js/", "/sandbox/");
} else if (getEnv() === "stage" || getEnv() === "local") {
url = url.replace("/js/", "/stage/");
}
return url;
}
export const getModal: (
clientID: string,
merchantID: $ReadOnlyArray<string> | void
) => Object = memoize(async (clientID, merchantID) => {
try {
const namespace = getNamespace();
if (!window[namespace].MessagesModal) {
// eslint-disable-next-line no-restricted-globals, promise/no-native
await new Promise((resolve, reject) => {
const script = document.createElement("script");
script.setAttribute("data-pp-namespace", namespace);
script.src = buildModalBundleUrl();
script.addEventListener("error", (err: Event) => {
reject(err);
});
script.addEventListener("load", () => {
document.body?.removeChild(script);
resolve();
});
document.body?.appendChild(script);
});
}
return window[namespace].MessagesModal({
account: `client-id:${clientID}`,
merchantId: merchantID?.join(",") || undefined,
});
} catch (err) {
// $FlowFixMe flow doesn't seem to understand that the reset function property exists on the function object itself
getModal.reset();
getLogger()
.error("button_message_modal_fetch_error", { err })
.track({
err: err.message || "BUTTON_MESSAGE_MODAL_FETCH_ERROR",
details: err.details,
stack: JSON.stringify(err.stack || err),
});
}
});

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc