playbook_ui 14.9.0.pre.alpha.play1742globalheightfixes4925 → 14.9.0.pre.alpha.play17004992
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +2 -2
- data/app/pb_kits/playbook/pb_layout/_layout.tsx +11 -30
- data/app/pb_kits/playbook/pb_section_separator/_section_separator.scss +4 -1
- data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +35 -3
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.jsx +88 -0
- data/app/pb_kits/playbook/pb_text_input/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_text_input/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_text_input/inputMask.ts +64 -0
- data/app/pb_kits/playbook/pb_text_input/text_input.test.js +139 -2
- data/dist/chunks/{_typeahead-D-DFD48D.js → _typeahead-l1kq1p9m.js} +1 -1
- data/dist/chunks/{_weekday_stacked-CCO9Egzl.js → _weekday_stacked-B28kYXl9.js} +2 -2
- data/dist/chunks/vendor.js +1 -1
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 585093eef9e79407e25a130a2a77f097c248bc2884116fc21bc9946c53b4cfe0
|
4
|
+
data.tar.gz: 82327cf34bd6c8b448e67549d84243c17622d2382ee07efa8730e13544c36be1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e62d590332efe256a1464c1a2dfb104cb6078ddae7003114d656b016921f4252537ce52c78265b8ab27c4bca5e1dd0c93344d32080bfc2183e75cad551d1ace0
|
7
|
+
data.tar.gz: 6935b07d0cadec5f1156367e0488ce352aaf2cacbe7d9310b10b064db8428e4801e4ba7805c66a53dc68a313c5ea2be87219684465c0a4f09712c5fcc057c1a3
|
@@ -287,6 +287,7 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
|
|
287
287
|
{...ariaProps}
|
288
288
|
{...dataProps}
|
289
289
|
{...htmlProps}
|
290
|
+
style={dynamicInlineProps}
|
290
291
|
className={classnames(drawerClassNames.base, {
|
291
292
|
[drawerClassNames.afterOpen]:
|
292
293
|
animationState === "afterOpen",
|
@@ -295,7 +296,6 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
|
|
295
296
|
})}
|
296
297
|
id={id}
|
297
298
|
onClick={(e) => e.stopPropagation()}
|
298
|
-
style={dynamicInlineProps}
|
299
299
|
>
|
300
300
|
{children}
|
301
301
|
</div>
|
@@ -306,6 +306,7 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
|
|
306
306
|
{...dataProps}
|
307
307
|
{...htmlProps}
|
308
308
|
className={classes}
|
309
|
+
style={dynamicInlineProps}
|
309
310
|
>
|
310
311
|
{isModalVisible && (
|
311
312
|
<div
|
@@ -326,7 +327,6 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
|
|
326
327
|
animationState === "beforeClose",
|
327
328
|
})}
|
328
329
|
onClick={(e) => e.stopPropagation()}
|
329
|
-
style={dynamicInlineProps}
|
330
330
|
>
|
331
331
|
{children}
|
332
332
|
</div>
|
@@ -24,37 +24,34 @@ type LayoutPropTypes = {
|
|
24
24
|
type LayoutSideProps = {
|
25
25
|
children: React.ReactNode[] | React.ReactNode,
|
26
26
|
className?: string,
|
27
|
-
}
|
27
|
+
}
|
28
28
|
|
29
29
|
type LayoutBodyProps = {
|
30
30
|
children: React.ReactNode[] | React.ReactNode,
|
31
31
|
className?: string,
|
32
|
-
}
|
32
|
+
}
|
33
33
|
|
34
34
|
type LayoutItemProps = {
|
35
35
|
children: React.ReactNode[] | React.ReactNode,
|
36
36
|
className?: string,
|
37
37
|
size?: "sm" | "md" | "lg"
|
38
|
-
}
|
38
|
+
}
|
39
39
|
|
40
40
|
type LayoutHeaderProps = {
|
41
41
|
children: React.ReactNode[] | React.ReactNode,
|
42
42
|
className?: string,
|
43
|
-
}
|
43
|
+
}
|
44
44
|
|
45
45
|
type LayoutFooterProps = {
|
46
46
|
children: React.ReactNode[] | React.ReactNode,
|
47
47
|
className?: string,
|
48
|
-
}
|
48
|
+
}
|
49
49
|
|
50
|
+
// Side component
|
50
51
|
const Side = (props: LayoutSideProps) => {
|
51
52
|
const { children, className } = props
|
52
|
-
const dynamicInlineProps = globalInlineProps(props)
|
53
53
|
return (
|
54
|
-
<div
|
55
|
-
className={classnames('layout_sidebar', globalProps(props), className)}
|
56
|
-
style={dynamicInlineProps}
|
57
|
-
>
|
54
|
+
<div className={classnames('layout_sidebar', globalProps(props), className)}>
|
58
55
|
{children}
|
59
56
|
</div>
|
60
57
|
)
|
@@ -63,12 +60,8 @@ const Side = (props: LayoutSideProps) => {
|
|
63
60
|
// Body component
|
64
61
|
const Body = (props: LayoutBodyProps) => {
|
65
62
|
const { children, className } = props
|
66
|
-
const dynamicInlineProps = globalInlineProps(props)
|
67
63
|
return (
|
68
|
-
<div
|
69
|
-
className={classnames('layout_body', globalProps(props), className)}
|
70
|
-
style={dynamicInlineProps}
|
71
|
-
>
|
64
|
+
<div className={classnames('layout_body', globalProps(props), className)}>
|
72
65
|
{children}
|
73
66
|
</div>
|
74
67
|
)
|
@@ -78,12 +71,8 @@ const Body = (props: LayoutBodyProps) => {
|
|
78
71
|
const Item = (props: LayoutItemProps) => {
|
79
72
|
const { children, className, size = 'sm' } = props
|
80
73
|
const sizeClass = `size_${size}`
|
81
|
-
const dynamicInlineProps = globalInlineProps(props)
|
82
74
|
return (
|
83
|
-
<div
|
84
|
-
className={classnames('layout_item', sizeClass, globalProps(props), className)}
|
85
|
-
style={dynamicInlineProps}
|
86
|
-
>
|
75
|
+
<div className={classnames('layout_item', sizeClass, globalProps(props), className)}>
|
87
76
|
{children}
|
88
77
|
</div>
|
89
78
|
)
|
@@ -92,12 +81,8 @@ const Item = (props: LayoutItemProps) => {
|
|
92
81
|
// Header component
|
93
82
|
const Header = (props: LayoutHeaderProps) => {
|
94
83
|
const { children, className } = props
|
95
|
-
const dynamicInlineProps = globalInlineProps(props)
|
96
84
|
return (
|
97
|
-
<div
|
98
|
-
className={classnames('layout_header', globalProps(props), className)}
|
99
|
-
style={dynamicInlineProps}
|
100
|
-
>
|
85
|
+
<div className={classnames('layout_header', globalProps(props), className)}>
|
101
86
|
{children}
|
102
87
|
</div>
|
103
88
|
)
|
@@ -106,12 +91,8 @@ const Header = (props: LayoutHeaderProps) => {
|
|
106
91
|
// Footer component
|
107
92
|
const Footer = (props: LayoutFooterProps) => {
|
108
93
|
const { children, className } = props
|
109
|
-
const dynamicInlineProps = globalInlineProps(props)
|
110
94
|
return (
|
111
|
-
<div
|
112
|
-
className={classnames('layout_footer', globalProps(props), className)}
|
113
|
-
style={dynamicInlineProps}
|
114
|
-
>
|
95
|
+
<div className={classnames('layout_footer', globalProps(props), className)}>
|
115
96
|
{children}
|
116
97
|
</div>
|
117
98
|
)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { forwardRef } from 'react'
|
1
|
+
import React, { forwardRef, ChangeEvent } from 'react'
|
2
2
|
import classnames from 'classnames'
|
3
3
|
|
4
4
|
import { globalProps, GlobalProps, domSafeProps } from '../utilities/globalProps'
|
@@ -10,6 +10,8 @@ import Caption from '../pb_caption/_caption'
|
|
10
10
|
import Body from '../pb_body/_body'
|
11
11
|
import Icon from '../pb_icon/_icon'
|
12
12
|
|
13
|
+
import { INPUTMASKS } from './inputMask'
|
14
|
+
|
13
15
|
type TextInputProps = {
|
14
16
|
aria?: { [key: string]: string },
|
15
17
|
className?: string,
|
@@ -22,6 +24,7 @@ type TextInputProps = {
|
|
22
24
|
inline?: boolean,
|
23
25
|
name: string,
|
24
26
|
label: string,
|
27
|
+
mask?: 'currency' | 'zipCode' | 'postalCode' | 'ssn',
|
25
28
|
onChange: (e: React.FormEvent<HTMLInputElement>) => void,
|
26
29
|
placeholder: string,
|
27
30
|
required?: boolean,
|
@@ -47,6 +50,7 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
|
|
47
50
|
htmlOptions = {},
|
48
51
|
id,
|
49
52
|
inline = false,
|
53
|
+
mask = null,
|
50
54
|
name,
|
51
55
|
label,
|
52
56
|
onChange = () => { void 0 },
|
@@ -90,6 +94,33 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
|
|
90
94
|
/>
|
91
95
|
)
|
92
96
|
|
97
|
+
const isMaskedInput = mask && mask in INPUTMASKS
|
98
|
+
|
99
|
+
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
100
|
+
if (isMaskedInput) {
|
101
|
+
const inputValue = e.target.value
|
102
|
+
|
103
|
+
let cursorPosition = e.target.selectionStart;
|
104
|
+
const isAtEnd = cursorPosition === inputValue.length;
|
105
|
+
|
106
|
+
const formattedValue = INPUTMASKS[mask].format(inputValue)
|
107
|
+
e.target.value = formattedValue
|
108
|
+
|
109
|
+
// Keep cursor position
|
110
|
+
if (!isAtEnd) {
|
111
|
+
// Account for extra characters (e.g., commas added/removed in currency)
|
112
|
+
if (formattedValue.length - inputValue.length === 1) {
|
113
|
+
cursorPosition = cursorPosition + 1
|
114
|
+
} else if (mask === "currency" && formattedValue.length - inputValue.length === -1) {
|
115
|
+
cursorPosition = cursorPosition - 1
|
116
|
+
}
|
117
|
+
e.target.selectionStart = e.target.selectionEnd = cursorPosition
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
onChange(e)
|
122
|
+
}
|
123
|
+
|
93
124
|
const childInput = children ? children.type === "input" : undefined
|
94
125
|
|
95
126
|
const textInput = (
|
@@ -101,8 +132,9 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
|
|
101
132
|
id={id}
|
102
133
|
key={id}
|
103
134
|
name={name}
|
104
|
-
onChange={onChange}
|
105
|
-
|
135
|
+
onChange={isMaskedInput ? handleChange : onChange}
|
136
|
+
pattern={isMaskedInput ? INPUTMASKS[mask]?.pattern : undefined}
|
137
|
+
placeholder={placeholder || (isMaskedInput ? INPUTMASKS[mask]?.placeholder : undefined)}
|
106
138
|
ref={ref}
|
107
139
|
required={required}
|
108
140
|
type={type}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
|
3
|
+
import Caption from '../../pb_caption/_caption'
|
4
|
+
import TextInput from '../../pb_text_input/_text_input'
|
5
|
+
import Title from '../../pb_title/_title'
|
6
|
+
|
7
|
+
const TextInputMask = (props) => {
|
8
|
+
const [ssn, setSSN] = useState('')
|
9
|
+
const handleOnChangeSSN = ({ target }) => {
|
10
|
+
setSSN(target.value)
|
11
|
+
}
|
12
|
+
const ref = React.createRef()
|
13
|
+
|
14
|
+
const [formFields, setFormFields] = useState({
|
15
|
+
currency: '',
|
16
|
+
zipCode: '',
|
17
|
+
postalCode: '',
|
18
|
+
ssn: '',
|
19
|
+
})
|
20
|
+
|
21
|
+
const handleOnChangeFormField = ({ target }) => {
|
22
|
+
const { name, value } = target
|
23
|
+
setFormFields({ ...formFields, [name]: value })
|
24
|
+
}
|
25
|
+
|
26
|
+
return (
|
27
|
+
<div>
|
28
|
+
<TextInput
|
29
|
+
label="Currency"
|
30
|
+
mask="currency"
|
31
|
+
name="currency"
|
32
|
+
onChange={handleOnChangeFormField}
|
33
|
+
value={formFields.currency}
|
34
|
+
{...props}
|
35
|
+
/>
|
36
|
+
<TextInput
|
37
|
+
label="Zip Code"
|
38
|
+
mask="zipCode"
|
39
|
+
name="zipCode"
|
40
|
+
onChange={handleOnChangeFormField}
|
41
|
+
value={formFields.zipCode}
|
42
|
+
{...props}
|
43
|
+
/>
|
44
|
+
<TextInput
|
45
|
+
label="Postal Code"
|
46
|
+
mask="postalCode"
|
47
|
+
name="postalCode"
|
48
|
+
onChange={handleOnChangeFormField}
|
49
|
+
value={formFields.postalCode}
|
50
|
+
{...props}
|
51
|
+
/>
|
52
|
+
<TextInput
|
53
|
+
label="SSN"
|
54
|
+
mask="ssn"
|
55
|
+
name="ssn"
|
56
|
+
onChange={handleOnChangeFormField}
|
57
|
+
value={formFields.ssn}
|
58
|
+
{...props}
|
59
|
+
/>
|
60
|
+
|
61
|
+
<br />
|
62
|
+
<br />
|
63
|
+
|
64
|
+
<Title>{'Event Handler Props'}</Title>
|
65
|
+
|
66
|
+
<br />
|
67
|
+
<Caption>{'onChange'}</Caption>
|
68
|
+
|
69
|
+
<br />
|
70
|
+
|
71
|
+
<TextInput
|
72
|
+
label="SSN"
|
73
|
+
mask="ssn"
|
74
|
+
onChange={handleOnChangeSSN}
|
75
|
+
placeholder="Enter SSN"
|
76
|
+
ref={ref}
|
77
|
+
value={ssn}
|
78
|
+
{...props}
|
79
|
+
/>
|
80
|
+
|
81
|
+
{ssn !== '' && (
|
82
|
+
<React.Fragment>{`SSN is: ${ssn}`}</React.Fragment>
|
83
|
+
)}
|
84
|
+
</div>
|
85
|
+
)
|
86
|
+
}
|
87
|
+
|
88
|
+
export default TextInputMask
|
@@ -5,3 +5,4 @@ export { default as TextInputDisabled } from './_text_input_disabled.jsx'
|
|
5
5
|
export { default as TextInputAddOn } from './_text_input_add_on.jsx'
|
6
6
|
export { default as TextInputInline } from './_text_input_inline.jsx'
|
7
7
|
export { default as TextInputNoLabel } from './_text_input_no_label.jsx'
|
8
|
+
export { default as TextInputMask } from './_text_input_mask.jsx'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
type InputMask = {
|
2
|
+
format: (value: string) => string
|
3
|
+
pattern: string
|
4
|
+
placeholder: string
|
5
|
+
}
|
6
|
+
|
7
|
+
type InputMaskDictionary = {
|
8
|
+
[key in 'currency' | 'zipCode' | 'postalCode' | 'ssn']: InputMask
|
9
|
+
}
|
10
|
+
|
11
|
+
const formatCurrency = (value: string): string => {
|
12
|
+
const numericValue = value.replace(/[^0-9]/g, '').slice(0, 15)
|
13
|
+
|
14
|
+
if (!numericValue) return ''
|
15
|
+
|
16
|
+
const dollars = parseFloat((parseInt(numericValue) / 100).toFixed(2))
|
17
|
+
if (dollars === 0) return ''
|
18
|
+
|
19
|
+
return new Intl.NumberFormat('en-US', {
|
20
|
+
style: 'currency',
|
21
|
+
currency: 'USD',
|
22
|
+
maximumFractionDigits: 2,
|
23
|
+
}).format(dollars)
|
24
|
+
}
|
25
|
+
|
26
|
+
const formatBasicPostal = (value: string): string => {
|
27
|
+
return value.replace(/\D/g, '').slice(0, 5)
|
28
|
+
}
|
29
|
+
|
30
|
+
const formatExtendedPostal = (value: string): string => {
|
31
|
+
const cleaned = value.replace(/\D/g, '').slice(0, 9)
|
32
|
+
return cleaned.replace(/(\d{5})(?=\d)/, '$1-')
|
33
|
+
}
|
34
|
+
|
35
|
+
const formatSSN = (value: string): string => {
|
36
|
+
const cleaned = value.replace(/\D/g, '').slice(0, 9)
|
37
|
+
return cleaned
|
38
|
+
.replace(/(\d{5})(?=\d)/, '$1-')
|
39
|
+
.replace(/(\d{3})(?=\d)/, '$1-')
|
40
|
+
}
|
41
|
+
|
42
|
+
export const INPUTMASKS: InputMaskDictionary = {
|
43
|
+
currency: {
|
44
|
+
format: formatCurrency,
|
45
|
+
// eslint-disable-next-line no-useless-escape
|
46
|
+
pattern: '^\\$\\d{1,3}(?:,\\d{3})*(?:\\.\\d{2})?$',
|
47
|
+
placeholder: '$0.00',
|
48
|
+
},
|
49
|
+
zipCode: {
|
50
|
+
format: formatBasicPostal,
|
51
|
+
pattern: '\\d{5}',
|
52
|
+
placeholder: '12345',
|
53
|
+
},
|
54
|
+
postalCode: {
|
55
|
+
format: formatExtendedPostal,
|
56
|
+
pattern: '\\d{5}-\\d{4}',
|
57
|
+
placeholder: '12345-6789',
|
58
|
+
},
|
59
|
+
ssn: {
|
60
|
+
format: formatSSN,
|
61
|
+
pattern: '\\d{3}-\\d{2}-\\d{4}',
|
62
|
+
placeholder: '123-45-6789',
|
63
|
+
},
|
64
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { render, screen } from '../utilities/test-utils'
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
import { render, screen, fireEvent, within } from '../utilities/test-utils'
|
3
3
|
|
4
4
|
import TextInput from './_text_input'
|
5
5
|
|
@@ -89,3 +89,140 @@ test('returns additional class name', () => {
|
|
89
89
|
const kit = screen.getByTestId(testId)
|
90
90
|
expect(kit).toHaveClass(`${kitClass} mb_lg`)
|
91
91
|
})
|
92
|
+
|
93
|
+
|
94
|
+
const TextInputCurrencyMask = (props) => {
|
95
|
+
const [currency, setValue] = useState('')
|
96
|
+
const handleOnChange = ({ target }) => {
|
97
|
+
setValue(target.value)
|
98
|
+
}
|
99
|
+
|
100
|
+
return (
|
101
|
+
<TextInput
|
102
|
+
mask="currency"
|
103
|
+
onChange={handleOnChange}
|
104
|
+
value={currency}
|
105
|
+
{...props}
|
106
|
+
/>
|
107
|
+
)
|
108
|
+
}
|
109
|
+
|
110
|
+
test('returns masked currency value', () => {
|
111
|
+
render(
|
112
|
+
<TextInputCurrencyMask
|
113
|
+
data={{ testid: testId }}
|
114
|
+
/>
|
115
|
+
)
|
116
|
+
|
117
|
+
const kit = screen.getByTestId(testId)
|
118
|
+
|
119
|
+
const input = within(kit).getByRole('textbox');
|
120
|
+
|
121
|
+
fireEvent.change(input, { target: { value: '123456' } });
|
122
|
+
|
123
|
+
expect(input.value).toBe('$1,234.56')
|
124
|
+
|
125
|
+
fireEvent.change(input, { target: { value: '1' } });
|
126
|
+
|
127
|
+
expect(input.value).toBe('$0.01')
|
128
|
+
|
129
|
+
fireEvent.change(input, { target: { value: '' } });
|
130
|
+
|
131
|
+
expect(input.value).toBe('')
|
132
|
+
})
|
133
|
+
|
134
|
+
const TextInputZipCodeMask = (props) => {
|
135
|
+
const [zipCode, setValue] = useState('')
|
136
|
+
const handleOnChange = ({ target }) => {
|
137
|
+
setValue(target.value)
|
138
|
+
}
|
139
|
+
|
140
|
+
return (
|
141
|
+
<TextInput
|
142
|
+
mask="zipCode"
|
143
|
+
onChange={handleOnChange}
|
144
|
+
value={zipCode}
|
145
|
+
{...props}
|
146
|
+
/>
|
147
|
+
)
|
148
|
+
}
|
149
|
+
|
150
|
+
test('returns masked zip code value', () => {
|
151
|
+
render(
|
152
|
+
<TextInputZipCodeMask
|
153
|
+
data={{ testid: testId }}
|
154
|
+
/>
|
155
|
+
)
|
156
|
+
|
157
|
+
const kit = screen.getByTestId(testId)
|
158
|
+
|
159
|
+
const input = within(kit).getByRole('textbox');
|
160
|
+
|
161
|
+
fireEvent.change(input, { target: { value: '123456' } });
|
162
|
+
|
163
|
+
expect(input.value).toBe('12345')
|
164
|
+
})
|
165
|
+
|
166
|
+
const TextInputPostalCodeMask = (props) => {
|
167
|
+
const [postalCode, setValue] = useState('')
|
168
|
+
const handleOnChange = ({ target }) => {
|
169
|
+
setValue(target.value)
|
170
|
+
}
|
171
|
+
|
172
|
+
return (
|
173
|
+
<TextInput
|
174
|
+
mask="postalCode"
|
175
|
+
onChange={handleOnChange}
|
176
|
+
value={postalCode}
|
177
|
+
{...props}
|
178
|
+
/>
|
179
|
+
)
|
180
|
+
}
|
181
|
+
|
182
|
+
test('returns masked postal code value', () => {
|
183
|
+
render(
|
184
|
+
<TextInputPostalCodeMask
|
185
|
+
data={{ testid: testId }}
|
186
|
+
/>
|
187
|
+
)
|
188
|
+
|
189
|
+
const kit = screen.getByTestId(testId)
|
190
|
+
|
191
|
+
const input = within(kit).getByRole('textbox');
|
192
|
+
|
193
|
+
fireEvent.change(input, { target: { value: '123456789' } });
|
194
|
+
|
195
|
+
expect(input.value).toBe('12345-6789')
|
196
|
+
})
|
197
|
+
|
198
|
+
const TextInputSSNMask = (props) => {
|
199
|
+
const [ssn, setValue] = useState('')
|
200
|
+
const handleOnChange = ({ target }) => {
|
201
|
+
setValue(target.value)
|
202
|
+
}
|
203
|
+
|
204
|
+
return (
|
205
|
+
<TextInput
|
206
|
+
mask="ssn"
|
207
|
+
onChange={handleOnChange}
|
208
|
+
value={ssn}
|
209
|
+
{...props}
|
210
|
+
/>
|
211
|
+
)
|
212
|
+
}
|
213
|
+
|
214
|
+
test('returns masked ssn value', () => {
|
215
|
+
render(
|
216
|
+
<TextInputSSNMask
|
217
|
+
data={{ testid: testId }}
|
218
|
+
/>
|
219
|
+
)
|
220
|
+
|
221
|
+
const kit = screen.getByTestId(testId)
|
222
|
+
|
223
|
+
const input = within(kit).getByRole('textbox');
|
224
|
+
|
225
|
+
fireEvent.change(input, { target: { value: '123456789' } });
|
226
|
+
|
227
|
+
expect(input.value).toBe('123-45-6789')
|
228
|
+
})
|