diff --git a/packages/lib/src/components/Card/components/CardInput/CardInput.scss b/packages/lib/src/components/Card/components/CardInput/CardInput.scss index 0608b2cbfa..393ac77d45 100644 --- a/packages/lib/src/components/Card/components/CardInput/CardInput.scss +++ b/packages/lib/src/components/Card/components/CardInput/CardInput.scss @@ -56,6 +56,7 @@ } } +/* TODO: When is this class is this ever set? */ .adyen-checkout__card-input__form { transition: opacity 0.25s ease-out; } @@ -230,3 +231,15 @@ margin-left: token(spacer-070); } } + +.adyen-checkout__card-input .adyen-checkout__fieldset--dual-brand-switcher { + margin-top: token(spacer-050); + + .adyen-checkout__radio_group{ + margin-top: token(spacer-050); + } + + .adyen-checkout__fieldset__title { + padding-bottom: 0; + } +} \ No newline at end of file diff --git a/packages/lib/src/components/Card/components/CardInput/components/CardFieldsWrapper.tsx b/packages/lib/src/components/Card/components/CardInput/components/CardFieldsWrapper.tsx index a6a3e6ab4f..78867d93f3 100644 --- a/packages/lib/src/components/Card/components/CardInput/components/CardFieldsWrapper.tsx +++ b/packages/lib/src/components/Card/components/CardInput/components/CardFieldsWrapper.tsx @@ -8,6 +8,13 @@ import Address from '../../../../internal/Address'; import CardHolderName from './CardHolderName'; import Installments from './Installments'; import DisclaimerMessage from '../../../../internal/DisclaimerMessage'; +import RadioGroupExtended from '../../../../internal/FormFields/RadioGroupExtended'; +import Field from '../../../../internal/FormFields/Field'; +import { getCardImageUrl, getFullBrandName } from '../utils'; +import useImage from '../../../../../core/Context/useImage'; +import Fieldset from '../../../../internal/FormFields/Fieldset'; +import { useCoreContext } from '../../../../../core/Context/CoreProvider'; +// import SegmentedControl from '../../../../internal/SegmentedControl'; export const CardFieldsWrapper = ({ // vars created in CardInput: @@ -71,6 +78,8 @@ export const CardFieldsWrapper = ({ onFieldFocusAnalytics, onFieldBlurAnalytics }) => { + const { i18n } = useCoreContext(); + const cardHolderField = ( 0 && dualBrandSelectElements && ( +
+ + { + const brand = item.id; + const getImage = useImage(); + const imageName = brand === 'card' ? 'nocard' : brand; + const imageURL = brandsConfiguration[brand]?.icon ?? getCardImageUrl(imageName, getImage); + + // TODO - check below if we have to still generate altName through the mapping function or whether it just + // corresponds to item.brandObject.localeBrand + return { id: item.id, name: item.brandObject.localeBrand, imageURL, altName: getFullBrandName(brand) }; + })} + onChange={extensions.handleDualBrandSelection} + required={true} + style={'button'} + showRadioIcon={false} + /> + + {/* { + const brand = item.id; + const getImage = useImage(); + const imageName = brand === 'card' ? 'nocard' : brand; + const imageURL = brandsConfiguration[brand]?.icon ?? getCardImageUrl(imageName, getImage); + + // TODO - check below if we have to still generate altName through the mapping function or whether it just + // corresponds to item.brandObject.localeBrand + return { value: item.id, label: item.brandObject.localeBrand, imageURL, altName: getFullBrandName(brand) }; + })} + onChange={extensions.handleDualBrandSelection} + required={true} + style={'button'} + showRadioIcon={false} + />*/} + +
+ )} + {showKCP && ( { + const [hasLoaded, setHasLoaded] = useState(false); + + const handleError = () => { + setHasLoaded(false); + }; + + const handleLoad = () => { + setHasLoaded(true); + }; + + const fieldClassnames = classNames({ + 'adyen-checkout__input-icon': true, + 'adyen-checkout__input-icon--hidden': !hasLoaded, + 'adyen-checkout__input-icon--no-radio-icon': !hasRadioIcon + }); + + return {altName}; +}; + +export default RadioButtonIcon; diff --git a/packages/lib/src/components/internal/FormFields/RadioGroupExtended/RadioGroupExtended.scss b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/RadioGroupExtended.scss new file mode 100644 index 0000000000..dcfb9fab61 --- /dev/null +++ b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/RadioGroupExtended.scss @@ -0,0 +1,57 @@ +@import 'styles/variable-generator'; + +.adyen-checkout__radio_group__label--no-radio { + margin:0; + padding-bottom: 0; + padding-left: token(spacer-090); + position: relative; + display: block; + color: inherit; + font-size: token(text-body-font-size); + font-weight: normal; + line-height: token(text-body-line-height); + overflow: visible; +} + +.adyen-checkout__radio_group__label--no-radio:hover { + border-color: token(color-label-primary); + cursor: pointer; +} + +.adyen-checkout__label--focused .adyen-checkout__radio_group__label--no-radio { + color: inherit; +} + +.adyen-checkout__radio_group__label--no-radio.adyen-checkout__radio_group__label--no-radio--invalid { + color: token(color-outline-critical); +} + +.adyen-checkout__radio_group--button { + .adyen-checkout__radio_group__label--no-radio { + padding: token(spacer-060); + padding-left: calc(token(spacer-060) + token(spacer-090)); + width: 100%; + border: token(border-width-s) solid token(color-outline-primary); + border-radius: token(border-radius-m); + background-color: token(color-background-primary); + } + + .adyen-checkout__radio_group__input:checked + .adyen-checkout__radio_group__label--no-radio { + box-shadow: 0 0 0 0.5px token(color-outline-primary-active); + border-color: token(color-outline-primary-active); + } + + .adyen-checkout__radio_group__input + .adyen-checkout__radio_group__label--no-radio:hover { + border-color: token(color-outline-primary-active); + } + + .adyen-checkout__radio_group__input:checked:focus + .adyen-checkout__radio_group__label--no-radio, + .adyen-checkout__radio_group__input:checked:active + .adyen-checkout__radio_group__label--no-radio { + box-shadow: 0 0 0 0.5px token(color-outline-primary-active); + border-color: token(color-outline-primary-active); + } + + .adyen-checkout__radio_group-extended__label-wrapper{ + display: flex; + } +} \ No newline at end of file diff --git a/packages/lib/src/components/internal/FormFields/RadioGroupExtended/RadioGroupExtended.tsx b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/RadioGroupExtended.tsx new file mode 100644 index 0000000000..9cc159c85a --- /dev/null +++ b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/RadioGroupExtended.tsx @@ -0,0 +1,71 @@ +import { h } from 'preact'; +import cx from 'classnames'; +import './RadioGroupExtended.scss'; +import { RadioGroupProps } from './types'; +import { getUniqueId } from '../../../../utils/idGenerator'; +import { useCoreContext } from '../../../../core/Context/CoreProvider'; +import RadioButtonIcon from './RadioButtonIcon'; + +export default function RadioGroupExtended(props: RadioGroupProps) { + const { items, name, onChange, value, isInvalid, uniqueId, ariaLabel, showRadioIcon = true, style = 'classic' } = props; + + const { i18n } = useCoreContext(); + const uniqueIdBase = uniqueId?.replace(/[0-9]/g, '').substring(0, uniqueId.lastIndexOf('-')); + + let invalidClassName = ''; + if (isInvalid) { + invalidClassName = showRadioIcon ? 'adyen-checkout__radio_group__label--invalid' : 'adyen-checkout__radio_group__label--no-radio--invalid'; + } + + // {...(showRadioIcon ? { type: 'radio' } : { role: 'radio' })} + + const fieldClassnames = cx([ + 'adyen-checkout__label__text', + showRadioIcon ? 'adyen-checkout__radio_group__label' : 'adyen-checkout__radio_group__label--no-radio', + props.className, + invalidClassName + ]); + + return ( +
+ {items.map(item => { + const uniqueId = getUniqueId(uniqueIdBase); + return ( +
+ + {/*eslint-disable-next-line jsx-a11y/label-has-associated-control*/} + +
+ ); + })} +
+ ); +} + +RadioGroupExtended.defaultProps = { + onChange: () => {}, + items: [] +}; diff --git a/packages/lib/src/components/internal/FormFields/RadioGroupExtended/index.ts b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/index.ts new file mode 100644 index 0000000000..47e7cea5a4 --- /dev/null +++ b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/index.ts @@ -0,0 +1 @@ +export { default } from './RadioGroupExtended'; diff --git a/packages/lib/src/components/internal/FormFields/RadioGroupExtended/types.ts b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/types.ts new file mode 100644 index 0000000000..7f94bf136f --- /dev/null +++ b/packages/lib/src/components/internal/FormFields/RadioGroupExtended/types.ts @@ -0,0 +1,30 @@ +import { InputBaseProps } from '../InputBase'; + +interface RadioGroupItem { + name: string; + id: string; + imageURL: string; + altName: string; +} + +export interface RadioGroupProps extends InputBaseProps { + className?: string; + isInvalid?: boolean; + items: RadioGroupItem[]; + name?: string; + onChange: (e) => void; + value?: string; + uniqueId?: string; + ariaLabel?: string; + style?: 'classic' | 'button'; + showRadioIcon?: boolean; +} + +export interface RadioButtonIconProps { + onClick?: any; + dataValue?: string; + notSelected?: boolean; // TODO - needed?? + imageURL?: string; + altName?: string; + hasRadioIcon?: boolean; +} diff --git a/packages/lib/src/components/internal/SecuredFields/binLookup/createCardVariantSwitcher.ts b/packages/lib/src/components/internal/SecuredFields/binLookup/createCardVariantSwitcher.ts index 3c98e8a5c1..f88a46a499 100644 --- a/packages/lib/src/components/internal/SecuredFields/binLookup/createCardVariantSwitcher.ts +++ b/packages/lib/src/components/internal/SecuredFields/binLookup/createCardVariantSwitcher.ts @@ -12,7 +12,7 @@ export default function createCardVariantSwitcher(brandObjArr: BrandObject[]) { { id: leadBrand.brand, brandObject: leadBrand }, { id: subBrand.brand, brandObject: subBrand } ] as DualBrandSelectElement[], - selectedBrandValue: '', // set to leadBrand.brand if an initial selection is to be made + selectedBrandValue: leadBrand.brand, // set to leadBrand.brand if an initial selection is to be made; else set to empty string leadBrand }; } diff --git a/packages/lib/src/components/internal/SecuredFields/binLookup/extensions.ts b/packages/lib/src/components/internal/SecuredFields/binLookup/extensions.ts index 53e3762fc8..13ba943fea 100644 --- a/packages/lib/src/components/internal/SecuredFields/binLookup/extensions.ts +++ b/packages/lib/src/components/internal/SecuredFields/binLookup/extensions.ts @@ -113,10 +113,9 @@ export default function extensions(props, refs, states, hasPanLengthRef: Partial */ handleDualBrandSelection: (e: Event | string): void => { let value: Event | string = e; - if (e instanceof Event) { const target = e.target as HTMLLIElement; - value = target.getAttribute('data-value') || target.getAttribute('alt'); + value = target.getAttribute('data-value') || target.getAttribute('value'); } // Check if we have a value and whether that value corresponds to a brandObject we can propagate