diff --git a/playbook/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.jsx b/playbook/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.jsx
index 3af05e3036..887fdd9176 100755
--- a/playbook/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.jsx
+++ b/playbook/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.jsx
@@ -16,6 +16,8 @@ const TextInputMask = (props) => {
zipCode: '',
postalCode: '',
ssn: '',
+ creditCard: '',
+ cvv: ''
})
const handleOnChangeFormField = ({ target }) => {
@@ -57,6 +59,22 @@ const TextInputMask = (props) => {
value={formFields.ssn}
{...props}
/>
+
+
diff --git a/playbook/app/pb_kits/playbook/pb_text_input/inputMask.ts b/playbook/app/pb_kits/playbook/pb_text_input/inputMask.ts
index 3b80cbb262..db7088fa23 100644
--- a/playbook/app/pb_kits/playbook/pb_text_input/inputMask.ts
+++ b/playbook/app/pb_kits/playbook/pb_text_input/inputMask.ts
@@ -6,7 +6,7 @@ type InputMask = {
}
type InputMaskDictionary = {
- [key in 'currency' | 'zipCode' | 'postalCode' | 'ssn']: InputMask
+ [key in 'currency' | 'zipCode' | 'postalCode' | 'ssn' | 'creditCard' | 'cvv']: InputMask
}
const formatCurrencyDefaultValue = (value: string): string => {
@@ -58,6 +58,15 @@ const formatSSN = (value: string): string => {
.replace(/(\d{3})(?=\d)/, '$1-')
}
+const formatCreditCard = (value: string): string => {
+ const cleaned = value.replace(/\D/g, '').slice(0, 16)
+ return cleaned.replace(/(\d{4})(?=\d)/g, '$1 ')
+}
+
+const formatCVV = (value: string): string => {
+ return value.replace(/\D/g, '').slice(0, 4)
+}
+
export const INPUTMASKS: InputMaskDictionary = {
currency: {
format: formatCurrency,
@@ -84,4 +93,16 @@ export const INPUTMASKS: InputMaskDictionary = {
pattern: '\\d{3}-\\d{2}-\\d{4}',
placeholder: '123-45-6789',
},
+ creditCard: {
+ format: formatCreditCard,
+ formatDefaultValue: formatCreditCard,
+ pattern: '\\d{4} \\d{4} \\d{4} \\d{4}',
+ placeholder: '1234 5678 9012 3456',
+ },
+ cvv: {
+ format: formatCVV,
+ formatDefaultValue: formatCVV,
+ pattern: '\\d{3,4}',
+ placeholder: '123',
+ },
}
diff --git a/playbook/app/pb_kits/playbook/pb_text_input/text_input.test.js b/playbook/app/pb_kits/playbook/pb_text_input/text_input.test.js
index d901dd55f5..8f678a9311 100644
--- a/playbook/app/pb_kits/playbook/pb_text_input/text_input.test.js
+++ b/playbook/app/pb_kits/playbook/pb_text_input/text_input.test.js
@@ -226,3 +226,83 @@ test('returns masked ssn value', () => {
expect(input.value).toBe('123-45-6789')
})
+
+const TextInputCreditCardMask = (props) => {
+ const [creditCard, setValue] = useState('')
+ const handleOnChange = ({ target }) => {
+ setValue(target.value)
+ }
+
+ return (
+
+ )
+}
+
+test('returns masked credit card value', () => {
+ render(
+
+ )
+
+ const kit = screen.getByTestId(testId)
+
+ const input = within(kit).getByRole('textbox')
+
+ fireEvent.change(input, { target: { value: '1234567890123456' } })
+
+ expect(input.value).toBe('1234 5678 9012 3456')
+
+ fireEvent.change(input, { target: { value: '1234' } })
+
+ expect(input.value).toBe('1234')
+
+ fireEvent.change(input, { target: { value: '' } })
+
+ expect(input.value).toBe('')
+})
+
+const TextInputCVVMask = (props) => {
+ const [cvv, setValue] = useState('')
+ const handleOnChange = ({ target }) => {
+ setValue(target.value)
+ }
+
+ return (
+
+ )
+}
+
+test('returns masked CVV value', () => {
+ render(
+
+ )
+
+ const kit = screen.getByTestId(testId)
+
+ const input = within(kit).getByRole('textbox')
+
+ fireEvent.change(input, { target: { value: '1234' } })
+
+ expect(input.value).toBe('1234')
+
+ fireEvent.change(input, { target: { value: '123' } })
+
+ expect(input.value).toBe('123')
+
+ fireEvent.change(input, { target: { value: '' } })
+
+ expect(input.value).toBe('')
+})