{"id":13422088,"url":"https://github.com/medipass/react-payment-inputs","last_synced_at":"2025-04-04T21:11:28.169Z","repository":{"id":35645108,"uuid":"186606783","full_name":"medipass/react-payment-inputs","owner":"medipass","description":"A React Hook \u0026 Container to help with payment card input fields.","archived":false,"fork":false,"pushed_at":"2024-07-21T23:53:39.000Z","size":3820,"stargazers_count":423,"open_issues_count":60,"forks_count":66,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-03-28T20:09:54.819Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://medipass.github.io/react-payment-inputs","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/medipass.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-14T11:17:51.000Z","updated_at":"2025-03-02T04:46:37.000Z","dependencies_parsed_at":"2024-07-22T00:39:07.350Z","dependency_job_id":"64c03a29-1eff-41e6-98f2-ea78d978bc03","html_url":"https://github.com/medipass/react-payment-inputs","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medipass%2Freact-payment-inputs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medipass%2Freact-payment-inputs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medipass%2Freact-payment-inputs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medipass%2Freact-payment-inputs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/medipass","download_url":"https://codeload.github.com/medipass/react-payment-inputs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247249534,"owners_count":20908212,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T23:00:36.722Z","updated_at":"2025-04-04T21:11:28.150Z","avatar_url":"https://github.com/medipass.png","language":"JavaScript","funding_links":[],"categories":["UI Components"],"sub_categories":["Form Components"],"readme":"# React Payment Inputs\n\n\u003e A React Hook \u0026 Container to help with payment card input fields.\n\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./assets/react-payment-inputs.png\" width=\"500px\" style=\"margin-bottom: 1rem; margin-top: 1rem;\"\u003e\u003c/img\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./assets/wrapper.gif\" width=\"500px\"\u003e\u003c/img\u003e\u003c/p\u003e\n\n- [React Payment Inputs](#react-payment-inputs)\n  - [Demos](#demos)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [With hooks](#with-hooks)\n    - [With render props](#with-render-props)\n    - [Using the built-in styled wrapper](#using-the-built-in-styled-wrapper)\n    - [More examples](#more-examples)\n  - [`data = usePaymentInputs(options)`](#data--usepaymentinputsoptions)\n    - [options](#options)\n      - [options.cardNumberValidator](#optionscardnumbervalidator)\n        - [Example](#example)\n      - [options.cvcValidator](#optionscvcvalidator)\n      - [options.errorMessages](#optionserrormessages)\n        - [Example](#example-1)\n      - [options.expiryDateValidator](#optionsexpirydatevalidator)\n      - [options.onBlur](#optionsonblur)\n      - [options.onChange](#optionsonchange)\n      - [options.onError](#optionsonerror)\n      - [options.onTouch](#optionsontouch)\n    - [`data`](#data)\n      - [getCardNumberProps](#getcardnumberprops)\n        - [Example snippet](#example-snippet)\n      - [getExpiryDateProps](#getexpirydateprops)\n        - [Example snippet](#example-snippet-1)\n      - [getCVCProps](#getcvcprops)\n        - [Example snippet](#example-snippet-2)\n      - [getZIPProps](#getzipprops)\n        - [Example snippet](#example-snippet-3)\n      - [getCardImageProps](#getcardimageprops)\n        - [Example snippet](#example-snippet-4)\n      - [meta.cardType](#metacardtype)\n        - [Example snippet](#example-snippet-5)\n      - [meta.error](#metaerror)\n        - [Example snippet](#example-snippet-6)\n      - [meta.isTouched](#metaistouched)\n      - [meta.erroredInputs](#metaerroredinputs)\n        - [Example snippet](#example-snippet-7)\n      - [meta.touchedInputs](#metatouchedinputs)\n        - [Example snippet](#example-snippet-8)\n      - [meta.focused](#metafocused)\n      - [wrapperProps](#wrapperprops)\n  - [`\u003cPaymentInputsWrapper\u003e` props](#paymentinputswrapper-props)\n    - [styles](#styles)\n      - [Schema](#schema)\n    - [errorTextProps](#errortextprops)\n    - [inputWrapperProps](#inputwrapperprops)\n  - [Using a third-party UI library](#using-a-third-party-ui-library)\n    - [Fannypack](#fannypack)\n    - [Bootstrap](#bootstrap)\n  - [Form library examples](#form-library-examples)\n    - [Formik](#formik)\n    - [React Final Form](#react-final-form)\n  - [Customising the in-built style wrapper](#customising-the-in-built-style-wrapper)\n  - [Custom card images](#custom-card-images)\n  - [License](#license)\n\n## [Demos](https://medipass.github.io/react-payment-inputs)\n\n## Requirements\n\nEnsure you are running on a hooks-compatible version of React (v16.8 \u0026 above).\n\n## Installation\n\n```\nnpm install react-payment-inputs --save\n```\n\nor install with [Yarn](https://yarnpkg.com) if you prefer:\n\n```\nyarn add react-payment-inputs\n```\n\n## Usage\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./assets/basic.gif\" width=\"300px\"\u003e\u003c/img\u003e\u003c/p\u003e\n\nBy default (as seen above), React Payment Inputs does not come with built-in styling meaning that you can easily adapt React Payment Inputs to your own design system.\n\nHowever, if you would like to use the built-in styles as seen in the animation above, [read \"Using the built-in styled wrapper\"](#using-the-built-in-styled-wrapper).\n\n### With hooks\n\nIf you'd like to use the hooks version of React Payment Inputs, you can import `usePaymentInputs` into your component.\n\n```jsx\nimport React from 'react';\nimport { usePaymentInputs } from 'react-payment-inputs';\n\nexport default function PaymentInputs() {\n  const { meta, getCardNumberProps, getExpiryDateProps, getCVCProps } = usePaymentInputs();\n\n  return (\n    \u003cdiv\u003e\n      \u003cinput {...getCardNumberProps({ onChange: handleChangeCardNumber })} value={cardNumber} /\u003e\n      \u003cinput {...getExpiryDateProps({ onChange: handleChangeExpiryDate })} value={expiryDate} /\u003e\n      \u003cinput {...getCVCProps({ onChange: handleChangeCVC })} value={cvc} /\u003e\n      {meta.isTouched \u0026\u0026 meta.error \u0026\u0026 \u003cspan\u003eError: {meta.error}\u003c/span\u003e}\n    \u003c/div\u003e\n  );\n}\n```\n\n\u003e By spreading the prop getter functions (e.g. `{...getCardNumberProps()}`) on the inputs as shown above, React Payment Inputs will automatically handle the formatting, focus \u0026 validation logic for you.\n\n\u003e **IMPORTANT:** You must place your event handlers (e.g. `onChange`, `onBlur`, etc) inside the prop getter function (e.g. `getCardNumberProps()`) so the default event handlers in React Payment Inputs don't get overridden.\n\n### With render props\n\nIf you'd like to use the render props version of React Payment Inputs, you can import `PaymentInputsContainer` into your component.\n\nThe **props** of `\u003cPaymentInputsContainer\u003e` are the same as the hook [options](#options) and the **render props** are the same as the hook [data](#data).\n\n```jsx\nimport React from 'react';\nimport { PaymentInputsContainer } from 'react-payment-inputs';\n\nexport default function PaymentInputs() {\n  return (\n    \u003cPaymentInputsContainer\u003e\n      {({ meta, getCardNumberProps, getExpiryDateProps, getCVCProps }) =\u003e (\n        \u003cdiv\u003e\n          \u003cinput {...getCardNumberProps({ onChange: handleChangeCardNumber })} value={cardNumber} /\u003e\n          \u003cinput {...getExpiryDateProps({ onChange: handleChangeExpiryDate })} value={expiryDate} /\u003e\n          \u003cinput {...getCVCProps({ onChange: handleChangeCVC })} value={cvc} /\u003e\n          {meta.isTouched \u0026\u0026 meta.error \u0026\u0026 \u003cspan\u003eError: {meta.error}\u003c/span\u003e}\n        \u003c/div\u003e\n      )}\n    \u003c/PaymentInputsContainer\u003e\n  );\n}\n```\n\n\u003e **IMPORTANT:** You must place your event handlers (e.g. `onChange`, `onBlur`, etc) inside the prop getter function (e.g. `getCardNumberProps()`) so the default event handlers in React Payment Inputs don't get overridden.\n\n### Using the built-in styled wrapper\n\n\u003e Note: `\u003cPaymentInputsWrapper\u003e` requires [styled-components](https://styled-components.com) to be installed as a dependency.\n\nBy default, React Payment Inputs does not have built-in styling for it's inputs. However, React Payment Inputs comes with a styled wrapper which combines the card number, expiry \u0026 CVC fields seen below:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./assets/wrapper.gif\" width=\"500px\"\u003e\u003c/img\u003e\u003c/p\u003e\n\n```jsx\nimport React from 'react';\nimport { PaymentInputsWrapper, usePaymentInputs } from 'react-payment-inputs';\nimport images from 'react-payment-inputs/images';\n\nexport default function PaymentInputs() {\n  const {\n    wrapperProps,\n    getCardImageProps,\n    getCardNumberProps,\n    getExpiryDateProps,\n    getCVCProps\n  } = usePaymentInputs();\n\n  return (\n    \u003cPaymentInputsWrapper {...wrapperProps}\u003e\n      \u003csvg {...getCardImageProps({ images })} /\u003e\n      \u003cinput {...getCardNumberProps()} /\u003e\n      \u003cinput {...getExpiryDateProps()} /\u003e\n      \u003cinput {...getCVCProps()} /\u003e\n    \u003c/PaymentInputsWrapper\u003e\n  );\n}\n```\n\n### More examples\n\n- [Storybook](https://medipass.github.io/react-payment-inputs)\n  - [Source](./stories/index.stories.js)\n\n## `data = usePaymentInputs(options)`\n\n\u003e returns [an object (`data`)](#data)\n\n### options\n\n\u003e `Object({ cardNumberValidator, cvcValidator, errorMessages, expiryValidator, onBlur, onChange, onError, onTouch  })`\n\n#### options.cardNumberValidator\n\u003e `function({cardNumber, cardType, errorMessages})`\n\nSet custom card number validator function\n\n##### Example\n\n```js\nconst cardNumberValidator = ({ cardNumber, cardType, errorMessages }) =\u003e {\n  if (cardType.displayName === 'Visa' || cardType.displayName === 'Mastercard') {\n    return;\n  }\n  return 'Card must be Visa or Mastercard';\n}\n\nexport default function MyComponent() {\n  const { ... } = usePaymentInputs({\n    cardNumberValidator\n  });\n}\n```\n\n#### options.cvcValidator\n\u003e `function({cvc, cardType, errorMessages})`\n\nSet custom cvc validator function\n\n\n#### options.errorMessages\n\n\u003e `Object`\n\nSet custom error messages for the inputs.\n\n##### Example\n\n```js\nconst ERROR_MESSAGES = {\n  emptyCardNumber: 'El número de la tarjeta es inválido',\n  invalidCardNumber: 'El número de la tarjeta es inválido',\n  emptyExpiryDate: 'La fecha de expiración es inválida',\n  monthOutOfRange: 'El mes de expiración debe estar entre 01 y 12',\n  yearOutOfRange: 'El año de expiración no puede estar en el pasado',\n  dateOutOfRange: 'La fecha de expiración no puede estar en el pasado',\n  invalidExpiryDate: 'La fecha de expiración es inválida',\n  emptyCVC: 'El código de seguridad es inválido',\n  invalidCVC: 'El código de seguridad es inválido'\n}\n\nexport default function MyComponent() {\n  const { ... } = usePaymentInputs({\n    errorMessages: ERROR_MESSAGES\n  });\n}\n```\n\n#### options.expiryDateValidator\n\u003e `function({expiryDate, errorMessages})`\n\nSet custom expiry date validator function\n\n\n#### options.onBlur\n\n\u003e `function(event)`\n\nFunction to handle the blur event on the inputs. It is invoked when any of the inputs blur.\n\n#### options.onChange\n\n\u003e `function(event)`\n\nFunction to handle the change event on the inputs. It is invoked when any of the inputs change.\n\n#### options.onError\n\n\u003e `function(error, erroredInputs)`\n\nFunction to invoke when any of the inputs error.\n\n#### options.onTouch\n\n\u003e `function(touchedInput, touchedInputs)`\n\nFunction to invoke when any of the inputs are touched.\n\n### `data`\n\n#### getCardNumberProps\n\n\u003e `function(overrideProps)` | returns `Object\u003cprops\u003e`\n\nReturns the props to apply to the **card number** input.\n\n**IMPORTANT:** You must place your event handlers (e.g. `onChange`, `onBlur`, etc) inside the `getCardNumberProps()` so the default event handlers in React Payment Inputs don't get overridden.\n\n##### Example snippet\n\n```jsx\n\u003cinput {...getCardNumberProps({ onBlur: handleBlur, onChange: handleChange })} /\u003e\n```\n\n#### getExpiryDateProps\n\n\u003e `function(overrideProps)` | returns `Object\u003cprops\u003e`\n\nReturns the props to apply to the **expiry date** input.\n\n**IMPORTANT:** You must place your event handlers (e.g. `onChange`, `onBlur`, etc) inside the `getExpiryDateProps()` so the default event handlers in React Payment Inputs don't get overridden.\n\n##### Example snippet\n\n```jsx\n\u003cinput {...getExpiryDateProps({ onBlur: handleBlur, onChange: handleChange })} /\u003e\n```\n\n#### getCVCProps\n\n\u003e `function(overrideProps)` | returns `Object\u003cprops\u003e`\n\nReturns the props to apply to the **CVC** input.\n\n**IMPORTANT:** You must place your event handlers (e.g. `onChange`, `onBlur`, etc) inside the `getCVCProps()` so the default event handlers in React Payment Inputs don't get overridden.\n\n##### Example snippet\n\n```jsx\n\u003cinput {...getCVCProps({ onBlur: handleBlur, onChange: handleChange })} /\u003e\n```\n\n#### getZIPProps\n\n\u003e `function(overrideProps)` | returns `Object\u003cprops\u003e`\n\nReturns the props to apply to the **ZIP** input.\n\n**IMPORTANT:** You must place your event handlers (e.g. `onChange`, `onBlur`, etc) inside the `getZIPProps()` so the default event handlers in React Payment Inputs don't get overridden.\n\n##### Example snippet\n\n```jsx\n\u003cinput {...getZIPProps({ onBlur: handleBlur, onChange: handleChange })} /\u003e\n```\n\n#### getCardImageProps\n\n\u003e `function({ images })` | returns `Object\u003cprops\u003e`\n\nReturns the props to apply to the **card image** SVG.\n\nThis function only supports SVG elements currently. If you have a need for another format, please raise an issue.\n\nYou can also supply [custom card images](#custom-card-images) using the `images` attribute. The example below uses the default card images from React Payment Inputs.\n\n##### Example snippet\n\n```jsx\nimport images from 'react-payment-inputs/images';\n\n\u003csvg {...getCardImageProps({ images })} /\u003e\n```\n\n#### meta.cardType\n\n\u003e Object\n\nReturns information about the current card type, including: name, lengths and formats.\n\n##### Example snippet\n\n```jsx\nconst { meta } = usePaymentInputs();\n\n\u003cspan\u003eCurrent card: {meta.cardType.displayName}\u003c/span\u003e\n```\n\n#### meta.error\n\n\u003e string\n\nReturns the current global error between all rendered inputs.\n\n##### Example snippet\n\n```jsx\nconst { meta } = usePaymentInputs();\n\nconsole.log(meta.error); // \"Card number is invalid\"\n```\n\n#### meta.isTouched\n\n\u003e boolean\n\nReturns the current global touched state between all rendered inputs.\n\n#### meta.erroredInputs\n\n\u003e Object\n\nReturns the error message of each rendered input.\n\n##### Example snippet\n\n```jsx\nconst { meta } = usePaymentInputs();\n\nconsole.log(meta.erroredInputs);\n/*\n{\n  cardNumber: undefined,\n  expiryDate: 'Enter an expiry date',\n  cvc: 'Enter a CVC'\n}\n*/\n```\n\n#### meta.touchedInputs\n\n\u003e Object\n\nReturns the touch state of each rendered input.\n\n##### Example snippet\n\n```jsx\nconst { meta } = usePaymentInputs();\n\nconsole.log(meta.touchedInputs);\n/*\n{\n  cardNumber: true,\n  expiryDate: true,\n  cvc: false\n}\n*/\n```\n\n#### meta.focused\n\n\u003e string\n\nReturns the current focused input.\n\n```jsx\nconst { meta } = usePaymentInputs();\n\nconsole.log(meta.focused); // \"cardNumber\"\n```\n\n#### wrapperProps\n\n\u003e Object\n\nReturns the props to apply to `\u003cPaymentInputsWrapper\u003e`.\n\n## `\u003cPaymentInputsWrapper\u003e` props\n\n### styles\n\n\u003e Object\n\nCustom styling to pass through to the wrapper. Either a styled-component's `css` or an Object can be passed.\n\n#### Schema\n\n```\n{\n  fieldWrapper: {\n    base: css | Object,\n    errored: css | Object\n  },\n  inputWrapper: {\n    base: css | Object,\n    errored: css | Object,\n    focused: css | Object\n  },\n  input: {\n    base: css | Object,\n    errored: css | Object,\n    cardNumber: css | Object,\n    expiryDate: css | Object,\n    cvc: css | Object\n  },\n  errorText: {\n    base: css | Object\n  }\n}\n```\n\n### errorTextProps\n\n\u003e Object\n\nCustom props to pass to the error text component.\n\n### inputWrapperProps\n\n\u003e Object\n\nCustom props to pass to the input wrapper component.\n\n## Using a third-party UI library\n\nReact Payment Inputs allows you to integrate into pretty much any React UI library. Below are a couple of examples of how you can fit React Payment Inputs into a UI library using `usePaymentInputs`. You can also do the same with `\u003cPaymentInputsContainer\u003e`.\n\n### Fannypack\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./assets/fannypack.gif\" width=\"500px\"\u003e\u003c/img\u003e\u003c/p\u003e\n\n```jsx\nimport React from 'react';\nimport { FieldSet, InputField } from 'fannypack';\nimport { usePaymentInputs } from 'react-payment-inputs';\nimport images from 'react-payment-inputs/images';\n\nexport default function PaymentInputs() {\n  const {\n    meta,\n    getCardNumberProps,\n    getExpiryDateProps,\n    getCVCProps\n  } = usePaymentInputs();\n  const { erroredInputs, touchedInputs } = meta;\n\n  return (\n    \u003cFieldSet isHorizontal\u003e\n      \u003cInputField\n        // Here is where React Payment Inputs injects itself into the input element.\n        {...getCardNumberProps()}\n        placeholder=\"0000 0000 0000 0000\"\n        label=\"Card number\"\n        inputRef={getCardNumberProps().ref}\n        // You can retrieve error state by making use of the error \u0026 touched attributes in `meta`.\n        state={erroredInputs.cardNumber \u0026\u0026 touchedInputs.cardNumber ? 'danger' : undefined}\n        validationText={touchedInputs.cardNumber \u0026\u0026 erroredInputs.cardNumber}\n        maxWidth=\"15rem\"\n      /\u003e\n      \u003cInputField\n        {...getExpiryDateProps()}\n        label=\"Expiry date\"\n        inputRef={getExpiryDateProps().ref}\n        state={erroredInputs.expiryDate \u0026\u0026 touchedInputs.expiryDate ? 'danger' : undefined}\n        validationText={touchedInputs.expiryDate \u0026\u0026 erroredInputs.expiryDate}\n        maxWidth=\"8rem\"\n      /\u003e\n      \u003cInputField\n        {...getCVCProps()}\n        placeholder=\"123\"\n        label=\"CVC\"\n        inputRef={getCVCProps().ref}\n        state={erroredInputs.cvc \u0026\u0026 touchedInputs.cvc ? 'danger' : undefined}\n        validationText={touchedInputs.cvc \u0026\u0026 erroredInputs.cvc}\n        maxWidth=\"5rem\"\n      /\u003e\n    \u003c/FieldSet\u003e\n  );\n}\n```\n\n### Bootstrap\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./assets/bootstrap.gif\" width=\"500px\"\u003e\u003c/img\u003e\u003c/p\u003e\n\n```jsx\nimport React from 'react';\nimport { FieldSet, InputField } from 'fannypack';\nimport { usePaymentInputs } from 'react-payment-inputs';\nimport images from 'react-payment-inputs/images';\n\nexport default function PaymentInputs() {\n  const {\n    meta,\n    getCardNumberProps,\n    getExpiryDateProps,\n    getCVCProps\n  } = usePaymentInputs();\n  const { erroredInputs, touchedInputs } = meta;\n\n  return (\n    \u003cForm\u003e\n      \u003cForm.Row\u003e\n        \u003cForm.Group as={Col} style={{ maxWidth: '15rem' }}\u003e\n          \u003cForm.Label\u003eCard number\u003c/Form.Label\u003e\n          \u003cForm.Control\n            // Here is where React Payment Inputs injects itself into the input element.\n            {...getCardNumberProps()}\n            // You can retrieve error state by making use of the error \u0026 touched attributes in `meta`.\n            isInvalid={touchedInputs.cardNumber \u0026\u0026 erroredInputs.cardNumber}\n            placeholder=\"0000 0000 0000 0000\"\n          /\u003e\n          \u003cForm.Control.Feedback type=\"invalid\"\u003e{erroredInputs.cardNumber}\u003c/Form.Control.Feedback\u003e\n        \u003c/Form.Group\u003e\n        \u003cForm.Group as={Col} style={{ maxWidth: '10rem' }}\u003e\n          \u003cForm.Label\u003eExpiry date\u003c/Form.Label\u003e\n          \u003cForm.Control\n            {...getExpiryDateProps()}\n            isInvalid={touchedInputs.expiryDate \u0026\u0026 erroredInputs.expiryDate}\n          /\u003e\n          \u003cForm.Control.Feedback type=\"invalid\"\u003e{erroredInputs.expiryDate}\u003c/Form.Control.Feedback\u003e\n        \u003c/Form.Group\u003e\n        \u003cForm.Group as={Col} style={{ maxWidth: '7rem' }}\u003e\n          \u003cForm.Label\u003eCVC\u003c/Form.Label\u003e\n          \u003cForm.Control\n            {...getCVCProps()}\n            isInvalid={touchedInputs.cvc \u0026\u0026 erroredInputs.cvc}\n            placeholder=\"123\"\n          /\u003e\n          \u003cForm.Control.Feedback type=\"invalid\"\u003e{erroredInputs.cvc}\u003c/Form.Control.Feedback\u003e\n        \u003c/Form.Group\u003e\n      \u003c/Form.Row\u003e\n    \u003c/Form\u003e\n  );\n}\n```\n\n## Form library examples\n\nReact Payment Inputs has support for any type of React form library. Below are examples using [Formik](https://jaredpalmer.com/formik/) \u0026 [React Final Form](https://github.com/final-form/react-final-form).\n\n### Formik\n\n```jsx\nimport { Formik, Field } from 'formik';\nimport { PaymentInputsWrapper, usePaymentInputs } from 'react-payment-inputs';\n\nfunction PaymentForm() {\n  const {\n    meta,\n    getCardImageProps,\n    getCardNumberProps,\n    getExpiryDateProps,\n    getCVCProps,\n    wrapperProps\n  } = usePaymentInputs();\n\n  return (\n    \u003cFormik\n      initialValues={{\n        cardNumber: '',\n        expiryDate: '',\n        cvc: ''\n      }}\n      onSubmit={data =\u003e console.log(data)}\n      validate={() =\u003e {\n        let errors = {};\n        if (meta.erroredInputs.cardNumber) {\n          errors.cardNumber = meta.erroredInputs.cardNumber;\n        }\n        if (meta.erroredInputs.expiryDate) {\n          errors.expiryDate = meta.erroredInputs.expiryDate;\n        }\n        if (meta.erroredInputs.cvc) {\n          errors.cvc = meta.erroredInputs.cvc;\n        }\n        return errors;\n      }}\n    \u003e\n      {({ handleSubmit }) =\u003e (\n        \u003cform onSubmit={handleSubmit}\u003e\n          \u003cdiv\u003e\n            \u003cPaymentInputsWrapper {...wrapperProps}\u003e\n              \u003csvg {...getCardImageProps({ images })} /\u003e\n              \u003cField name=\"cardNumber\"\u003e\n                {({ field }) =\u003e (\n                  \u003cinput {...getCardNumberProps({ onBlur: field.onBlur, onChange: field.onChange })} /\u003e\n                )}\n              \u003c/Field\u003e\n              \u003cField name=\"expiryDate\"\u003e\n                {({ field }) =\u003e (\n                  \u003cinput {...getExpiryDateProps({ onBlur: field.onBlur, onChange: field.onChange })} /\u003e\n                )}\n              \u003c/Field\u003e\n              \u003cField name=\"cvc\"\u003e\n                {({ field }) =\u003e \u003cinput {...getCVCProps({ onBlur: field.onBlur, onChange: field.onChange })} /\u003e}\n              \u003c/Field\u003e\n            \u003c/PaymentInputsWrapper\u003e\n          \u003c/div\u003e\n          \u003cButton marginTop=\"major-2\" type=\"submit\"\u003e\n            Submit\n          \u003c/Button\u003e\n        \u003c/form\u003e\n      )}\n    \u003c/Formik\u003e\n  );\n}\n```\n\n[See this example in Storybook](https://medipass.github.io/react-payment-inputs/?path=/story/usepaymentinputs--using-a-form-library-formik)\n\n### React Final Form\n\n```jsx\nimport { Form, Field } from 'react-final-form';\nimport { PaymentInputsWrapper, usePaymentInputs } from 'react-payment-inputs';\n\nfunction PaymentForm() {\n  const {\n    meta,\n    getCardImageProps,\n    getCardNumberProps,\n    getExpiryDateProps,\n    getCVCProps,\n    wrapperProps\n  } = usePaymentInputs();\n\n  return (\n    \u003cForm\n      onSubmit={data =\u003e console.log(data)}\n      validate={() =\u003e {\n        let errors = {};\n        if (meta.erroredInputs.cardNumber) {\n          errors.cardNumber = meta.erroredInputs.cardNumber;\n        }\n        if (meta.erroredInputs.expiryDate) {\n          errors.expiryDate = meta.erroredInputs.expiryDate;\n        }\n        if (meta.erroredInputs.cvc) {\n          errors.cvc = meta.erroredInputs.cvc;\n        }\n        return errors;\n      }}\n    \u003e\n      {({ handleSubmit }) =\u003e (\n        \u003cform onSubmit={handleSubmit}\u003e\n          \u003cdiv\u003e\n            \u003cPaymentInputsWrapper {...wrapperProps}\u003e\n              \u003csvg {...getCardImageProps({ images })} /\u003e\n              \u003cField name=\"cardNumber\"\u003e\n                {({ input }) =\u003e (\n                  \u003cinput {...getCardNumberProps({ onBlur: input.onBlur, onChange: input.onChange })} /\u003e\n                )}\n              \u003c/Field\u003e\n              \u003cField name=\"expiryDate\"\u003e\n                {({ input }) =\u003e (\n                  \u003cinput {...getExpiryDateProps({ onBlur: input.onBlur, onChange: input.onChange })} /\u003e\n                )}\n              \u003c/Field\u003e\n              \u003cField name=\"cvc\"\u003e\n                {({ input }) =\u003e \u003cinput {...getCVCProps({ onBlur: input.onBlur, onChange: input.onChange })} /\u003e}\n              \u003c/Field\u003e\n            \u003c/PaymentInputsWrapper\u003e\n          \u003c/div\u003e\n          \u003cButton marginTop=\"major-2\" type=\"submit\"\u003e\n            Submit\n          \u003c/Button\u003e\n        \u003c/form\u003e\n      )}\n    \u003c/Form\u003e\n  );\n}\n```\n\n[See this example in Storybook](https://medipass.github.io/react-payment-inputs/?path=/story/usepaymentinputs--using-a-form-library-react-final-form)\n\n## Customising the in-built style wrapper\n\nReact Payment Input's default style wrapper can be customized by supplying a `styles` prop.\n\n```jsx\nimport { css } from 'styled-components';\nimport { usePaymentInputs, PaymentInputsWrapper } from 'react-payment-inputs';\n\nfunction PaymentForm() {\n  const {\n    getCardNumberProps,\n    getExpiryDateProps,\n    getCVCProps,\n    wrapperProps\n  } = usePaymentInputs();\n\n  return (\n    \u003cPaymentInputsWrapper\n      {...wrapperProps}\n      styles={{\n        fieldWrapper: {\n          base: css`\n            margin-bottom: 1rem;\n          `\n        },\n        inputWrapper: {\n          base: css`\n            border-color: green;\n          `,\n          errored: css`\n            border-color: maroon;\n          `,\n          focused: css`\n            border-color: unset;\n            box-shadow: unset;\n            outline: 2px solid blue;\n            outline-offset: 2px;\n          `\n        },\n        input: {\n          base: css`\n            color: green;\n          `,\n          errored: css`\n            color: maroon;\n          `,\n          cardNumber: css`\n            width: 15rem;\n          `,\n          expiryDate: css`\n            width: 10rem;\n          `,\n          cvc: css`\n            width: 5rem;\n          `\n        },\n        errorText: {\n          base: css`\n            color: maroon;\n          `\n        }\n      }}\n    \u003e\n      \u003cinput {...getCardNumberProps()} /\u003e\n      \u003cinput {...getExpiryDateProps()} /\u003e\n      \u003cinput {...getCVCProps()} /\u003e\n    \u003c/PaymentInputsWrapper\u003e\n  );\n}\n```\n\n[See the example on Storybook](https://medipass.github.io/react-payment-inputs/?path=/story/usepaymentinputs--styled-wrapper-with-custom-styling)\n\n## Custom card images\n\nThe card images can be customized by passing the `images` attribute to `getCardImageProps({ images })`. The `images` object must consist of SVG paths.\n\n```jsx\nimport { css } from 'styled-components';\nimport { usePaymentInputs, PaymentInputsWrapper } from 'react-payment-inputs';\n\nconst images = {\n  mastercard: (\n    \u003cg fill=\"none\" fillRule=\"evenodd\"\u003e\n      \u003crect fill=\"#252525\" height=\"16\" rx=\"2\" width=\"24\" /\u003e\n      \u003ccircle cx=\"9\" cy=\"8\" fill=\"#eb001b\" r=\"5\" /\u003e\n      \u003ccircle cx=\"15\" cy=\"8\" fill=\"#f79e1b\" r=\"5\" /\u003e\n      \u003cpath\n        d=\"m12 3.99963381c1.2144467.91220633 2 2.36454836 2 4.00036619s-.7855533 3.0881599-2 4.0003662c-1.2144467-.9122063-2-2.36454837-2-4.0003662s.7855533-3.08815986 2-4.00036619z\"\n        fill=\"#ff5f00\"\n      /\u003e\n    \u003c/g\u003e\n  )\n}\n\nfunction PaymentForm() {\n  const {\n    getCardNumberProps,\n    getExpiryDateProps,\n    getCVCProps,\n    getCardImageProps,\n    wrapperProps\n  } = usePaymentInputs();\n\n  return (\n    \u003cPaymentInputsWrapper {...wrapperProps}\u003e\n      \u003csvg {...getCardImageProps({ images })} /\u003e\n      \u003cinput {...getCardNumberProps()} /\u003e\n      \u003cinput {...getExpiryDateProps()} /\u003e\n      \u003cinput {...getCVCProps()} /\u003e\n    \u003c/PaymentInputsWrapper\u003e\n  );\n}\n```\n\n## License\n\nMIT © [Medipass Solutions Pty. Ltd.](https://github.com/medipass)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedipass%2Freact-payment-inputs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmedipass%2Freact-payment-inputs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedipass%2Freact-payment-inputs/lists"}