Skip to content

Commit

Permalink
[PLAY-1866] Mask Use PBenahcnedElement (#4201)
Browse files Browse the repository at this point in the history
Runway [PLAY-1866](https://runway.powerhrg.com/backlog_items/PLAY-1866)
Alpha powerhome/nitro-web#45790

The input mask isn't working in Nitro because Nitro wasn't expecting the
JS module to be the new pattern Mark made in

I changed it to use our PbEnhancedElement kit
  • Loading branch information
markdoeswork authored Feb 7, 2025
1 parent 1f59b48 commit 15b964b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
margin_bottom: "md",
name: "currency_name",
id: "example-currency",
placeholder: "$0.00",
value: "$99.99",
}) %>

<style>
Expand Down
135 changes: 52 additions & 83 deletions playbook/app/pb_kits/playbook/pb_text_input/index.js
Original file line number Diff line number Diff line change
@@ -1,102 +1,71 @@
export default class PbTextInput {
static start() {
const inputElements = document.querySelectorAll('[data-pb-input-mask="true"]');

inputElements.forEach((inputElement) => {
inputElement.addEventListener("input", (event) => {
const maskType = inputElement.getAttribute("mask");
const cursorPosition = inputElement.selectionStart;

let rawValue = event.target.value;
let formattedValue = rawValue;

// Apply formatting based on the mask type
switch (maskType) {
case "currency":
formattedValue = formatCurrency(rawValue);
break;
case "ssn":
formattedValue = formatSSN(rawValue);
break;
case "postal_code":
formattedValue = formatPostalCode(rawValue);
break;
case "zip_code":
formattedValue = formatZipCode(rawValue);
break;
}

// Update the sanitized input field in the same wrapper
const sanitizedInput = inputElement
.closest(".text_input_wrapper")
?.querySelector('[data="sanitized-pb-input"]');

if (sanitizedInput) {
switch (maskType) {
case "ssn":
sanitizedInput.value = sanitizeSSN(formattedValue);
break;
case "currency":
sanitizedInput.value = sanitizeCurrency(formattedValue);
break;
default:
sanitizedInput.value = formattedValue;
}
}

inputElement.value = formattedValue;
setCursorPosition(inputElement, cursorPosition, rawValue, formattedValue);
});
});
import PbEnhancedElement from "../pb_enhanced_element"
import { INPUTMASKS } from "./inputMask"

export default class PbTextInput extends PbEnhancedElement {
static get selector() {
return '[data-pb-input-mask="true"]';
}
}

function formatCurrency(value) {
const numericValue = value.replace(/[^0-9]/g, "").slice(0, 15);

if (!numericValue) return "";

const dollars = parseFloat((parseInt(numericValue) / 100).toFixed(2));
if (dollars === 0) return "";

return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 2,
}).format(dollars);
}

function formatSSN(value) {
const cleaned = value.replace(/\D/g, "").slice(0, 9);
return cleaned
.replace(/(\d{5})(?=\d)/, "$1-")
.replace(/(\d{3})(?=\d)/, "$1-");
}
connect() {
this.handleInput = this.handleInput.bind(this);
this.element.addEventListener("input", this.handleInput);
this.handleInput();
}

function formatZipCode(value) {
return value.replace(/\D/g, "").slice(0, 5);
}
disconnect() {
this.element.removeEventListener("input", this.handleInput);
}

function formatPostalCode(value) {
const cleaned = value.replace(/\D/g, "").slice(0, 9);
return cleaned.replace(/(\d{5})(?=\d)/, "$1-");
handleInput() {
const maskType = this.element.getAttribute("mask");
const cursorPosition = this.element.selectionStart;
const rawValue = this.element.value;
let formattedValue = rawValue;

const maskKey = {
currency: 'currency',
ssn: 'ssn',
postal_code: 'postalCode',
zip_code: 'zipCode',
}[maskType];

if (maskKey && INPUTMASKS[maskKey]) {
formattedValue = INPUTMASKS[maskKey].format(rawValue);
}

const sanitizedInput = this.element
.closest(".text_input_wrapper")
?.querySelector('[data="sanitized-pb-input"]');

if (sanitizedInput) {
switch (maskType) {
case "ssn":
sanitizedInput.value = sanitizeSSN(formattedValue);
break;
case "currency":
sanitizedInput.value = sanitizeCurrency(formattedValue);
break;
default:
sanitizedInput.value = formattedValue;
}
}

this.element.value = formattedValue;
setCursorPosition(this.element, cursorPosition, rawValue, formattedValue);
}
}

function sanitizeSSN(input) {
return input.replace(/\D/g, "");
return input.replace(/\D/g, "");
}

function sanitizeCurrency(input) {
return input.replace(/[$,]/g, "");
return input.replace(/[$,]/g, "");
}

// function to set cursor position
function setCursorPosition(inputElement, cursorPosition, rawValue, formattedValue) {
const difference = formattedValue.length - rawValue.length;

const newPosition = Math.max(0, cursorPosition + difference);

requestAnimationFrame(() => {
inputElement.setSelectionRange(newPosition, newPosition);
});
Expand Down

0 comments on commit 15b964b

Please sign in to comment.