@transferwise/components 0.0.0-experimental-1f8ed05 → 0.0.0-experimental-adcaf57

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.
Files changed (49) hide show
  1. package/build/index.esm.js +68 -142
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +69 -143
  4. package/build/index.js.map +1 -1
  5. package/build/types/common/textFormat/formatWithPattern/formatWithPattern.d.ts +1 -1
  6. package/build/types/common/textFormat/formatWithPattern/formatWithPattern.d.ts.map +1 -1
  7. package/build/types/common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.d.ts +2 -1
  8. package/build/types/common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.d.ts.map +1 -1
  9. package/build/types/common/textFormat/getSymbolsInPatternWithPosition/getSymbolsInPatternWithPosition.d.ts +5 -1
  10. package/build/types/common/textFormat/getSymbolsInPatternWithPosition/getSymbolsInPatternWithPosition.d.ts.map +1 -1
  11. package/build/types/common/textFormat/unformatWithPattern/unformatWithPattern.d.ts +1 -1
  12. package/build/types/common/textFormat/unformatWithPattern/unformatWithPattern.d.ts.map +1 -1
  13. package/build/types/index.d.ts +2 -0
  14. package/build/types/index.d.ts.map +1 -1
  15. package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts +5 -11
  16. package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts.map +1 -1
  17. package/build/types/inputWithDisplayFormat/index.d.ts +2 -1
  18. package/build/types/inputWithDisplayFormat/index.d.ts.map +1 -1
  19. package/build/types/inputs/Input.d.ts +8 -6
  20. package/build/types/inputs/Input.d.ts.map +1 -1
  21. package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts +5 -11
  22. package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts.map +1 -1
  23. package/build/types/textareaWithDisplayFormat/index.d.ts +2 -1
  24. package/build/types/textareaWithDisplayFormat/index.d.ts.map +1 -1
  25. package/build/types/withDisplayFormat/WithDisplayFormat.d.ts +55 -82
  26. package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
  27. package/build/types/withDisplayFormat/index.d.ts +2 -1
  28. package/build/types/withDisplayFormat/index.d.ts.map +1 -1
  29. package/package.json +1 -1
  30. package/src/common/textFormat/formatWithPattern/{formatWithPattern.js → formatWithPattern.ts} +8 -4
  31. package/src/common/textFormat/getCursorPositionAfterKeystroke/{getCursorPositionAfterKeystroke.js → getCursorPositionAfterKeystroke.ts} +7 -6
  32. package/src/common/textFormat/getSymbolsInPatternWithPosition/{getSymbolsInPatternWithPosition.js → getSymbolsInPatternWithPosition.ts} +7 -2
  33. package/src/common/textFormat/unformatWithPattern/{unformatWithPattern.js → unformatWithPattern.ts} +3 -2
  34. package/src/index.ts +2 -0
  35. package/src/inputWithDisplayFormat/InputWithDisplayFormat.tsx +11 -0
  36. package/src/inputWithDisplayFormat/index.ts +2 -0
  37. package/src/inputs/Input.tsx +6 -11
  38. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.spec.js +3 -1
  39. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.story.tsx +30 -0
  40. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.tsx +11 -0
  41. package/src/textareaWithDisplayFormat/index.ts +2 -0
  42. package/src/withDisplayFormat/WithDisplayFormat.tsx +303 -0
  43. package/src/withDisplayFormat/index.ts +2 -0
  44. package/src/inputWithDisplayFormat/InputWithDisplayFormat.js +0 -14
  45. package/src/inputWithDisplayFormat/index.js +0 -1
  46. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.js +0 -14
  47. package/src/textareaWithDisplayFormat/index.js +0 -1
  48. package/src/withDisplayFormat/WithDisplayFormat.js +0 -312
  49. package/src/withDisplayFormat/index.js +0 -1
