@paypal/checkout-components 5.0.189 → 5.0.190

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.
@@ -0,0 +1,35 @@
1
+ /* @flow */
2
+ /** @jsx node */
3
+
4
+ import { node, type ElementNode } from 'jsx-pragmatic/src';
5
+
6
+ import { getComponentScript } from '../script';
7
+
8
+ type ScriptProps = {|
9
+ nonce : ?string,
10
+ buttonDesignScript : string
11
+ |};
12
+
13
+ export function ButtonDesignExperimentScriptWrapper({ nonce, buttonDesignScript } : ScriptProps) : ElementNode {
14
+
15
+ const scripts = `
16
+ const scriptFns = ${ getComponentScript().toString() };
17
+ scriptFns();
18
+ function onDomLoad(){ ${ buttonDesignScript } };
19
+ document.addEventListener('DOMContentLoaded', onDomLoad);
20
+ `;
21
+ return (
22
+ <script nonce={ nonce } innerHTML={ `(function(){ ${ scripts }})()` } />
23
+ );
24
+ }
25
+
26
+ export function getDesignScript(designFn : Function, getValidDesignProps : Function, designConfig : Object) : string {
27
+ const buttonDesignScript = `
28
+ const designProps = ${ getValidDesignProps.toString() }( document, ${ JSON.stringify(designConfig) })
29
+ if (designProps) {
30
+ const applyDesign = ${ designFn.toString() }
31
+ applyDesign(designProps, ${ JSON.stringify(designConfig) })
32
+ }
33
+ `;
34
+ return buttonDesignScript;
35
+ }
@@ -0,0 +1,13 @@
1
+ /* @flow */
2
+ import { type ChildType } from 'jsx-pragmatic/src';
3
+
4
+ export type ButtonDesignOutputParams ={|
5
+ buttonDesignContainerClass : string,
6
+ buttonDesignScript : string,
7
+ buttonDesignComponent : ChildType
8
+
9
+ |};
10
+
11
+ export type ContentOptions = {|
12
+ designLabelText : string
13
+ |};
@@ -10,8 +10,8 @@ import { CLASS, BUTTON_NUMBER, BUTTON_LAYOUT, BUTTON_FLOW } from '../../constant
10
10
  import { determineEligibleFunding, isWalletFundingEligible } from '../../funding';
11
11
  import { ValidationError } from '../../lib';
12
12
 
13
- import { getButtonAnimation } from './button-animations';
14
- import { ButtonAnimationExperimentScriptWrapper } from './button-animations/script';
13
+ import { getButtonDesign } from './buttonDesigns';
14
+ import { ButtonDesignExperimentScriptWrapper } from './buttonDesigns/script';
15
15
  import { normalizeButtonProps, type ButtonPropsInputs, type OnShippingChange } from './props';
16
16
  import { Style } from './style';
17
17
  import { Button } from './button';
@@ -110,7 +110,7 @@ export function Buttons(props : ButtonsProps) : ElementNode {
110
110
  }
111
111
 
112
112
  if (fundingSources.indexOf(FUNDING.CARD) !== -1) {
113
- fundingSources = fundingSources.filter(src => src !== FUNDING.CARD).concat([ FUNDING.CARD ]);
113
+ fundingSources = [ ...fundingSources.filter(src => src !== FUNDING.CARD), FUNDING.CARD ];
114
114
  }
115
115
 
116
116
  const instruments = getWalletInstruments({ wallet, fundingSources, layout, onShippingChange });
@@ -119,8 +119,8 @@ export function Buttons(props : ButtonsProps) : ElementNode {
119
119
  flow === BUTTON_FLOW.PURCHASE &&
120
120
  ((__WEB__ && userIDToken) || Object.keys(instruments).length)
121
121
  );
122
-
123
- const { buttonAnimationScript = '' } = getButtonAnimation(personalization);
122
+
123
+ const { buttonDesignScript = '' } = getButtonDesign(personalization);
124
124
 
