Skip to content

Commit 3491874

Browse files
chris-soar40818419
authored andcommitted
Allow filter chars to act as blacklist or whitelist (40818419#82)
1 parent c22c327 commit 3491874

File tree

5 files changed

+78
-30
lines changed

5 files changed

+78
-30
lines changed

README.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -83,26 +83,27 @@ const ReactCodeInput = dynamic(import('react-code-input'));
8383

8484
## Props:
8585

86-
| Property | Type | Description |
87-
|:---|:---|:---|
88-
| type | string | Only types like: `text`, `number`, `password` and `tel` are accepted.|
89-
| fields | number | Allowed amount of characters to enter. |
90-
| value | string | Setting the value of code input field. |
91-
| name | string | Setting the name of component. |
92-
| onChange | func | Function, which is called whenever there is a change of value in the input box. |
93-
| touch | func | Marks the given fields as "touched" to show errors. |
94-
| untouch | func | Clears the "touched" flag for the given fields. |
95-
| className | string | Add classname to the root element. |
96-
| style | object | Setting the styles of container element. |
97-
| inputStyle | object | Setting the styles of each input field. |
98-
| inputStyleInvalid | object | Setting the styles of each input field if `isValid` prop is `false`. |
99-
| isValid | bool | Returns true if an input element contains valid data. |
100-
| disabled | bool | When present, it specifies that the element should be disabled. |
101-
| autoFocus | bool | Setup autofocus on the first input, `true` by default. |
102-
| filterKeyCodes | array | Filter characters on key down. |
103-
| filterChars | array | Filter characters. | default: ['-', '.'] |
104-
| pattern | string | The pattern prop specifies a regular expression that the <input> element's value is checked against. |
105-
| inputMode | string | The inputMode prop tells the browser on devices with dynamic keyboards which keyboard to display. |
86+
| Property | Type | Description |
87+
| :--------------------- | :----- | :--------------------------------------------------------------------------------------------------- |
88+
| type | string | Only types like: `text`, `number`, `password` and `tel` are accepted. |
89+
| fields | number | Allowed amount of characters to enter. |
90+
| value | string | Setting the value of code input field. |
91+
| name | string | Setting the name of component. |
92+
| onChange | func | Function, which is called whenever there is a change of value in the input box. |
93+
| touch | func | Marks the given fields as "touched" to show errors. |
94+
| untouch | func | Clears the "touched" flag for the given fields. |
95+
| className | string | Add classname to the root element. |
96+
| style | object | Setting the styles of container element. |
97+
| inputStyle | object | Setting the styles of each input field. |
98+
| inputStyleInvalid | object | Setting the styles of each input field if `isValid` prop is `false`. |
99+
| isValid | bool | Returns true if an input element contains valid data. |
100+
| disabled | bool | When present, it specifies that the element should be disabled. |
101+
| autoFocus | bool | Setup autofocus on the first input, `true` by default. |
102+
| filterKeyCodes | array | Filter characters on key down. |
103+
| filterChars | array | Filter characters; default is ['-', '.'] |
104+
| filterCharsIsWhitelist | bool | `filterChars` acts as blacklist if `false`, whitelist if `true`; `false` by default. |
105+
| pattern | string | The pattern prop specifies a regular expression that the <input> element's value is checked against. |
106+
| inputMode | string | The inputMode prop tells the browser on devices with dynamic keyboards which keyboard to display. |
106107

107108
## Compatible with
108109
[`redux-form`](https://github.com/erikras/redux-form) from [erikras](https://github.com/erikras)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-code-input",
3-
"version": "3.8.2",
3+
"version": "3.9.0",
44
"description": "React component for entering and validating numbers, text or password.",
55
"main": "dist/ReactCodeInput.js",
66
"scripts": {

src/ReactCodeInput.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ export interface ReactCodeInputProps {
6161
// Filter characters.
6262
filterChars?: Array<string>
6363

64+
// Filter above acts as blacklist if false, whitelist if true; false by default.
65+
filterCharsIsWhitelist?: boolean;
66+
6467
// The pattern prop specifies a regular expression that the element's value is checked against.
6568
pattern?: string
6669

src/ReactCodeInput.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class ReactCodeInput extends Component {
8888
}
8989

9090
handleChange(e) {
91-
const { filterChars } = this.props;
91+
const { filterChars, filterCharsIsWhitelist } = this.props;
9292

9393
let value = String(e.target.value);
9494

@@ -101,7 +101,12 @@ class ReactCodeInput extends Component {
101101
}
102102

103103
/** Filter Chars */
104-
value = value.split('').filter(currChar => !filterChars.includes(currChar)).join('');
104+
value = value.split('').filter(currChar => {
105+
if (filterCharsIsWhitelist) {
106+
return filterChars.includes(currChar);
107+
}
108+
return !filterChars.includes(currChar);
109+
}).join('');
105110

106111
let fullValue = value;
107112

@@ -213,6 +218,7 @@ class ReactCodeInput extends Component {
213218
e.preventDefault();
214219
break;
215220
}
221+
break;
216222

217223
default:
218224
break;
@@ -225,14 +231,10 @@ class ReactCodeInput extends Component {
225231
const { className, style = {}, inputStyle = {}, inputStyleInvalid = {}, type, autoFocus, pattern, inputMode } = this.props,
226232
{ disabled, input, isValid, defaultInputStyle } = this.state,
227233
styles = {
228-
container: style,
234+
container: { display: 'inline-block', ...style },
229235
input: isValid ? inputStyle : inputStyleInvalid,
230236
};
231237

232-
Object.assign(styles.container, {
233-
display: 'inline-block',
234-
});
235-
236238
if (!className && Object.keys(inputStyle).length === 0) {
237239
Object.assign(inputStyle, {
238240
...defaultInputStyle,
@@ -305,6 +307,7 @@ ReactCodeInput.defaultProps = {
305307
type: 'text',
306308
filterKeyCodes: [189, 190],
307309
filterChars: ['-', '.'],
310+
filterCharsIsWhitelist: false,
308311
};
309312

310313
ReactCodeInput.propTypes = {
@@ -325,6 +328,7 @@ ReactCodeInput.propTypes = {
325328
forceUppercase: PropTypes.bool,
326329
filterKeyCodes: PropTypes.array,
327330
filterChars: PropTypes.array,
331+
filterCharsIsWhitelist: PropTypes.bool,
328332
pattern: PropTypes.string,
329333
inputMode: PropTypes.oneOf([
330334
'verbatim', 'latin', 'latin-name', 'latin-prose',

src/ReactCodeInput.spec.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,31 @@ describe('CodeInputField', () => {
5151
expect(wrapper.find('input')).toHaveLength(4);
5252
});
5353

54-
test('simulates onChange events', () => {
54+
test('simulates onKeydown events', () => {
5555
const onChange = jest.fn();
5656
const wrapper = mount(<CodeInputField onChange={onChange} fields={3} value="123" type="number"/>);
5757
const element = wrapper.find('input').at(0);
5858
element.simulate('change');
59-
element.simulate('keydown', { keyCode: 8 });
59+
element.simulate('keydown', { keyCode: 8 }); // "backspace"
6060
element.simulate('keydown', { keyCode: 13 });
6161
element.simulate('keydown', { keyCode: 65 }); // "a"
6262
element.simulate('keydown', { keyCode: 69 }); // "e"
6363
expect(wrapper.state().value).toEqual('23');
6464
});
6565

66+
test('simulates onKeydown events; start at 2nd input', () => {
67+
const onChange = jest.fn();
68+
const wrapper = mount(<CodeInputField onChange={onChange} fields={3} value="123" type="number"/>);
69+
const element = wrapper.find('input').at(1);
70+
element.simulate('change');
71+
element.simulate('keydown', { keyCode: 8 }); // "backspace"
72+
element.simulate('keydown', { keyCode: 13 });
73+
element.simulate('keydown', { keyCode: 65 }); // "a"
74+
element.simulate('keydown', { keyCode: 69 }); // "e"
75+
expect(wrapper.state().value).toEqual('13');
76+
expect(wrapper.find('input').at(0).instance()).toEqual(document.activeElement);
77+
});
78+
6679
test('simulates onChange from paste type=text', () => {
6780
const onChange = jest.fn();
6881
const wrapper = mount(<CodeInputField onChange={onChange} fields={6} type="text"/>);
@@ -180,4 +193,31 @@ describe('CodeInputField', () => {
180193
element.simulate('blur');
181194
expect(element.instance()).toEqual(document.activeElement);
182195
});
196+
197+
test('should block characters that are in filter; default', () => {
198+
const wrapper = mount(<CodeInputField fields={6} type="text" filterChars={['1', '2', '3', '4', '5', '6']}/>);
199+
const element = wrapper.find('input').at(0);
200+
const target = element.instance();
201+
target.value = 'ab12cd3e4f56';
202+
element.simulate('change', { target });
203+
expect(wrapper.state().value).toEqual("abcdef");
204+
});
205+
206+
test('should block characters that are in filter; flag set to false', () => {
207+
const wrapper = mount(<CodeInputField fields={6} type="text" filterChars={['1', '2', '3', '4', '5', '6']} filterCharsIsWhitelist={false} />);
208+
const element = wrapper.find('input').at(0);
209+
const target = element.instance();
210+
target.value = 'ab12cd3e4f56';
211+
element.simulate('change', { target });
212+
expect(wrapper.state().value).toEqual("abcdef");
213+
});
214+
215+
test('should only allow characters that are in filter; flag set to true', () => {
216+
const wrapper = mount(<CodeInputField fields={6} type="text" filterChars={['1', '2', '3', '4', '5', '6']} filterCharsIsWhitelist />);
217+
const element = wrapper.find('input').at(0);
218+
const target = element.instance();
219+
target.value = 'ab12cd3e4f56';
220+
element.simulate('change', { target });
221+
expect(wrapper.state().value).toEqual("123456");
222+
});
183223
});

0 commit comments

Comments
 (0)