@paypal/checkout-components 5.0.203 → 5.0.206

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paypal/checkout-components",
3
- "version": "5.0.203",
3
+ "version": "5.0.206",
4
4
  "description": "PayPal Checkout components, for integrating checkout products.",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -61,3 +61,7 @@ export const MENU_PLACEMENT = {
61
61
  ABOVE: ('above' : 'above'),
62
62
  BELOW: ('below' : 'below')
63
63
  };
64
+
65
+ export const EXPERIENCE = {
66
+ INLINE: ('inline' : 'inline')
67
+ };
@@ -38,5 +38,7 @@ export const CLASS = {
38
38
 
39
39
  HIDDEN: ('hidden' : 'hidden'),
40
40
 
41
- IMMEDIATE: ('immediate' : 'immediate')
41
+ IMMEDIATE: ('immediate' : 'immediate'),
42
+
43
+ CUSTOM: ('custom' : 'custom')
42
44
  };
@@ -121,7 +121,15 @@ export function getCardConfig() : FundingSourceConfig {
121
121
  );
122
122
  },
123
123
 
124
- Label: ({ logo, locale, content }) => {
124
+ Label: ({ logo, locale, content, custom }) => {
125
+ if (custom && custom.label) {
126
+ return (
127
+ <Fragment>
128
+ <Text>{ custom.label }</Text>
129
+ <Space />
130
+ </Fragment>
131
+ );
132
+ }
125
133
  const { lang } = locale;
126
134
  const isRTL = isRTLLanguage(lang);
127
135
  return (
@@ -7,7 +7,7 @@ import type { FundingEligibilityType } from '@paypal/sdk-client/src';
7
7
  import { PLATFORM, type LocaleType, COUNTRY, CARD, COMPONENTS, FUNDING, ENV } from '@paypal/sdk-constants/src';
8
8
  import { LOGO_COLOR } from '@paypal/sdk-logos/src';
9
9
 
10
- import type { ContentType, WalletInstrument, Experiment, Requires, Wallet } from '../types';
10
+ import type { ContentType, CustomStyle, WalletInstrument, Experiment, Requires, Wallet } from '../types';
11
11
  import { BUTTON_COLOR, BUTTON_SHAPE, BUTTON_LAYOUT, DEFAULT, BUTTON_LABEL, BUTTON_FLOW, TEXT_COLOR } from '../constants';
12
12
  import type { Personalization } from '../ui/buttons/props';
13
13
 
@@ -47,7 +47,8 @@ export type LabelOptions = {|
47
47
  nonce : ?string,
48
48
  tagline : ?boolean,
49
49
  content : ?ContentType,
50
- experiment? : Experiment
50
+ experiment? : Experiment,
51
+ custom? : ?CustomStyle
51
52
  |};
52
53
 
53
54
  export type DesignExperimentLabelOptions = {|
package/src/types.js CHANGED
@@ -53,6 +53,13 @@ export type Requires = {|
53
53
  native? : boolean
54
54
  |};
55
55
 
56
+ export type CustomStyle = {|
57
+ css : {|
58
+ [string] : string
59
+ |},
60
+ label : string
61
+ |};
62
+
56
63
  export type LazyExport<T> = {|
57
64
  __get__ : () => T
58
65
  |};
@@ -8,7 +8,7 @@ import { LOGO_COLOR, LOGO_CLASS } from '@paypal/sdk-logos/src';
8
8
  import { noop, preventClickFocus, isBrowser, isElement } from 'belter/src';
9
9
 
10
10
  import type { ContentType, Wallet, Experiment, WalletInstrument } from '../../types';
11
- import { ATTRIBUTE, CLASS, BUTTON_COLOR, BUTTON_NUMBER, TEXT_COLOR, BUTTON_FLOW } from '../../constants';
11
+ import { ATTRIBUTE, CLASS, BUTTON_COLOR, BUTTON_NUMBER, EXPERIENCE, TEXT_COLOR, BUTTON_FLOW } from '../../constants';
12
12
  import { getFundingConfig } from '../../funding';
13
13
  import { DesignExperimentLabel } from '../../funding/paypal/template';
14
14
 
@@ -38,12 +38,14 @@ type IndividualButtonProps = {|
38
38
  flow : $Values<typeof BUTTON_FLOW>,
39
39
  vault : boolean,
40
40
  merchantFundingSource : ?$Values<typeof FUNDING>,
41
- instrument : ?WalletInstrument
41
+ instrument : ?WalletInstrument,
42
+ experience? : string
42
43
  |};
43
44
 
44
45
  export function Button({ fundingSource, style, multiple, locale, env, fundingEligibility, i, nonce, flow, vault,
45
- userIDToken, personalization, onClick = noop, content, tagline, commit, experiment, instrument } : IndividualButtonProps) : ElementNode {
46
+ userIDToken, personalization, onClick = noop, content, tagline, commit, experiment, instrument, experience } : IndividualButtonProps) : ElementNode {
46
47
 
48
+ const inlineExperience = experience === EXPERIENCE.INLINE;
47
49
  const fundingConfig = getFundingConfig()[fundingSource];
48
50
 
49
51
  if (!fundingConfig) {
@@ -94,9 +96,9 @@ export function Button({ fundingSource, style, multiple, locale, env, fundingEli
94
96
  }
95
97
  };
96
98
 
97
- const { layout, shape } = style;
99
+ const { custom, layout, shape } = style;
98
100
 
99
- const labelText = typeof fundingConfig.labelText === 'function' ? fundingConfig.labelText({ content, fundingEligibility }) : (fundingConfig.labelText || fundingSource);
101
+ const labelText = typeof fundingConfig.labelText === 'function' ? fundingConfig.labelText({ content, fundingEligibility }) : (fundingConfig.labelText || fundingSource);
100
102
 
101
103
  const logoNode = (
102
104
  <Logo
@@ -129,6 +131,7 @@ export function Button({ fundingSource, style, multiple, locale, env, fundingEli
129
131
  personalization={ personalization }
130
132
  tagline={ tagline }
131
133
  content={ content }
134
+ custom={ inlineExperience ? custom : null }
132
135
  experiment={ experiment }
133
136
  />
134
137
  );
@@ -197,6 +200,7 @@ export function Button({ fundingSource, style, multiple, locale, env, fundingEli
197
200
  <div
198
201
  class={ [
199
202
  CLASS.BUTTON_ROW,
203
+ inlineExperience && fundingSource === FUNDING.CARD ? CLASS.CUSTOM : '',
200
204
  `${ CLASS.NUMBER }-${ i }`,
201
205
  `${ CLASS.LAYOUT }-${ layout }`,
202
206
  `${ CLASS.SHAPE }-${ shape }`,
@@ -221,6 +225,7 @@ export function Button({ fundingSource, style, multiple, locale, env, fundingEli
221
225
  } }
222
226
  class={ [
223
227
  CLASS.BUTTON,
228
+ inlineExperience && fundingSource === FUNDING.CARD ? CLASS.CUSTOM : '',
224
229
  `${ CLASS.NUMBER }-${ i }`,
225
230
  `${ CLASS.LAYOUT }-${ layout }`,
226
231
  `${ CLASS.SHAPE }-${ shape }`,
@@ -6,7 +6,7 @@ import { FUNDING, WALLET_INSTRUMENT } from '@paypal/sdk-constants/src';
6
6
  import { noop } from 'belter/src';
7
7
 
8
8
  import type { Wallet, WalletInstrument } from '../../types';
9
- import { CLASS, BUTTON_NUMBER, BUTTON_LAYOUT, BUTTON_FLOW } from '../../constants';
9
+ import { CLASS, BUTTON_NUMBER, BUTTON_LAYOUT, BUTTON_FLOW, EXPERIENCE } from '../../constants';
10
10
  import { determineEligibleFunding, isWalletFundingEligible } from '../../funding';
11
11
  import { ValidationError } from '../../lib';
12
12
 
@@ -99,8 +99,10 @@ export function validateButtonProps(props : ButtonPropsInputs) {
99
99
  export function Buttons(props : ButtonsProps) : ElementNode {
100
100
  const { onClick = noop } = props;
101
101
  const { wallet, fundingSource, style, locale, remembered, env, fundingEligibility, platform, commit, vault,
102
- nonce, components, onShippingChange, personalization, userIDToken, content, flow, experiment, applePaySupport, supportsPopups, supportedNativeBrowser } = normalizeButtonProps(props);
102
+ nonce, components, onShippingChange, personalization, userIDToken, content, flow, experiment, applePaySupport,
103
+ supportsPopups, supportedNativeBrowser, experience } = normalizeButtonProps(props);
103
104
  const { layout, shape, tagline } = style;
105
+ const inlineExperience = experience === EXPERIENCE.INLINE;
104
106
 
105
107
  let fundingSources = determineEligibleFunding({ fundingSource, layout, remembered, platform, fundingEligibility, components, onShippingChange, flow, wallet, applePaySupport, supportsPopups, supportedNativeBrowser, experiment });
106
108
  const multiple = fundingSources.length > 1;
@@ -110,7 +112,11 @@ export function Buttons(props : ButtonsProps) : ElementNode {
110
112
  }
111
113
 
112
114
  if (fundingSources.indexOf(FUNDING.CARD) !== -1) {
113
- fundingSources = [ ...fundingSources.filter(src => src !== FUNDING.CARD), FUNDING.CARD ];
115
+ if (inlineExperience) {
116
+ fundingSources = [ FUNDING.CARD, ...fundingSources.filter(src => src !== FUNDING.CARD) ];
117
+ } else {
118
+ fundingSources = [ ...fundingSources.filter(src => src !== FUNDING.CARD), FUNDING.CARD ];
119
+ }
114
120
  }
115
121
 
116
122
  const instruments = getWalletInstruments({ wallet, fundingSources, layout, onShippingChange });
@@ -121,6 +127,18 @@ export function Buttons(props : ButtonsProps) : ElementNode {
121
127
  );
122
128
 
123
129
  const { buttonDesignScript = '' } = getButtonDesign(personalization);
130
+ const index = (i) => {
131
+ if (!inlineExperience) {
132
+ return i;
133
+ }
134
+
135
+ // InlineXO: Need to change color indexing because we bring Cards to the top
136
+ if (i === 0) {
137
+ return fundingSources.length - 1;
138
+ } else {
139
+ return i - 1;
140
+ }
141
+ };
124
142
 
125
143
  return (
126
144
  <div class={ [
@@ -142,7 +160,7 @@ export function Buttons(props : ButtonsProps) : ElementNode {
142
160
  fundingSources.map((source, i) => (
143
161
  <Button
144
162
  content={ content }
145
- i={ i }
163
+ i={ index(i) }
146
164
  style={ style }
147
165
  merchantFundingSource={ fundingSource }
148
166
  fundingSource={ source }
@@ -162,6 +180,7 @@ export function Buttons(props : ButtonsProps) : ElementNode {
162
180
  flow={ flow }
163
181
  vault={ vault }
164
182
  instrument={ instruments[source] }
183
+ experience={ experience }
165
184
  />
166
185
  ))
167
186
  }
@@ -12,7 +12,7 @@ import { LOGO_COLOR } from '@paypal/sdk-logos/src';
12
12
  import { SUPPORTED_FUNDING_SOURCES } from '@paypal/funding-components/src';
13
13
  import type { ComponentFunctionType } from 'jsx-pragmatic/src';
14
14
 
15
- import type { ContentType, Wallet, Experiment } from '../../types';
15
+ import type { ContentType, CustomStyle, Wallet, Experiment } from '../../types';
16
16
  import { BUTTON_LABEL, BUTTON_COLOR, BUTTON_LAYOUT, BUTTON_SHAPE, BUTTON_SIZE, BUTTON_FLOW, MENU_PLACEMENT } from '../../constants';
17
17
  import { getFundingConfig, isFundingEligible } from '../../funding';
18
18
 
@@ -130,7 +130,8 @@ export type ButtonStyle = {|
130
130
  layout : $Values<typeof BUTTON_LAYOUT>,
131
131
  menuPlacement : $Values<typeof MENU_PLACEMENT>,
132
132
  period? : number,
133
- height? : number
133
+ height? : number,
134
+ custom? : CustomStyle
134
135
  |};
135
136
 
136
137
  export type ButtonStyleInputs = {|
@@ -140,7 +141,8 @@ export type ButtonStyleInputs = {|
140
141
  tagline? : boolean | void,
141
142
  layout? : $Values<typeof BUTTON_LAYOUT> | void,
142
143
  period? : number | void,
143
- height? : number | void
144
+ height? : number | void,
145
+ custom? : CustomStyle
144
146
  |};
145
147
 
146
148
  type PersonalizationComponentProps = {|
@@ -262,7 +264,7 @@ export type RenderButtonProps = {|
262
264
  applePaySupport : boolean,
263
265
  supportsPopups : boolean,
264
266
  supportedNativeBrowser : boolean,
265
- inline : boolean | void
267
+ experience : string
266
268
  |};
267
269
 
268
270
  export type PrerenderDetails = {|
@@ -311,7 +313,7 @@ export type ButtonProps = {|
311
313
  applePay : ApplePaySessionConfigRequest,
312
314
  meta : {||},
313
315
  renderedButtons : $ReadOnlyArray<$Values<typeof FUNDING>>,
314
- inline : boolean | void
316
+ experience : string
315
317
  |};
316
318
 
317
319
  // eslint-disable-next-line flowtype/require-exact-type
@@ -349,7 +351,7 @@ export type ButtonPropsInputs = {
349
351
  applePaySupport : boolean,
350
352
  supportsPopups : boolean,
351
353
  supportedNativeBrowser : boolean,
352
- inline : boolean | void
354
+ experience : string
353
355
  };
354
356
 
355
357
  export const DEFAULT_STYLE = {
@@ -397,7 +399,8 @@ export function normalizeButtonStyle(props : ?ButtonPropsInputs, style : ButtonS
397
399
  tagline = (layout === BUTTON_LAYOUT.HORIZONTAL && !fundingSource),
398
400
  height,
399
401
  period,
400
- menuPlacement = MENU_PLACEMENT.BELOW
402
+ menuPlacement = MENU_PLACEMENT.BELOW,
403
+ custom
401
404
  } = style;
402
405
 
403
406
  // $FlowFixMe
@@ -443,7 +446,7 @@ export function normalizeButtonStyle(props : ?ButtonPropsInputs, style : ButtonS
443
446
  }
444
447
  }
445
448
 
446
- return { label, layout, color, shape, tagline, height, period, menuPlacement };
449
+ return { custom, label, layout, color, shape, tagline, height, period, menuPlacement };
447
450
  }
448
451
 
449
452
  const COUNTRIES = values(COUNTRY);
@@ -494,7 +497,7 @@ export function normalizeButtonProps(props : ?ButtonPropsInputs) : RenderButtonP
494
497
  applePaySupport = false,
495
498
  supportsPopups = false,
496
499
  supportedNativeBrowser = false,
497
- inline = false
500
+ experience = ''
498
501
  } = props;
499
502
 
500
503
  const { country, lang } = locale;
@@ -537,5 +540,5 @@ export function normalizeButtonProps(props : ?ButtonPropsInputs) : RenderButtonP
537
540
 
538
541
  return { clientID, fundingSource, style, locale, remembered, env, fundingEligibility, platform, clientAccessToken,
539
542
  buttonSessionID, commit, sessionID, nonce, components, onShippingChange, personalization, content, wallet, flow,
540
- experiment, vault, userIDToken, applePay, applePaySupport, supportsPopups, supportedNativeBrowser, inline };
543
+ experiment, vault, userIDToken, applePay, applePaySupport, supportsPopups, supportedNativeBrowser, experience };
541
544
  }
@@ -15,8 +15,8 @@ type StyleProps = {|
15
15
 
16
16
  export function Style({ style, nonce, fundingEligibility } : StyleProps) : ElementNode {
17
17
 
18
- const { height } = style;
19
- const css = componentStyle({ height, fundingEligibility });
18
+ const { custom, height } = style;
19
+ const css = componentStyle({ custom, height, fundingEligibility });
20
20
 
21
21
  return (
22
22
  <style nonce={ nonce } innerHTML={ css } />
@@ -2,18 +2,22 @@
2
2
 
3
3
  import { type FundingEligibilityType } from '@paypal/sdk-constants/src';
4
4
 
5
+ import type { CustomStyle } from '../../../types';
6
+
5
7
  import { pageStyle } from './page';
6
8
  import { buttonStyle } from './button';
7
9
  import { labelStyle } from './labels';
8
10
  import { buttonResponsiveStyle } from './responsive';
9
11
  import { buttonColorStyle } from './color';
12
+ import { customStyle } from './custom';
10
13
 
11
- export function componentStyle({ height, fundingEligibility } : {| height? : ?number, fundingEligibility : FundingEligibilityType |}) : string {
14
+ export function componentStyle({ custom, height, fundingEligibility } : {| custom? : CustomStyle, height? : ?number, fundingEligibility : FundingEligibilityType |}) : string {
12
15
  return `
13
16
  ${ pageStyle }
14
17
  ${ buttonStyle }
15
18
  ${ buttonColorStyle }
16
19
  ${ labelStyle }
17
20
  ${ buttonResponsiveStyle({ height, fundingEligibility }) }
21
+ ${ customStyle({ custom }) }
18
22
  `;
19
23
  }
@@ -1,9 +1,9 @@
1
1
  /* @flow */
2
2
 
3
- import { ENV, FUNDING } from '@paypal/sdk-constants/src';
3
+ import { ENV } from '@paypal/sdk-constants/src';
4
4
  import { LOGO_CLASS } from '@paypal/sdk-logos/src';
5
5
 
6
- import { CLASS, ATTRIBUTE } from '../../../constants';
6
+ import { CLASS } from '../../../constants';
7
7
 
8
8
  const MIN_VAULT_BUTTON_WIDTH = 250;
9
9
 
@@ -126,11 +126,6 @@ export const buttonStyle = `
126
126
  margin-top: 10px;
127
127
  }
128
128
 
129
- .${ CLASS.BUTTON }[${ ATTRIBUTE.FUNDING_SOURCE }=${ FUNDING.VENMO }] .${ CLASS.BUTTON_LABEL } .${ CLASS.TEXT } {
130
- font-size: 18px;
131
- font-weight: 500;
132
- }
133
-
134
129
  @media only screen and (max-width: ${ MIN_VAULT_BUTTON_WIDTH }px) {
135
130
  .menu-button {
136
131
  display: none;
@@ -0,0 +1,31 @@
1
+ /* @flow */
2
+
3
+ import type { CustomStyle } from '../../../types';
4
+ import { CLASS } from '../../../constants';
5
+
6
+ export const customStyle = ({ custom } : {| custom? : CustomStyle |}) : string => {
7
+ if (!custom) {
8
+ return '';
9
+ }
10
+
11
+ const { css } = custom || {};
12
+
13
+ let heightStyle = '';
14
+ let marginStyle = '';
15
+ let style = Object.keys(css).reduce((acc, key) => {
16
+ if (key === 'height') {
17
+ heightStyle = `
18
+ height: ${ css[key] };
19
+ max-height: ${ css[key] };
20
+ `;
21
+ } else if (key.indexOf('margin') !== -1) {
22
+ marginStyle = `${ key }: ${ css[key] };`;
23
+ }
24
+
25
+ acc += `${ key }: ${ css[key] };`;
26
+ return acc;
27
+ }, '');
28
+ style = `.${ CLASS.BUTTON }.${ CLASS.CUSTOM } { ${ style } } .${ CLASS.BUTTON_ROW }.${ CLASS.CUSTOM } { ${ heightStyle + marginStyle }}`;
29
+
30
+ return style;
31
+ };
@@ -16,6 +16,7 @@ import { node, dom } from 'jsx-pragmatic/src';
16
16
  import { getSessionID, storageState, sessionState } from '../../lib';
17
17
  import { normalizeButtonStyle, type ButtonProps } from '../../ui/buttons/props';
18
18
  import { isFundingEligible } from '../../funding';
19
+ import { EXPERIENCE } from '../../constants';
19
20
 
20
21
  import { containerTemplate } from './container';
21
22
  import { PrerenderedButtons } from './prerender';
@@ -597,10 +598,16 @@ export const getButtonsComponent : () => ButtonsComponent = memoize(() => {
597
598
  value: applePaySession
598
599
  },
599
600
 
600
- inline: {
601
+ experience: {
601
602
  queryParam: true,
602
603
  required: false,
603
- type: 'boolean'
604
+ type: 'string',
605
+ value: ({ props }) => {
606
+ const { style: { custom }, fundingEligibility } = props;
607
+ const isInlineXO = (custom && (custom.label || custom.css)) && fundingEligibility[FUNDING.CARD]?.eligible;
608
+
609
+ return isInlineXO ? EXPERIENCE.INLINE : '';
610
+ }
604
611
  },
605
612
 
606
613
  // allowBillingPayments prop is used by Honey Extension to render the one-click button
@@ -50,7 +50,7 @@ export function getCheckoutComponent() : CheckoutComponent {
50
50
  },
51
51
 
52
52
  containerTemplate: ({ context, close, focus, doc, event, frame, prerenderFrame, props }) => {
53
- const { nonce, locale: { lang }, inline } = props;
53
+ const { nonce, locale: { lang }, inlinexo } = props;
54
54
  const content = containerContent[lang];
55
55
  return (
56
56
  <Overlay
@@ -62,7 +62,7 @@ export function getCheckoutComponent() : CheckoutComponent {
62
62
  prerenderFrame={ prerenderFrame }
63
63
  content={ content }
64
64
  nonce={ nonce }
65
- fullScreen={ inline === true }
65
+ fullScreen={ inlinexo === true }
66
66
  />
67
67
  ).render(dom({ doc }));
68
68
  },
@@ -232,7 +232,7 @@ export function getCheckoutComponent() : CheckoutComponent {
232
232
  default: () => (window.__test__ || { action: 'checkout' })
233
233
  },
234
234
 
235
- inline: {
235
+ inlinexo: {
236
236
  type: 'boolean',
237
237
  required: false,
238
238
  queryParam: true,
@@ -39,5 +39,5 @@ export type CheckoutPropsType = {|
39
39
  csp : {|
40
40
  nonce : string
41
41
  |},
42
- inline : boolean
42
+ inlinexo : boolean
43
43
  |};