125
125
  return (
126
126
  <div class={ [
@@ -169,12 +169,12 @@ export function Buttons(props : ButtonsProps) : ElementNode {
169
169
  {
170
170
  (tagline && layout === BUTTON_LAYOUT.HORIZONTAL && !fundingSource)
171
171
  ? <TagLine
172
- fundingSource={ fundingSources[0] }
173
- style={ style }
174
- locale={ locale }
175
- multiple={ multiple }
176
- nonce={ nonce }
177
- personalization={ personalization }
172
+ fundingSource={ fundingSources[0] }
173
+ style={ style }
174
+ locale={ locale }
175
+ multiple={ multiple }
176
+ nonce={ nonce }
177
+ personalization={ personalization }
178
178
  /> : null
179
179
  }
180
180
 
@@ -187,19 +187,19 @@ export function Buttons(props : ButtonsProps) : ElementNode {
187
187
  {
188
188
  (layout === BUTTON_LAYOUT.VERTICAL && fundingSources.indexOf(FUNDING.CARD) !== -1)
189
189
  ? <PoweredByPayPal
190
- locale={ locale }
191
- nonce={ nonce }
190
+ locale={ locale }
191
+ nonce={ nonce }
192
192
  /> : null
193
193
  }
194
194
 
195
195
  {
196
- buttonAnimationScript
197
- ? <ButtonAnimationExperimentScriptWrapper
198
- nonce={ nonce }
199
- buttonAnimation={ buttonAnimationScript }
196
+ buttonDesignScript
197
+ ? <ButtonDesignExperimentScriptWrapper
198
+ nonce={ nonce }
199
+ buttonDesignScript={ buttonDesignScript }
200
200
  />
201
201
  : <Script
202
- nonce={ nonce }
202
+ nonce={ nonce }
203
203
  />
204
204
  }
205
205
  </div>
@@ -164,7 +164,7 @@ export type Personalization = {|
164
164
  click : string
165
165
  |}
166
166
  |},
167
- buttonAnimation? : {|
167
+ buttonDesign? : {|
168
168
  id : string,
169
169
  text : string,
170
170
  tracking : {|
@@ -189,6 +189,7 @@ export function applePaySession() : ?ApplePaySessionConfigRequest {
189
189
  listeners.paymentauthorized({ payment });
190
190
  };
191
191
 
192
+ // eslint-disable-next-line unicorn/prefer-add-event-listener
192
193
  session.oncancel = () => {
193
194
  listeners.cancel();
194
195
  };
@@ -20,7 +20,8 @@ const CARD_FIELD_TYPE = {
20
20
  SINGLE: 'single',
21
21
  NUMBER: 'number',
22
22
  CVV: 'cvv',
23
- EXPIRY: 'expiry'
23
+ EXPIRY: 'expiry',
24
+ NAME: 'name'
24
25
  };
25
26
 
26
27
  type CardFieldsProps = {|
@@ -66,7 +67,8 @@ type CardFieldsExports = {|
66
67
  type CardFieldsChildren = {|
67
68
  NumberField : CardFieldComponent,
68
69
  CVVField : CardFieldComponent,
69
- ExpiryField : CardFieldComponent
70
+ ExpiryField : CardFieldComponent,
71
+ NameField : CardFieldComponent
70
72
  |};
71
73
 
72
74
  const url = () => `${ getPayPalDomain() }${ __PAYPAL_CHECKOUT__.__URI__.__CARD_FIELD__ }`;
@@ -240,6 +242,7 @@ export const getCardFieldsComponent : () => CardFieldsComponent = memoize(() : C
240
242
  const NumberField = genericCardField(CARD_FIELD_TYPE.NUMBER);
241
243
  const CVVField = genericCardField(CARD_FIELD_TYPE.CVV);
242
244
  const ExpiryField = genericCardField(CARD_FIELD_TYPE.EXPIRY);
245
+ const NameField = genericCardField(CARD_FIELD_TYPE.NAME);
243
246
 
244
247
  const CardFields = create({
245
248
  tag: 'paypal-card-fields',
@@ -267,7 +270,8 @@ export const getCardFieldsComponent : () => CardFieldsComponent = memoize(() : C
267
270
  return {
268
271
  NumberField,
269
272
  CVVField,
270
- ExpiryField
273
+ ExpiryField,
274
+ NameField
271
275
  };
272
276
  },
273
277
 
@@ -19,36 +19,13 @@ export function PaymentFieldsPrerender({ nonce } : PrerenderedPaymentFieldsProps
19
19
  margin: 0;
20
20
  width: 100%;
21
21
  height: 100%;
22
- background: transparent;
22
+ background: rgba(240,240,240,0.5);
23
23
  }
24
24
 
25
25
  body {
26
- background: transparent;
27
26
  position: relative;
28
27
  overflow: hidden;
29
28
  }
30
-
31
- body::after {
32
- content: "";
33
- display: block;
34
- background-color: transparent;
35
- overflow: hidden;
36
- position: absolute;
37
- top: 0;
38
- bottom: 0;
39
- width: 100%;
40
- height: 100%;
41
- transform: translateX(0);
42
- }
43
-
44
- @keyframes loading-placeholder {
45
- 0% {
46
- transform: translateX(-150%);
47
- }
48
- 100% {
49
- transform: translateX(150%);
50
- }
51
- }
52
29
  ` }
53
30
  />
54
31
  </body>
@@ -1,175 +0,0 @@
1
- /* @flow */
2
- /** @jsx node */
3
- import { LOGO_CLASS } from '@paypal/sdk-logos/src';
4
- import { node, Fragment, type ChildType } from 'jsx-pragmatic/src';
5
-
6
- import { CLASS } from '../../../constants';
7
- import { BUTTON_SIZE_STYLE } from '../config';
8
-
9
- import type { ButtonAnimationOutputParams, LabelOptions, ButtonSizes, DivideLogoAnimationProps } from './types';
10
-
11
- export const ANIMATION = {
12
- LABEL_CONTAINER: ('divide-logo-animation-label-container' : 'divide-logo-animation-label-container'),
13
- CONTAINER: ('divide-logo-animation' : 'divide-logo-animation')
14
- };
15
-
16
- export function LabelForDivideLogoAnimation({ animationLabelText } : LabelOptions) : ChildType {
17
- // experimentName must match elmo experiment name
18
- const config = {
19
- labelText: animationLabelText,
20
- labelClass: ANIMATION.LABEL_CONTAINER,
21
- experimentName: 'Varied_Button_Design'
22
- };
23
-
24
- return (
25
- <Fragment>
26
- <div class={ config.labelClass } data-animation-experiment={ config.experimentName }> <span>{config.labelText}</span></div>
27
- <style innerHTML={ `
28
- .${ CLASS.DOM_READY } .${ ANIMATION.CONTAINER } img.${ LOGO_CLASS.LOGO }{
29
- position: relative;
30
- }
31
-
32
- .${ ANIMATION.CONTAINER } .${ ANIMATION.LABEL_CONTAINER } {
33
- position: absolute;
34
- opacity: 0;
35
- color: #142C8E;
36
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
37
- font-size: 14px;
38
- }
39
-
40
- .${ ANIMATION.CONTAINER } .${ ANIMATION.LABEL_CONTAINER } span {
41
- display: flex;
42
- flex-direction: column;
43
- justify-content: space-around;
44
- }
45
- ` } />;
46
- </Fragment>
47
- );
48
- }
49
-
50
- // Returns label container if the button sizes match
51
- const getAnimationProps = function(document, configuration) : DivideLogoAnimationProps | null {
52
- const { ANIMATION_CONTAINER, PAYPAL_BUTTON_LABEL, PAYPAL_LOGO } = configuration.cssClasses;
53
- const { large } = configuration;
54
-
55
- // get the animation main container to force specificity( in css ) and make sure we are running the right animation
56
- const animationContainer = (document && document.querySelector(`.${ ANIMATION_CONTAINER }`)) || null;
57
- if (!animationContainer) {
58
- return null;
59
- }
60
-
61
- // return null if animation should not be played for the button size
62
- const animationContainerWidth = animationContainer.offsetWidth;
63
- if (animationContainerWidth < large.min) {
64
- return null;
65
- }
66
-
67
- // get the label container that animation will be applied to
68
- const paypalLabelContainerElement = animationContainer.querySelector(`.${ PAYPAL_BUTTON_LABEL }`) || null;
69
- // get starting position for element so it doesn't jump when animation begins
70
- const paypalLogoElement = (paypalLabelContainerElement && paypalLabelContainerElement.querySelector(`.${ PAYPAL_LOGO }`)) || null;
71
- const paypalLogoStartingLeftPosition = paypalLogoElement
72
- ? `${ (paypalLogoElement.offsetLeft / paypalLabelContainerElement.offsetWidth) * 100 }%`
73
- : '44.5%';
74
-
75
- return {
76
- paypalLabelContainerElement,
77
- paypalLogoStartingLeftPosition
78
- };
79
- };
80
-
81
- function animationConfiguration () : ButtonSizes {
82
- return {
83
- large: { min: BUTTON_SIZE_STYLE.large.minWidth },
84
- huge: { max: BUTTON_SIZE_STYLE.huge.maxWidth },
85
- cssClasses: {
86
- DOM_READY: CLASS.DOM_READY,
87
- ANIMATION_CONTAINER: ANIMATION.CONTAINER,
88
- PAYPAL_LOGO: LOGO_CLASS.LOGO,
89
- ANIMATION_LABEL_CONTAINER: ANIMATION.LABEL_CONTAINER,
90
- PAYPAL_BUTTON_LABEL: CLASS.BUTTON_LABEL
91
- }
92
- };
93
- }
94
-
95
- export function createDivideLogoAnimation() : Function {
96
- return (animationProps, cssClasses) : void => {
97
- const { ANIMATION_LABEL_CONTAINER, ANIMATION_CONTAINER, DOM_READY, PAYPAL_LOGO } = cssClasses;
98
- const { paypalLabelContainerElement, paypalLogoStartingLeftPosition } = animationProps;
99
- const animations = `
100
- .${ DOM_READY } .${ ANIMATION_CONTAINER } img.${ PAYPAL_LOGO }{
101
- animation: 3s divide-logo-animation-left-side 2s infinite alternate;
102
- }
103
-
104
- .${ ANIMATION_CONTAINER } .${ ANIMATION_LABEL_CONTAINER } {
105
- animation: 3s divide-logo-animation-right-side 2s infinite alternate;
106
- }
107
-
108
- @keyframes divide-logo-animation-left-side {
109
- 0% {
110
- position: fixed;
111
- left: ${ paypalLogoStartingLeftPosition };
112
- }
113
- 33% {
114
- position: fixed;
115
- left: ${ paypalLogoStartingLeftPosition };
116
- }
117
- 66% {
118
- position: fixed;
119
- left: 0%;
120
- }
121
- 100% {
122
- position: fixed;
123
- left: 0%;
124
- }
125
- }
126
-
127
- @keyframes divide-logo-animation-right-side {
128
- 0%{
129
- opacity: 0;
130
- position: fixed;
131
- right: 45%;
132
- }
133
- 33%{
134
- opacity: 0;
135
- position: fixed;
136
- right: 45%;
137
- }
138
- 66% {
139
- opacity: 1;
140
- position: fixed;
141
- right: 0%;
142
- }
143
- 100% {
144
- opacity: 1;
145
- position: fixed;
146
- right: 0%;
147
- }
148
- }
149
- `;
150
-
151
- if (paypalLabelContainerElement) {
152
- const style = document.createElement('style');
153
- paypalLabelContainerElement.appendChild(style);
154
- style.appendChild(document.createTextNode(animations));
155
- }
156
- };
157
- }
158
-
159
- export function setupDivideLogoAnimation (animationLabelText : string) : ButtonAnimationOutputParams {
160
- const animationData = { animationLabelText };
161
- const animationFn = createDivideLogoAnimation();
162
- const animationConfig = animationConfiguration();
163
- const buttonAnimationScript = `
164
- const animationProps = ${ getAnimationProps.toString() }( document, ${ JSON.stringify(animationConfig) });
165
- if (animationProps && animationProps.paypalLabelContainerElement && animationProps.paypalLogoStartingLeftPosition) {
166
- const animation = ${ animationFn.toString() }
167
- animation(animationProps, ${ JSON.stringify(animationConfig.cssClasses) })
168
- }
169
- `;
170
- return {
171
- buttonAnimationContainerClass: ANIMATION.CONTAINER,
172
- buttonAnimationScript,
173
- buttonAnimationComponent: (<LabelForDivideLogoAnimation { ...animationData } />)
174
- };
175
- }
@@ -1,38 +0,0 @@
1
- /* @flow */
2
-
3
- import { type Personalization } from '../props';
4
-
5
- import { setupDivideLogoAnimation } from './divide-logo-animation';
6
- import { setupLabelTextNextToLogoAnimation } from './label-text-next-to-logo-animation';
7
- import { type ButtonAnimationOutputParams } from './types';
8
-
9
-
10
- export function getButtonAnimation(personalization : ?Personalization) : ButtonAnimationOutputParams | Object {
11
-
12
- // check valid personalization
13
- if (
14
- __WEB__
15
- || !personalization
16
- || typeof personalization !== 'object'
17
- || !personalization.buttonAnimation
18
- ) {
19
- return {};
20
- }
21
-
22
- const {
23
- buttonAnimation: {
24
- id: animationId = '',
25
- text: animationLabelText = 'Safe and easy way to pay'
26
- } = {}
27
- } = personalization;
28
-
29
- if (animationId === 'run-divide-logo-animation') {
30
- return setupDivideLogoAnimation(animationLabelText);
31
- }
32
-
33
- if (animationId === 'run-add-label-text-next-to-logo-animation') {
34
- return setupLabelTextNextToLogoAnimation(animationLabelText);
35
- }
36
-
37
- return {};
38
- }
@@ -1,106 +0,0 @@
1
- /* @flow */
2
- /** @jsx node */
3
- import { LOGO_CLASS } from '@paypal/sdk-logos/src';
4
- import { node, Fragment, type ChildType, type ElementNode } from 'jsx-pragmatic/src';
5
-
6
- import { BUTTON_SIZE_STYLE } from '../config';
7
- import { CLASS } from '../../../constants';
8
-
9
- import type { ButtonAnimationOutputParams, LabelOptions } from './types';
10
-
11
- export const ANIMATION = {
12
- ELEMENT: ('label-next-to-logo-animation-element' : 'label-next-to-logo-animation-element'),
13
- CONTAINER: ('label-next-to-logo-animation' : 'label-next-to-logo-animation')
14
- };
15
-
16
- function ComponentForAnimation({ animationLabelText } : LabelOptions) : ChildType {
17
- return (
18
- <Fragment>
19
- <span data-animation-experiment="Varied_Button_Design" class={ ANIMATION.ELEMENT }>{animationLabelText}</span>
20
- <style innerHTML={ `
21
- .${ CLASS.DOM_READY } .${ ANIMATION.CONTAINER } img.${ LOGO_CLASS.LOGO }{
22
- position: relative;
23
- }
24
-
25
- .${ ANIMATION.CONTAINER } .${ ANIMATION.ELEMENT } {
26
- position: absolute;
27
- opacity: 0;
28
- color: #142C8E;
29
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
30
- font-size: 14px;
31
- display: flex;
32
- flex-direction: column;
33
- justify-content: space-around;
34
- }
35
- ` } />;
36
- </Fragment>
37
- );
38
- }
39
-
40
- const getValidLabelContainer = function (document, configuration) : ElementNode | null {
41
- const { ANIMATION_CONTAINER, PAYPAL_LABEL_CONTAINER } = configuration.cssStyles;
42
- const { large, huge } = configuration;
43
-
44
- // get the animation main container to force specificity( in css ) and make sure we are running the right animation
45
- const animationContainer = (document && document.querySelector(`.${ ANIMATION_CONTAINER }`)) || null;
46
- // get the label container element having into account the animation container to force specificity in css
47
- const paypalLabelContainerElement = (animationContainer && animationContainer.querySelector(`.${ PAYPAL_LABEL_CONTAINER }`)) || null;
48
- if (!animationContainer) {
49
- return null;
50
- }
51
-
52
- const animationContainerWidth = animationContainer.offsetWidth;
53
- // only support large and extra large button sizes
54
- if (animationContainerWidth < large.min || animationContainerWidth > huge.max) {
55
- return null;
56
- }
57
- return paypalLabelContainerElement;
58
- };
59
-
60
- const createAnimation = function (animationContainerElement, cssClasses) : void {
61
- const { ANIMATION_CONTAINER, DOM_READY, PAYPAL_LOGO, ANIMATION_ELEMENT } = cssClasses;
62
- const animations = `
63
- .${ DOM_READY } .${ ANIMATION_CONTAINER } img.${ PAYPAL_LOGO }{
64
- position: fixed;
65
- left: 0%;
66
- }
67
-
68
- .${ ANIMATION_CONTAINER } .${ ANIMATION_ELEMENT } {
69
- position: fixed;
70
- opacity: 1;
71
- right:0%;
72
- }
73
- `;
74
-
75
- const style = document.createElement('style');
76
- animationContainerElement.appendChild(style);
77
- style.appendChild(document.createTextNode(animations));
78
- };
79
-
80
-
81
- export function setupLabelTextNextToLogoAnimation (animationLabelText : string) : ButtonAnimationOutputParams {
82
- const animationProps = { animationLabelText };
83
- const animationConfig = {
84
- cssStyles: {
85
- ANIMATION_CONTAINER: ANIMATION.CONTAINER,
86
- ANIMATION_ELEMENT: ANIMATION.ELEMENT,
87
- PAYPAL_LABEL_CONTAINER: CLASS.BUTTON_LABEL,
88
- PAYPAL_LOGO: LOGO_CLASS.LOGO,
89
- DOM_READY: CLASS.DOM_READY
90
- },
91
- large: { min: BUTTON_SIZE_STYLE.large.minWidth, max: BUTTON_SIZE_STYLE.large.maxWidth },
92
- huge: { max: BUTTON_SIZE_STYLE.huge.maxWidth }
93
- };
94
- const buttonAnimationScript = `
95
- const animationContainerElement = ${ getValidLabelContainer.toString() }( document, ${ JSON.stringify(animationConfig) })
96
- if (animationContainerElement) {
97
- const animation = ${ createAnimation.toString() }
98
- animation(animationContainerElement, ${ JSON.stringify(animationConfig.cssStyles) })
99
- }
100
- `;
101
- return {
102
- buttonAnimationContainerClass: ANIMATION.CONTAINER,
103
- buttonAnimationScript,
104
- buttonAnimationComponent: (<ComponentForAnimation { ...animationProps } />)
105
- };
106
- }
@@ -1,24 +0,0 @@
1
- /* @flow */
2
- /** @jsx node */
3
-
4
- import { node, type ElementNode } from 'jsx-pragmatic/src';
5
-
6
- import { getComponentScript } from '../script';
7
-
8
- type ScriptProps = {|
9
- nonce : ?string,
10
- buttonAnimation : string
11
- |};
12
-
13
- export function ButtonAnimationExperimentScriptWrapper({ nonce, buttonAnimation } : ScriptProps) : ElementNode {
14
-
15
- const scripts = `
16
- const scriptFns = ${ getComponentScript().toString() };
17
- scriptFns();
18
- function onDomLoad(){ ${ buttonAnimation } };
19
- document.addEventListener('DOMContentLoaded', onDomLoad);
20
- `;
21
- return (
22
- <script nonce={ nonce } innerHTML={ `(function(){ ${ scripts }})()` } />
23
- );
24
- }
@@ -1,41 +0,0 @@
1
- /* @flow */
2
- import { type ChildType, type ElementNode } from 'jsx-pragmatic/src';
3
-
4
- export type ButtonAnimationOutputParams ={|
5
- buttonAnimationContainerClass : string,
6
- buttonAnimationScript : string,
7
- buttonAnimationComponent : ChildType | null
8
- |};
9
-
10
- export type ButtonSizeProperties = {|
11
- min? : number,
12
- max? : number
13
- |};
14
-
15
- type ButtonAnimationCss = {|
16
- DOM_READY : string,
17
- ANIMATION_CONTAINER : string,
18
- PAYPAL_LOGO : string,
19
- ANIMATION_LABEL_CONTAINER : string,
20
- PAYPAL_BUTTON_LABEL : string
21
- |};
22
-
23
- export type ButtonSizes = {|
24
- large : ButtonSizeProperties,
25
- huge : ButtonSizeProperties,
26
- cssClasses : ButtonAnimationCss
27
- |};
28
-
29
- export type ButtonAnimation = {|
30
- params : ButtonSizes,
31
- fn : Function
32
- |};
33
-
34
- export type LabelOptions = {|
35
- animationLabelText : string
36
- |};
37
-
38
- export type DivideLogoAnimationProps = {|
39
- paypalLabelContainerElement : ElementNode,
40
- paypalLogoStartingLeftPosition : string
41
- |};