JSFiddle - React, Tailwind, and code Playground

by VeryGoodFiddle

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>VGS Collect Credit Card Example</title>

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

  <!--Replace with generated for your organization JS file.-->
  <script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/1/vgs-collect-examples.js"></script>

</head>
<body>
<main>
  <div class="row">
    <div class="col-md-2"></div>
    <div class="col-md-4">
      <div class="row card card-outline-secondary">
        <div class="card-body">
          <h3 class="text-center">Credit Card Payment</h3>
          <hr>
          <div class="alert alert-info p-2">
            Please fill in and submit a form to see redacted data in response window.
          </div>
          <form id="cc-form">
            <div class="form-group">
              <label for="cc-name">Name</label>
              <span id="cc-name" class="form-field">
                <!--VGS Collect iframe for card name field will be here!-->
              </span>
            </div>
            <div class="form-group">
              <label for="cc-number">Card number</label>
              <span id="cc-number" class="form-field">
                <!--VGS Collect iframe for card number field will be here!-->
              </span>
            </div>
            <div class="form-group">
              <label for="cc-cvc">CVC</label>
              <span id="cc-cvc" class="form-field">
              <!--VGS Collect iframe for CVC field will be here!-->
              </span>
            </div>
            <div class="form-group">
              <label for="cc-expiration-date">Expiration date</label>
              <span id="cc-expiration-date" class="form-field">
              <!--VGS Collect iframe for expiration date field will be here!-->
              </span>
    ...

CSS

body {
  padding: 25px;
}

span[id*="cc-"] {
  display: block;
  height: 40px;
  margin-bottom: 15px;
}

span[id*="cc-"] iframe {
  height: 100%;
  width: 100%;
}

pre {
  font-size: 12px;
}

.form-field {
  display: block;
  width: 100%;
  height: calc(2.25rem + 2px);
  padding: .375rem .75rem;
  font-size: 1rem;
  line-height: 1.5;
  color: #495057;
  background-color: #fff;
  background-clip: padding-box;
  border: 1px solid #ced4da;
  border-radius: .25rem;
  transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}

.form-field iframe {
  border: 0 none transparent;
  height: 100%;
  vertical-align: middle;
  width: 100%;
}

p {
  margin-bottom: 10px;
}

JavaScript

const form = VGSCollect.create('tntq4dwvhri', function(state) {
 const form = VGSCollect.create('tntq4dwvhri', function(state) {
    for (const key in state) {
      if (state.hasOwnProperty(key)) {
        if(state[key].errorMessages.length === 0) {
          const elem = document.getElementById(key);
          elem.classList.remove('focus-invalid');
          document.querySelector('#' + focusedField + ' ~ .error-message').innerHTML = '';
        }
        if (state[key].isFocused) {
          const elem = document.getElementById(key);
          // handle first focus
          if (!focusedField) {
            focusedField = key;
            elem.classList.add('focus-valid');
          } else if (focusedField !== key) {
            const prevFocused = document.getElementById(focusedField);
            const error = document.querySelector('#' + focusedField + ' ~ .error-message');
            // if previous focused field is invalid
            if( state[focusedField].errorMessages.length !== 0) {
              if(!state[focusedField].isEmpty) {
                error.innerHTML = state[focusedField].errorMessages[0];
                prevFocused.classList.remove('focus-valid');
                prevFocused.classList.add('focus-invalid');
              }
            } // if previous focused field is valid
            else if (state[focusedField].errorMessages.length === 0) {
              error.innerHTML = '';
              prevFocused.classList.remove('focus-invalid');
              prevFocused.classList.add('focus-valid');
            }
            focusedField = key;
            elem.classList.add('focus-valid');
          }
        }
      }
    }
  });
 });

  // Create VGS Collect field for credit card name
  form.field('#cc-name', {
    type: 'text',
    name: 'card_name',
    placeholder: 'Joe Business',
    validations: ['required'],
    autoComplete: 'cc-name',
  });

  // Create VGS Collect field for credit card number
  form.field('#cc-number', {
    type:...