Skip to content
This repository was archived by the owner on Jul 29, 2025. It is now read-only.

Commit e3373bb

Browse files
author
Matt Goo
committed
feat(material-icon): typescript (#525)
1 parent 4dcf389 commit e3373bb

File tree

10 files changed

+65
-93
lines changed

10 files changed

+65
-93
lines changed

packages/material-icon/index.js renamed to packages/material-icon/index.tsx

Lines changed: 41 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,50 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
// THE SOFTWARE.
2222

23-
import React from 'react';
24-
import classnames from 'classnames';
25-
import PropTypes from 'prop-types';
23+
import * as React from 'react';
24+
import * as classnames from 'classnames';
25+
import * as Ripple from '@material/react-ripple';
2626

27-
import {withRipple} from '@material/react-ripple';
27+
export interface MaterialIconDefaultProps extends React.HTMLAttributes<HTMLElement> {
28+
icon?: string;
29+
className?: string;
30+
hasRipple?: boolean;
31+
unbounded?: boolean;
32+
};
2833

29-
export default class MaterialIcon extends React.Component {
30-
render() {
31-
const {
32-
icon,
33-
hasRipple,
34-
...otherProps
35-
} = this.props;
34+
export interface MaterialIconProps extends MaterialIconDefaultProps, Ripple.InjectedProps<HTMLElement> {};
35+
36+
const MaterialIconDefault: React.FunctionComponent<MaterialIconProps> = ({
37+
className, icon, initRipple, hasRipple, unbounded, ...otherProps // eslint-disable-line react/prop-types
38+
}) => {
39+
const classes = classnames('material-icons', className, {
40+
'material-icons--ripple-surface': hasRipple,
41+
});
42+
return (
43+
<i
44+
className={classes}
45+
ref={initRipple}
46+
{...otherProps}
47+
>
48+
{icon}
49+
</i>
50+
);
51+
};
52+
53+
export const RippleMaterialIcon = Ripple.withRipple<MaterialIconProps, HTMLElement>(MaterialIconDefault);
3654

55+
export default class MaterialIcon extends React.Component<
56+
MaterialIconProps, {}
57+
> {
58+
static defaultProps: Partial<MaterialIconProps> = {
59+
icon: '',
60+
className: '',
61+
hasRipple: false,
62+
unbounded: false,
63+
};
64+
65+
render() {
66+
const {icon, hasRipple, unbounded, ...otherProps} = this.props; // eslint-disable-line no-unused-vars
3767
if (hasRipple) {
3868
return (
3969
<RippleMaterialIcon
@@ -44,7 +74,6 @@ export default class MaterialIcon extends React.Component {
4474
/>
4575
);
4676
}
47-
4877
return (
4978
<MaterialIconDefault
5079
icon={icon}
@@ -53,52 +82,3 @@ export default class MaterialIcon extends React.Component {
5382
);
5483
}
5584
}
56-
57-
const MaterialIconDefault = (props) => {
58-
const {
59-
className,
60-
icon,
61-
initRipple,
62-
hasRipple,
63-
...otherProps
64-
} = props;
65-
const classes = classnames('material-icons', className, {
66-
'material-icons--ripple-surface': hasRipple,
67-
});
68-
69-
return (
70-
<i
71-
className={classes}
72-
ref={initRipple}
73-
{...otherProps}
74-
>
75-
{icon}
76-
</i>
77-
);
78-
};
79-
80-
export const RippleMaterialIcon = withRipple(MaterialIconDefault);
81-
82-
MaterialIcon.propTypes = {
83-
icon: PropTypes.string,
84-
hasRipple: PropTypes.bool,
85-
};
86-
87-
MaterialIcon.defaultProps = {
88-
icon: '',
89-
hasRipple: false,
90-
};
91-
92-
MaterialIconDefault.propTypes = {
93-
icon: PropTypes.string,
94-
className: PropTypes.string,
95-
initRipple: PropTypes.func,
96-
hasRipple: PropTypes.bool,
97-
};
98-
99-
MaterialIconDefault.defaultProps = {
100-
icon: '',
101-
className: '',
102-
initRipple: () => {},
103-
hasRipple: false,
104-
};

packages/text-field/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ class TextField<T extends {}> extends React.Component<TextFieldProps<T>, TextFie
282282
}
283283

284284
inputProps(child: React.ReactElement<InputProps<T>>) {
285+
// ref does exist on React.ReactElement<InputProps<T>>
285286
// @ts-ignore
286287
const {props, ref} = child;
287288
return Object.assign({}, props, {

test/screenshot/material-icon/index.js renamed to test/screenshot/material-icon/index.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import React from 'react';
1+
import * as React from 'react';
22
import MaterialIcon from '../../../packages/material-icon';
33
import '../../../packages/material-icon/index.scss';
44

5-
6-
const MaterialIconScreenshotTest = () => {
5+
const MaterialIconScreenshotTest: React.FunctionComponent = () => {
76
return (
87
<div>
98
<MaterialIcon icon='menu' hasRipple />

test/screenshot/text-field/attributesMap.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
22
import {HelperText} from '../../../packages/text-field';
3-
// @ts-ignore
43
import MaterialIcon from '../../../packages/material-icon/index';
54

65
export declare type HelperTextMapType = {helperText: HelperText};

test/screenshot/text-field/helper-text/index.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
2-
// @ts-ignore
3-
import HelperText from '../../../../packages/text-field/helper-text/index.tsx';
2+
import HelperText from '../../../../packages/text-field/helper-text/index';
43

54
import '../../../../packages/text-field/helper-text/index.scss';
65

test/screenshot/text-field/icon/index.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import * as React from 'react';
2-
// @ts-ignore
3-
import Icon from '../../../../packages/text-field/icon/index.tsx';
4-
// TODO: return to remove these ts-ignores
5-
// @ts-ignore
6-
import MaterialIcon from '../../../../packages/material-icon/index.js';
2+
import Icon from '../../../../packages/text-field/icon/index';
3+
import MaterialIcon from '../../../../packages/material-icon/index';
74
import '../../../../packages/text-field/icon/index.scss';
85

96
const TextFieldIconScreenshotTest = () => {
@@ -16,7 +13,7 @@ const TextFieldIconScreenshotTest = () => {
1613
</Icon>
1714

1815
<Icon>
19-
<MaterialIcon tabIndex='0' role='button' icon='favorite' />
16+
<MaterialIcon tabIndex={0} role='button' icon='favorite' />
2017
</Icon>
2118
</div>
2219
);

test/screenshot/text-field/textArea.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import * as React from 'react';
2-
// @ts-ignore
3-
import HelperText from '../../../packages/text-field/helper-text/index.tsx'; // eslint-disable-line no-unused-vars
42
import {
53
denseMap,
64
requiredMap,
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
import React from 'react';
1+
import * as React from 'react';
22
import {assert} from 'chai';
33
import {mount} from 'enzyme';
4-
import MaterialIcon, {RippleMaterialIcon} from '../../../packages/material-icon/index';
4+
5+
import MaterialIcon, {
6+
RippleMaterialIcon,
7+
} from '../../../packages/material-icon/index';
58

69
suite('MaterialIcon');
710

811
test('classNames adds classes', () => {
9-
const wrapper = mount(<MaterialIcon className='test-class-name'/>);
12+
const wrapper = mount(<MaterialIcon className='test-class-name' />);
1013
const icon = wrapper.find('.material-icons');
1114
assert.isTrue(icon.hasClass('test-class-name'));
1215
assert.equal(icon.length, 1);
1316
});
1417

1518
test('classNames adds ripple class if hasRipple is true', () => {
16-
const wrapper = mount(<MaterialIcon hasRipple className='test-class-name'/>);
19+
const wrapper = mount(<MaterialIcon hasRipple className='test-class-name' />);
1720
const icon = wrapper.find('.material-icons');
1821
assert.isTrue(icon.hasClass('test-class-name'));
1922
assert.isTrue(icon.hasClass('material-icons--ripple-surface'));
@@ -23,19 +26,16 @@ test('has icon type as child', () => {
2326
const wrapper = mount(<MaterialIcon icon='menu' />);
2427
assert.equal(wrapper.find('.material-icons').text(), 'menu');
2528
});
26-
27-
const rippledIconComponent = <RippleMaterialIcon hasRipple unbounded icon='menu' />;
29+
const rippledIconComponent = (
30+
<RippleMaterialIcon hasRipple unbounded icon='menu' />
31+
);
2832

2933
test('if hasRipple true, then it should contain RippleMaterialIcon', () => {
30-
const wrapper = mount(
31-
<MaterialIcon icon='menu' hasRipple />
32-
);
34+
const wrapper = mount(<MaterialIcon icon='menu' hasRipple />);
3335
assert.isTrue(wrapper.contains(rippledIconComponent));
3436
});
3537

3638
test('if hasRipple false, then it should not contain RippleMaterialIcon', () => {
37-
const wrapper = mount(
38-
<MaterialIcon icon='menu' />
39-
);
39+
const wrapper = mount(<MaterialIcon icon='menu' />);
4040
assert.isFalse(wrapper.contains(rippledIconComponent));
4141
});

test/unit/text-field/icon/index.test.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import * as td from 'testdouble';
33
import {assert} from 'chai';
44
import {shallow} from 'enzyme';
55
import Icon from '../../../../packages/text-field/icon/index';
6-
// TODO: fix with #513
7-
// @ts-ignore
8-
import MaterialIcon from '../../../../packages/material-icon/index.js';
6+
import MaterialIcon from '../../../../packages/material-icon/index';
97

108
suite('Text Field Icon');
119

@@ -166,7 +164,7 @@ test('#adapter.removeAttr for role', () => {
166164
test('#adapter.getAttr for tabIndex works with Custom Component', () => {
167165
const wrapper = shallow<Icon>(
168166
<Icon>
169-
<MaterialIcon icon='favorite' tabIndex='0' />
167+
<MaterialIcon icon='favorite' tabIndex={0} />
170168
</Icon>
171169
);
172170
const tabIndex = wrapper.instance().foundation_.adapter_.getAttr('tabindex');
@@ -186,7 +184,7 @@ test('#adapter.getAttr for role works with Custom Component', () => {
186184
test('#adapter.setAttr for tabIndex works with Custom Component', () => {
187185
const wrapper = shallow<Icon>(
188186
<Icon>
189-
<MaterialIcon icon='favorite' tabIndex='0' />
187+
<MaterialIcon icon='favorite' tabIndex={0} />
190188
</Icon>
191189
);
192190
wrapper.instance().foundation_.adapter_.setAttr('tabindex', -1);

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
],
2121
"baseUrl": ".",
2222
"paths": {
23-
"@material/react-ripple": ["packages/ripple/"]
23+
"@material/react-ripple": ["packages/ripple/"],
24+
"@material/react-material-icon": ["packages/material-icon/"],
2425
}
2526
}

0 commit comments

Comments
 (0)