📟 PIN Field

Native web component for entering PIN codes.

$ npm i @soywod/pin-field

Basic

Source code
<swd-pin-field></swd-pin-field>

Custom length

The length of the field can be customized via the length attribute/property (default to 5).

Source code
<swd-pin-field length="3"></swd-pin-field>

Custom validation

The validation can be handled by a string of allowed chars (attribute), a regex (property), or a function (property).

Only numbers:

Source code
<swd-pin-field validate="0123456789"></swd-pin-field>

Custom formatter

Resolved keys can be formatted with the format prop.

All uppercase:

Source code
<swd-pin-field id="field"></swd-pin-field>

const field = document.getElementById("field");
field.format = key => key.toUpperCase();

Custom events

Source code
<swd-pin-field id="field"></swd-pin-field>

const field = document.getElementById("field");
field.addEventListener("change", evt => alert(`PIN Field changed: ${evt.detail.value}`));
field.addEventListener("complete", evt => alert(`PIN Field completed: ${evt.detail.value}`));
field.addEventListener("resolve", evt => alert(`PIN Field key resolved: ${evt.detail.key}`));
field.addEventListener("reject", evt => alert(`PIN Field key resolved: ${evt.detail.key}`));

Custom style

The field can be customized with the class and style attributes. Standard validation pseudo-classes :valid and :invalid can also be used. Since there is no :complete pseudo-classe, the field exposes a custom attribute completed to match with disabled.

Source code
<swd-pin-field
  class="pin-field"
  type="password"
  autocapitalize="off"
  autocorrect="off"
  autocomplete="off"
  inputmode="text"
></swd-pin-field>

.pin-field {
  background-color: rgb(248, 249, 250);
  border: 1px solid rgb(204, 204, 204);
  border-radius: 0.3rem;
  font-size: 2rem;
  margin: 0.25rem;
  height: 3.5rem;
  outline: none;
  text-align: center;
  transition-duration: 250ms;
  transition-property: background, color, border, box-shadow, transform;
  width: 3rem;
}

.pin-field:focus {
  border-color: rgb(0, 123, 255);
  outline: none;
  transform: scale(1.05);
}

.pin-field:invalid {
  animation: shake 3 linear 75ms;
  border-color: rgb(220, 53, 69);
  box-shadow: 0 0 0.25rem rgba(220, 53, 69, 0.5);
}

swd-pin-field[completed] .pin-field {
  border-color: rgb(40, 167, 69);
  background-color: rgba(40, 167, 69, 0.25);
}

@keyframes shake {
  from {
    transform: scale(1.05) translateY(-5%);
  }
  to {
    transform: scale(1.05) translateY(5%);
  }
}