card-element.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import { useState, useEffect, useRef } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { FormGroup, ControlLabel } from 'react-bootstrap'
  4. import { CardElementChangeState } from '../../../../../../../types/recurly/elements'
  5. import { ElementsInstance } from 'recurly__recurly-js'
  6. import classnames from 'classnames'
  7. import getMeta from '../../../../../utils/meta'
  8. type CardElementProps = {
  9. className?: string
  10. elements: ElementsInstance
  11. onChange: (state: CardElementChangeState) => void
  12. }
  13. function CardElement({ className, elements, onChange }: CardElementProps) {
  14. const { t } = useTranslation()
  15. const [showCardElementInvalid, setShowCardElementInvalid] =
  16. useState<boolean>()
  17. const cardRef = useRef<HTMLDivElement | null>(null)
  18. // Card initialization
  19. useEffect(() => {
  20. if (!cardRef.current) return
  21. const showNewDesign =
  22. getMeta('ol-splitTestVariants')?.['design-system-updates'] === 'enabled'
  23. const style = showNewDesign
  24. ? {
  25. fontColor: '#1b222c',
  26. placeholder: {
  27. color: '#677283',
  28. },
  29. invalid: {
  30. fontColor: '#b83a33',
  31. },
  32. }
  33. : {
  34. fontColor: '#5d6879',
  35. placeholder: {},
  36. invalid: {
  37. fontColor: '#a93529',
  38. },
  39. }
  40. const card = elements.CardElement({
  41. displayIcon: true,
  42. inputType: 'mobileSelect',
  43. style,
  44. })
  45. card.attach(cardRef.current)
  46. card.on('change', state => {
  47. setShowCardElementInvalid(!state.focus && !state.empty && !state.valid)
  48. onChange(state)
  49. })
  50. return () => {
  51. cardRef.current = null
  52. }
  53. }, [elements, onChange])
  54. return (
  55. <FormGroup
  56. className={classnames(className, { 'has-error': showCardElementInvalid })}
  57. >
  58. <ControlLabel>{t('card_details')}</ControlLabel>
  59. <div ref={cardRef} />
  60. {showCardElementInvalid && (
  61. <span className="input-feedback-message">
  62. {t('card_details_are_not_valid')}
  63. </span>
  64. )}
  65. </FormGroup>
  66. )
  67. }
  68. export default CardElement