Skip to content

Commit 48771a9

Browse files
authored
chore: Convert into TS (#289)
* Divider ts * DOMWrapper * Wrapper TS & Util TS * Group TS * MenuItem TS * SubPopupMenu TS * Menu TS * add in TS * clean up * update ignore
1 parent dcfbfb3 commit 48771a9

File tree

14 files changed

+642
-386
lines changed

14 files changed

+642
-386
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ es
2929
coverage
3030
yarn.lock
3131
package-lock.json
32+
.vscode

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"scripts": {
3434
"start": "cross-env NODE_ENV=development father doc dev --storybook",
3535
"build": "father doc build --storybook",
36-
"compile": "father build",
36+
"compile": "father build && lessc assets/index.less assets/index.css",
3737
"prepublishOnly": "npm run compile && np --no-cleanup --yolo --no-publish",
3838
"lint": "eslint src/ examples/ --ext .tsx,.ts,.jsx,.js",
3939
"test": "father test",
@@ -49,7 +49,6 @@
4949
"dom-scroll-into-view": "1.x",
5050
"mini-store": "^2.0.0",
5151
"mutationobserver-shim": "^0.3.2",
52-
"prop-types": "^15.5.6",
5352
"rc-animate": "2.x",
5453
"rc-trigger": "^2.3.0",
5554
"rc-util": "^4.13.0",
@@ -66,7 +65,9 @@
6665
"enzyme-adapter-react-16": "^1.0.2",
6766
"enzyme-to-json": "^3.4.0",
6867
"father": "^2.22.0",
68+
"less": "^3.10.3",
6969
"np": "^5.0.3",
70+
"prop-types": "^15.5.6",
7071
"react": "^16.9.0",
7172
"react-dom": "^16.9.0",
7273
"typescript": "^3.5.2"

src/DOMWrap.jsx renamed to src/DOMWrap.tsx

Lines changed: 125 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
3-
import PropTypes from 'prop-types';
43
import ResizeObserver from 'resize-observer-polyfill';
54
import SubMenu from './SubMenu';
65
import { getWidth, setStyle, menuAllProps } from './util';
6+
import { MenuMode } from './interface';
77

88
const canUseDOM = !!(
99
typeof window !== 'undefined' &&
@@ -20,15 +20,53 @@ if (canUseDOM) {
2020
require('mutationobserver-shim');
2121
}
2222

23-
class DOMWrap extends React.Component {
24-
state = {
23+
interface DOMWrapProps {
24+
className?: string;
25+
children?: React.ReactElement[];
26+
mode?: MenuMode;
27+
prefixCls?: string;
28+
level?: number;
29+
theme?: string;
30+
overflowedIndicator?: React.ReactNode;
31+
visible?: boolean;
32+
hiddenClassName?: string;
33+
tag?: string;
34+
style?: React.CSSProperties;
35+
}
36+
37+
interface DOMWrapState {
38+
lastVisibleIndex: number;
39+
}
40+
41+
class DOMWrap extends React.Component<DOMWrapProps, DOMWrapState> {
42+
static defaultProps = {
43+
tag: 'div',
44+
className: '',
45+
};
46+
47+
overflowedIndicatorWidth: number;
48+
49+
resizeObserver = null;
50+
51+
mutationObserver = null;
52+
53+
// original scroll size of the list
54+
originalTotalWidth = 0;
55+
56+
// copy of overflowed items
57+
overflowedItems: React.ReactElement[] = [];
58+
59+
// cache item of the original items (so we can track the size and order)
60+
menuItemSizes: number[] = [];
61+
62+
state: DOMWrapState = {
2563
lastVisibleIndex: undefined,
2664
};
2765

2866
componentDidMount() {
2967
this.setChildrenWidthAndResize();
3068
if (this.props.level === 1 && this.props.mode === 'horizontal') {
31-
const menuUl = ReactDOM.findDOMNode(this);
69+
const menuUl = ReactDOM.findDOMNode(this) as HTMLElement;
3270
if (!menuUl) {
3371
return;
3472
}
@@ -39,7 +77,7 @@ class DOMWrap extends React.Component {
3977
[].slice
4078
.call(menuUl.children)
4179
.concat(menuUl)
42-
.forEach(el => {
80+
.forEach((el: HTMLElement) => {
4381
this.resizeObserver.observe(el);
4482
});
4583

@@ -49,7 +87,7 @@ class DOMWrap extends React.Component {
4987
[].slice
5088
.call(menuUl.children)
5189
.concat(menuUl)
52-
.forEach(el => {
90+
.forEach((el: HTMLElement) => {
5391
this.resizeObserver.observe(el);
5492
});
5593
this.setChildrenWidthAndResize();
@@ -73,9 +111,9 @@ class DOMWrap extends React.Component {
73111
}
74112

75113
// get all valid menuItem nodes
76-
getMenuItemNodes = () => {
114+
getMenuItemNodes = (): HTMLElement[] => {
77115
const { prefixCls } = this.props;
78-
const ul = ReactDOM.findDOMNode(this);
116+
const ul = ReactDOM.findDOMNode(this) as HTMLElement;
79117
if (!ul) {
80118
return [];
81119
}
@@ -84,17 +122,17 @@ class DOMWrap extends React.Component {
84122
return [].slice
85123
.call(ul.children)
86124
.filter(
87-
node =>
125+
(node: HTMLElement) =>
88126
node.className.split(' ').indexOf(`${prefixCls}-overflowed-submenu`) <
89127
0,
90128
);
91129
};
92130

93131
getOverflowedSubMenuItem = (
94-
keyPrefix,
95-
overflowedItems,
96-
renderPlaceholder,
97-
) => {
132+
keyPrefix: string,
133+
overflowedItems: React.ReactElement[],
134+
renderPlaceholder?: boolean,
135+
): React.ReactElement => {
98136
const { overflowedIndicator, level, mode, prefixCls, theme } = this.props;
99137
if (level !== 1 || mode !== 'horizontal') {
100138
return null;
@@ -109,7 +147,7 @@ class DOMWrap extends React.Component {
109147
...rest
110148
} = copy.props;
111149

112-
let style = { ...propStyle };
150+
let style: React.CSSProperties = { ...propStyle };
113151
let key = `${keyPrefix}-overflowed-indicator`;
114152
let eventKey = `${keyPrefix}-overflowed-indicator`;
115153

@@ -158,7 +196,7 @@ class DOMWrap extends React.Component {
158196
if (this.props.mode !== 'horizontal') {
159197
return;
160198
}
161-
const ul = ReactDOM.findDOMNode(this);
199+
const ul = ReactDOM.findDOMNode(this) as HTMLElement;
162200

163201
if (!ul) {
164202
return;
@@ -170,8 +208,9 @@ class DOMWrap extends React.Component {
170208
return;
171209
}
172210

173-
const lastOverflowedIndicatorPlaceholder =
174-
ul.children[ulChildrenNodes.length - 1];
211+
const lastOverflowedIndicatorPlaceholder = ul.children[
212+
ulChildrenNodes.length - 1
213+
] as HTMLElement;
175214

176215
// need last overflowed indicator for calculating length;
177216
setStyle(lastOverflowedIndicatorPlaceholder, 'display', 'inline-block');
@@ -194,9 +233,9 @@ class DOMWrap extends React.Component {
194233
overflowedItems.forEach(c => {
195234
setStyle(c, 'display', 'none');
196235
});
197-
this.overflowedIndicatorWidth = getWidth(
198-
ul.children[ul.children.length - 1],
199-
);
236+
this.overflowedIndicatorWidth = getWidth(ul.children[
237+
ul.children.length - 1
238+
] as HTMLElement);
200239
this.originalTotalWidth = this.menuItemSizes.reduce(
201240
(acc, cur) => acc + cur,
202241
0,
@@ -206,25 +245,12 @@ class DOMWrap extends React.Component {
206245
setStyle(lastOverflowedIndicatorPlaceholder, 'display', 'none');
207246
};
208247

209-
resizeObserver = null;
210-
211-
mutationObserver = null;
212-
213-
// original scroll size of the list
214-
originalTotalWidth = 0;
215-
216-
// copy of overflowed items
217-
overflowedItems = [];
218-
219-
// cache item of the original items (so we can track the size and order)
220-
menuItemSizes = [];
221-
222248
handleResize = () => {
223249
if (this.props.mode !== 'horizontal') {
224250
return;
225251
}
226252

227-
const ul = ReactDOM.findDOMNode(this);
253+
const ul = ReactDOM.findDOMNode(this) as HTMLElement;
228254
if (!ul) {
229255
return;
230256
}
@@ -234,7 +260,7 @@ class DOMWrap extends React.Component {
234260
let currentSumWidth = 0;
235261

236262
// index for last visible child in horizontal mode
237-
let lastVisibleIndex;
263+
let lastVisibleIndex: number;
238264

239265
// float number comparison could be problematic
240266
// e.g. 0.1 + 0.2 > 0.3 =====> true
@@ -253,60 +279,73 @@ class DOMWrap extends React.Component {
253279
this.setState({ lastVisibleIndex });
254280
};
255281

256-
renderChildren(children) {
282+
renderChildren(children: React.ReactElement[]) {
257283
// need to take care of overflowed items in horizontal mode
258284
const { lastVisibleIndex } = this.state;
259-
return (children || []).reduce((acc, childNode, index) => {
260-
let item = childNode;
261-
if (this.props.mode === 'horizontal') {
262-
let overflowed = this.getOverflowedSubMenuItem(
263-
childNode.props.eventKey,
264-
[],
265-
);
266-
if (
267-
lastVisibleIndex !== undefined &&
268-
this.props.className.indexOf(`${this.props.prefixCls}-root`) !== -1
269-
) {
270-
if (index > lastVisibleIndex) {
271-
item = React.cloneElement(
272-
childNode,
273-
// 这里修改 eventKey 是为了防止隐藏状态下还会触发 openkeys 事件
274-
{
275-
style: { display: 'none' },
276-
eventKey: `${childNode.props.eventKey}-hidden`,
277-
className: `${childNode.className} ${MENUITEM_OVERFLOWED_CLASSNAME}`,
278-
},
279-
);
285+
return (children || []).reduce(
286+
(
287+
acc: React.ReactElement[],
288+
childNode: React.ReactElement,
289+
index: number,
290+
) => {
291+
let item = childNode;
292+
if (this.props.mode === 'horizontal') {
293+
let overflowed = this.getOverflowedSubMenuItem(
294+
childNode.props.eventKey,
295+
[],
296+
);
297+
if (
298+
lastVisibleIndex !== undefined &&
299+
this.props.className.indexOf(`${this.props.prefixCls}-root`) !== -1
300+
) {
301+
if (index > lastVisibleIndex) {
302+
item = React.cloneElement(
303+
childNode,
304+
// 这里修改 eventKey 是为了防止隐藏状态下还会触发 openkeys 事件
305+
{
306+
style: { display: 'none' },
307+
eventKey: `${childNode.props.eventKey}-hidden`,
308+
/**
309+
* Legacy code. Here `className` never used:
310+
* https://github.com/react-component/menu/commit/4cd6b49fce9d116726f4ea00dda85325d6f26500#diff-e2fa48f75c2dd2318295cde428556a76R240
311+
*/
312+
className: `${MENUITEM_OVERFLOWED_CLASSNAME}`,
313+
},
314+
);
315+
}
316+
if (index === lastVisibleIndex + 1) {
317+
this.overflowedItems = children
318+
.slice(lastVisibleIndex + 1)
319+
.map(c =>
320+
React.cloneElement(
321+
c,
322+
// children[index].key will become '.$key' in clone by default,
323+
// we have to overwrite with the correct key explicitly
324+
{ key: c.props.eventKey, mode: 'vertical-left' },
325+
),
326+
);
327+
328+
overflowed = this.getOverflowedSubMenuItem(
329+
childNode.props.eventKey,
330+
this.overflowedItems,
331+
);
332+
}
280333
}
281-
if (index === lastVisibleIndex + 1) {
282-
this.overflowedItems = children.slice(lastVisibleIndex + 1).map(c =>
283-
React.cloneElement(
284-
c,
285-
// children[index].key will become '.$key' in clone by default,
286-
// we have to overwrite with the correct key explicitly
287-
{ key: c.props.eventKey, mode: 'vertical-left' },
288-
),
289-
);
290334

291-
overflowed = this.getOverflowedSubMenuItem(
292-
childNode.props.eventKey,
293-
this.overflowedItems,
335+
const ret: React.ReactElement[] = [...acc, overflowed, item];
336+
337+
if (index === children.length - 1) {
338+
// need a placeholder for calculating overflowed indicator width
339+
ret.push(
340+
this.getOverflowedSubMenuItem(childNode.props.eventKey, [], true),
294341
);
295342
}
343+
return ret;
296344
}
297-
298-
const ret = [...acc, overflowed, item];
299-
300-
if (index === children.length - 1) {
301-
// need a placeholder for calculating overflowed indicator width
302-
ret.push(
303-
this.getOverflowedSubMenuItem(childNode.props.eventKey, [], true),
304-
);
305-
}
306-
return ret;
307-
}
308-
return [...acc, item];
309-
}, []);
345+
return [...acc, item];
346+
},
347+
[],
348+
);
310349
}
311350

312351
render() {
@@ -317,7 +356,7 @@ class DOMWrap extends React.Component {
317356
overflowedIndicator,
318357
mode,
319358
level,
320-
tag: Tag,
359+
tag,
321360
children,
322361
theme,
323362
...rest
@@ -327,33 +366,10 @@ class DOMWrap extends React.Component {
327366
rest.className += ` ${hiddenClassName}`;
328367
}
329368

330-
return <Tag {...rest}>{this.renderChildren(this.props.children)}</Tag>;
369+
const Tag = tag as any;
370+
371+
return <Tag {...rest}>{this.renderChildren(children)}</Tag>;
331372
}
332373
}
333374

334-
DOMWrap.propTypes = {
335-
className: PropTypes.string,
336-
children: PropTypes.node,
337-
mode: PropTypes.oneOf([
338-
'horizontal',
339-
'vertical',
340-
'vertical-left',
341-
'vertical-right',
342-
'inline',
343-
]),
344-
prefixCls: PropTypes.string,
345-
level: PropTypes.number,
346-
theme: PropTypes.string,
347-
overflowedIndicator: PropTypes.node,
348-
visible: PropTypes.bool,
349-
hiddenClassName: PropTypes.string,
350-
tag: PropTypes.string,
351-
style: PropTypes.object,
352-
};
353-
354-
DOMWrap.defaultProps = {
355-
tag: 'div',
356-
className: '',
357-
};
358-
359375
export default DOMWrap;

0 commit comments

Comments
 (0)