Skip to content

Commit 7d56aa9

Browse files
authored
refactor(text-input): migrate to TypeScript (#1868)
1 parent 4acb66d commit 7d56aa9

File tree

7 files changed

+103
-95
lines changed

7 files changed

+103
-95
lines changed

.changeset/lovely-tips-build.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@commercetools-uikit/text-input': patch
3+
---
4+
5+
Migrate `<TextInput />` to TypeScript

packages/components/inputs/text-input/README.md

+17-17
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,23 @@ export default Example;
4242

4343
## Properties
4444

45-
| Props | Type | Required | Default | Description |
46-
| ---------------------- | -------------------------------------------------------------------------------------------------- | :------: | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
47-
| `id` | `string` | | | Used as HTML id property. An id is auto-generated when it is not specified. |
48-
| `autoComplete` | `string` | | | Used as HTML autocomplete property |
49-
| `className` | `string` | | | |
50-
| `name` | `string` | | | Used as HTML name of the input component. property |
51-
| `value` | `string` || | Value of the input component. |
52-
| `onChange` | `custom` | | | Called with an event containing the new value. Required when input is not read only. Parent should pass it back as value.&#xA;<br />&#xA;Signature: `(event) => void` |
53-
| `onBlur` | `func` | | | Called when input is blurred&#xA;Signature: `(event) => void` |
54-
| `onFocus` | `func` | | | Called when input is focused&#xA;Signature: `(event) => void` |
55-
| `isAutofocussed` | `bool` | | | Focus the input on initial render |
56-
| `isDisabled` | `bool` | | | Indicates that the input cannot be modified (e.g not authorized, or changes currently saving). |
57-
| `isReadOnly` | `bool` | | | Indicates that the field is displaying read-only content |
58-
| `hasError` | `bool` | | | Indicates if the input has invalid values |
59-
| `hasWarning` | `bool` | | | |
60-
| `placeholder` | `string` | | | Placeholder text for the input |
61-
| `horizontalConstraint` | `enum`<br/>Possible values:<br/>`3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 'scale', 'auto'` | | `'scale'` | Horizontal size limit of the input fields. |
45+
| Props | Type | Required | Default | Description |
46+
| ---------------------- | ----------------------------------------------------------------------------------------------------- | :------: | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
47+
| `id` | `string` | | | Used as HTML id property. An id is auto-generated when it is not specified. |
48+
| `autoComplete` | `string` | | | Used as HTML autocomplete property |
49+
| `className` | `string` | | | `className` forwarded to the underlying `<input />`. |
50+
| `name` | `string` | | | Used as HTML name of the input component. property |
51+
| `value` | `string` || | Value of the input component. |
52+
| `onChange` | `ChangeEventHandler` | | | Called with an event containing the new value. Required when input is not read only. Parent should pass it back as value.&#xA;<br />&#xA;Signature: `(event) => void` |
53+
| `onBlur` | `FocusEventHandler` | | | Called when input is blurred&#xA;Signature: `(event) => void` |
54+
| `onFocus` | `FocusEventHandler` | | | Called when input is focused&#xA;Signature: `(event) => void` |
55+
| `isAutofocussed` | `boolean` | | | Focus the input on initial render |
56+
| `isDisabled` | `boolean` | | | Indicates that the input cannot be modified (e.g not authorized, or changes currently saving). |
57+
| `isReadOnly` | `boolean` | | | Indicates that the field is displaying read-only content |
58+
| `hasError` | `boolean` | | | Indicates if the input has invalid values |
59+
| `hasWarning` | `boolean` | | | |
60+
| `placeholder` | `string` | | | Placeholder text for the input |
61+
| `horizontalConstraint` | `union`<br/>Possible values:<br/>`, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 'scale', 'auto'` | | `'scale'` | Horizontal size limit of the input fields. |
6262

6363
## `data-*` props
6464

packages/components/inputs/text-input/package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
"@commercetools-uikit/utils": "12.0.0",
3232
"@emotion/react": "^11.1.1",
3333
"@emotion/styled": "^11.0.0",
34-
"prop-types": "15.7.2",
35-
"react-required-if": "1.0.3"
34+
"prop-types": "15.7.2"
3635
},
3736
"devDependencies": {
3837
"react": "17.0.1"
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,131 @@
1-
import React from 'react';
2-
import PropTypes from 'prop-types';
3-
import requiredIf from 'react-required-if';
1+
import React, { FocusEventHandler, ChangeEventHandler } from 'react';
42
import { useTheme } from '@emotion/react';
5-
import { filterDataAttributes } from '@commercetools-uikit/utils';
3+
import { filterDataAttributes, warning } from '@commercetools-uikit/utils';
64
import Constraints from '@commercetools-uikit/constraints';
75
import { getInputStyles } from '@commercetools-uikit/input-utils';
86

9-
const TextInput = (props) => {
10-
const theme = useTheme();
11-
return (
12-
<Constraints.Horizontal max={props.horizontalConstraint}>
13-
<input
14-
id={props.id}
15-
name={props.name}
16-
type="text"
17-
value={props.value}
18-
onChange={props.onChange}
19-
onBlur={props.onBlur}
20-
onFocus={props.onFocus}
21-
disabled={props.isDisabled}
22-
placeholder={props.placeholder}
23-
readOnly={props.isReadOnly}
24-
autoFocus={props.isAutofocussed}
25-
autoComplete={props.autoComplete}
26-
css={getInputStyles(props, theme)}
27-
// Allow to override the styles by passing a `className` prop.
28-
// Custom styles can also be passed using the `css` prop from emotion.
29-
// https://emotion.sh/docs/css-prop#style-precedence
30-
className={props.className}
31-
{...filterDataAttributes(props)}
32-
/* ARIA */
33-
aria-readonly={props.isReadOnly}
34-
role="textbox"
35-
contentEditable={!props.isReadOnly}
36-
/>
37-
</Constraints.Horizontal>
38-
);
39-
};
40-
41-
TextInput.displayName = 'TextInput';
42-
43-
TextInput.propTypes = {
7+
type TTextInputProps = {
448
/**
459
* Used as HTML id property. An id is auto-generated when it is not specified.
4610
*/
47-
id: PropTypes.string,
11+
id?: string;
4812
/**
4913
* Used as HTML autocomplete property
5014
*/
51-
autoComplete: PropTypes.string,
52-
className: PropTypes.string,
15+
autoComplete?: string;
16+
/**
17+
* `className` forwarded to the underlying `<input />`.
18+
*/
19+
className?: string;
5320
/**
5421
* Used as HTML name of the input component. property
5522
*/
56-
name: PropTypes.string,
23+
name?: string;
5724
/**
5825
* Value of the input component.
5926
*/
60-
value: PropTypes.string.isRequired,
27+
value: string;
6128
/**
6229
* Called with an event containing the new value. Required when input is not read only. Parent should pass it back as value.
6330
* <br />
64-
* Signature: `(event) => void`
6531
*/
66-
onChange: requiredIf(PropTypes.func, (props) => !props.isReadOnly),
32+
onChange: ChangeEventHandler;
6733
/**
6834
* Called when input is blurred
69-
* Signature: `(event) => void`
7035
*/
71-
onBlur: PropTypes.func,
36+
onBlur?: FocusEventHandler;
7237
/**
7338
* Called when input is focused
74-
* Signature: `(event) => void`
7539
*/
76-
onFocus: PropTypes.func,
40+
onFocus?: FocusEventHandler;
7741
/**
7842
* Focus the input on initial render
7943
*/
80-
isAutofocussed: PropTypes.bool,
44+
isAutofocussed?: boolean;
8145
/**
8246
* Indicates that the input cannot be modified (e.g not authorized, or changes currently saving).
8347
*/
84-
isDisabled: PropTypes.bool,
48+
isDisabled?: boolean;
8549
/**
8650
* Indicates that the field is displaying read-only content
8751
*/
88-
isReadOnly: PropTypes.bool,
52+
isReadOnly?: boolean;
8953
/**
9054
* Indicates if the input has invalid values
9155
*/
92-
hasError: PropTypes.bool,
93-
hasWarning: PropTypes.bool,
56+
hasError?: boolean;
57+
hasWarning?: boolean;
9458
/**
9559
* Placeholder text for the input
9660
*/
97-
placeholder: PropTypes.string,
61+
placeholder?: string;
9862
/**
9963
* Horizontal size limit of the input fields.
10064
*/
101-
horizontalConstraint: PropTypes.oneOf([
102-
3,
103-
4,
104-
5,
105-
6,
106-
7,
107-
8,
108-
9,
109-
10,
110-
11,
111-
12,
112-
13,
113-
14,
114-
15,
115-
16,
116-
'scale',
117-
'auto',
118-
]),
65+
horizontalConstraint:
66+
| 3
67+
| 4
68+
| 5
69+
| 6
70+
| 7
71+
| 8
72+
| 9
73+
| 10
74+
| 11
75+
| 12
76+
| 13
77+
| 14
78+
| 15
79+
| 16
80+
| 'scale'
81+
| 'auto';
11982
};
12083

121-
TextInput.defaultProps = {
84+
const defaultProps: Pick<TTextInputProps, 'horizontalConstraint'> = {
12285
horizontalConstraint: 'scale',
12386
};
12487

125-
TextInput.isEmpty = (value) => !value || value.trim().length === 0;
88+
const TextInput = (props: TTextInputProps) => {
89+
const theme = useTheme();
90+
if (!props.isReadOnly) {
91+
warning(
92+
Boolean(props.onChange),
93+
'TextInput: `onChange` is required when is not read only.'
94+
);
95+
}
96+
return (
97+
<Constraints.Horizontal max={props.horizontalConstraint}>
98+
<input
99+
id={props.id}
100+
name={props.name}
101+
type="text"
102+
value={props.value}
103+
onChange={props.onChange}
104+
onBlur={props.onBlur}
105+
onFocus={props.onFocus}
106+
disabled={props.isDisabled}
107+
placeholder={props.placeholder}
108+
readOnly={props.isReadOnly}
109+
autoFocus={props.isAutofocussed}
110+
autoComplete={props.autoComplete}
111+
css={getInputStyles(props, theme)}
112+
// Allow to override the styles by passing a `className` prop.
113+
// Custom styles can also be passed using the `css` prop from emotion.
114+
// https://emotion.sh/docs/css-prop#style-precedence
115+
className={props.className}
116+
{...filterDataAttributes(props)}
117+
/* ARIA */
118+
aria-readonly={props.isReadOnly}
119+
role="textbox"
120+
contentEditable={!props.isReadOnly}
121+
/>
122+
</Constraints.Horizontal>
123+
);
124+
};
125+
126+
TextInput.displayName = 'TextInput';
127+
TextInput.defaultProps = defaultProps;
128+
TextInput.isEmpty = (value: TTextInputProps['value']) =>
129+
!value || value.trim().length === 0;
126130

127131
export default TextInput;

0 commit comments

Comments
 (0)