mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Merge trunk
This commit is contained in:
commit
bef1c92f3f
165 changed files with 3796 additions and 3028 deletions
|
@ -1,53 +1,33 @@
|
|||
import { Icon } from '@wordpress/components';
|
||||
import { chevronDown, chevronUp } from '@wordpress/icons';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { useAccordionState } from '../../hooks/useAccordionState';
|
||||
|
||||
// Provide defaults for all layout components so the generic version just works.
|
||||
const DefaultHeader = ( { children, className = '' } ) => (
|
||||
<div className={ `ppcp-r-accordion__header ${ className }`.trim() }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
const DefaultTitleWrapper = ( { children } ) => (
|
||||
<div className="ppcp-r-accordion__title-wrapper">{ children }</div>
|
||||
);
|
||||
const DefaultTitle = ( { children } ) => (
|
||||
<span className="ppcp-r-accordion__title">{ children }</span>
|
||||
);
|
||||
const DefaultAction = ( { children } ) => (
|
||||
<span className="ppcp-r-accordion__action">{ children }</span>
|
||||
);
|
||||
const DefaultDescription = ( { children } ) => (
|
||||
<div className="ppcp-r-accordion__description">{ children }</div>
|
||||
);
|
||||
|
||||
const AccordionContent = ( { isOpen, children } ) => {
|
||||
if ( ! isOpen || ! children ) {
|
||||
return null;
|
||||
}
|
||||
return <div className="ppcp-r-accordion__content">{ children }</div>;
|
||||
};
|
||||
import {
|
||||
Content,
|
||||
Description,
|
||||
Header,
|
||||
Title,
|
||||
Action,
|
||||
TitleWrapper,
|
||||
} from './Elements';
|
||||
|
||||
const Accordion = ( {
|
||||
title,
|
||||
id = '',
|
||||
noCaps = false,
|
||||
initiallyOpen = null,
|
||||
description = '',
|
||||
children = null,
|
||||
className = '',
|
||||
|
||||
// Layout components can be overridden by the caller
|
||||
Header = DefaultHeader,
|
||||
TitleWrapper = DefaultTitleWrapper,
|
||||
Title = DefaultTitle,
|
||||
Action = DefaultAction,
|
||||
Description = DefaultDescription,
|
||||
} ) => {
|
||||
const { isOpen, toggleOpen } = useAccordionState( { id, initiallyOpen } );
|
||||
const wrapperClasses = classNames( 'ppcp-r-accordion', className, {
|
||||
'ppcp--is-open': isOpen,
|
||||
} );
|
||||
const contentClass = classNames( 'ppcp--accordion-content', {
|
||||
'ppcp--is-open': isOpen,
|
||||
} );
|
||||
|
||||
const icon = isOpen ? chevronUp : chevronDown;
|
||||
|
||||
|
@ -55,22 +35,22 @@ const Accordion = ( {
|
|||
<div className={ wrapperClasses } { ...( id && { id } ) }>
|
||||
<button
|
||||
type="button"
|
||||
className="ppcp-r-accordion__toggler"
|
||||
className="ppcp--toggler"
|
||||
onClick={ toggleOpen }
|
||||
>
|
||||
<Header>
|
||||
<TitleWrapper>
|
||||
<Title>{ title }</Title>
|
||||
<Title noCaps={ noCaps }>{ title }</Title>
|
||||
<Action>
|
||||
<Icon icon={ icon } />
|
||||
</Action>
|
||||
</TitleWrapper>
|
||||
{ description && (
|
||||
<Description>{ description }</Description>
|
||||
) }
|
||||
<Description>{ description }</Description>
|
||||
</Header>
|
||||
</button>
|
||||
<AccordionContent isOpen={ isOpen }>{ children }</AccordionContent>
|
||||
<div className={ contentClass }>
|
||||
<Content asCard={ false }>{ children }</Content>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { CommonHooks } from '../../data';
|
||||
|
||||
const ConnectionInfo = () => {
|
||||
const { merchant } = CommonHooks.useMerchantInfo();
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-connection-status__data">
|
||||
<StatusRow
|
||||
label={ __( 'Merchant ID', 'woocommerce-paypal-payments' ) }
|
||||
value={ merchant.id }
|
||||
/>
|
||||
<StatusRow
|
||||
label={ __( 'Email address', 'woocommerce-paypal-payments' ) }
|
||||
value={ merchant.email }
|
||||
/>
|
||||
<StatusRow
|
||||
label={ __( 'Client ID', 'woocommerce-paypal-payments' ) }
|
||||
value={ merchant.clientId }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default ConnectionInfo;
|
||||
|
||||
const StatusRow = ( { label, value } ) => (
|
||||
<div className="ppcp-r-connection-status__status-row">
|
||||
<span className="ppcp-r-connection-status__status-label">
|
||||
{ label }
|
||||
</span>
|
||||
<span className="ppcp-r-connection-status__status-value">
|
||||
{ value }
|
||||
</span>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,18 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
|
||||
import { Action } from '../Elements';
|
||||
|
||||
const ControlButton = ( {
|
||||
type = 'secondary',
|
||||
isBusy,
|
||||
onClick,
|
||||
buttonLabel,
|
||||
} ) => (
|
||||
<Action>
|
||||
<Button isBusy={ isBusy } variant={ type } onClick={ onClick }>
|
||||
{ buttonLabel }
|
||||
</Button>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlButton;
|
|
@ -0,0 +1,14 @@
|
|||
import { Action } from '../Elements';
|
||||
import { RadioGroup } from '../Fields';
|
||||
|
||||
const ControlRadioGroup = ( { options, value, onChange } ) => (
|
||||
<Action>
|
||||
<RadioGroup
|
||||
options={ options }
|
||||
selected={ value }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlRadioGroup;
|
|
@ -0,0 +1,22 @@
|
|||
import { Select } from '../Fields';
|
||||
import { Action } from '../Elements';
|
||||
|
||||
const ControlSelect = ( {
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
placeholder,
|
||||
isMulti = false,
|
||||
} ) => (
|
||||
<Action>
|
||||
<Select
|
||||
isMulti={ isMulti }
|
||||
options={ options }
|
||||
value={ value }
|
||||
placeholder={ placeholder }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlSelect;
|
|
@ -0,0 +1,9 @@
|
|||
import { Action } from '../Elements';
|
||||
|
||||
const ControlStaticValue = ( { value } ) => (
|
||||
<Action>
|
||||
<div className="ppcp--static-value">{ value }</div>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlStaticValue;
|
|
@ -0,0 +1,22 @@
|
|||
import { TextControl } from '@wordpress/components';
|
||||
|
||||
import { Action, Description } from '../Elements';
|
||||
|
||||
const ControlTextInput = ( {
|
||||
value,
|
||||
description,
|
||||
onChange,
|
||||
placeholder = '',
|
||||
} ) => (
|
||||
<Action>
|
||||
<TextControl
|
||||
className="ppcp-r-vertical-text-control"
|
||||
placeholder={ placeholder }
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
<Description>{ description }</Description>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlTextInput;
|
|
@ -0,0 +1,19 @@
|
|||
import { ToggleControl } from '@wordpress/components';
|
||||
import { Action, Description } from '../Elements';
|
||||
|
||||
const ControlToggleButton = ( { label, description, value, onChange } ) => (
|
||||
<Action>
|
||||
<ToggleControl
|
||||
className="ppcp--control-toggle"
|
||||
__nextHasNoMarginBottom={ true }
|
||||
checked={ value }
|
||||
onChange={ onChange }
|
||||
label={ label }
|
||||
help={
|
||||
description ? <Description>{ description }</Description> : null
|
||||
}
|
||||
/>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlToggleButton;
|
|
@ -0,0 +1,6 @@
|
|||
export { default as ControlStaticValue } from './ControlStaticValue';
|
||||
export { default as ControlTextInput } from './ControlTextInput';
|
||||
export { default as ControlToggleButton } from './ControlToggleButton';
|
||||
export { default as ControlButton } from './ControlButton';
|
||||
export { default as ControlRadioGroup } from './ControlRadioGroup';
|
||||
export { default as ControlSelect } from './ControlSelect';
|
|
@ -0,0 +1,5 @@
|
|||
const Action = ( { children } ) => (
|
||||
<div className="ppcp--action">{ children }</div>
|
||||
);
|
||||
|
||||
export default Action;
|
|
@ -0,0 +1,15 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Content = ( { children, asCard = true, className = '', id = '' } ) => {
|
||||
const elementClasses = classNames( 'ppcp--content', className, {
|
||||
'ppcp--is-card': asCard,
|
||||
} );
|
||||
|
||||
return (
|
||||
<div id={ id } className={ elementClasses }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Content;
|
|
@ -0,0 +1,5 @@
|
|||
const ContentWrapper = ( { children } ) => (
|
||||
<div className="ppcp-r-settings-card__content-wrapper">{ children }</div>
|
||||
);
|
||||
|
||||
export default ContentWrapper;
|
|
@ -0,0 +1,23 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Description = ( { children, className = '' } ) => {
|
||||
// Don't output anything if description is empty.
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames( 'ppcp--description', className );
|
||||
|
||||
if ( 'string' !== typeof children ) {
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className={ elementClasses }
|
||||
dangerouslySetInnerHTML={ { __html: children } }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Description;
|
|
@ -0,0 +1,13 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Header = ( { children, className = '' } ) => {
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames( 'ppcp--header', className );
|
||||
|
||||
return <div className={ elementClasses }>{ children }</div>;
|
||||
};
|
||||
|
||||
export default Header;
|
|
@ -0,0 +1,16 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Title = ( { children, noCaps = false, big = false, className = '' } ) => {
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames( 'ppcp--title', className, {
|
||||
'ppcp--no-caps': noCaps,
|
||||
'ppcp--big': big,
|
||||
} );
|
||||
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
};
|
||||
|
||||
export default Title;
|
|
@ -0,0 +1,9 @@
|
|||
const TitleExtra = ( { children } ) => {
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <span className="ppcp--title-extra">{ children }</span>;
|
||||
};
|
||||
|
||||
export default TitleExtra;
|
|
@ -0,0 +1,5 @@
|
|||
const TitleWrapper = ( { children } ) => (
|
||||
<span className="ppcp--title-wrapper">{ children }</span>
|
||||
);
|
||||
|
||||
export default TitleWrapper;
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Static elements used to build UI layouts.
|
||||
*/
|
||||
|
||||
export { default as Action } from './Action';
|
||||
export { default as Content } from './Content';
|
||||
export { default as ContentWrapper } from './ContentWrapper';
|
||||
export { default as Description } from './Description';
|
||||
export { default as Header } from './Header';
|
||||
export { default as Title } from './Title';
|
||||
export { default as TitleExtra } from './TitleExtra';
|
||||
export { default as TitleWrapper } from './TitleWrapper';
|
||||
export { default as Separator } from './Separator';
|
|
@ -1,138 +0,0 @@
|
|||
import { CheckboxControl } from '@wordpress/components';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export const PayPalCheckbox = ( {
|
||||
currentValue,
|
||||
label,
|
||||
value,
|
||||
checked = null,
|
||||
disabled = null,
|
||||
changeCallback,
|
||||
} ) => {
|
||||
let isChecked = checked;
|
||||
|
||||
if ( null === isChecked ) {
|
||||
if ( Array.isArray( currentValue ) ) {
|
||||
isChecked = currentValue.includes( value );
|
||||
} else {
|
||||
isChecked = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
const className = classNames( { 'is-disabled': disabled } );
|
||||
|
||||
const onChange = ( newState ) => {
|
||||
let newValue;
|
||||
|
||||
if ( ! Array.isArray( currentValue ) ) {
|
||||
newValue = newState;
|
||||
} else if ( newState ) {
|
||||
newValue = [ ...currentValue, value ];
|
||||
} else {
|
||||
newValue = currentValue.filter(
|
||||
( optionValue ) => optionValue !== value
|
||||
);
|
||||
}
|
||||
|
||||
changeCallback( newValue );
|
||||
};
|
||||
|
||||
return (
|
||||
<CheckboxControl
|
||||
label={ label }
|
||||
value={ value }
|
||||
checked={ isChecked }
|
||||
disabled={ disabled }
|
||||
onChange={ onChange }
|
||||
className={ className }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const CheckboxGroup = ( { options, value, onChange } ) => (
|
||||
<>
|
||||
{ options.map( ( checkbox ) => (
|
||||
<PayPalCheckbox
|
||||
key={ checkbox.value }
|
||||
label={ checkbox.label }
|
||||
value={ checkbox.value }
|
||||
checked={ checkbox.checked }
|
||||
disabled={ checkbox.disabled }
|
||||
description={ checkbox.description }
|
||||
tooltip={ checkbox.tooltip }
|
||||
currentValue={ value }
|
||||
changeCallback={ onChange }
|
||||
/>
|
||||
) ) }
|
||||
</>
|
||||
);
|
||||
|
||||
export const PayPalRdb = ( {
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
currentValue,
|
||||
handleRdbState,
|
||||
} ) => {
|
||||
return (
|
||||
<div className="ppcp-r__radio">
|
||||
{ /* todo: Can we remove the wrapper div? */ }
|
||||
<input
|
||||
className="ppcp-r__radio-value"
|
||||
type="radio"
|
||||
id={ id }
|
||||
checked={ value === currentValue }
|
||||
name={ name }
|
||||
value={ value }
|
||||
onChange={ () => handleRdbState( value ) }
|
||||
/>
|
||||
<span className="ppcp-r__radio-presentation"></span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const PayPalRdbWithContent = ( {
|
||||
className,
|
||||
id,
|
||||
name,
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
currentValue,
|
||||
handleRdbState,
|
||||
toggleAdditionalContent,
|
||||
children,
|
||||
} ) => {
|
||||
const wrapperClasses = classNames( 'ppcp-r__radio-wrapper', className );
|
||||
|
||||
return (
|
||||
<div className="ppcp-r__radio-outer-wrapper">
|
||||
<div className={ wrapperClasses }>
|
||||
<PayPalRdb
|
||||
id={ id }
|
||||
name={ name }
|
||||
value={ value }
|
||||
currentValue={ currentValue }
|
||||
handleRdbState={ handleRdbState }
|
||||
/>
|
||||
|
||||
<div className="ppcp-r__radio-content">
|
||||
<label htmlFor={ id }>{ label }</label>
|
||||
{ description && (
|
||||
<p
|
||||
className="ppcp-r__radio-description"
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: description,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
{ toggleAdditionalContent && children && value === currentValue && (
|
||||
<div className="ppcp-r__radio-content-additional">
|
||||
{ children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
import { CheckboxControl } from '@wordpress/components';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const Checkbox = ( {
|
||||
label,
|
||||
value,
|
||||
checked = null,
|
||||
disabled = null,
|
||||
onChange,
|
||||
changeCallback, // deprecated.
|
||||
} ) => {
|
||||
const className = classNames( { 'ppcp--is-disabled': disabled } );
|
||||
|
||||
const handleChange = ( isChecked ) => {
|
||||
if ( onChange ) {
|
||||
onChange( value, isChecked );
|
||||
} else if ( changeCallback ) {
|
||||
console.warn(
|
||||
'Deprecated prop, use "onChange" instead of "changeCallback"'
|
||||
);
|
||||
changeCallback( value, isChecked );
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CheckboxControl
|
||||
label={ label }
|
||||
value={ value }
|
||||
checked={ checked }
|
||||
disabled={ disabled }
|
||||
onChange={ handleChange }
|
||||
className={ className }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Checkbox;
|
|
@ -0,0 +1,42 @@
|
|||
import { PayPalCheckbox } from './index';
|
||||
|
||||
const CheckboxGroup = ( { options, value, onChange } ) => {
|
||||
const handleChange = ( key, checked ) => {
|
||||
const getNewValue = () => {
|
||||
if ( checked ) {
|
||||
return [ ...value, key ];
|
||||
}
|
||||
return value.filter( ( val ) => val !== key );
|
||||
};
|
||||
|
||||
onChange( getNewValue() );
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{ options.map(
|
||||
( {
|
||||
value: itemValue,
|
||||
label,
|
||||
checked,
|
||||
disabled,
|
||||
description,
|
||||
tooltip,
|
||||
} ) => (
|
||||
<PayPalCheckbox
|
||||
key={ itemValue }
|
||||
value={ itemValue }
|
||||
label={ label }
|
||||
checked={ checked }
|
||||
disabled={ disabled }
|
||||
description={ description }
|
||||
tooltip={ tooltip }
|
||||
changeCallback={ handleChange }
|
||||
/>
|
||||
)
|
||||
) }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CheckboxGroup;
|
|
@ -0,0 +1,100 @@
|
|||
import classNames from 'classnames';
|
||||
import { PayPalCheckbox, PayPalRdb } from './index';
|
||||
|
||||
const OptionSelector = ( {
|
||||
multiSelect = false,
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
} ) => (
|
||||
<div className="ppcp-r-select-box-wrapper">
|
||||
{ options.map(
|
||||
( { value: itemValue, title, description, contents } ) => {
|
||||
let isSelected;
|
||||
|
||||
if ( Array.isArray( value ) ) {
|
||||
isSelected = value.includes( itemValue );
|
||||
} else {
|
||||
isSelected = value === itemValue;
|
||||
}
|
||||
|
||||
return (
|
||||
<OptionItem
|
||||
key={ itemValue }
|
||||
itemTitle={ title }
|
||||
itemDescription={ description }
|
||||
itemValue={ itemValue }
|
||||
onChange={ onChange }
|
||||
isMulti={ multiSelect }
|
||||
isSelected={ isSelected }
|
||||
>
|
||||
{ contents }
|
||||
</OptionItem>
|
||||
);
|
||||
}
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
|
||||
export default OptionSelector;
|
||||
|
||||
const OptionItem = ( {
|
||||
itemTitle,
|
||||
itemDescription,
|
||||
itemValue,
|
||||
onChange,
|
||||
isMulti,
|
||||
isSelected,
|
||||
children,
|
||||
} ) => {
|
||||
const boxClassName = classNames( 'ppcp-r-select-box', {
|
||||
'ppcp--selected': isSelected,
|
||||
} );
|
||||
|
||||
return (
|
||||
<div className={ boxClassName }>
|
||||
<InputField
|
||||
value={ itemValue }
|
||||
isRadio={ ! isMulti }
|
||||
onChange={ onChange }
|
||||
isSelected={ isSelected }
|
||||
/>
|
||||
|
||||
<div className="ppcp-r-select-box__content">
|
||||
<div className="ppcp-r-select-box__content-inner">
|
||||
<span className="ppcp-r-select-box__title">
|
||||
{ itemTitle }
|
||||
</span>
|
||||
<p className="ppcp-r-select-box__description">
|
||||
{ itemDescription }
|
||||
</p>
|
||||
{ children && (
|
||||
<div className="ppcp-r-select-box__additional-content">
|
||||
{ children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const InputField = ( { value, onChange, isRadio, isSelected } ) => {
|
||||
if ( isRadio ) {
|
||||
return (
|
||||
<PayPalRdb
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
checked={ isSelected }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PayPalCheckbox
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
checked={ isSelected }
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
|
||||
const RadioButton = ( {
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
currentValue,
|
||||
checked = null, // alternative to currentValue.
|
||||
onChange,
|
||||
handleRdbState, // deprecated
|
||||
} ) => {
|
||||
const handleChange = useCallback( () => {
|
||||
if ( onChange ) {
|
||||
onChange( value );
|
||||
} else if ( handleRdbState ) {
|
||||
console.warn(
|
||||
'Deprecated prop, use "onChange" instead of "handleRdbState"'
|
||||
);
|
||||
handleRdbState( value );
|
||||
}
|
||||
}, [ handleRdbState, onChange, value ] );
|
||||
|
||||
const radioProps = {
|
||||
className: 'ppcp-r__radio-value',
|
||||
type: 'radio',
|
||||
onChange: handleChange,
|
||||
checked: null === checked ? value === currentValue : checked,
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="ppcp-r__radio">
|
||||
{ /* todo: Can we remove the wrapper div? */ }
|
||||
<input { ...radioProps } />
|
||||
<span className="ppcp-r__radio-presentation"></span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioButton;
|
|
@ -0,0 +1,50 @@
|
|||
import classNames from 'classnames';
|
||||
import { PayPalRdb } from './index';
|
||||
|
||||
const RadioButtonWithContent = ( {
|
||||
className,
|
||||
id,
|
||||
name,
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
currentValue,
|
||||
handleRdbState,
|
||||
toggleAdditionalContent,
|
||||
children,
|
||||
} ) => {
|
||||
const wrapperClasses = classNames( 'ppcp-r__radio-wrapper', className );
|
||||
|
||||
return (
|
||||
<div className="ppcp-r__radio-outer-wrapper">
|
||||
<div className={ wrapperClasses }>
|
||||
<PayPalRdb
|
||||
id={ id }
|
||||
name={ name }
|
||||
value={ value }
|
||||
currentValue={ currentValue }
|
||||
handleRdbState={ handleRdbState }
|
||||
/>
|
||||
|
||||
<div className="ppcp-r__radio-content">
|
||||
<label htmlFor={ id }>{ label }</label>
|
||||
{ description && (
|
||||
<p
|
||||
className="ppcp-r__radio-description"
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: description,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
{ toggleAdditionalContent && children && value === currentValue && (
|
||||
<div className="ppcp-r__radio-content-additional">
|
||||
{ children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioButtonWithContent;
|
|
@ -0,0 +1,13 @@
|
|||
import { RadioControl } from '@wordpress/components';
|
||||
|
||||
const RadioGroup = ( { options, selected, onChange } ) => {
|
||||
return (
|
||||
<RadioControl
|
||||
options={ options }
|
||||
onChange={ onChange }
|
||||
selected={ selected }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioGroup;
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* TODO: Replace this with the WordPress select control once V2 with multi-select is ready.
|
||||
*
|
||||
* This component has a lot of compatibility logic to (a) make the ReactSelect component look like
|
||||
* a WordPress select component, and (b) convert values from Redux-format (value-strings) to
|
||||
* ReactSelect values (objects containing value and label). When switching to the
|
||||
* SelectControl from `@wordpress/components`, we can remove a lot of this code.
|
||||
*
|
||||
* @see https://wordpress.github.io/gutenberg/?path=/story/components-customselectcontrol-v2--multiple-selection
|
||||
* @file
|
||||
*/
|
||||
|
||||
import { default as ReactSelect, components } from 'react-select';
|
||||
import { Icon } from '@wordpress/components';
|
||||
import { chevronDown, chevronUp } from '@wordpress/icons';
|
||||
import { useCallback, useEffect, useState } from '@wordpress/element';
|
||||
|
||||
const DropdownIndicator = ( props ) => (
|
||||
<components.DropdownIndicator { ...props }>
|
||||
<Icon icon={ props.selectProps.menuIsOpen ? chevronUp : chevronDown } />
|
||||
</components.DropdownIndicator>
|
||||
);
|
||||
|
||||
const IndicatorSeparator = () => null;
|
||||
|
||||
// Convert a plain value string/array to react-select objects.
|
||||
const toInternalValue = ( selected, options ) => {
|
||||
if ( Array.isArray( selected ) ) {
|
||||
return selected.map( ( value ) =>
|
||||
options.find( ( option ) => option.value === value )
|
||||
);
|
||||
}
|
||||
|
||||
return options.find( ( option ) => option.value === selected );
|
||||
};
|
||||
|
||||
// Convert react-select object(s) to a plain value string/array.
|
||||
const toStoreValue = ( selected ) => {
|
||||
if ( ! selected ) {
|
||||
return null;
|
||||
}
|
||||
if ( Array.isArray( selected ) ) {
|
||||
return selected.map( ( value ) => value.value );
|
||||
}
|
||||
return selected.value;
|
||||
};
|
||||
|
||||
const Select = ( { options, value, onChange, isMulti, placeholder } ) => {
|
||||
const [ internalValue, setInternalValue ] = useState(
|
||||
toInternalValue( value, options )
|
||||
);
|
||||
|
||||
const onInternalValueChange = useCallback(
|
||||
( selected ) => {
|
||||
setInternalValue( selected );
|
||||
|
||||
if ( Array.isArray( selected ) ) {
|
||||
return onChange( selected.map( ( option ) => option.id ) );
|
||||
}
|
||||
return onChange( selected.id );
|
||||
},
|
||||
[ onChange ]
|
||||
);
|
||||
|
||||
// Forward changes of the internal ReactSelect value to the onChange callback.
|
||||
useEffect( () => {
|
||||
onChange( toStoreValue( internalValue ) );
|
||||
}, [ internalValue, onChange ] );
|
||||
|
||||
return (
|
||||
<ReactSelect
|
||||
className="ppcp-r-select"
|
||||
classNamePrefix="ppcp"
|
||||
isMulti={ isMulti }
|
||||
options={ options }
|
||||
value={ internalValue }
|
||||
onChange={ onInternalValueChange }
|
||||
placeholder={ placeholder }
|
||||
components={ { DropdownIndicator, IndicatorSeparator } }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Select;
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Generic input fields.
|
||||
*/
|
||||
|
||||
export { default as PayPalCheckbox } from './Checkbox';
|
||||
export { default as CheckboxGroup } from './CheckboxGroup';
|
||||
export { default as RadioGroup } from './RadioGroup';
|
||||
export { default as PayPalRdb } from './RadioButton';
|
||||
export { default as PayPalRdbWithContent } from './RadioContent';
|
||||
export { default as OptionSelector } from './OptionSelector';
|
||||
export { default as Select } from './Select';
|
|
@ -1,49 +0,0 @@
|
|||
import data from '../../utils/data';
|
||||
import { PayPalCheckbox, PayPalRdb } from './Fields';
|
||||
|
||||
const SelectBox = ( props ) => {
|
||||
let boxClassName = 'ppcp-r-select-box';
|
||||
|
||||
if (
|
||||
props.value === props.currentValue ||
|
||||
( Array.isArray( props.currentValue ) &&
|
||||
props.currentValue.includes( props.value ) )
|
||||
) {
|
||||
boxClassName += ' selected';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ boxClassName }>
|
||||
{ props.type === 'radio' && (
|
||||
<PayPalRdb
|
||||
{ ...{
|
||||
...props,
|
||||
handleRdbState: props.changeCallback,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
{ props.type === 'checkbox' && (
|
||||
<PayPalCheckbox
|
||||
{ ...props }
|
||||
/>
|
||||
) }
|
||||
<div className="ppcp-r-select-box__content">
|
||||
<div className="ppcp-r-select-box__content-inner">
|
||||
<span className="ppcp-r-select-box__title">
|
||||
{ props.title }
|
||||
</span>
|
||||
<p className="ppcp-r-select-box__description">
|
||||
{ props.description }
|
||||
</p>
|
||||
{ props.children && (
|
||||
<div className="ppcp-r-select-box__additional-content">
|
||||
{ props.children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectBox;
|
|
@ -1,5 +0,0 @@
|
|||
const SelectBoxWrapper = ( props ) => {
|
||||
return <div className="ppcp-r-select-box-wrapper">{ props.children }</div>;
|
||||
};
|
||||
|
||||
export default SelectBoxWrapper;
|
|
@ -0,0 +1,47 @@
|
|||
import classNames from 'classnames';
|
||||
import { Description, Header, Title, TitleExtra, Content } from './Elements';
|
||||
|
||||
const SettingsBlock = ( {
|
||||
className,
|
||||
children,
|
||||
title,
|
||||
titleSuffix,
|
||||
description,
|
||||
horizontalLayout = false,
|
||||
separatorAndGap = true,
|
||||
} ) => {
|
||||
const blockClassName = classNames( 'ppcp-r-settings-block', className, {
|
||||
'ppcp--no-gap': ! separatorAndGap,
|
||||
'ppcp--horizontal': horizontalLayout,
|
||||
} );
|
||||
|
||||
const BlockTitle = ( { blockTitle, blockSuffix, blockDescription } ) => {
|
||||
if ( ! blockTitle && ! blockDescription ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Header>
|
||||
<Title>
|
||||
{ blockTitle }
|
||||
<TitleExtra>{ blockSuffix }</TitleExtra>
|
||||
</Title>
|
||||
<Description>{ blockDescription }</Description>
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={ blockClassName }>
|
||||
<BlockTitle
|
||||
blockTitle={ title }
|
||||
blockSuffix={ titleSuffix }
|
||||
blockDescription={ description }
|
||||
/>
|
||||
|
||||
<Content asCard={ false }>{ children }</Content>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsBlock;
|
|
@ -1,27 +0,0 @@
|
|||
import Accordion from '../AccordionSection';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import {
|
||||
Header,
|
||||
Title,
|
||||
Action,
|
||||
Description,
|
||||
TitleWrapper,
|
||||
} from './SettingsBlockElements';
|
||||
|
||||
const SettingsAccordion = ( { title, description, children, ...props } ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__accordion">
|
||||
<Accordion
|
||||
title={ title }
|
||||
description={ description }
|
||||
Header={ Header }
|
||||
TitleWrapper={ TitleWrapper }
|
||||
Title={ Title }
|
||||
Action={ Action }
|
||||
Description={ Description }
|
||||
>
|
||||
{ children }
|
||||
</Accordion>
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default SettingsAccordion;
|
|
@ -1,27 +0,0 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Action, Description, Header, Title } from './SettingsBlockElements';
|
||||
|
||||
const ButtonSettingsBlock = ( { title, description, ...props } ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__button">
|
||||
<Header>
|
||||
<Title>{ title }</Title>
|
||||
<Description>{ description }</Description>
|
||||
</Header>
|
||||
<Action>
|
||||
<Button
|
||||
isBusy={ props.actionProps?.isBusy }
|
||||
variant={ props.actionProps?.buttonType }
|
||||
onClick={
|
||||
props.actionProps?.callback
|
||||
? () => props.actionProps.callback()
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{ props?.actionProps?.value }
|
||||
</Button>
|
||||
</Action>
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default ButtonSettingsBlock;
|
|
@ -1,6 +1,7 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Header, Title, Action, Description } from './SettingsBlockElements';
|
||||
|
||||
import { Header, Title, Action, Description } from '../Elements';
|
||||
import SettingsBlock from '../SettingsBlock';
|
||||
import TitleBadge from '../TitleBadge';
|
||||
|
||||
const FeatureSettingsBlock = ( { title, description, ...props } ) => {
|
||||
|
@ -41,13 +42,17 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
|
|||
</Button>
|
||||
);
|
||||
|
||||
return button.urls ? (
|
||||
<a href={ button.urls.live } key={ button.text }>
|
||||
{ buttonElement }
|
||||
</a>
|
||||
) : (
|
||||
buttonElement
|
||||
);
|
||||
// If there's a URL (either direct or in urls object), wrap in anchor tag
|
||||
if ( button.url || button.urls ) {
|
||||
const href = button.urls ? button.urls.live : button.url;
|
||||
return (
|
||||
<a href={ href } key={ button.text }>
|
||||
{ buttonElement }
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return buttonElement;
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import { TextControl } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import {
|
||||
Title,
|
||||
Action,
|
||||
Description,
|
||||
SupplementaryLabel,
|
||||
} from './SettingsBlockElements';
|
||||
|
||||
const DEFAULT_ELEMENT_ORDER = [ 'title', 'action', 'description' ];
|
||||
|
||||
const ELEMENT_RENDERERS = {
|
||||
title: ( { title, supplementaryLabel } ) => (
|
||||
<Title>
|
||||
{ title }
|
||||
{ supplementaryLabel && (
|
||||
<SupplementaryLabel>{ supplementaryLabel }</SupplementaryLabel>
|
||||
) }
|
||||
</Title>
|
||||
),
|
||||
action: ( { actionProps } ) => (
|
||||
<Action>
|
||||
<TextControl
|
||||
className="ppcp-r-vertical-text-control"
|
||||
placeholder={ actionProps?.placeholder }
|
||||
value={ actionProps?.value }
|
||||
onChange={ ( newValue ) =>
|
||||
actionProps?.callback( actionProps?.key, newValue )
|
||||
}
|
||||
/>
|
||||
</Action>
|
||||
),
|
||||
description: ( { description } ) => (
|
||||
<Description>{ description }</Description>
|
||||
),
|
||||
};
|
||||
|
||||
const InputSettingsBlock = ( {
|
||||
title,
|
||||
description,
|
||||
supplementaryLabel,
|
||||
order = DEFAULT_ELEMENT_ORDER,
|
||||
...props
|
||||
} ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__input">
|
||||
{ order.map( ( elementKey ) => {
|
||||
const RenderElement = ELEMENT_RENDERERS[ elementKey ];
|
||||
return RenderElement ? (
|
||||
<RenderElement
|
||||
key={ elementKey }
|
||||
title={ title }
|
||||
description={ description }
|
||||
supplementaryLabel={ supplementaryLabel }
|
||||
actionProps={ props.actionProps }
|
||||
/>
|
||||
) : null;
|
||||
} ) }
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default InputSettingsBlock;
|
|
@ -1,32 +1,29 @@
|
|||
import { ToggleControl } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
|
||||
import SettingsBlock from '../SettingsBlock';
|
||||
import PaymentMethodIcon from '../PaymentMethodIcon';
|
||||
import data from '../../../utils/data';
|
||||
import { hasSettings } from '../../Screens/Overview/TabSettingsElements/Blocks/PaymentMethods';
|
||||
|
||||
const PaymentMethodItemBlock = ( {
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
paymentMethod,
|
||||
onTriggerModal,
|
||||
onSelect,
|
||||
isSelected,
|
||||
} ) => {
|
||||
// Only show settings icon if this method has fields configured
|
||||
const hasModal = hasSettings( id );
|
||||
|
||||
return (
|
||||
<SettingsBlock className="ppcp-r-settings-block__payment-methods__item">
|
||||
<div className="ppcp-r-settings-block__payment-methods__item__inner">
|
||||
<div className="ppcp-r-settings-block__payment-methods__item__title-wrapper">
|
||||
<PaymentMethodIcon icons={ [ icon ] } type={ icon } />
|
||||
<PaymentMethodIcon
|
||||
icons={ [ paymentMethod.icon ] }
|
||||
type={ paymentMethod.icon }
|
||||
/>
|
||||
<span className="ppcp-r-settings-block__payment-methods__item__title">
|
||||
{ title }
|
||||
{ paymentMethod.itemTitle }
|
||||
</span>
|
||||
</div>
|
||||
<p className="ppcp-r-settings-block__payment-methods__item__description">
|
||||
{ description }
|
||||
{ paymentMethod.itemDescription }
|
||||
</p>
|
||||
<div className="ppcp-r-settings-block__payment-methods__item__footer">
|
||||
<ToggleControl
|
||||
|
@ -34,7 +31,7 @@ const PaymentMethodItemBlock = ( {
|
|||
checked={ isSelected }
|
||||
onChange={ onSelect }
|
||||
/>
|
||||
{ hasModal && onTriggerModal && (
|
||||
{ paymentMethod?.fields && onTriggerModal && (
|
||||
<div
|
||||
className="ppcp-r-settings-block__payment-methods__item__settings"
|
||||
onClick={ onTriggerModal }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import SettingsBlock from './SettingsBlock';
|
||||
import SettingsBlock from '../SettingsBlock';
|
||||
import PaymentMethodItemBlock from './PaymentMethodItemBlock';
|
||||
import { usePaymentMethods } from '../../../data/payment/hooks';
|
||||
|
||||
|
@ -27,7 +27,7 @@ const PaymentMethodsBlock = ( {
|
|||
{ paymentMethods.map( ( paymentMethod ) => (
|
||||
<PaymentMethodItemBlock
|
||||
key={ paymentMethod.id }
|
||||
{ ...paymentMethod }
|
||||
paymentMethod={ paymentMethod }
|
||||
isSelected={ paymentMethod.enabled }
|
||||
onSelect={ ( checked ) =>
|
||||
handleSelect( paymentMethod, checked )
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import SettingsBlock from './SettingsBlock';
|
||||
import { Header, Title, Description } from './SettingsBlockElements';
|
||||
import { PayPalRdbWithContent } from '../Fields';
|
||||
|
||||
const RadioSettingsBlock = ( {
|
||||
title,
|
||||
description,
|
||||
options = [],
|
||||
...props
|
||||
} ) => (
|
||||
<SettingsBlock
|
||||
{ ...props }
|
||||
className="ppcp-r-settings-block__radio ppcp-r-settings-block--expert-rdb"
|
||||
>
|
||||
<Header>
|
||||
<Title>{ title }</Title>
|
||||
<Description>{ description }</Description>
|
||||
</Header>
|
||||
{ options.map( ( option ) => (
|
||||
<PayPalRdbWithContent
|
||||
key={ option.id }
|
||||
id={ option.id }
|
||||
name={ props.actionProps?.name }
|
||||
value={ option.value }
|
||||
currentValue={ props.actionProps?.currentValue }
|
||||
handleRdbState={ ( newValue ) =>
|
||||
props.actionProps?.callback(
|
||||
props.actionProps?.key,
|
||||
newValue
|
||||
)
|
||||
}
|
||||
label={ option.label }
|
||||
description={ option.description }
|
||||
toggleAdditionalContent={ true }
|
||||
>
|
||||
{ option.additionalContent }
|
||||
</PayPalRdbWithContent>
|
||||
) ) }
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default RadioSettingsBlock;
|
|
@ -1,53 +0,0 @@
|
|||
import Select, { components } from 'react-select';
|
||||
import data from '../../../utils/data';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Title, Action, Description } from './SettingsBlockElements';
|
||||
|
||||
const DEFAULT_ELEMENT_ORDER = [ 'title', 'action', 'description' ];
|
||||
|
||||
const DropdownIndicator = ( props ) => (
|
||||
<components.DropdownIndicator { ...props }>
|
||||
{ data().getImage( 'icon-arrow-down.svg' ) }
|
||||
</components.DropdownIndicator>
|
||||
);
|
||||
|
||||
const ELEMENT_RENDERERS = {
|
||||
title: ( { title } ) => <Title>{ title }</Title>,
|
||||
action: ( { actionProps } ) => (
|
||||
<Action>
|
||||
<Select
|
||||
className="ppcp-r-multiselect"
|
||||
classNamePrefix="ppcp-r"
|
||||
isMulti={ actionProps?.isMulti }
|
||||
options={ actionProps?.options }
|
||||
components={ { DropdownIndicator } }
|
||||
/>
|
||||
</Action>
|
||||
),
|
||||
description: ( { description } ) => (
|
||||
<Description>{ description }</Description>
|
||||
),
|
||||
};
|
||||
|
||||
const SelectSettingsBlock = ( {
|
||||
title,
|
||||
description,
|
||||
order = DEFAULT_ELEMENT_ORDER,
|
||||
...props
|
||||
} ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__select">
|
||||
{ order.map( ( elementKey ) => {
|
||||
const RenderElement = ELEMENT_RENDERERS[ elementKey ];
|
||||
return RenderElement ? (
|
||||
<RenderElement
|
||||
key={ elementKey }
|
||||
title={ title }
|
||||
description={ description }
|
||||
actionProps={ props.actionProps }
|
||||
/>
|
||||
) : null;
|
||||
} ) }
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default SelectSettingsBlock;
|
|
@ -1,11 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const SettingsBlock = ( { className, children, separatorAndGap = true } ) => {
|
||||
const blockClassName = classNames( 'ppcp-r-settings-block', className, {
|
||||
'no-gap': ! separatorAndGap,
|
||||
} );
|
||||
|
||||
return <div className={ blockClassName }>{ children }</div>;
|
||||
};
|
||||
|
||||
export default SettingsBlock;
|
|
@ -1,81 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
// Block Elements
|
||||
export const Title = ( {
|
||||
children,
|
||||
altStyle = false,
|
||||
big = false,
|
||||
className = '',
|
||||
} ) => {
|
||||
const elementClasses = classNames(
|
||||
'ppcp-r-settings-block__title',
|
||||
className,
|
||||
{
|
||||
'style-alt': altStyle,
|
||||
'style-big': big,
|
||||
}
|
||||
);
|
||||
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
};
|
||||
|
||||
export const TitleWrapper = ( { children } ) => (
|
||||
<span className="ppcp-r-settings-block__title-wrapper">{ children }</span>
|
||||
);
|
||||
|
||||
export const SupplementaryLabel = ( { children } ) => (
|
||||
<span className="ppcp-r-settings-block__supplementary-title-label">
|
||||
{ children }
|
||||
</span>
|
||||
);
|
||||
|
||||
export const Description = ( { children, asHtml = false, className = '' } ) => {
|
||||
// Don't output anything if description is empty.
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames(
|
||||
'ppcp-r-settings-block__description',
|
||||
className
|
||||
);
|
||||
|
||||
if ( ! asHtml ) {
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className={ elementClasses }
|
||||
dangerouslySetInnerHTML={ { __html: children } }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Action = ( { children } ) => (
|
||||
<div className="ppcp-r-settings-block__action">{ children }</div>
|
||||
);
|
||||
|
||||
export const Header = ( { children, className = '' } ) => (
|
||||
<div className={ `ppcp-r-settings-block__header ${ className }`.trim() }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
|
||||
// Card Elements
|
||||
export const Content = ( { children, className = '', id = '' } ) => {
|
||||
const elementClasses = classNames(
|
||||
'ppcp-r-settings-card__content',
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<div id={ id } className={ elementClasses }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ContentWrapper = ( { children } ) => (
|
||||
<div className="ppcp-r-settings-card__content-wrapper">{ children }</div>
|
||||
);
|
|
@ -1,27 +0,0 @@
|
|||
import { ToggleControl } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Header, Title, Action, Description } from './SettingsBlockElements';
|
||||
|
||||
const ToggleSettingsBlock = ( { title, description, ...props } ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__toggle">
|
||||
<Action>
|
||||
<ToggleControl
|
||||
className="ppcp-r-settings-block__toggle-control"
|
||||
__nextHasNoMarginBottom={ true }
|
||||
checked={ props.actionProps?.value }
|
||||
onChange={ ( newValue ) =>
|
||||
props.actionProps?.callback(
|
||||
props.actionProps?.key,
|
||||
newValue
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Action>
|
||||
<Header>
|
||||
{ title && <Title>{ title }</Title> }
|
||||
{ description && <Description>{ description }</Description> }
|
||||
</Header>
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default ToggleSettingsBlock;
|
|
@ -1,20 +1,4 @@
|
|||
export { default as SettingsBlock } from './SettingsBlock';
|
||||
export { default as ButtonSettingsBlock } from './ButtonSettingsBlock';
|
||||
export { default as InputSettingsBlock } from './InputSettingsBlock';
|
||||
export { default as SelectSettingsBlock } from './SelectSettingsBlock';
|
||||
export { default as AccordionSettingsBlock } from './AccordionSettingsBlock';
|
||||
export { default as ToggleSettingsBlock } from './ToggleSettingsBlock';
|
||||
export { default as RadioSettingsBlock } from './RadioSettingsBlock';
|
||||
export { default as PaymentMethodsBlock } from './PaymentMethodsBlock';
|
||||
export { default as PaymentMethodItemBlock } from './PaymentMethodItemBlock';
|
||||
|
||||
export {
|
||||
Title,
|
||||
TitleWrapper,
|
||||
SupplementaryLabel,
|
||||
Description,
|
||||
Action,
|
||||
Content,
|
||||
ContentWrapper,
|
||||
Header,
|
||||
} from './SettingsBlockElements';
|
||||
export { default as TodoSettingsBlock } from './TodoSettingsBlock';
|
||||
export { default as FeatureSettingsBlock } from './FeatureSettingsBlock';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { Content, ContentWrapper } from './SettingsBlocks';
|
||||
import { Content, ContentWrapper } from './Elements';
|
||||
|
||||
const SettingsCard = ( {
|
||||
id,
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { Spinner } from '@wordpress/components';
|
||||
|
||||
const SpinnerOverlay = ( { message = '' } ) => {
|
||||
const SpinnerOverlay = ( { message = null } ) => {
|
||||
if ( null === message ) {
|
||||
message = __( 'Loading…', 'woocommerce-paypal-payments' );
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-spinner-overlay">
|
||||
{ message && (
|
||||
|
|
|
@ -20,10 +20,10 @@ const TopNavigation = ( {
|
|||
const { isScrolled } = useIsScrolled();
|
||||
|
||||
const className = classNames( 'ppcp-r-navigation-container', {
|
||||
'is-scrolled': isScrolled,
|
||||
'ppcp--is-scrolled': isScrolled,
|
||||
} );
|
||||
const titleClassName = classNames( 'title', {
|
||||
big: isMainTitle,
|
||||
const titleClassName = classNames( 'ppcp--nav-title', {
|
||||
'ppcp--big': isMainTitle,
|
||||
} );
|
||||
|
||||
const handleTitleClick = useCallback( () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue