@transferwise/components 46.5.0 → 46.7.0

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 (173) hide show
  1. package/build/i18n/th.json +3 -3
  2. package/build/index.esm.js +252 -464
  3. package/build/index.esm.js.map +1 -1
  4. package/build/index.js +253 -465
  5. package/build/index.js.map +1 -1
  6. package/build/main.css +6 -17
  7. package/build/styles/inputs/Input.css +0 -4
  8. package/build/styles/inputs/SelectInput.css +6 -1
  9. package/build/styles/inputs/TextArea.css +0 -4
  10. package/build/styles/main.css +6 -17
  11. package/build/styles/select/Select.css +0 -4
  12. package/build/types/common/locale/index.d.ts +26 -43
  13. package/build/types/common/locale/index.d.ts.map +1 -1
  14. package/build/types/common/textFormat/formatWithPattern/formatWithPattern.d.ts +1 -1
  15. package/build/types/common/textFormat/formatWithPattern/formatWithPattern.d.ts.map +1 -1
  16. package/build/types/common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.d.ts +2 -2
  17. package/build/types/common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.d.ts.map +1 -1
  18. package/build/types/common/textFormat/getSymbolsInPatternWithPosition/getSymbolsInPatternWithPosition.d.ts +5 -1
  19. package/build/types/common/textFormat/getSymbolsInPatternWithPosition/getSymbolsInPatternWithPosition.d.ts.map +1 -1
  20. package/build/types/common/textFormat/unformatWithPattern/unformatWithPattern.d.ts +1 -1
  21. package/build/types/common/textFormat/unformatWithPattern/unformatWithPattern.d.ts.map +1 -1
  22. package/build/types/index.d.ts +3 -0
  23. package/build/types/index.d.ts.map +1 -1
  24. package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts +7 -11
  25. package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts.map +1 -1
  26. package/build/types/inputWithDisplayFormat/index.d.ts +2 -1
  27. package/build/types/inputWithDisplayFormat/index.d.ts.map +1 -1
  28. package/build/types/inputs/SelectInput.d.ts +6 -5
  29. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  30. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts +22 -27
  31. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
  32. package/build/types/phoneNumberInput/data/countries.d.ts +5 -10
  33. package/build/types/phoneNumberInput/data/countries.d.ts.map +1 -1
  34. package/build/types/phoneNumberInput/index.d.ts +1 -1
  35. package/build/types/phoneNumberInput/index.d.ts.map +1 -1
  36. package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts +1 -1
  37. package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts.map +1 -1
  38. package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts +1 -1
  39. package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts.map +1 -1
  40. package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts +8 -1
  41. package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts.map +1 -1
  42. package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts +1 -1
  43. package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts.map +1 -1
  44. package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts +8 -4
  45. package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts.map +1 -1
  46. package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts +1 -1
  47. package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts.map +1 -1
  48. package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts +1 -1
  49. package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts.map +1 -1
  50. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts +2 -1
  51. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts.map +1 -1
  52. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts +1 -1
  53. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts.map +1 -1
  54. package/build/types/phoneNumberInput/utils/index.d.ts +11 -13
  55. package/build/types/phoneNumberInput/utils/index.d.ts.map +1 -1
  56. package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts +1 -1
  57. package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts.map +1 -1
  58. package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts +1 -1
  59. package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts.map +1 -1
  60. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts +1 -1
  61. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts.map +1 -1
  62. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts +6 -1
  63. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts.map +1 -1
  64. package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts +2 -1
  65. package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts.map +1 -1
  66. package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts +7 -1
  67. package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts.map +1 -1
  68. package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts +1 -1
  69. package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts.map +1 -1
  70. package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts +1 -1
  71. package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts.map +1 -1
  72. package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts +7 -11
  73. package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts.map +1 -1
  74. package/build/types/textareaWithDisplayFormat/index.d.ts +2 -1
  75. package/build/types/textareaWithDisplayFormat/index.d.ts.map +1 -1
  76. package/build/types/withDisplayFormat/WithDisplayFormat.d.ts +55 -83
  77. package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
  78. package/build/types/withDisplayFormat/index.d.ts +2 -1
  79. package/build/types/withDisplayFormat/index.d.ts.map +1 -1
  80. package/package.json +3 -4
  81. package/src/common/locale/{index.spec.js → index.spec.ts} +4 -4
  82. package/src/common/locale/index.ts +96 -0
  83. package/src/common/textFormat/formatWithPattern/{formatWithPattern.js → formatWithPattern.ts} +8 -4
  84. package/src/common/textFormat/getCursorPositionAfterKeystroke/{getCursorPositionAfterKeystroke.js → getCursorPositionAfterKeystroke.ts} +8 -8
  85. package/src/common/textFormat/getSymbolsInPatternWithPosition/{getSymbolsInPatternWithPosition.js → getSymbolsInPatternWithPosition.ts} +7 -2
  86. package/src/common/textFormat/unformatWithPattern/{unformatWithPattern.js → unformatWithPattern.ts} +3 -2
  87. package/src/i18n/th.json +3 -3
  88. package/src/index.ts +3 -0
  89. package/src/inputWithDisplayFormat/InputWithDisplayFormat.tsx +10 -0
  90. package/src/inputWithDisplayFormat/index.ts +2 -0
  91. package/src/inputs/Input.css +0 -4
  92. package/src/inputs/SelectInput.css +6 -1
  93. package/src/inputs/SelectInput.less +8 -1
  94. package/src/inputs/SelectInput.spec.tsx +26 -0
  95. package/src/inputs/SelectInput.story.tsx +73 -1
  96. package/src/inputs/SelectInput.tsx +104 -85
  97. package/src/inputs/TextArea.css +0 -4
  98. package/src/main.css +6 -17
  99. package/src/phoneNumberInput/PhoneNumberInput.spec.js +18 -22
  100. package/src/phoneNumberInput/PhoneNumberInput.tsx +193 -0
  101. package/src/phoneNumberInput/data/{countries.js → countries.ts} +9 -1
  102. package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.ts +3 -0
  103. package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.spec.js → excludeCountries.spec.ts} +1 -1
  104. package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.js → excludeCountries.ts} +6 -5
  105. package/src/phoneNumberInput/utils/explodeNumberModel/{explodeNumberModel.spec.js → explodeNumberModel.spec.ts} +1 -1
  106. package/src/phoneNumberInput/utils/explodeNumberModel/index.ts +24 -0
  107. package/src/phoneNumberInput/utils/findCountryByCode/{findCountryByCode.spec.js → findCountryByCode.spec.ts} +0 -1
  108. package/src/phoneNumberInput/utils/findCountryByCode/index.ts +12 -0
  109. package/src/phoneNumberInput/utils/findCountryByPrefix/index.ts +12 -0
  110. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.ts +102 -0
  111. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.ts +12 -0
  112. package/src/phoneNumberInput/utils/{index.js → index.ts} +0 -2
  113. package/src/phoneNumberInput/utils/isStringNumeric/{isStringNumeric.spec.js → isStringNumeric.spec.ts} +0 -1
  114. package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.ts +1 -0
  115. package/src/phoneNumberInput/utils/isValidPhoneNumber/{isValidPhoneNumber.spec.js → isValidPhoneNumber.spec.ts} +1 -1
  116. package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.ts +7 -0
  117. package/src/phoneNumberInput/utils/longestMatchingPrefix/index.ts +4 -0
  118. package/src/phoneNumberInput/utils/setDefaultPrefix/index.ts +20 -0
  119. package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.ts +6 -0
  120. package/src/select/Select.css +0 -4
  121. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.spec.js +3 -1
  122. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.story.tsx +32 -0
  123. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.tsx +13 -0
  124. package/src/textareaWithDisplayFormat/index.ts +2 -0
  125. package/src/withDisplayFormat/WithDisplayFormat.spec.js +1 -1
  126. package/src/withDisplayFormat/{WithDisplayFormat.js → WithDisplayFormat.tsx} +127 -107
  127. package/src/withDisplayFormat/index.ts +2 -0
  128. package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts +0 -2
  129. package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts.map +0 -1
  130. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts +0 -2
  131. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts.map +0 -1
  132. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts +0 -3
  133. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts.map +0 -1
  134. package/build/types/utilities/wrapInFragment.d.ts +0 -3
  135. package/build/types/utilities/wrapInFragment.d.ts.map +0 -1
  136. package/src/common/locale/index.js +0 -139
  137. package/src/inputWithDisplayFormat/InputWithDisplayFormat.js +0 -14
  138. package/src/inputWithDisplayFormat/index.js +0 -1
  139. package/src/phoneNumberInput/PhoneNumberInput.js +0 -210
  140. package/src/phoneNumberInput/data/countries.spec.js +0 -12
  141. package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.js +0 -4
  142. package/src/phoneNumberInput/utils/explodeNumberModel/index.js +0 -27
  143. package/src/phoneNumberInput/utils/filterOptionsForQuery/filterOptionsForQuery.spec.js +0 -36
  144. package/src/phoneNumberInput/utils/filterOptionsForQuery/index.js +0 -11
  145. package/src/phoneNumberInput/utils/findCountryByCode/index.js +0 -10
  146. package/src/phoneNumberInput/utils/findCountryByPrefix/index.js +0 -11
  147. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.js +0 -26
  148. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.js +0 -67
  149. package/src/phoneNumberInput/utils/isOptionAndFitsQuery/index.js +0 -1
  150. package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.js +0 -25
  151. package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.spec.js +0 -66
  152. package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.js +0 -1
  153. package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js +0 -10
  154. package/src/phoneNumberInput/utils/longestMatchingPrefix/index.js +0 -2
  155. package/src/phoneNumberInput/utils/setDefaultPrefix/index.js +0 -25
  156. package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.js +0 -3
  157. package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.js +0 -14
  158. package/src/textareaWithDisplayFormat/index.js +0 -1
  159. package/src/utilities/wrapInFragment.tsx +0 -3
  160. package/src/withDisplayFormat/index.js +0 -1
  161. /package/src/phoneNumberInput/{PhoneNumberInput.story.js → PhoneNumberInput.story.tsx} +0 -0
  162. /package/src/phoneNumberInput/{index.js → index.ts} +0 -0
  163. /package/src/phoneNumberInput/utils/cleanNumber/{cleanNumber.spec.js → cleanNumber.spec.ts} +0 -0
  164. /package/src/phoneNumberInput/utils/cleanNumber/{index.js → index.ts} +0 -0
  165. /package/src/phoneNumberInput/utils/excludeCountries/{index.js → index.ts} +0 -0
  166. /package/src/phoneNumberInput/utils/findCountryByPrefix/{findCountryByPrefix.spec.js → findCountryByPrefix.spec.ts} +0 -0
  167. /package/src/phoneNumberInput/utils/groupCountriesByPrefix/{index.js → index.ts} +0 -0
  168. /package/src/phoneNumberInput/utils/isStringNumeric/{index.js → index.ts} +0 -0
  169. /package/src/phoneNumberInput/utils/isValidPhoneNumber/{index.js → index.ts} +0 -0
  170. /package/src/phoneNumberInput/utils/longestMatchingPrefix/{longestMatchingPrefix.spec.js → longestMatchingPrefix.spec.ts} +0 -0
  171. /package/src/phoneNumberInput/utils/setDefaultPrefix/{setDefaultPrefix.spec.js → setDefaultPrefix.spec.ts} +0 -0
  172. /package/src/phoneNumberInput/utils/sortArrayByProperty/{index.js → index.ts} +0 -0
  173. /package/src/phoneNumberInput/utils/sortArrayByProperty/{sortArrayByProperty.spec.js → sortArrayByProperty.spec.ts} +0 -0
@@ -1,5 +1,7 @@
1
1
  import { shallow } from 'enzyme';
2
2
 
3
+ import { TextArea } from '../inputs/TextArea';
4
+
3
5
  import TextareaWithDisplayFormat from '.';
4
6
 
5
7
  describe('TextareaWithDisplayFormat', () => {
@@ -10,6 +12,6 @@ describe('TextareaWithDisplayFormat', () => {
10
12
  .find('WithDisplayFormat')
11
13
  .renderProp('render')({ value: 'test' });
12
14
 
13
- expect(view.find('textarea').props('value')).toStrictEqual({ value: 'test' });
15
+ expect(view.find(TextArea).props('value')).toStrictEqual({ value: 'test' });
14
16
  });
15
17
  });
@@ -0,0 +1,32 @@
1
+ import { StoryObj } from '@storybook/react';
2
+
3
+ import { userEvent, within } from '../test-utils';
4
+
5
+ import TextareaWithDisplayFormat from './TextareaWithDisplayFormat';
6
+
7
+ export default {
8
+ component: TextareaWithDisplayFormat,
9
+ title: 'Forms/TextareaWithDisplayFormat',
10
+ };
11
+
12
+ type Story = StoryObj<typeof TextareaWithDisplayFormat>;
13
+
14
+ export const Basic: Story = {
15
+ render: (args) => {
16
+ return (
17
+ <>
18
+ <TextareaWithDisplayFormat
19
+ value="0000"
20
+ displayPattern="**** - **** - ****"
21
+ onChange={console.log}
22
+ />
23
+ </>
24
+ );
25
+ },
26
+ // intentionally use interactive typing (over init value via `value` prop)
27
+ // to trigger event handlers in the component
28
+ play: ({ canvasElement }) => {
29
+ const canvas = within(canvasElement);
30
+ userEvent.type(canvas.getByRole('textbox'), '111122223333');
31
+ },
32
+ };
@@ -0,0 +1,13 @@
1
+ import { TextArea, type TextAreaProps } from '../inputs/TextArea';
2
+ import WithDisplayFormat, { type WithDisplayFormatProps } from '../withDisplayFormat';
3
+
4
+ export interface TextareaWithDisplayFormatProps extends Omit<WithDisplayFormatProps, 'render'> {}
5
+
6
+ const TextareaWithDisplayFormat = (props: TextareaWithDisplayFormatProps) => (
7
+ <WithDisplayFormat<TextAreaProps>
8
+ {...props}
9
+ render={(renderProps) => <TextArea {...renderProps} />}
10
+ />
11
+ );
12
+
13
+ export default TextareaWithDisplayFormat;
@@ -0,0 +1,2 @@
1
+ export { default } from './TextareaWithDisplayFormat';
2
+ export type { TextareaWithDisplayFormatProps } from './TextareaWithDisplayFormat';
@@ -145,7 +145,7 @@ describe('InputWithTextFormat', () => {
145
145
  });
146
146
 
147
147
  describe('set cursor position', () => {
148
- const triggerEventA = { ...triggerEvent, target: { setSelectionRange: () => {} } };
148
+ const triggerEventA = { ...triggerEvent, currentTarget: { setSelectionRange: () => {} } };
149
149
  beforeEach(() => {
150
150
  component.setState({
151
151
  triggerEvent: triggerEventA,
@@ -1,4 +1,3 @@
1
- import PropTypes from 'prop-types';
2
1
  import { Component } from 'react';
3
2
 
4
3
  import { HistoryNavigator } from '../common';
@@ -10,27 +9,93 @@ import {
10
9
  getDistanceToPreviousSymbol,
11
10
  getDistanceToNextSymbol,
12
11
  } from '../common/textFormat';
12
+ import { InputProps } from '../inputs/Input';
13
+ import { TextAreaProps } from '../inputs/TextArea';
14
+
15
+ type HTMLTextElement = HTMLInputElement | HTMLTextAreaElement;
16
+ type TextElementProps = InputProps | TextAreaProps;
17
+
18
+ export type EventType =
19
+ | 'KeyDown'
20
+ | 'Paste'
21
+ | 'Cut'
22
+ | 'Undo'
23
+ | 'Redo'
24
+ | 'Backspace'
25
+ | 'Delete'
26
+ | 'Initial';
27
+
28
+ interface WithDisplayFormatState {
29
+ value: string;
30
+ historyNavigator: HistoryNavigator;
31
+ prevDisplayPattern: string;
32
+ triggerType: EventType;
33
+ triggerEvent: React.KeyboardEvent<HTMLTextElement> | null;
34
+ pastedLength: number;
35
+ selectionStart: number;
36
+ selectionEnd: number;
37
+ }
38
+
39
+ export interface WithDisplayFormatProps<T extends TextElementProps = TextElementProps>
40
+ extends Pick<
41
+ TextElementProps,
42
+ | 'className'
43
+ | 'disabled'
44
+ | 'id'
45
+ | 'maxLength'
46
+ | 'minLength'
47
+ | 'name'
48
+ | 'placeholder'
49
+ | 'readOnly'
50
+ | 'required'
51
+ | 'inputMode'
52
+ > {
53
+ value?: string;
54
+ displayPattern: string;
55
+ /**
56
+ * autocomplete hides our form help so we need to disable it when help text
57
+ * is present. Chrome ignores autocomplete=off, the only way to disable it is
58
+ * to provide an 'invalid' value, for which 'disabled' serves.
59
+ */
60
+ autoComplete?: TextElementProps['autoComplete'] | 'disabled';
61
+ onChange?: (value: string) => void;
62
+ onBlur?: (value: string) => void;
63
+ onFocus?: (value: string) => void;
64
+ render: (renderProps: T) => JSX.Element;
65
+ }
13
66
 
14
- class WithDisplayFormat extends Component {
15
- constructor(props) {
67
+ class WithDisplayFormat<T extends TextElementProps> extends Component<
68
+ WithDisplayFormatProps<T>,
69
+ WithDisplayFormatState
70
+ > {
71
+ declare props: WithDisplayFormatProps<T> &
72
+ Required<Pick<WithDisplayFormatProps<T>, keyof typeof WithDisplayFormat.defaultProps>>;
73
+ static defaultProps = {
74
+ autoComplete: 'off',
75
+ displayPattern: '',
76
+ value: '',
77
+ };
78
+
79
+ constructor(props: WithDisplayFormatProps) {
16
80
  super(props);
17
- const { value, displayPattern } = props;
18
- const unformattedValue = unformatWithPattern(value, displayPattern);
81
+ const unformattedValue = unformatWithPattern(props.value ?? '', props.displayPattern);
19
82
  this.state = {
20
- value: formatWithPattern(unformattedValue, displayPattern),
83
+ value: formatWithPattern(unformattedValue, props.displayPattern),
21
84
  historyNavigator: new HistoryNavigator(),
22
85
  prevDisplayPattern: props.displayPattern,
23
- triggerType: null,
86
+ triggerType: 'Initial',
24
87
  triggerEvent: null,
88
+ selectionStart: 0,
89
+ selectionEnd: 0,
90
+ pastedLength: 0,
25
91
  };
26
92
  }
27
93
 
28
- static getDerivedStateFromProps(nextProps, previousState) {
29
- const { displayPattern } = nextProps;
30
- const { prevDisplayPattern } = previousState;
31
- if (previousState.prevDisplayPattern !== displayPattern) {
32
- const { value, historyNavigator } = previousState;
33
-
94
+ static getDerivedStateFromProps(
95
+ { displayPattern }: WithDisplayFormatProps,
96
+ { prevDisplayPattern = displayPattern, value, historyNavigator }: WithDisplayFormatState,
97
+ ) {
98
+ if (prevDisplayPattern !== displayPattern) {
34
99
  const unFormattedValue = unformatWithPattern(value, prevDisplayPattern);
35
100
  historyNavigator.reset();
36
101
 
@@ -45,43 +110,48 @@ class WithDisplayFormat extends Component {
45
110
  return null;
46
111
  }
47
112
 
48
- getUserAction = (unformattedValue) => {
113
+ getUserAction = (unformattedValue: string): EventType | string => {
49
114
  const { triggerEvent, triggerType, value } = this.state;
50
115
  const { displayPattern } = this.props;
51
116
 
52
- const charCode = String.fromCharCode(triggerEvent.which).toLowerCase();
117
+ if (triggerEvent) {
118
+ const charCode = String.fromCharCode(triggerEvent.which).toLowerCase();
53
119
 
54
- if (triggerType === 'Paste' || triggerType === 'Cut') {
55
- return triggerType;
56
- }
120
+ if (triggerType === 'Paste' || triggerType === 'Cut') {
121
+ return triggerType;
122
+ }
57
123
 
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
- }
124
+ if ((triggerEvent.ctrlKey || triggerEvent.metaKey) && charCode === 'z') {
125
+ return triggerEvent.shiftKey ? 'Redo' : 'Undo';
126
+ }
127
+ // Detect mouse event redo
128
+ if (triggerEvent.ctrlKey && charCode === 'd') {
129
+ return 'Delete';
130
+ }
65
131
 
66
- // Android Fix.
67
- if (typeof triggerEvent.key === 'undefined') {
68
- if (unformattedValue.length <= unformatWithPattern(value, displayPattern).length) {
132
+ // Android Fix.
133
+ if (
134
+ typeof triggerEvent.key === 'undefined' &&
135
+ unformattedValue.length <= unformatWithPattern(value, displayPattern).length
136
+ ) {
69
137
  return 'Backspace';
70
138
  }
139
+ return triggerEvent.key;
140
+ } else {
141
+ // triggerEvent can be null only in case of "autofilling" (via password manager extension or browser build-in one) events
142
+ return 'Paste';
71
143
  }
72
-
73
- return triggerEvent.key;
74
144
  };
75
145
 
76
146
  resetEvent = () => {
77
147
  this.setState({
78
- triggerType: null,
148
+ triggerType: 'Initial',
79
149
  triggerEvent: null,
80
150
  pastedLength: 0,
81
151
  });
82
152
  };
83
153
 
84
- detectUndoRedo = (event) => {
154
+ detectUndoRedo = (event: React.KeyboardEvent<HTMLTextElement>) => {
85
155
  const charCode = String.fromCharCode(event.which).toLowerCase();
86
156
  if ((event.ctrlKey || event.metaKey) && charCode === 'z') {
87
157
  return event.shiftKey ? 'Redo' : 'Undo';
@@ -89,9 +159,9 @@ class WithDisplayFormat extends Component {
89
159
  return null;
90
160
  };
91
161
 
92
- handleOnKeyDown = (event) => {
162
+ handleOnKeyDown: React.KeyboardEventHandler<HTMLTextElement> = (event) => {
93
163
  event.persist();
94
- const { selectionStart, selectionEnd } = event.target;
164
+ const { selectionStart, selectionEnd } = event.currentTarget;
95
165
  const { historyNavigator } = this.state;
96
166
  const { displayPattern } = this.props;
97
167
 
@@ -108,13 +178,13 @@ class WithDisplayFormat extends Component {
108
178
  this.setState({
109
179
  triggerEvent: event,
110
180
  triggerType: 'KeyDown',
111
- selectionStart,
112
- selectionEnd,
181
+ selectionStart: selectionStart ?? 0,
182
+ selectionEnd: selectionEnd ?? 0,
113
183
  });
114
184
  }
115
185
  };
116
186
 
117
- handleOnPaste = (event) => {
187
+ handleOnPaste: React.ClipboardEventHandler<HTMLTextElement> = (event) => {
118
188
  const { displayPattern } = this.props;
119
189
  const pastedLength = unformatWithPattern(
120
190
  event.clipboardData.getData('Text'),
@@ -124,27 +194,23 @@ class WithDisplayFormat extends Component {
124
194
  this.setState({ triggerType: 'Paste', pastedLength });
125
195
  };
126
196
 
127
- handleOnCut = () => {
197
+ handleOnCut: React.ClipboardEventHandler<HTMLTextElement> = () => {
128
198
  this.setState({ triggerType: 'Cut' });
129
199
  };
130
200
 
131
- isKeyAllowed = (action) => {
201
+ isKeyAllowed = (action: EventType | string) => {
132
202
  const { displayPattern } = this.props;
133
203
  const symbolsInPattern = displayPattern.split('').filter((character) => character !== '*');
134
204
 
135
205
  return !symbolsInPattern.includes(action);
136
206
  };
137
207
 
138
- handleOnChange = (event) => {
139
- const { historyNavigator, triggerEvent, triggerType } = this.state;
208
+ handleOnChange: React.ChangeEventHandler<HTMLTextElement> = (event) => {
209
+ const { historyNavigator, triggerType } = this.state;
140
210
  const { displayPattern, onChange } = this.props;
141
211
  const { value } = event.target;
142
212
  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);
213
+ const action = this.getUserAction(unformattedValue);
148
214
  if (!this.isKeyAllowed(action) || triggerType === 'Undo' || triggerType === 'Redo') {
149
215
  return;
150
216
  }
@@ -158,19 +224,20 @@ class WithDisplayFormat extends Component {
158
224
 
159
225
  this.handleCursorPositioning(action);
160
226
 
161
- const broadcastValue = unformatWithPattern(newFormattedValue, displayPattern);
162
-
163
- this.setState({ value: newFormattedValue }, this.resetEvent(), onChange(broadcastValue));
227
+ this.setState({ value: newFormattedValue }, () => {
228
+ this.resetEvent();
229
+ if (onChange) {
230
+ const broadcastValue = unformatWithPattern(newFormattedValue, displayPattern);
231
+ onChange(broadcastValue);
232
+ }
233
+ });
164
234
  };
165
235
 
166
- handleOnBlur = (event) => {
167
- const { displayPattern, onBlur } = this.props;
168
- if (onBlur) {
169
- onBlur(unformatWithPattern(event.target.value, displayPattern));
170
- }
236
+ handleOnBlur: React.FocusEventHandler<HTMLTextElement> = (event) => {
237
+ this.props.onBlur?.(unformatWithPattern(event.target.value, this.props.displayPattern));
171
238
  };
172
239
 
173
- handleOnFocus = (event) => {
240
+ handleOnFocus: React.FocusEventHandler<HTMLTextElement> = (event) => {
174
241
  const { displayPattern, onFocus } = this.props;
175
242
  if (onFocus) {
176
243
  this.handleOnChange(event);
@@ -178,7 +245,7 @@ class WithDisplayFormat extends Component {
178
245
  }
179
246
  };
180
247
 
181
- handleDelete = (unformattedValue, action) => {
248
+ handleDelete = (unformattedValue: string, action: EventType) => {
182
249
  const { displayPattern } = this.props;
183
250
  const { selectionStart, selectionEnd } = this.state;
184
251
  const newStack = [...unformattedValue];
@@ -203,7 +270,7 @@ class WithDisplayFormat extends Component {
203
270
  return newStack.join('');
204
271
  };
205
272
 
206
- handleCursorPositioning = (action) => {
273
+ handleCursorPositioning = (action: string) => {
207
274
  const { displayPattern } = this.props;
208
275
  const { triggerEvent, selectionStart, selectionEnd, pastedLength } = this.state;
209
276
 
@@ -217,7 +284,7 @@ class WithDisplayFormat extends Component {
217
284
 
218
285
  setTimeout(() => {
219
286
  if (triggerEvent) {
220
- triggerEvent.target.setSelectionRange(cursorPosition, cursorPosition);
287
+ triggerEvent.currentTarget.setSelectionRange(cursorPosition, cursorPosition);
221
288
  }
222
289
  this.setState({ selectionStart: cursorPosition, selectionEnd: cursorPosition });
223
290
  }, 0);
@@ -225,7 +292,6 @@ class WithDisplayFormat extends Component {
225
292
 
226
293
  render() {
227
294
  const {
228
- type,
229
295
  inputMode,
230
296
  className,
231
297
  id,
@@ -239,8 +305,7 @@ class WithDisplayFormat extends Component {
239
305
  autoComplete,
240
306
  } = this.props;
241
307
  const { value } = this.state;
242
- const renderProps = {
243
- type,
308
+ const renderProps: TextElementProps = {
244
309
  inputMode,
245
310
  className,
246
311
  id,
@@ -260,53 +325,8 @@ class WithDisplayFormat extends Component {
260
325
  onChange: this.handleOnChange,
261
326
  onCut: this.handleOnCut,
262
327
  };
263
- return this.props.render(renderProps);
328
+ return this.props.render(renderProps as T);
264
329
  }
265
330
  }
266
331
 
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
332
  export default WithDisplayFormat;
@@ -0,0 +1,2 @@
1
+ export { default } from './WithDisplayFormat';
2
+ export type { WithDisplayFormatProps } from './WithDisplayFormat';
@@ -1,2 +0,0 @@
1
- export function filterOptionsForQuery(options: any, query: any): any;
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/filterOptionsForQuery/index.js"],"names":[],"mappings":"AASO,qEAC0D"}
@@ -1,2 +0,0 @@
1
- export { isOptionAndFitsQuery, startsWith } from "./isOptionAndFitsQuery";
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isOptionAndFitsQuery/index.js"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- export function isOptionAndFitsQuery(option: object, query: string): boolean;
2
- export function startsWith(property: any, query: any): boolean;
3
- //# sourceMappingURL=isOptionAndFitsQuery.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"isOptionAndFitsQuery.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.js"],"names":[],"mappings":"AAQO,6CAJI,MAAM,SACN,MAAM,GACJ,OAAO,CAMa;AAE1B,+DAQN"}
@@ -1,3 +0,0 @@
1
- /// <reference types="react" />
2
- export declare function wrapInFragment(value: unknown): import("react").JSX.Element;
3
- //# sourceMappingURL=wrapInFragment.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wrapInFragment.d.ts","sourceRoot":"","sources":["../../../src/utilities/wrapInFragment.tsx"],"names":[],"mappings":";AAAA,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,+BAE5C"}
@@ -1,139 +0,0 @@
1
- import { Direction } from '..';
2
-
3
- /**
4
- * Default language
5
- *
6
- * @type {string}
7
- */
8
- export const DEFAULT_LANG = 'en';
9
-
10
- /**
11
- * Default locale
12
- *
13
- * @type {string}
14
- */
15
- export const DEFAULT_LOCALE = 'en-GB';
16
-
17
- /**
18
- * Array of languages that are written from the right to the left
19
- *
20
- * @type {string[]}
21
- */
22
- export const RTL_LANGUAGES = ['ar', 'he'];
23
-
24
- /**
25
- * @deprecated The source of truth for supported languages lives in Crab.
26
- * @type {string[]}
27
- */
28
- export const SUPPORTED_LANGUAGES = [
29
- DEFAULT_LANG,
30
- 'de',
31
- 'es',
32
- 'fr',
33
- 'hu',
34
- 'id',
35
- 'it',
36
- 'ja',
37
- 'pl',
38
- 'pt',
39
- 'ro',
40
- 'ru',
41
- 'th',
42
- 'tr',
43
- 'uk',
44
- 'zh',
45
- ];
46
-
47
- /**
48
- * Verifies and adjusts locale (replace `_` with `-`)
49
- * Returns null if locale is unrecognized by {Intl.Locale}
50
- *
51
- * @param {string} locale (`es`, `es_ES`, `en-GB`, `en`, `ja`, `ja-JP` etc)
52
- * @returns {string|null}
53
- */
54
- export function adjustLocale(locale) {
55
- if (!locale || locale.trim().length === 0) {
56
- return null;
57
- }
58
- try {
59
- const { baseName } = new Intl.Locale(locale.trim().replace('_', '-'));
60
- return baseName;
61
- } catch (error) {
62
- // eslint-disable-next-line no-console
63
- console.error(error);
64
- return null;
65
- }
66
- }
67
-
68
- /**
69
- * Provides corresponding lang (iso2) for provided locale
70
- * if locale is invalid or language is unsupported returns null
71
- *
72
- * @deprecated The use of this function almost always breaks language variants
73
- * e.g. Simplified and Traditional Chinese.
74
- * There should be no use case for this function.
75
- * To select the correct translations from a translations object, pass the
76
- * locale directly into Crab's getLocalisedMessages.
77
- * @param {string} locale (`es`, `es-ES`, `en-GB`, `en`, `ja`, `ja-JP` etc)
78
- * @returns {string|null} two-letter ISO639-1 language
79
- */
80
- export function getLangFromLocale(locale) {
81
- const adjustedLocale = adjustLocale(locale);
82
- if (adjustedLocale === null) {
83
- return null;
84
- }
85
- try {
86
- const { language } = new Intl.Locale(adjustedLocale);
87
-
88
- if (SUPPORTED_LANGUAGES.includes(language)) {
89
- return language;
90
- }
91
- return null;
92
- } catch (error) {
93
- // eslint-disable-next-line no-console
94
- console.error(error);
95
- return null;
96
- }
97
- }
98
-
99
- /**
100
- * Provides corresponding country code (iso2) for locales code with explicit region value (`es-ES`, `en-GB`, `ja-JP` etc.)
101
- * if the value is invalid or missing region it returns null
102
- *
103
- * @param {string} locale
104
- * @returns {string|null}
105
- */
106
- export function getCountryFromLocale(locale) {
107
- const adjustedLocale = adjustLocale(locale);
108
- if (adjustedLocale === null) {
109
- return null;
110
- }
111
- try {
112
- const { region } = new Intl.Locale(adjustedLocale);
113
- return region ?? null;
114
- } catch (error) {
115
- // eslint-disable-next-line no-console
116
- console.error(error);
117
- return null;
118
- }
119
- }
120
-
121
- /**
122
- * Provides the layout direction for a given locale.
123
- * If locale is invalid or language is unsupported returns Direction.LTR
124
- *
125
- * @param {string} locale (`es`, `es-ES`, `en-GB`, `en`, `ja`, `ja-JP` etc)
126
- * @returns {Direction} The layout direction based on the locale
127
- */
128
- export function getDirectionFromLocale(locale) {
129
- try {
130
- const adjustedLocale = adjustLocale(locale);
131
- const { language } = new Intl.Locale(adjustedLocale);
132
-
133
- return RTL_LANGUAGES.includes(language) ? Direction.RTL : Direction.LTR;
134
- } catch (error) {
135
- // eslint-disable-next-line no-console
136
- console.error(error);
137
- return Direction.LTR;
138
- }
139
- }
@@ -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';