|
22 | 22 |
|
23 | 23 | import * as React from 'react';
|
24 | 24 | import classnames from 'classnames';
|
| 25 | +import {MDCListFoundation} from '@material/list/foundation'; |
25 | 26 |
|
26 | 27 | export interface ListItemProps<T> extends React.HTMLProps<T> {
|
27 |
| - className?: string; |
28 |
| - classNamesFromList?: string[]; |
29 |
| - attributesFromList?: object; |
30 |
| - childrenTabIndex?: number; |
31 |
| - tabIndex?: number; |
32 |
| - shouldFocus?: boolean; |
33 |
| - shouldFollowHref?: boolean; |
34 |
| - shouldToggleCheckbox?: boolean; |
| 28 | + checkboxList?: boolean; |
| 29 | + radioList?: boolean; |
| 30 | + onKeyDown?: React.KeyboardEventHandler<T>; |
| 31 | + onClick?: React.MouseEventHandler<T>; |
| 32 | + onFocus?: React.FocusEventHandler<T>; |
| 33 | + onBlur?: React.FocusEventHandler<T>; |
35 | 34 | tag?: string;
|
36 |
| - children?: React.ReactNode; |
| 35 | + activated?: boolean; |
| 36 | + selected?: boolean; |
37 | 37 | };
|
38 | 38 |
|
39 |
| -function isAnchorElement(element: any): element is HTMLAnchorElement { |
40 |
| - return !!element.href; |
41 |
| -} |
42 |
| - |
43 |
| -function isFocusableElement(element: any): element is HTMLElement { |
44 |
| - return typeof <HTMLElement>element.focus === 'function'; |
45 |
| -} |
46 |
| - |
47 |
| -export default class ListItem<T extends {} = HTMLElement> extends React.Component< |
| 39 | +// TODO: convert to functional component |
| 40 | +// https://github.com/material-components/material-components-web-react/issues/729 |
| 41 | +export default class ListItem<T extends HTMLElement = HTMLElement> extends React.Component< |
48 | 42 | ListItemProps<T>,
|
49 | 43 | {}
|
50 | 44 | > {
|
51 |
| - listItemElement_: React.RefObject<T> = React.createRef(); |
| 45 | + private listItemElement = React.createRef<T>(); |
52 | 46 |
|
53 | 47 | static defaultProps: Partial<ListItemProps<HTMLElement>> = {
|
| 48 | + checkboxList: false, |
| 49 | + radioList: false, |
54 | 50 | className: '',
|
55 |
| - classNamesFromList: [], |
56 |
| - attributesFromList: {}, |
57 |
| - childrenTabIndex: -1, |
58 | 51 | tabIndex: -1,
|
59 |
| - shouldFocus: false, |
60 |
| - shouldFollowHref: false, |
61 |
| - shouldToggleCheckbox: false, |
62 | 52 | onKeyDown: () => {},
|
63 | 53 | onClick: () => {},
|
64 | 54 | onFocus: () => {},
|
65 | 55 | onBlur: () => {},
|
66 | 56 | tag: 'li',
|
67 | 57 | };
|
68 | 58 |
|
69 |
| - componentDidUpdate(prevProps: ListItemProps<T>) { |
70 |
| - const {shouldFocus, shouldFollowHref, shouldToggleCheckbox} = this.props; |
71 |
| - if (shouldFocus && !prevProps.shouldFocus) { |
72 |
| - this.focus(); |
73 |
| - } |
74 |
| - if (shouldFollowHref && !prevProps.shouldFollowHref) { |
75 |
| - this.followHref(); |
76 |
| - } |
77 |
| - if (shouldToggleCheckbox && !prevProps.shouldToggleCheckbox) { |
78 |
| - this.toggleCheckbox(); |
79 |
| - } |
80 |
| - } |
81 |
| - |
82 | 59 | get classes() {
|
83 |
| - const {className, classNamesFromList} = this.props; |
84 |
| - return classnames('mdc-list-item', className, classNamesFromList); |
| 60 | + const {className, activated, selected} = this.props; |
| 61 | + return classnames('mdc-list-item', className, { |
| 62 | + [MDCListFoundation.cssClasses.LIST_ITEM_ACTIVATED_CLASS]: activated, |
| 63 | + [MDCListFoundation.cssClasses.LIST_ITEM_SELECTED_CLASS]: selected, |
| 64 | + }); |
85 | 65 | }
|
86 | 66 |
|
87 |
| - focus() { |
88 |
| - const element = this.listItemElement_.current; |
89 |
| - if (isFocusableElement(element)) { |
90 |
| - element.focus(); |
| 67 | + get role() { |
| 68 | + const {checkboxList, radioList, role} = this.props; |
| 69 | + if (role) { |
| 70 | + return role; |
| 71 | + } else if (checkboxList) { |
| 72 | + return 'checkbox'; |
| 73 | + } else if (radioList) { |
| 74 | + return 'radio'; |
91 | 75 | }
|
92 |
| - } |
93 |
| - |
94 |
| - followHref() { |
95 |
| - const element = this.listItemElement_.current; |
96 |
| - if (isAnchorElement(element)) { |
97 |
| - element.click(); |
98 |
| - } |
99 |
| - } |
100 |
| - |
101 |
| - toggleCheckbox() { |
102 |
| - // TODO(bonniez): implement |
103 |
| - // https://github.com/material-components/material-components-web-react/issues/352 |
| 76 | + return null; |
104 | 77 | }
|
105 | 78 |
|
106 | 79 | render() {
|
107 | 80 | const {
|
108 |
| - /* eslint-disable */ |
| 81 | + /* eslint-disable no-unused-vars */ |
109 | 82 | className,
|
110 |
| - classNamesFromList, |
111 |
| - childrenTabIndex, |
112 |
| - shouldFocus, |
113 |
| - shouldFollowHref, |
114 |
| - shouldToggleCheckbox, |
115 |
| - /* eslint-enable */ |
116 |
| - attributesFromList, |
117 | 83 | children,
|
| 84 | + role, |
| 85 | + checkboxList, |
| 86 | + radioList, |
| 87 | + /* eslint-enable no-unused-vars */ |
118 | 88 | tag: Tag,
|
| 89 | + |
119 | 90 | ...otherProps
|
120 | 91 | } = this.props;
|
121 | 92 | return (
|
122 | 93 | // https://github.com/Microsoft/TypeScript/issues/28892
|
123 | 94 | // @ts-ignore
|
124 | 95 | <Tag
|
| 96 | + role={this.role} |
125 | 97 | className={this.classes}
|
| 98 | + ref={this.listItemElement} |
126 | 99 | {...otherProps}
|
127 |
| - {...attributesFromList} // overrides attributes in otherProps |
128 |
| - ref={this.listItemElement_} |
129 | 100 | >
|
130 |
| - {React.Children.map(children, this.renderChild)} |
| 101 | + {this.props.children} |
131 | 102 | </Tag>
|
132 | 103 | );
|
133 | 104 | }
|
134 |
| - |
135 |
| - renderChild = (child: React.ReactChild) => { |
136 |
| - if (typeof child === 'string' || typeof child === 'number' || child === null) { |
137 |
| - return child; |
138 |
| - } |
139 |
| - |
140 |
| - const tabIndex = this.props.childrenTabIndex; |
141 |
| - const props = {...child.props, tabIndex}; |
142 |
| - return React.cloneElement(child, props); |
143 |
| - }; |
144 | 105 | }
|
0 commit comments