@paypal/checkout-components 5.0.297 → 5.0.298-alpha.2
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/README.md +4 -0
- package/dist/button.js +1 -1
- package/dist/test/button.js +1 -1
- package/package.json +4 -3
- package/src/api/shopper-insights/validation.js +8 -7
- package/src/api/shopper-insights/validation.test.js +3 -1
- package/src/connect/component.jsx +25 -30
- package/src/connect/component.test.js +2 -11
- package/src/constants/api.js +1 -2
- package/src/constants/button.js +21 -0
- package/src/constants/class.js +5 -0
- package/src/hosted-buttons/index.js +25 -26
- package/src/hosted-buttons/index.test.js +7 -4
- package/src/hosted-buttons/types.js +8 -7
- package/src/hosted-buttons/utils.js +43 -36
- package/src/hosted-buttons/utils.test.js +11 -6
- package/src/ui/buttons/buttons.jsx +28 -4
- package/src/ui/buttons/message.jsx +31 -0
- package/src/ui/buttons/props.js +86 -0
- package/src/ui/buttons/util.js +36 -0
- package/src/zoid/buttons/component.jsx +15 -1
- package/src/connect/sendCountMetric.js +0 -25
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
BUTTON_NUMBER,
|
|
16
16
|
BUTTON_LAYOUT,
|
|
17
17
|
BUTTON_FLOW,
|
|
18
|
+
MESSAGE_POSITION,
|
|
18
19
|
} from "../../constants";
|
|
19
20
|
import {
|
|
20
21
|
determineEligibleFunding,
|
|
@@ -36,6 +37,8 @@ import { Button } from "./button";
|
|
|
36
37
|
import { TagLine } from "./tagline";
|
|
37
38
|
import { Script } from "./script";
|
|
38
39
|
import { PoweredByPayPal } from "./poweredBy";
|
|
40
|
+
import { Message } from "./message";
|
|
41
|
+
import { calculateMessagePosition } from "./util";
|
|
39
42
|
|
|
40
43
|
type GetWalletInstrumentOptions = {|
|
|
41
44
|
wallet: ?Wallet,
|
|
@@ -179,6 +182,8 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
179
182
|
supportedNativeBrowser,
|
|
180
183
|
showPayLabel,
|
|
181
184
|
displayOnly,
|
|
185
|
+
message,
|
|
186
|
+
messageMarkup,
|
|
182
187
|
} = normalizeButtonProps(props);
|
|
183
188
|
const { layout, shape, tagline } = style;
|
|
184
189
|
|
|
@@ -240,6 +245,20 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
240
245
|
return i;
|
|
241
246
|
};
|
|
242
247
|
|
|
248
|
+
const showTagline =
|
|
249
|
+
tagline &&
|
|
250
|
+
layout === BUTTON_LAYOUT.HORIZONTAL &&
|
|
251
|
+
!fundingSource &&
|
|
252
|
+
!message;
|
|
253
|
+
const showPoweredBy =
|
|
254
|
+
layout === BUTTON_LAYOUT.VERTICAL && fundingSources.includes(FUNDING.CARD);
|
|
255
|
+
|
|
256
|
+
const calculatedMessagePosition = calculateMessagePosition({
|
|
257
|
+
message,
|
|
258
|
+
showPoweredBy,
|
|
259
|
+
layout,
|
|
260
|
+
});
|
|
261
|
+
|
|
243
262
|
return (
|
|
244
263
|
<div
|
|
245
264
|
class={[
|
|
@@ -259,6 +278,10 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
259
278
|
fundingEligibility={fundingEligibility}
|
|
260
279
|
/>
|
|
261
280
|
|
|
281
|
+
{message && calculatedMessagePosition === MESSAGE_POSITION.TOP ? (
|
|
282
|
+
<Message markup={messageMarkup} position={calculatedMessagePosition} />
|
|
283
|
+
) : null}
|
|
284
|
+
|
|
262
285
|
{fundingSources.map((source, i) => (
|
|
263
286
|
<Button
|
|
264
287
|
content={content}
|
|
@@ -288,7 +311,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
288
311
|
/>
|
|
289
312
|
))}
|
|
290
313
|
|
|
291
|
-
{
|
|
314
|
+
{showTagline ? (
|
|
292
315
|
<TagLine
|
|
293
316
|
fundingSource={fundingSources[0]}
|
|
294
317
|
style={style}
|
|
@@ -310,9 +333,10 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
310
333
|
/>
|
|
311
334
|
) : null}
|
|
312
335
|
|
|
313
|
-
{
|
|
314
|
-
|
|
315
|
-
|
|
336
|
+
{showPoweredBy ? <PoweredByPayPal locale={locale} nonce={nonce} /> : null}
|
|
337
|
+
|
|
338
|
+
{message && calculatedMessagePosition === MESSAGE_POSITION.BOTTOM ? (
|
|
339
|
+
<Message markup={messageMarkup} position={calculatedMessagePosition} />
|
|
316
340
|
) : null}
|
|
317
341
|
|
|
318
342
|
{buttonDesignScript ? (
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
/** @jsx node */
|
|
3
|
+
|
|
4
|
+
import { node, type ChildType } from "@krakenjs/jsx-pragmatic/src";
|
|
5
|
+
|
|
6
|
+
import { CLASS } from "../../constants";
|
|
7
|
+
|
|
8
|
+
const INITIAL_RESERVED_HEIGHT = "36px";
|
|
9
|
+
|
|
10
|
+
type MessageProps = {|
|
|
11
|
+
markup: ?string,
|
|
12
|
+
position: string,
|
|
13
|
+
|};
|
|
14
|
+
|
|
15
|
+
export function Message({ markup, position }: MessageProps): ChildType {
|
|
16
|
+
const messageClassNames = [
|
|
17
|
+
CLASS.BUTTON_MESSAGE,
|
|
18
|
+
`${CLASS.BUTTON_MESSAGE}-${position}`,
|
|
19
|
+
].join(" ");
|
|
20
|
+
|
|
21
|
+
if (typeof markup !== "string") {
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
className={`${messageClassNames} ${CLASS.BUTTON_MESSAGE_RESERVE}`}
|
|
25
|
+
style={`height:${INITIAL_RESERVED_HEIGHT}`}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return <div class={messageClassNames} innerHTML={markup} />;
|
|
31
|
+
}
|
package/src/ui/buttons/props.js
CHANGED
|
@@ -40,6 +40,10 @@ import {
|
|
|
40
40
|
BUTTON_SIZE,
|
|
41
41
|
BUTTON_FLOW,
|
|
42
42
|
MENU_PLACEMENT,
|
|
43
|
+
MESSAGE_OFFER,
|
|
44
|
+
MESSAGE_COLOR,
|
|
45
|
+
MESSAGE_POSITION,
|
|
46
|
+
MESSAGE_ALIGN,
|
|
43
47
|
} from "../../constants";
|
|
44
48
|
import { getFundingConfig, isFundingEligible } from "../../funding";
|
|
45
49
|
|
|
@@ -432,6 +436,22 @@ export type ApplePaySessionConfigRequest = (
|
|
|
432
436
|
request: Object
|
|
433
437
|
) => ApplePaySessionConfig;
|
|
434
438
|
|
|
439
|
+
export type ButtonMessage = {|
|
|
440
|
+
amount?: number,
|
|
441
|
+
offer?: $ReadOnlyArray<$Values<typeof MESSAGE_OFFER>>,
|
|
442
|
+
color?: $Values<typeof MESSAGE_COLOR>,
|
|
443
|
+
position?: $Values<typeof MESSAGE_POSITION>,
|
|
444
|
+
align?: $Values<typeof MESSAGE_ALIGN>,
|
|
445
|
+
|};
|
|
446
|
+
|
|
447
|
+
export type ButtonMessageInputs = {|
|
|
448
|
+
amount?: number | void,
|
|
449
|
+
offer?: $ReadOnlyArray<$Values<typeof MESSAGE_OFFER>> | void,
|
|
450
|
+
color?: $Values<typeof MESSAGE_COLOR> | void,
|
|
451
|
+
position?: $Values<typeof MESSAGE_POSITION> | void,
|
|
452
|
+
align?: $Values<typeof MESSAGE_ALIGN> | void,
|
|
453
|
+
|};
|
|
454
|
+
|
|
435
455
|
export type RenderButtonProps = {|
|
|
436
456
|
style: ButtonStyle,
|
|
437
457
|
locale: LocaleType,
|
|
@@ -466,6 +486,8 @@ export type RenderButtonProps = {|
|
|
|
466
486
|
supportedNativeBrowser: boolean,
|
|
467
487
|
showPayLabel: boolean,
|
|
468
488
|
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|
|
489
|
+
message?: ButtonMessage,
|
|
490
|
+
messageMarkup?: string,
|
|
469
491
|
|};
|
|
470
492
|
|
|
471
493
|
export type PrerenderDetails = {|
|
|
@@ -525,6 +547,8 @@ export type ButtonProps = {|
|
|
|
525
547
|
createVaultSetupToken: CreateVaultSetupToken,
|
|
526
548
|
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|
|
527
549
|
hostedButtonId?: string,
|
|
550
|
+
message?: ButtonMessage,
|
|
551
|
+
messageMarkup?: string,
|
|
528
552
|
|};
|
|
529
553
|
|
|
530
554
|
// eslint-disable-next-line flowtype/require-exact-type
|
|
@@ -567,6 +591,8 @@ export type ButtonPropsInputs = {
|
|
|
567
591
|
supportedNativeBrowser: boolean,
|
|
568
592
|
showPayLabel: boolean,
|
|
569
593
|
displayOnly: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|
|
594
|
+
message?: ButtonMessageInputs | void,
|
|
595
|
+
messageMarkup?: string | void,
|
|
570
596
|
};
|
|
571
597
|
|
|
572
598
|
export const DEFAULT_STYLE = {
|
|
@@ -715,6 +741,62 @@ export function normalizeButtonStyle(
|
|
|
715
741
|
};
|
|
716
742
|
}
|
|
717
743
|
|
|
744
|
+
export function normalizeButtonMessage(
|
|
745
|
+
props: ?ButtonPropsInputs,
|
|
746
|
+
message: ButtonMessageInputs
|
|
747
|
+
): ButtonMessage {
|
|
748
|
+
const { amount, offer, color, position, align } = message;
|
|
749
|
+
|
|
750
|
+
if (typeof amount !== "undefined") {
|
|
751
|
+
if (typeof amount !== "number") {
|
|
752
|
+
throw new TypeError(
|
|
753
|
+
`Expected message.amount to be a number, got: ${amount}`
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
if (amount < 0) {
|
|
757
|
+
throw new Error(
|
|
758
|
+
`Expected message.amount to be a positive number, got: ${amount}`
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
if (offer) {
|
|
764
|
+
if (!Array.isArray(offer)) {
|
|
765
|
+
throw new TypeError(
|
|
766
|
+
`Expected message.offer to be an array of strings, got: ${String(
|
|
767
|
+
offer
|
|
768
|
+
)}`
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
const invalidOffers = offer.filter(
|
|
772
|
+
(o) => !values(MESSAGE_OFFER).includes(o)
|
|
773
|
+
);
|
|
774
|
+
if (invalidOffers.length > 0) {
|
|
775
|
+
throw new Error(`Invalid offer(s): ${invalidOffers.join(",")}`);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
if (color && !values(MESSAGE_COLOR).includes(color)) {
|
|
780
|
+
throw new Error(`Invalid color: ${color}`);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (position && !values(MESSAGE_POSITION).includes(position)) {
|
|
784
|
+
throw new Error(`Invalid position: ${position}`);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
if (align && !values(MESSAGE_ALIGN).includes(align)) {
|
|
788
|
+
throw new Error(`Invalid align: ${align}`);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
return {
|
|
792
|
+
amount,
|
|
793
|
+
offer,
|
|
794
|
+
color,
|
|
795
|
+
position,
|
|
796
|
+
align,
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
|
|
718
800
|
const COUNTRIES = values(COUNTRY);
|
|
719
801
|
const FUNDING_SOURCES = values(FUNDING);
|
|
720
802
|
const ENVS = values(ENV);
|
|
@@ -769,6 +851,8 @@ export function normalizeButtonProps(
|
|
|
769
851
|
supportedNativeBrowser = false,
|
|
770
852
|
showPayLabel = true,
|
|
771
853
|
displayOnly = [],
|
|
854
|
+
message,
|
|
855
|
+
messageMarkup,
|
|
772
856
|
} = props;
|
|
773
857
|
|
|
774
858
|
const { country, lang } = locale;
|
|
@@ -860,5 +944,7 @@ export function normalizeButtonProps(
|
|
|
860
944
|
supportedNativeBrowser,
|
|
861
945
|
showPayLabel,
|
|
862
946
|
displayOnly,
|
|
947
|
+
message: message ? normalizeButtonMessage(props, message) : undefined,
|
|
948
|
+
messageMarkup,
|
|
863
949
|
};
|
|
864
950
|
}
|
package/src/ui/buttons/util.js
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
/* @flow */
|
|
2
|
+
import { BUTTON_LAYOUT, MESSAGE_POSITION } from "../../constants";
|
|
3
|
+
import { ValidationError } from "../../lib";
|
|
4
|
+
|
|
5
|
+
import type { ButtonMessage } from "./props";
|
|
2
6
|
|
|
3
7
|
export function isBorderRadiusNumber(borderRadius?: number): boolean {
|
|
4
8
|
return typeof borderRadius === "number";
|
|
5
9
|
}
|
|
10
|
+
|
|
11
|
+
type calculateMessagePositionProps = {|
|
|
12
|
+
message: ButtonMessage | void,
|
|
13
|
+
showPoweredBy: boolean,
|
|
14
|
+
layout: string,
|
|
15
|
+
|};
|
|
16
|
+
|
|
17
|
+
export function calculateMessagePosition({
|
|
18
|
+
message,
|
|
19
|
+
showPoweredBy,
|
|
20
|
+
layout,
|
|
21
|
+
}: calculateMessagePositionProps): string {
|
|
22
|
+
if (!message) {
|
|
23
|
+
return "none";
|
|
24
|
+
}
|
|
25
|
+
const { position } = message;
|
|
26
|
+
|
|
27
|
+
if (showPoweredBy && position === MESSAGE_POSITION.BOTTOM) {
|
|
28
|
+
throw new ValidationError(
|
|
29
|
+
"Message position must be 'top' when Debit and/or Credit Card button is present"
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (
|
|
34
|
+
showPoweredBy ||
|
|
35
|
+
position === MESSAGE_POSITION.TOP ||
|
|
36
|
+
(layout === BUTTON_LAYOUT.VERTICAL && !position)
|
|
37
|
+
) {
|
|
38
|
+
return MESSAGE_POSITION.TOP;
|
|
39
|
+
}
|
|
40
|
+
return MESSAGE_POSITION.BOTTOM;
|
|
41
|
+
}
|
|
@@ -73,7 +73,11 @@ import {
|
|
|
73
73
|
logLatencyInstrumentationPhase,
|
|
74
74
|
prepareInstrumentationPayload,
|
|
75
75
|
} from "../../lib";
|
|
76
|
-
import {
|
|
76
|
+
import {
|
|
77
|
+
normalizeButtonStyle,
|
|
78
|
+
normalizeButtonMessage,
|
|
79
|
+
type ButtonProps,
|
|
80
|
+
} from "../../ui/buttons/props";
|
|
77
81
|
import { isFundingEligible } from "../../funding";
|
|
78
82
|
|
|
79
83
|
import { containerTemplate } from "./container";
|
|
@@ -887,6 +891,16 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
|
|
|
887
891
|
required: false,
|
|
888
892
|
default: () => window.__TEST_WALLET__,
|
|
889
893
|
},
|
|
894
|
+
|
|
895
|
+
message: {
|
|
896
|
+
type: "object",
|
|
897
|
+
queryParam: true,
|
|
898
|
+
required: false,
|
|
899
|
+
decorate: ({ props, value }) => {
|
|
900
|
+
// $FlowFixMe
|
|
901
|
+
return normalizeButtonMessage(props, value);
|
|
902
|
+
},
|
|
903
|
+
},
|
|
890
904
|
},
|
|
891
905
|
});
|
|
892
906
|
});
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/* @flow */
|
|
2
|
-
import { getLogger } from "@paypal/sdk-client/src";
|
|
3
|
-
|
|
4
|
-
// TODO: This will be pulled in to a shared sdk-client util
|
|
5
|
-
export const sendCountMetric = ({
|
|
6
|
-
dimensions,
|
|
7
|
-
event = "unused",
|
|
8
|
-
name,
|
|
9
|
-
value = 1,
|
|
10
|
-
}: {|
|
|
11
|
-
event?: string,
|
|
12
|
-
name: string,
|
|
13
|
-
value?: number,
|
|
14
|
-
dimensions: {
|
|
15
|
-
[string]: mixed,
|
|
16
|
-
},
|
|
17
|
-
// $FlowIssue return type
|
|
18
|
-
|}) =>
|
|
19
|
-
getLogger().metric({
|
|
20
|
-
dimensions,
|
|
21
|
-
metricEventName: event,
|
|
22
|
-
metricNamespace: name,
|
|
23
|
-
metricValue: value,
|
|
24
|
-
metricType: "counter",
|
|
25
|
-
});
|