@@ -0,0 +1,303 @@
1
+ import { Component, KeyboardEvent, ClipboardEvent, ChangeEvent, FocusEvent } from 'react';
2
+
3
+ import { HistoryNavigator } from '../common';
4
+ import {
5
+ formatWithPattern,
6
+ getCountOfSymbolsInSelection,
7
+ getCursorPositionAfterKeystroke,
8
+ unformatWithPattern,
9
+ getDistanceToPreviousSymbol,
10
+ getDistanceToNextSymbol,
11
+ } from '../common/textFormat';
12
+ import { InputProps } from '../inputs/Input';
13
+ import { TextAreaProps } from '../inputs/TextArea';
14
+ import { Merge } from '../utils';
15
+
16
+ export type TextInputProps = Merge<
17
+ InputProps,
18
+ {
19
+ value?: string;
20
+ displayPattern: string;
21
+ /**
22
+ * autocomplete hides our form help so we need to disable it when help text
23
+ * is present. Chrome ignores autocomplete=off, the only way to disable it is
24
+ * to provide an 'invalid' value, for which 'disabled' serves.
25
+ */
26
+ autoComplete?: InputProps['autoComplete'] | 'disabled';
27
+ onChange?: (value: string) => void;
28
+ onBlur?: (value: string) => void;
29
+ onFocus?: (value: string) => void;
30
+ }
31
+ >;
32
+
33
+ export type Props = typeof WithDisplayFormat.defaultProps & {
34
+ render: (renderProps: InputProps | TextAreaProps) => JSX.Element;
35
+ } & TextInputProps;
36
+
37
+ export type EventType =
38
+ | 'KeyDown'
39
+ | 'Paste'
40
+ | 'Cut'
41
+ | 'Undo'
42
+ | 'Redo'
43
+ | 'Backspace'
44
+ | 'Delete'
45
+ | null;
46
+
47
+ type State = {
48
+ value: string;
49
+ historyNavigator: HistoryNavigator;
50
+ prevDisplayPattern?: string;
51
+ triggerType?: EventType;
52
+ triggerEvent?: KeyboardEvent<HTMLInputElement> | null;
53
+ pastedLength?: number;
54
+ selectionStart?: HTMLInputElement['selectionStart'];
55
+ selectionEnd?: HTMLInputElement['selectionEnd'];
56
+ };
57
+
58
+ class WithDisplayFormat extends Component<Props, State> {
59
+ static defaultProps = {
60
+ autoComplete: 'off',
61
+ displayPattern: '',
62
+ type: 'text',
63
+ value: '',
64
+ };
65
+
66
+ constructor(props: Props) {
67
+ super(props);
68
+ const unformattedValue = unformatWithPattern(props.value, props.displayPattern);
69
+ this.state = {
70
+ value: formatWithPattern(unformattedValue, props.displayPattern),
71
+ historyNavigator: new HistoryNavigator(),
72
+ prevDisplayPattern: props.displayPattern,
73
+ triggerType: null,
74
+ triggerEvent: null,
75
+ };
76
+ }
77
+
78
+ static getDerivedStateFromProps(
79
+ { displayPattern }: Props,
80
+ { prevDisplayPattern = displayPattern, value, historyNavigator }: State,
81
+ ) {
82
+ if (prevDisplayPattern !== displayPattern) {
83
+ const unFormattedValue = unformatWithPattern(value, prevDisplayPattern);
84
+ historyNavigator.reset();
85
+
86
+ return {
87
+ prevDisplayPattern: displayPattern,
88
+ value: formatWithPattern(unFormattedValue, displayPattern),
89
+ triggerType: null,
90
+ triggerEvent: null,
91
+ pastedLength: 0,
92
+ };
93
+ }
94
+ return null;
95
+ }
96
+
97
+ getUserAction = (unformattedValue: string): EventType => {
98
+ const { triggerEvent, triggerType, value } = this.state;
99
+ const { displayPattern } = this.props;
100
+
101
+ if (triggerEvent) {
102
+ const charCode = String.fromCharCode(triggerEvent.which).toLowerCase();
103
+
104
+ if (triggerType === 'Paste' || triggerType === 'Cut') {
105
+ return triggerType;
106
+ }
107
+
108
+ if ((triggerEvent.ctrlKey || triggerEvent.metaKey) && charCode === 'z') {
109
+ return triggerEvent.shiftKey ? 'Redo' : 'Undo';
110
+ }
111
+ // Detect mouse event redo
112
+ if (triggerEvent.ctrlKey && charCode === 'd') {
113
+ return 'Delete';
114
+ }
115
+
116
+ // Android Fix.
117
+ if (
118
+ typeof triggerEvent.key === 'undefined' &&
119
+ unformattedValue.length <= unformatWithPattern(value, displayPattern).length
120
+ ) {
121
+ return 'Backspace';
122
+ }
123
+ return triggerEvent.key as EventType;
124
+ } else {
125
+ // triggerEvent can be null only in case of "autofilling" (via password manager extension or browser build-in one) events
126
+ return 'Paste';
127
+ }
128
+ };
129
+
130
+ resetEvent = () => {
131
+ this.setState({
132
+ triggerType: null,
133
+ triggerEvent: null,
134
+ pastedLength: 0,
135
+ });
136
+ };
137
+
138
+ detectUndoRedo = (event: KeyboardEvent<HTMLInputElement>) => {
139
+ const charCode = String.fromCharCode(event.which).toLowerCase();
140
+ if ((event.ctrlKey || event.metaKey) && charCode === 'z') {
141
+ return event.shiftKey ? 'Redo' : 'Undo';
142
+ }
143
+ return null;
144
+ };
145
+
146
+ handleOnKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
147
+ event.persist();
148
+ const { selectionStart, selectionEnd } = event.target as HTMLInputElement;
149
+ const { historyNavigator } = this.state;
150
+ const { displayPattern } = this.props;
151
+
152
+ // Unfortunately Undo and Redo don't trigger OnChange event so we need to handle some value logic here.
153
+ let newFormattedValue = '';
154
+
155
+ if (this.detectUndoRedo(event) === 'Undo') {
156
+ newFormattedValue = formatWithPattern(historyNavigator.undo(), displayPattern);
157
+ this.setState({ value: newFormattedValue, triggerType: 'Undo' });
158
+ } else if (this.detectUndoRedo(event) === 'Redo') {
159
+ newFormattedValue = formatWithPattern(historyNavigator.redo(), displayPattern);
160
+ this.setState({ value: newFormattedValue, triggerType: 'Redo' });
161
+ } else {
162
+ this.setState({
163
+ triggerEvent: event,
164
+ triggerType: 'KeyDown',
165
+ selectionStart,
166
+ selectionEnd,
167
+ });
168
+ }
169
+ };
170
+
171
+ handleOnPaste = (event: ClipboardEvent<HTMLInputElement>) => {
172
+ const { displayPattern } = this.props;
173
+ const pastedLength = unformatWithPattern(
174
+ event.clipboardData.getData('Text'),
175
+ displayPattern,
176
+ ).length;
177
+
178
+ this.setState({ triggerType: 'Paste', pastedLength });
179
+ };
180
+
181
+ handleOnCut = () => {
182
+ this.setState({ triggerType: 'Cut' });
183
+ };
184
+
185
+ isKeyAllowed = (action: EventType) => {
186
+ const { displayPattern } = this.props;
187
+ const symbolsInPattern = displayPattern.split('').filter((character) => character !== '*');
188
+
189
+ return !symbolsInPattern.includes(action as string);
190
+ };
191
+
192
+ handleOnChange = (event: ChangeEvent<HTMLInputElement>) => {
193
+ const { historyNavigator, triggerType } = this.state;
194
+ const { displayPattern, onChange } = this.props;
195
+ const { value } = event.target;
196
+ let unformattedValue = unformatWithPattern(value, displayPattern);
197
+ const action = this.getUserAction(unformattedValue);
198
+ if (!this.isKeyAllowed(action) || triggerType === 'Undo' || triggerType === 'Redo') {
199
+ return;
200
+ }
201
+
202
+ if (action === 'Backspace' || action === 'Delete') {
203
+ unformattedValue = this.handleDelete(unformattedValue, action);
204
+ }
205
+
206
+ const newFormattedValue = formatWithPattern(unformattedValue, displayPattern);
207
+ historyNavigator.add(unformattedValue);
208
+
209
+ this.handleCursorPositioning(action);
210
+
211
+ this.setState({ value: newFormattedValue }, () => {
212
+ this.resetEvent();
213
+ if (onChange) {
214
+ const broadcastValue = unformatWithPattern(newFormattedValue, displayPattern);
215
+ onChange(broadcastValue);
216
+ }
217
+ });
218
+ };
219
+
220
+ handleOnBlur = (event: FocusEvent<HTMLInputElement>) => {
221
+ this.props.onBlur?.(unformatWithPattern(event.target.value, this.props.displayPattern));
222
+ };
223
+
224
+ handleOnFocus = (event: FocusEvent<HTMLInputElement>) => {
225
+ const { displayPattern, onFocus } = this.props;
226
+ if (onFocus) {
227
+ this.handleOnChange(event);
228
+ onFocus(unformatWithPattern(event.target.value, displayPattern));
229
+ }
230
+ };
231
+
232
+ handleDelete = (unformattedValue: string, action: EventType) => {
233
+ const { displayPattern } = this.props;
234
+ const { selectionStart, selectionEnd } = this.state;
235
+ const newStack = [...unformattedValue];
236
+ if (selectionStart === selectionEnd) {
237
+ let startPosition =
238
+ (selectionStart as number) -
239
+ getCountOfSymbolsInSelection(0, selectionStart, displayPattern);
240
+ let toDelete = 0;
241
+
242
+ let count = getDistanceToNextSymbol(selectionStart, displayPattern);
243
+ if (action === 'Backspace') {
244
+ startPosition -= 1;
245
+ count = getDistanceToPreviousSymbol(selectionStart, displayPattern);
246
+ }
247
+
248
+ if (startPosition >= 0 && count) {
249
+ toDelete = 1;
250
+ }
251
+
252
+ newStack.splice(startPosition, toDelete);
253
+ }
254
+
255
+ return newStack.join('');
256
+ };
257
+
258
+ handleCursorPositioning = (action: EventType) => {
259
+ const { displayPattern } = this.props;
260
+ const { triggerEvent, selectionStart, selectionEnd, pastedLength } = this.state;
261
+
262
+ const cursorPosition = getCursorPositionAfterKeystroke(
263
+ action,
264
+ selectionStart as number,
265
+ selectionEnd as number,
266
+ displayPattern,
267
+ pastedLength as number,
268
+ );
269
+
270
+ setTimeout(() => {
271
+ if (triggerEvent) {
272
+ (triggerEvent.target as HTMLInputElement).setSelectionRange(cursorPosition, cursorPosition);
273
+ }
274
+ this.setState({ selectionStart: cursorPosition, selectionEnd: cursorPosition });
275
+ }, 0);
276
+ };
277
+
278
+ render() {
279
+ return this.props.render({
280
+ value: this.state.value,
281
+ type: this.props.type,
282
+ inputMode: this.props.inputMode,
283
+ className: this.props.className,
284
+ id: this.props.id,
285
+ name: this.props.name,
286
+ placeholder: this.props.placeholder,
287
+ readOnly: this.props.readOnly,
288
+ required: this.props.required,
289
+ minLength: this.props.minLength,
290
+ maxLength: this.props.maxLength,
291
+ disabled: this.props.disabled,
292
+ autoComplete: this.props.autoComplete,
293
+ onFocus: this.handleOnFocus,
294
+ onBlur: this.handleOnBlur,
295
+ onPaste: this.handleOnPaste,
296
+ onKeyDown: this.handleOnKeyDown,
297
+ onChange: this.handleOnChange,
298
+ onCut: this.handleOnCut,
299
+ });
300
+ }
301
+ }
302
+
303
+ export default WithDisplayFormat;
@@ -0,0 +1,2 @@
1
+ export { default } from './WithDisplayFormat';
2
+ export type { Props as WithDisplayFormatProps, TextInputProps } from './WithDisplayFormat';
@@ -1,14 +0,0 @@
1
- import PropTypes from 'prop-types';
2
-
3
- import WithDisplayFormat from '../withDisplayFormat';
4
-
5
- const InputWithDisplayFormat = (props) => (
6
- <WithDisplayFormat {...props} render={(renderProps) => <input {...renderProps} />} />
7
- );
8
-
9
- InputWithDisplayFormat.propTypes = {
10
- displayPattern: PropTypes.string.isRequired,
11
- onChange: PropTypes.func.isRequired,
12
- };
13
-
14
- export default InputWithDisplayFormat;
@@ -1 +0,0 @@
1
- export { default } from './InputWithDisplayFormat';
@@ -1,14 +0,0 @@
1
- import PropTypes from 'prop-types';
2
-
3
- import WithDisplayFormat from '../withDisplayFormat';
4
-
5
- const TextareaWithDisplayFormat = (props) => (
6
- <WithDisplayFormat {...props} render={(renderProps) => <textarea {...renderProps} />} />
7
- );
8
-
9
- TextareaWithDisplayFormat.propTypes = {
10
- displayPattern: PropTypes.string.isRequired,
11
- onChange: PropTypes.func.isRequired,
12
- };
13
-
14
- export default TextareaWithDisplayFormat;
@@ -1 +0,0 @@
1
- export { default } from './TextareaWithDisplayFormat';
@@ -1,312 +0,0 @@
1
- import PropTypes from 'prop-types';
2
- import { Component } from 'react';
3
-
4
- import { HistoryNavigator } from '../common';
5
- import {
6
- formatWithPattern,
7
- getCountOfSymbolsInSelection,
8
- getCursorPositionAfterKeystroke,
9
- unformatWithPattern,
10
- getDistanceToPreviousSymbol,
11
- getDistanceToNextSymbol,
12
- } from '../common/textFormat';
13
-
14
- class WithDisplayFormat extends Component {
15
- constructor(props) {
16
- super(props);
17
- const { value, displayPattern } = props;
18
- const unformattedValue = unformatWithPattern(value, displayPattern);
19
- this.state = {
20
- value: formatWithPattern(unformattedValue, displayPattern),
21
- historyNavigator: new HistoryNavigator(),
22
- prevDisplayPattern: props.displayPattern,
23
- triggerType: null,
24
- triggerEvent: null,
25
- };
26
- }
27
-
28
- static getDerivedStateFromProps(nextProps, previousState) {
29
- const { displayPattern } = nextProps;
30
- const { prevDisplayPattern } = previousState;
31
- if (previousState.prevDisplayPattern !== displayPattern) {
32
- const { value, historyNavigator } = previousState;
33
-
34
- const unFormattedValue = unformatWithPattern(value, prevDisplayPattern);
35
- historyNavigator.reset();
36
-
37
- return {
38
- prevDisplayPattern: displayPattern,
39
- value: formatWithPattern(unFormattedValue, displayPattern),
40
- triggerType: null,
41
- triggerEvent: null,
42
- pastedLength: 0,
43
- };
44
- }
45
- return null;
46
- }
47
-
48
- getUserAction = (unformattedValue) => {
49
- const { triggerEvent, triggerType, value } = this.state;
50
- const { displayPattern } = this.props;
51
-
52
- const charCode = String.fromCharCode(triggerEvent.which).toLowerCase();
53
-
54
- if (triggerType === 'Paste' || triggerType === 'Cut') {
55
- return triggerType;
56
- }
57
-
58
- if ((triggerEvent.ctrlKey || triggerEvent.metaKey) && charCode === 'z') {
59
- return triggerEvent.shiftKey ? 'Redo' : 'Undo';
60
- }
61
- // Detect mouse event redo
62
- if (triggerEvent.ctrlKey && charCode === 'd') {
63
- return 'Delete';
64
- }
65
-
66
- // Android Fix.
67
- if (typeof triggerEvent.key === 'undefined') {
68
- if (unformattedValue.length <= unformatWithPattern(value, displayPattern).length) {
69
- return 'Backspace';
70
- }
71
- }
72
-
73
- return triggerEvent.key;
74
- };
75
-
76
- resetEvent = () => {
77
- this.setState({
78
- triggerType: null,
79
- triggerEvent: null,
80
- pastedLength: 0,
81
- });
82
- };
83
-
84
- detectUndoRedo = (event) => {
85
- const charCode = String.fromCharCode(event.which).toLowerCase();
86
- if ((event.ctrlKey || event.metaKey) && charCode === 'z') {
87
- return event.shiftKey ? 'Redo' : 'Undo';
88
- }
89
- return null;
90
- };
91
-
92
- handleOnKeyDown = (event) => {
93
- event.persist();
94
- const { selectionStart, selectionEnd } = event.target;
95
- const { historyNavigator } = this.state;
96
- const { displayPattern } = this.props;
97
-
98
- // Unfortunately Undo and Redo don't trigger OnChange event so we need to handle some value logic here.
99
- let newFormattedValue = '';
100
-
101
- if (this.detectUndoRedo(event) === 'Undo') {
102
- newFormattedValue = formatWithPattern(historyNavigator.undo(), displayPattern);
103
- this.setState({ value: newFormattedValue, triggerType: 'Undo' });
104
- } else if (this.detectUndoRedo(event) === 'Redo') {
105
- newFormattedValue = formatWithPattern(historyNavigator.redo(), displayPattern);
106
- this.setState({ value: newFormattedValue, triggerType: 'Redo' });
107
- } else {
108
- this.setState({
109
- triggerEvent: event,
110
- triggerType: 'KeyDown',
111
- selectionStart,
112
- selectionEnd,
113
- });
114
- }
115
- };
116
-
117
- handleOnPaste = (event) => {
118
- const { displayPattern } = this.props;
119
- const pastedLength = unformatWithPattern(
120
- event.clipboardData.getData('Text'),
121
- displayPattern,
122
- ).length;
123
-
124
- this.setState({ triggerType: 'Paste', pastedLength });
125
- };
126
-
127
- handleOnCut = () => {
128
- this.setState({ triggerType: 'Cut' });
129
- };
130
-
131
- isKeyAllowed = (action) => {
132
- const { displayPattern } = this.props;
133
- const symbolsInPattern = displayPattern.split('').filter((character) => character !== '*');
134
-
135
- return !symbolsInPattern.includes(action);
136
- };
137
-
138
- handleOnChange = (event) => {
139
- const { historyNavigator, triggerEvent, triggerType } = this.state;
140
- const { displayPattern, onChange } = this.props;
141
- const { value } = event.target;
142
- let unformattedValue = unformatWithPattern(value, displayPattern);
143
- const action =
144
- triggerEvent === null
145
- ? // triggerEvent can be null only in case of "autofilling" (via password manager extension or browser build-in one) events
146
- 'Paste'
147
- : this.getUserAction(unformattedValue);
148
- if (!this.isKeyAllowed(action) || triggerType === 'Undo' || triggerType === 'Redo') {
149
- return;
150
- }
151
-
152
- if (action === 'Backspace' || action === 'Delete') {
153
- unformattedValue = this.handleDelete(unformattedValue, action);
154
- }
155
-
156
- const newFormattedValue = formatWithPattern(unformattedValue, displayPattern);
157
- historyNavigator.add(unformattedValue);
158
-
159
- this.handleCursorPositioning(action);
160
-
161
- const broadcastValue = unformatWithPattern(newFormattedValue, displayPattern);
162
-
163
- this.setState({ value: newFormattedValue }, this.resetEvent(), onChange(broadcastValue));
164
- };
165
-
166
- handleOnBlur = (event) => {
167
- const { displayPattern, onBlur } = this.props;
168
- if (onBlur) {
169
- onBlur(unformatWithPattern(event.target.value, displayPattern));
170
- }
171
- };
172
-
173
- handleOnFocus = (event) => {
174
- const { displayPattern, onFocus } = this.props;
175
- if (onFocus) {
176
- this.handleOnChange(event);
177
- onFocus(unformatWithPattern(event.target.value, displayPattern));
178
- }
179
- };
180
-
181
- handleDelete = (unformattedValue, action) => {
182
- const { displayPattern } = this.props;
183
- const { selectionStart, selectionEnd } = this.state;
184
- const newStack = [...unformattedValue];
185
- if (selectionStart === selectionEnd) {
186
- let startPosition =
187
- selectionStart - getCountOfSymbolsInSelection(0, selectionStart, displayPattern);
188
- let toDelete = 0;
189
-
190
- let count = getDistanceToNextSymbol(selectionStart, displayPattern);
191
- if (action === 'Backspace') {
192
- startPosition -= 1;
193
- count = getDistanceToPreviousSymbol(selectionStart, displayPattern);
194
- }
195
-
196
- if (startPosition >= 0 && count) {
197
- toDelete = 1;
198
- }
199
-
200
- newStack.splice(startPosition, toDelete);
201
- }
202
-
203
- return newStack.join('');
204
- };
205
-
206
- handleCursorPositioning = (action) => {
207
- const { displayPattern } = this.props;
208
- const { triggerEvent, selectionStart, selectionEnd, pastedLength } = this.state;
209
-
210
- const cursorPosition = getCursorPositionAfterKeystroke(
211
- action,
212
- selectionStart,
213
- selectionEnd,
214
- displayPattern,
215
- pastedLength,
216
- );
217
-
218
- setTimeout(() => {
219
- if (triggerEvent) {
220
- triggerEvent.target.setSelectionRange(cursorPosition, cursorPosition);
221
- }
222
- this.setState({ selectionStart: cursorPosition, selectionEnd: cursorPosition });
223
- }, 0);
224
- };
225
-
226
- render() {
227
- const {
228
- type,
229
- inputMode,
230
- className,
231
- id,
232
- name,
233
- placeholder,
234
- readOnly,
235
- required,
236
- minLength,
237
- maxLength,
238
- disabled,
239
- autoComplete,
240
- } = this.props;
241
- const { value } = this.state;
242
- const renderProps = {
243
- type,
244
- inputMode,
245
- className,
246
- id,
247
- name,
248
- placeholder,
249
- readOnly,
250
- required,
251
- minLength,
252
- maxLength,
253
- disabled,
254
- autoComplete,
255
- value,
256
- onFocus: this.handleOnFocus,
257
- onBlur: this.handleOnBlur,
258
- onPaste: this.handleOnPaste,
259
- onKeyDown: this.handleOnKeyDown,
260
- onChange: this.handleOnChange,
261
- onCut: this.handleOnCut,
262
- };
263
- return this.props.render(renderProps);
264
- }
265
- }
266
-
267
- WithDisplayFormat.propTypes = {
268
- /**
269
- * autocomplete hides our form help so we need to disable it when help text
270
- * is present. Chrome ignores autocomplete=off, the only way to disable it is
271
- * to provide an 'invalid' value, for which 'disabled' serves.
272
- */
273
- autoComplete: PropTypes.oneOf(['on', 'off', 'disabled']),
274
- className: PropTypes.string,
275
- disabled: PropTypes.bool,
276
- id: PropTypes.string,
277
- maxLength: PropTypes.number,
278
- minLength: PropTypes.number,
279
- name: PropTypes.string,
280
- onFocus: PropTypes.func,
281
- onBlur: PropTypes.func,
282
- onChange: PropTypes.func.isRequired,
283
- placeholder: PropTypes.string,
284
- readOnly: PropTypes.bool,
285
- render: PropTypes.func.isRequired,
286
- required: PropTypes.bool,
287
- displayPattern: PropTypes.string,
288
- type: PropTypes.string,
289
- inputMode: PropTypes.string,
290
- value: PropTypes.string,
291
- };
292
-
293
- WithDisplayFormat.defaultProps = {
294
- autoComplete: 'off',
295
- className: null,
296
- disabled: false,
297
- id: null,
298
- maxLength: null,
299
- minLength: null,
300
- name: null,
301
- placeholder: null,
302
- readOnly: false,
303
- required: false,
304
- displayPattern: '',
305
- type: 'text',
306
- inputMode: null,
307
- value: '',
308
- onFocus: null,
309
- onBlur: null,
310
- };
311
-
312
- export default WithDisplayFormat;
@@ -1 +0,0 @@
1
- export { default } from './WithDisplayFormat';