@paypal/checkout-components 5.0.383 → 5.0.385
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/dist/button.js +1 -1
- package/dist/test/button.js +1 -1
- package/package.json +3 -2
- package/src/funding/bancontact/config.jsx +4 -0
- package/src/funding/common.jsx +1 -0
- package/src/funding/credit/config.jsx +4 -0
- package/src/funding/funding.js +17 -4
- package/src/funding/funding.test.js +300 -16
- package/src/funding/paylater/config.jsx +4 -0
- package/src/funding/util.js +99 -0
- package/src/funding/util.test.js +264 -0
- package/src/funding/venmo/config.jsx +7 -8
- package/src/funding/venmo/config.test.js +17 -37
- package/src/marks/component.jsx +28 -9
- package/src/marks/template.jsx +3 -8
- package/src/marks/templateRebrand.jsx +177 -0
- package/src/ui/buttons/buttons.jsx +2 -0
- package/src/ui/buttons/props.js +6 -0
- package/src/zoid/buttons/component.jsx +33 -2
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
|
|
3
|
+
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
isWebView,
|
|
6
|
+
isIosWebview,
|
|
7
|
+
isAndroidWebview,
|
|
8
|
+
isFacebookWebView,
|
|
9
|
+
isOperaMini,
|
|
10
|
+
isFirefoxIOS,
|
|
11
|
+
isEdgeIOS,
|
|
12
|
+
isQQBrowser,
|
|
13
|
+
isElectron,
|
|
14
|
+
supportsPopups,
|
|
15
|
+
isTablet,
|
|
16
|
+
isIos,
|
|
17
|
+
isSafari,
|
|
18
|
+
isAndroid,
|
|
19
|
+
isChrome,
|
|
20
|
+
isFirefox,
|
|
21
|
+
} from "@krakenjs/belter/src";
|
|
22
|
+
|
|
23
|
+
import { supportsVenmoPopups, isSupportedNativeVenmoBrowser } from "./util";
|
|
24
|
+
|
|
25
|
+
// Mock all the browser detection functions from belter
|
|
26
|
+
vi.mock("@krakenjs/belter/src", () => ({
|
|
27
|
+
isWebView: vi.fn(),
|
|
28
|
+
isIosWebview: vi.fn(),
|
|
29
|
+
isAndroidWebview: vi.fn(),
|
|
30
|
+
isFacebookWebView: vi.fn(),
|
|
31
|
+
isOperaMini: vi.fn(),
|
|
32
|
+
isFirefoxIOS: vi.fn(),
|
|
33
|
+
isEdgeIOS: vi.fn(),
|
|
34
|
+
isQQBrowser: vi.fn(),
|
|
35
|
+
isElectron: vi.fn(),
|
|
36
|
+
supportsPopups: vi.fn(),
|
|
37
|
+
isTablet: vi.fn(),
|
|
38
|
+
isIos: vi.fn(),
|
|
39
|
+
isSafari: vi.fn(),
|
|
40
|
+
isAndroid: vi.fn(),
|
|
41
|
+
isChrome: vi.fn(),
|
|
42
|
+
isFirefox: vi.fn(),
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
describe("funding/util", () => {
|
|
46
|
+
const defaultUserAgent =
|
|
47
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1";
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
// Reset all mocks before each test
|
|
51
|
+
vi.clearAllMocks();
|
|
52
|
+
|
|
53
|
+
// Reset window.popupBridge
|
|
54
|
+
delete window.popupBridge;
|
|
55
|
+
|
|
56
|
+
// Set default mock return values
|
|
57
|
+
vi.mocked(isWebView).mockReturnValue(false);
|
|
58
|
+
vi.mocked(isIosWebview).mockReturnValue(false);
|
|
59
|
+
vi.mocked(isAndroidWebview).mockReturnValue(false);
|
|
60
|
+
vi.mocked(isFacebookWebView).mockReturnValue(false);
|
|
61
|
+
vi.mocked(isOperaMini).mockReturnValue(false);
|
|
62
|
+
vi.mocked(isFirefoxIOS).mockReturnValue(false);
|
|
63
|
+
vi.mocked(isEdgeIOS).mockReturnValue(false);
|
|
64
|
+
vi.mocked(isQQBrowser).mockReturnValue(false);
|
|
65
|
+
vi.mocked(isElectron).mockReturnValue(false);
|
|
66
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
67
|
+
vi.mocked(isTablet).mockReturnValue(false);
|
|
68
|
+
vi.mocked(isIos).mockReturnValue(false);
|
|
69
|
+
vi.mocked(isSafari).mockReturnValue(false);
|
|
70
|
+
vi.mocked(isAndroid).mockReturnValue(false);
|
|
71
|
+
vi.mocked(isChrome).mockReturnValue(false);
|
|
72
|
+
vi.mocked(isFirefox).mockReturnValue(false);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
afterEach(() => {
|
|
76
|
+
vi.resetAllMocks();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe("supportsVenmoPopups", () => {
|
|
80
|
+
describe("when in supported webview", () => {
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
vi.mocked(isWebView).mockReturnValue(true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should return true when popupBridge is available", () => {
|
|
86
|
+
window.popupBridge = {};
|
|
87
|
+
|
|
88
|
+
expect(supportsVenmoPopups({}, defaultUserAgent)).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should return false when popupBridge is not available", () => {
|
|
92
|
+
expect(supportsVenmoPopups({}, defaultUserAgent)).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe("when not in supported webview", () => {
|
|
97
|
+
it("should return true when experiment flag is enabled and user agent supports popups", () => {
|
|
98
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
99
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
100
|
+
|
|
101
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isOperaMini", () => {
|
|
105
|
+
vi.mocked(isOperaMini).mockReturnValue(true);
|
|
106
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
107
|
+
|
|
108
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isFirefoxIOS", () => {
|
|
112
|
+
vi.mocked(isFirefoxIOS).mockReturnValue(true);
|
|
113
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
114
|
+
|
|
115
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isEdgeIOS", () => {
|
|
119
|
+
vi.mocked(isEdgeIOS).mockReturnValue(true);
|
|
120
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
121
|
+
|
|
122
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isQQBrowser", () => {
|
|
126
|
+
vi.mocked(isQQBrowser).mockReturnValue(true);
|
|
127
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
128
|
+
|
|
129
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(false);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isElectron", () => {
|
|
133
|
+
vi.mocked(isElectron).mockReturnValue(true);
|
|
134
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
135
|
+
|
|
136
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("should fall back to supportsPopups when experiment flag is not enabled", () => {
|
|
140
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
141
|
+
const experiment = {};
|
|
142
|
+
|
|
143
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("should fall back to supportsPopups when experiment flag is false", () => {
|
|
147
|
+
vi.mocked(supportsPopups).mockReturnValue(false);
|
|
148
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: false };
|
|
149
|
+
|
|
150
|
+
expect(supportsVenmoPopups(experiment, defaultUserAgent)).toBe(false);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("should handle undefined experiment", () => {
|
|
154
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
155
|
+
|
|
156
|
+
expect(supportsVenmoPopups(undefined, defaultUserAgent)).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe("isSupportedNativeVenmoBrowser", () => {
|
|
162
|
+
describe("when in supported webview", () => {
|
|
163
|
+
beforeEach(() => {
|
|
164
|
+
vi.mocked(isWebView).mockReturnValue(true);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("should return true when popupBridge is available", () => {
|
|
168
|
+
window.popupBridge = {};
|
|
169
|
+
|
|
170
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("should return false when popupBridge is not available", () => {
|
|
174
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe("when not in supported webview", () => {
|
|
179
|
+
it("should return false when on tablet", () => {
|
|
180
|
+
vi.mocked(isTablet).mockReturnValue(true);
|
|
181
|
+
|
|
182
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("should return true for iOS Safari by default", () => {
|
|
186
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
187
|
+
vi.mocked(isSafari).mockReturnValue(true);
|
|
188
|
+
|
|
189
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(true);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("should return true for Android Chrome by default", () => {
|
|
193
|
+
vi.mocked(isAndroid).mockReturnValue(true);
|
|
194
|
+
vi.mocked(isChrome).mockReturnValue(true);
|
|
195
|
+
|
|
196
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("should return false for iOS Chrome without experiment flag", () => {
|
|
200
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
201
|
+
vi.mocked(isChrome).mockReturnValue(true);
|
|
202
|
+
|
|
203
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("should return true for iOS Chrome with experiment flag", () => {
|
|
207
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
208
|
+
vi.mocked(isChrome).mockReturnValue(true);
|
|
209
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
210
|
+
|
|
211
|
+
expect(
|
|
212
|
+
isSupportedNativeVenmoBrowser(experiment, defaultUserAgent)
|
|
213
|
+
).toBe(true);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should return false for Android Firefox without experiment flag", () => {
|
|
217
|
+
vi.mocked(isAndroid).mockReturnValue(true);
|
|
218
|
+
vi.mocked(isFirefox).mockReturnValue(true);
|
|
219
|
+
|
|
220
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("should return true for Android Firefox with experiment flag", () => {
|
|
224
|
+
vi.mocked(isAndroid).mockReturnValue(true);
|
|
225
|
+
vi.mocked(isFirefox).mockReturnValue(true);
|
|
226
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
227
|
+
|
|
228
|
+
expect(
|
|
229
|
+
isSupportedNativeVenmoBrowser(experiment, defaultUserAgent)
|
|
230
|
+
).toBe(true);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("should return false for unsupported browser combinations", () => {
|
|
234
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
235
|
+
vi.mocked(isFirefox).mockReturnValue(true); // iOS Firefox (not Chrome)
|
|
236
|
+
|
|
237
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("should return false for desktop browsers", () => {
|
|
241
|
+
// No mobile flags set, simulating desktop
|
|
242
|
+
|
|
243
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("should handle undefined experiment", () => {
|
|
247
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
248
|
+
vi.mocked(isSafari).mockReturnValue(true);
|
|
249
|
+
|
|
250
|
+
expect(isSupportedNativeVenmoBrowser(undefined, defaultUserAgent)).toBe(
|
|
251
|
+
true
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("should prioritize tablet check over browser checks", () => {
|
|
256
|
+
vi.mocked(isTablet).mockReturnValue(true);
|
|
257
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
258
|
+
vi.mocked(isSafari).mockReturnValue(true);
|
|
259
|
+
|
|
260
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
});
|
|
@@ -48,19 +48,18 @@ export function getVenmoConfig(): FundingSourceConfig {
|
|
|
48
48
|
return true;
|
|
49
49
|
},
|
|
50
50
|
|
|
51
|
-
requires: ({
|
|
52
|
-
const isNonNativeSupported =
|
|
53
|
-
experiment?.venmoEnableWebOnNonNativeBrowser === true ||
|
|
54
|
-
(__WEB__ && window.popupBridge);
|
|
55
|
-
|
|
51
|
+
requires: ({ platform }) => {
|
|
56
52
|
if (platform === PLATFORM.MOBILE) {
|
|
57
53
|
return {
|
|
58
|
-
native:
|
|
59
|
-
popup:
|
|
54
|
+
native: true,
|
|
55
|
+
popup: true,
|
|
60
56
|
};
|
|
61
57
|
}
|
|
62
58
|
|
|
63
|
-
return {
|
|
59
|
+
return {
|
|
60
|
+
native: false,
|
|
61
|
+
popup: false,
|
|
62
|
+
};
|
|
64
63
|
},
|
|
65
64
|
|
|
66
65
|
Logo: ({ logoColor, optional, shouldApplyRebrandedStyles }) => {
|
|
@@ -8,6 +8,9 @@ import { BUTTON_FLOW } from "../../constants";
|
|
|
8
8
|
import { getVenmoConfig } from "./config";
|
|
9
9
|
|
|
10
10
|
describe("Venmo eligibility", () => {
|
|
11
|
+
window.navigator.mockUserAgent =
|
|
12
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1";
|
|
13
|
+
|
|
11
14
|
const baseEligibilityProps = {
|
|
12
15
|
fundingSource: undefined,
|
|
13
16
|
components: ["buttons"],
|
|
@@ -102,58 +105,35 @@ describe("Venmo eligibility", () => {
|
|
|
102
105
|
});
|
|
103
106
|
|
|
104
107
|
describe("requires", () => {
|
|
105
|
-
test("should
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const isVenmoEligible = venmoConfig.requires?.({
|
|
109
|
-
experiment: {
|
|
110
|
-
venmoEnableWebOnNonNativeBrowser: true,
|
|
111
|
-
},
|
|
108
|
+
test("should require native and popup support when platform is mobile", () => {
|
|
109
|
+
const venmoRequires = venmoConfig.requires?.({
|
|
112
110
|
platform: PLATFORM.MOBILE,
|
|
113
111
|
});
|
|
114
112
|
|
|
115
|
-
expect(
|
|
116
|
-
native:
|
|
117
|
-
popup:
|
|
113
|
+
expect(venmoRequires).toEqual({
|
|
114
|
+
native: true,
|
|
115
|
+
popup: true,
|
|
118
116
|
});
|
|
119
|
-
|
|
120
|
-
window.popupBridge = undefined;
|
|
121
117
|
});
|
|
122
118
|
|
|
123
|
-
test("should not
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
venmoEnableWebOnNonNativeBrowser: true,
|
|
127
|
-
},
|
|
128
|
-
platform: PLATFORM.MOBILE,
|
|
119
|
+
test("should not require native or popup support when platform is desktop", () => {
|
|
120
|
+
const venmoRequires = venmoConfig.requires?.({
|
|
121
|
+
platform: PLATFORM.DESKTOP,
|
|
129
122
|
});
|
|
130
123
|
|
|
131
|
-
expect(
|
|
124
|
+
expect(venmoRequires).toEqual({
|
|
132
125
|
native: false,
|
|
133
126
|
popup: false,
|
|
134
127
|
});
|
|
135
128
|
});
|
|
136
129
|
|
|
137
|
-
test("should
|
|
138
|
-
const
|
|
139
|
-
experiment: {
|
|
140
|
-
venmoEnableWebOnNonNativeBrowser: false,
|
|
141
|
-
},
|
|
142
|
-
platform: PLATFORM.MOBILE,
|
|
143
|
-
});
|
|
130
|
+
test("should not require native or popup support when platform is not specified", () => {
|
|
131
|
+
const venmoRequires = venmoConfig.requires?.({});
|
|
144
132
|
|
|
145
|
-
expect(
|
|
146
|
-
native:
|
|
147
|
-
popup:
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("should not check for native and popup eligibility if platform is not mobile", () => {
|
|
152
|
-
const isVenmoEligible = venmoConfig.requires?.({
|
|
153
|
-
platform: PLATFORM.DESKTOP,
|
|
133
|
+
expect(venmoRequires).toEqual({
|
|
134
|
+
native: false,
|
|
135
|
+
popup: false,
|
|
154
136
|
});
|
|
155
|
-
|
|
156
|
-
expect(isVenmoEligible).toEqual({});
|
|
157
137
|
});
|
|
158
138
|
});
|
|
159
139
|
});
|
package/src/marks/component.jsx
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
memoize,
|
|
10
10
|
isApplePaySupported,
|
|
11
11
|
supportsPopups as userAgentSupportsPopups,
|
|
12
|
+
getUserAgent,
|
|
12
13
|
} from "@krakenjs/belter/src";
|
|
13
14
|
import {
|
|
14
15
|
PLATFORM,
|
|
@@ -32,10 +33,11 @@ import { BUTTON_LAYOUT, BUTTON_FLOW } from "../constants";
|
|
|
32
33
|
import { determineEligibleFunding, isFundingEligible } from "../funding";
|
|
33
34
|
import {
|
|
34
35
|
isSupportedNativeBrowser,
|
|
35
|
-
|
|
36
|
+
getButtonExperiments,
|
|
36
37
|
} from "../zoid/buttons/util";
|
|
37
38
|
|
|
38
39
|
import { MarksElement } from "./template";
|
|
40
|
+
import { MarksElementRebrand } from "./templateRebrand";
|
|
39
41
|
|
|
40
42
|
const DEFAULT_HEIGHT = 20;
|
|
41
43
|
|
|
@@ -50,6 +52,7 @@ type MarksProps = {|
|
|
|
50
52
|
onShippingAddressChange?: OnShippingAddressChange,
|
|
51
53
|
onShippingOptionsChange?: OnShippingOptionsChange,
|
|
52
54
|
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|
|
55
|
+
userAgent: string,
|
|
53
56
|
|};
|
|
54
57
|
|
|
55
58
|
export type MarksComponent = (MarksProps) => MarksInstance;
|
|
@@ -61,6 +64,7 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
61
64
|
onShippingAddressChange,
|
|
62
65
|
onShippingOptionsChange,
|
|
63
66
|
displayOnly,
|
|
67
|
+
userAgent = getUserAgent(),
|
|
64
68
|
}: MarksProps = {}): MarksInstance {
|
|
65
69
|
const height = DEFAULT_HEIGHT;
|
|
66
70
|
const fundingEligibility = getFundingEligibility();
|
|
@@ -75,7 +79,8 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
75
79
|
: false;
|
|
76
80
|
const supportsPopups = userAgentSupportsPopups();
|
|
77
81
|
const supportedNativeBrowser = isSupportedNativeBrowser();
|
|
78
|
-
const experiment =
|
|
82
|
+
const experiment = getButtonExperiments();
|
|
83
|
+
|
|
79
84
|
const hasShippingCallback = Boolean(
|
|
80
85
|
onShippingChange || onShippingAddressChange || onShippingOptionsChange
|
|
81
86
|
);
|
|
@@ -97,6 +102,7 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
97
102
|
supportedNativeBrowser,
|
|
98
103
|
experiment,
|
|
99
104
|
displayOnly,
|
|
105
|
+
userAgent,
|
|
100
106
|
});
|
|
101
107
|
const env = getEnv();
|
|
102
108
|
|
|
@@ -121,6 +127,7 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
121
127
|
supportedNativeBrowser,
|
|
122
128
|
experiment,
|
|
123
129
|
displayOnly,
|
|
130
|
+
userAgent,
|
|
124
131
|
});
|
|
125
132
|
};
|
|
126
133
|
|
|
@@ -130,16 +137,28 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
130
137
|
throw new Error(`${fundingSource || "marks"} not eligible`);
|
|
131
138
|
}
|
|
132
139
|
|
|
140
|
+
const isRebrandEnabled = experiment?.isPaypalRebrandEnabled;
|
|
141
|
+
|
|
133
142
|
getElement(container).appendChild(
|
|
134
143
|
(
|
|
135
144
|
<div>
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
{isRebrandEnabled ? (
|
|
146
|
+
<MarksElementRebrand
|
|
147
|
+
fundingEligibility={fundingEligibility}
|
|
148
|
+
fundingSources={fundingSources}
|
|
149
|
+
height={height}
|
|
150
|
+
experiment={experiment}
|
|
151
|
+
env={env}
|
|
152
|
+
/>
|
|
153
|
+
) : (
|
|
154
|
+
<MarksElement
|
|
155
|
+
fundingEligibility={fundingEligibility}
|
|
156
|
+
fundingSources={fundingSources}
|
|
157
|
+
height={height}
|
|
158
|
+
experiment={experiment}
|
|
159
|
+
env={env}
|
|
160
|
+
/>
|
|
161
|
+
)}
|
|
143
162
|
</div>
|
|
144
163
|
).render(dom({ doc: document }))
|
|
145
164
|
);
|
package/src/marks/template.jsx
CHANGED
|
@@ -33,19 +33,14 @@ function Mark({
|
|
|
33
33
|
throw new Error(`Can not find funding config for ${fundingSource}`);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const { Logo } = fundingConfig;
|
|
36
|
+
const { Logo, shouldUseMarkForRebrandOnly } = fundingConfig;
|
|
37
37
|
const MarkLogo = fundingConfig.Mark;
|
|
38
38
|
const marksDefined = typeof MarkLogo !== "undefined";
|
|
39
39
|
|
|
40
40
|
return (
|
|
41
41
|
<div class="paypal-mark">
|
|
42
|
-
{marksDefined && MarkLogo ? (
|
|
43
|
-
<MarkLogo
|
|
44
|
-
fundingEligibility={fundingEligibility}
|
|
45
|
-
locale={getLocale()}
|
|
46
|
-
experiment={experiment}
|
|
47
|
-
env={env}
|
|
48
|
-
/>
|
|
42
|
+
{marksDefined && MarkLogo && !shouldUseMarkForRebrandOnly ? (
|
|
43
|
+
<MarkLogo />
|
|
49
44
|
) : (
|
|
50
45
|
<Logo
|
|
51
46
|
fundingEligibility={fundingEligibility}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
/** @jsx node */
|
|
3
|
+
|
|
4
|
+
import { FUNDING, ENV } from "@paypal/sdk-constants/src";
|
|
5
|
+
import {
|
|
6
|
+
node,
|
|
7
|
+
type ChildNodeType,
|
|
8
|
+
type ElementNode,
|
|
9
|
+
} from "@krakenjs/jsx-pragmatic/src";
|
|
10
|
+
import { getLocale, type FundingEligibilityType } from "@paypal/sdk-client/src";
|
|
11
|
+
import { toPx } from "@krakenjs/belter/src";
|
|
12
|
+
|
|
13
|
+
import type { Experiment } from "../types";
|
|
14
|
+
import { getFundingConfig } from "../funding";
|
|
15
|
+
import { CLASS } from "../constants";
|
|
16
|
+
|
|
17
|
+
type MarkOptions = {|
|
|
18
|
+
fundingSource: $Values<typeof FUNDING>,
|
|
19
|
+
fundingEligibility: FundingEligibilityType,
|
|
20
|
+
experiment: Experiment,
|
|
21
|
+
env: $Values<typeof ENV>,
|
|
22
|
+
|};
|
|
23
|
+
|
|
24
|
+
function Mark({
|
|
25
|
+
fundingSource,
|
|
26
|
+
fundingEligibility,
|
|
27
|
+
experiment,
|
|
28
|
+
env,
|
|
29
|
+
}: MarkOptions): ChildNodeType {
|
|
30
|
+
const fundingConfig = getFundingConfig()[fundingSource];
|
|
31
|
+
|
|
32
|
+
if (!fundingConfig) {
|
|
33
|
+
throw new Error(`Can not find funding config for ${fundingSource}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const { Logo } = fundingConfig;
|
|
37
|
+
const MarkLogo = fundingConfig.Mark;
|
|
38
|
+
const marksDefined = typeof MarkLogo !== "undefined";
|
|
39
|
+
|
|
40
|
+
let backgroundClasses = "paypal-mark-rebrand";
|
|
41
|
+
|
|
42
|
+
const hasBlueBackground =
|
|
43
|
+
fundingSource === FUNDING.PAYPAL ||
|
|
44
|
+
fundingSource === FUNDING.PAYLATER ||
|
|
45
|
+
fundingSource === FUNDING.CREDIT;
|
|
46
|
+
|
|
47
|
+
backgroundClasses += hasBlueBackground
|
|
48
|
+
? " paypal-mark-rebrand-blue"
|
|
49
|
+
: " paypal-mark-rebrand-white";
|
|
50
|
+
|
|
51
|
+
const shouldUseOwnBorderAndPadding = fundingSource === FUNDING.APPLEPAY;
|
|
52
|
+
if (shouldUseOwnBorderAndPadding) {
|
|
53
|
+
backgroundClasses += " paypal-mark-rebrand-own-border-and-padding";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div class={backgroundClasses}>
|
|
58
|
+
{marksDefined && MarkLogo ? (
|
|
59
|
+
<MarkLogo shouldApplyRebrandedStyles={true} />
|
|
60
|
+
) : (
|
|
61
|
+
<Logo
|
|
62
|
+
fundingEligibility={fundingEligibility}
|
|
63
|
+
locale={getLocale()}
|
|
64
|
+
experiment={experiment}
|
|
65
|
+
env={env}
|
|
66
|
+
shouldApplyRebrandedStyles={true}
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
type MarksElementOptions = {|
|
|
74
|
+
fundingEligibility: FundingEligibilityType,
|
|
75
|
+
fundingSources: $ReadOnlyArray<$Values<typeof FUNDING>>,
|
|
76
|
+
height: number,
|
|
77
|
+
experiment: Experiment,
|
|
78
|
+
env: $Values<typeof ENV>,
|
|
79
|
+
|};
|
|
80
|
+
|
|
81
|
+
export function MarksElementRebrand({
|
|
82
|
+
fundingEligibility,
|
|
83
|
+
fundingSources,
|
|
84
|
+
experiment,
|
|
85
|
+
env,
|
|
86
|
+
}: MarksElementOptions): ElementNode {
|
|
87
|
+
// Rebrand dimensions: 32px height, 48px width
|
|
88
|
+
const rebrandHeight = 32;
|
|
89
|
+
const rebrandWidth = 48;
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<div>
|
|
93
|
+
<style>
|
|
94
|
+
{`
|
|
95
|
+
.${CLASS.TEXT} {
|
|
96
|
+
font-family: PayPal Pro Book, system-ui, -apple-system, Roboto, "Segoe UI", Helvetica-Neue, Helvetica, Arial, sans-serif;
|
|
97
|
+
font-size: 12px;
|
|
98
|
+
vertical-align: middle;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.paypal-marks-rebrand {
|
|
102
|
+
display: flex;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.paypal-mark-rebrand {
|
|
106
|
+
display: inline-flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
border-radius: 3px;
|
|
110
|
+
margin: ${toPx(rebrandHeight / 5)};
|
|
111
|
+
position: relative;
|
|
112
|
+
width: ${toPx(rebrandWidth)};
|
|
113
|
+
height: ${toPx(rebrandHeight)};
|
|
114
|
+
padding: 3px;
|
|
115
|
+
box-sizing: border-box;
|
|
116
|
+
overflow: hidden;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.paypal-mark-rebrand:last-child {
|
|
120
|
+
margin-right: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.paypal-mark-rebrand-white {
|
|
124
|
+
background: #fff;
|
|
125
|
+
border: 1px solid #E6E6E6;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.paypal-mark-rebrand-blue {
|
|
129
|
+
background: #60CDFF;
|
|
130
|
+
border: 1px solid #60CDFF;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.paypal-mark-rebrand-own-border-and-padding {
|
|
134
|
+
border: none;
|
|
135
|
+
padding: 0px;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.paypal-mark-rebrand img {
|
|
139
|
+
max-width: 100%;
|
|
140
|
+
max-height: 100%;
|
|
141
|
+
width: auto;
|
|
142
|
+
height: auto;
|
|
143
|
+
object-fit: contain;
|
|
144
|
+
display: block;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.paypal-button-card {
|
|
148
|
+
display: inline-block;
|
|
149
|
+
margin-right: ${toPx(rebrandHeight / 4)};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.paypal-button-card:last-child {
|
|
153
|
+
margin-right: 0px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.paypal-mark-rebrand .paypal-logo {
|
|
157
|
+
margin-right: ${toPx(rebrandHeight / 5)};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.paypal-mark-rebrand .paypal-logo:last-child {
|
|
161
|
+
margin-right: 0px;
|
|
162
|
+
}
|
|
163
|
+
`}
|
|
164
|
+
</style>
|
|
165
|
+
<div class="paypal-marks-rebrand">
|
|
166
|
+
{fundingSources.map((fundingSource) => (
|
|
167
|
+
<Mark
|
|
168
|
+
fundingEligibility={fundingEligibility}
|
|
169
|
+
fundingSource={fundingSource}
|
|
170
|
+
experiment={experiment}
|
|
171
|
+
env={env}
|
|
172
|
+
/>
|
|
173
|
+
))}
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
@@ -168,6 +168,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
168
168
|
userIDToken,
|
|
169
169
|
vault,
|
|
170
170
|
wallet,
|
|
171
|
+
userAgent,
|
|
171
172
|
} = normalizeButtonProps(props);
|
|
172
173
|
const { layout, shape, tagline } = style;
|
|
173
174
|
|
|
@@ -190,6 +191,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
190
191
|
supportedNativeBrowser,
|
|
191
192
|
experiment,
|
|
192
193
|
displayOnly,
|
|
194
|
+
userAgent,
|
|
193
195
|
});
|
|
194
196
|
const multiple = fundingSources.length > 1;
|
|
195
197
|
|