playbook_ui 14.9.0.pre.alpha.play1703errorstatealignment4889 → 14.9.0.pre.alpha.play1703errorstatealignment4991
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_bar_graph/docs/_bar_graph_custom.jsx +53 -49
- data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_custom_rails.html.erb +29 -36
- data/app/pb_kits/playbook/pb_collapsible/_collapsible.tsx +9 -4
- data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleContent.tsx +2 -2
- data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleMain.tsx +2 -2
- data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +49 -0
- data/app/pb_kits/playbook/pb_form_group/_form_group.scss +46 -12
- data/app/pb_kits/playbook/pb_link/_link.scss +3 -3
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible.jsx +75 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible.md +1 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.jsx +108 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.md +2 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_content.jsx +94 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_content.md +0 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows.jsx +83 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows.md +3 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table.jsx +120 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table.md +1 -0
- data/app/pb_kits/playbook/pb_table/docs/example.yml +5 -0
- data/app/pb_kits/playbook/pb_table/docs/index.js +5 -0
- data/app/pb_kits/playbook/pb_table/styles/_all.scss +2 -1
- data/app/pb_kits/playbook/pb_table/styles/_collapsible.scss +35 -0
- data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +106 -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-l1kq1p9m.js +22 -0
- data/dist/chunks/_weekday_stacked-B28kYXl9.js +45 -0
- data/dist/chunks/{lib-CVPInSs5.js → lib-CuCy3_xO.js} +3 -3
- data/dist/chunks/{pb_form_validation-CDLJ5eAG.js → pb_form_validation-D37k10a0.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +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 +20 -6
- data/dist/chunks/_typeahead-4sdDeM4X.js +0 -22
- data/dist/chunks/_weekday_stacked-CblTZ9cd.js +0 -45
@@ -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
|
+
})
|