UNPKG

47.5 kBJavaScriptView Raw
1import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
2import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
3import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
4import _inherits from 'babel-runtime/helpers/inherits';
5import _extends from 'babel-runtime/helpers/extends';
6
7var _class, _temp;
8
9/* eslint-disable max-depth */
10import React, { Component, Children, cloneElement } from 'react';
11import PropTypes from 'prop-types';
12import cloneDeep from 'lodash.clonedeep';
13import { polyfill } from 'react-lifecycles-compat';
14import cx from 'classnames';
15import { func, dom, obj, KEYCODE } from '../../util';
16import TreeNode from './tree-node';
17import VirtualList from '../../virtual-list';
18import { normalizeToArray, isDescendantOrSelf, isSiblingOrSelf, filterChildKey, filterParentKey, getAllCheckedKeys, forEachEnableNode, isNodeChecked, getAllDescendantKeys, convertChildren2Data } from './util';
19
20var bindCtx = func.bindCtx,
21 noop = func.noop;
22var getOffset = dom.getOffset;
23var pickOthers = obj.pickOthers,
24 pickProps = obj.pickProps,
25 isPlainObject = obj.isPlainObject;
26
27
28export var treeNodeProps = ['key', 'label', 'selectable', 'checkable', 'editable', 'draggable', 'disabled', 'checkboxDisabled', 'isLeaf', 'icon'];
29
30var getExpandedKeys = function getExpandedKeys(props, willReceiveProps, _k2n, _p2n) {
31 var expandedKeys = void 0;
32
33 if (!willReceiveProps && props.defaultExpandAll) {
34 expandedKeys = Object.keys(_k2n).filter(function (key) {
35 var children = _k2n[key].children;
36 return children && children.length;
37 });
38 } else {
39 expandedKeys = 'expandedKeys' in props ? props.expandedKeys : willReceiveProps ? [] : props.defaultExpandedKeys;
40 expandedKeys = normalizeToArray(expandedKeys);
41
42 if (props.autoExpandParent) {
43 var newExpandedKeys = [];
44
45 var expandedPoss = expandedKeys.reduce(function (ret, key) {
46 var pos = _k2n[key] && _k2n[key].pos;
47 if (pos) {
48 ret.push(pos);
49 newExpandedKeys.push(key);
50 }
51 return ret;
52 }, []);
53
54 expandedPoss.forEach(function (pos) {
55 var nums = pos.split('-');
56 if (nums.length === 2) {
57 return;
58 }
59 for (var i = 1; i <= nums.length - 2; i++) {
60 var ancestorPos = nums.slice(0, i + 1).join('-');
61 var ancestorKey = _p2n[ancestorPos].key;
62 if (newExpandedKeys.indexOf(ancestorKey) === -1) {
63 newExpandedKeys.push(ancestorKey);
64 }
65 }
66 });
67
68 return newExpandedKeys;
69 }
70 }
71
72 return expandedKeys;
73};
74
75var getSelectedKeys = function getSelectedKeys(props, willReceiveProps, _k2n) {
76 var selectedKeys = 'selectedKeys' in props ? props.selectedKeys : willReceiveProps ? [] : props.defaultSelectedKeys;
77 selectedKeys = normalizeToArray(selectedKeys);
78
79 return selectedKeys.filter(function (key) {
80 return _k2n[key];
81 });
82};
83
84var getIndeterminateKeys = function getIndeterminateKeys(checkedKeys, checkStrictly, _k2n, _p2n) {
85 if (checkStrictly) {
86 return [];
87 }
88
89 var indeterminateKeys = [];
90
91 var poss = filterChildKey(checkedKeys.filter(function (key) {
92 return !!_k2n[key];
93 }).filter(function (key) {
94 return !_k2n[key].disabled && !_k2n[key].checkboxDisabled && _k2n[key].checkable !== false;
95 }), _k2n, _p2n).map(function (key) {
96 return _k2n[key].pos;
97 });
98
99 poss.forEach(function (pos) {
100 var nums = pos.split('-');
101 for (var i = nums.length; i > 2; i--) {
102 var parentPos = nums.slice(0, i - 1).join('-');
103 var parent = _p2n[parentPos];
104 if (parent.disabled || parent.checkboxDisabled) break;
105 var parentKey = parent.key;
106 if (indeterminateKeys.indexOf(parentKey) === -1) {
107 indeterminateKeys.push(parentKey);
108 }
109 }
110 });
111
112 return indeterminateKeys;
113};
114
115var getCheckedKeys = function getCheckedKeys(props, willReceiveProps, _k2n, _p2n) {
116 var checkedKeys = props.defaultCheckedKeys;
117 var indeterminateKeys = void 0;
118
119 if ('checkedKeys' in props) {
120 checkedKeys = props.checkedKeys;
121 } else if (willReceiveProps) {
122 checkedKeys = [];
123 }
124
125 var checkStrictly = props.checkStrictly; // TODO TEST
126
127 if (checkStrictly) {
128 if (isPlainObject(checkedKeys)) {
129 var _checkedKeys = checkedKeys,
130 checked = _checkedKeys.checked,
131 indeterminate = _checkedKeys.indeterminate;
132
133 checkedKeys = normalizeToArray(checked);
134 indeterminateKeys = normalizeToArray(indeterminate);
135 } else {
136 checkedKeys = normalizeToArray(checkedKeys);
137 }
138
139 checkedKeys = checkedKeys.filter(function (key) {
140 return !!_k2n[key];
141 });
142 } else {
143 checkedKeys = getAllCheckedKeys(checkedKeys, _k2n, _p2n);
144 checkedKeys = checkedKeys.filter(function (key) {
145 return !!_k2n[key];
146 });
147
148 indeterminateKeys = getIndeterminateKeys(checkedKeys, props.checkStrictly, _k2n, _p2n);
149 }
150
151 return { checkedKeys: checkedKeys, indeterminateKeys: indeterminateKeys };
152};
153
154var preHandleData = function preHandleData(dataSource, props) {
155 var k2n = {};
156 var p2n = {};
157 var keyList = [];
158
159 var drill = function drill() {
160 var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
161 var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
162 var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
163 var parent = arguments[3];
164 return data.map(function (item, index) {
165 // 为了兼容之前的实现 保留非法节点
166 if (item.illegalFlag) {
167 return item;
168 }
169
170 var children = item.children;
171
172 var pos = prefix + '-' + index;
173 var key = item.key;
174
175
176 item.pos = pos;
177 item.level = level;
178
179 // 判断为叶子节点
180 // - 指定isLeaf属性
181 // - loadData模式下 没有指定isLeaf为true
182 // - 存在children元素
183 if (!('isLeaf' in item)) {
184 item.isLeaf = !(children && children.length || props.loadData);
185 }
186
187 item.isLastChild = parent ? [].concat(parent.isLastChild || [], index === data.length - 1) : [];
188
189 if (key === undefined || key === null) {
190 item.key = key = pos;
191 }
192 keyList.push(key);
193 !item.isLeaf && drill(children, level + 1, pos, item);
194
195 k2n[key] = p2n[pos] = _extends({}, item);
196
197 return item;
198 });
199 };
200
201 return { dataSource: drill(dataSource), k2n: k2n, p2n: p2n, keyList: keyList };
202};
203
204var preHandleChildren = function preHandleChildren(props) {
205 var k2n = {};
206 var p2n = {};
207 var keyList = [];
208
209 var loop = function loop(children) {
210 var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '0';
211 var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
212 return Children.map(children, function (node, index) {
213 if (!React.isValidElement(node)) {
214 return;
215 }
216 var pos = prefix + '-' + index;
217 var key = node.key;
218
219
220 key = key || pos;
221
222 var item = _extends({}, node.props, { key: key, pos: pos, level: level });
223 var children = node.props.children;
224
225 var hasChildren = children && Children.count(children);
226
227 if (!('isLeaf' in item)) {
228 item.isLeaf = !(hasChildren || props.loadData);
229 }
230 keyList.push(key);
231 if (hasChildren) {
232 item.children = loop(children, pos, level + 1);
233 }
234
235 k2n[key] = p2n[pos] = item;
236 return item;
237 });
238 };
239 loop(props.children);
240
241 return { k2n: k2n, p2n: p2n, keyList: keyList };
242};
243
244var getData = function getData(props) {
245 var dataSource = props.dataSource,
246 renderChildNodes = props.renderChildNodes,
247 _props$children = props.children,
248 children = _props$children === undefined ? [] : _props$children,
249 useVirtual = props.useVirtual,
250 immutable = props.immutable;
251
252 var data = immutable ? cloneDeep(dataSource) : dataSource;
253
254 if ((renderChildNodes || useVirtual) && !('dataSource' in props)) {
255 data = convertChildren2Data(children);
256 }
257
258 if (data) {
259 try {
260 return preHandleData(data, props);
261 } catch (err) {
262 if ((err.message || '').match('object is not extensible')) {
263 // eslint-disable-next-line no-console
264 console.error(err.message, 'try to set immutable to true to allow immutable dataSource');
265 } else {
266 throw err;
267 }
268 }
269 } else {
270 return preHandleChildren(props);
271 }
272};
273
274/**
275 * Tree
276 */
277var Tree = (_temp = _class = function (_Component) {
278 _inherits(Tree, _Component);
279
280 function Tree(props) {
281 _classCallCheck(this, Tree);
282
283 var _this = _possibleConstructorReturn(this, _Component.call(this, props));
284
285 var _getData = getData(props),
286 _getData$dataSource = _getData.dataSource,
287 dataSource = _getData$dataSource === undefined ? [] : _getData$dataSource,
288 k2n = _getData.k2n,
289 p2n = _getData.p2n,
290 keyList = _getData.keyList;
291
292 var _this$props = _this.props,
293 focusable = _this$props.focusable,
294 autoFocus = _this$props.autoFocus,
295 focusedKey = _this$props.focusedKey;
296
297 var willReceiveProps = false;
298
299 var _getCheckedKeys = getCheckedKeys(props, willReceiveProps, k2n, p2n),
300 checkedKeys = _getCheckedKeys.checkedKeys,
301 _getCheckedKeys$indet = _getCheckedKeys.indeterminateKeys,
302 indeterminateKeys = _getCheckedKeys$indet === undefined ? [] : _getCheckedKeys$indet;
303
304 _this.state = {
305 _k2n: k2n,
306 _p2n: p2n,
307 _keyList: keyList,
308 dataSource: dataSource,
309 willReceiveProps: willReceiveProps,
310 expandedKeys: getExpandedKeys(props, willReceiveProps, k2n, p2n),
311 selectedKeys: getSelectedKeys(props, willReceiveProps, k2n, p2n),
312 checkedKeys: checkedKeys,
313 indeterminateKeys: indeterminateKeys
314 };
315
316 if (focusable) {
317 _this.tabbableKey = _this.getFirstAvaliablelChildKey('0');
318 }
319
320 _this.state.focusedKey = 'focusedKey' in props ? focusedKey : focusable && autoFocus ? _this.tabbableKey : null;
321
322 if (focusable) {
323 _this.tabbableKey = _this.getFirstAvaliablelChildKey('0');
324 }
325
326 bindCtx(_this, ['handleExpand', 'handleSelect', 'handleCheck', 'handleBlur']);
327 return _this;
328 }
329
330 Tree.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) {
331 var _getData2 = getData(props),
332 _getData2$dataSource = _getData2.dataSource,
333 dataSource = _getData2$dataSource === undefined ? [] : _getData2$dataSource,
334 k2n = _getData2.k2n,
335 p2n = _getData2.p2n,
336 keyList = _getData2.keyList;
337
338 var st = {};
339
340 if (!state.willReceiveProps) {
341 return {
342 willReceiveProps: true,
343 _k2n: k2n,
344 _p2n: p2n,
345 _keyList: keyList
346 };
347 }
348
349 if ('expandedKeys' in props) {
350 st.expandedKeys = getExpandedKeys(props, state.willReceiveProps, k2n, p2n);
351 }
352
353 if ('selectedKeys' in props) {
354 st.selectedKeys = getSelectedKeys(props, state.willReceiveProps, k2n);
355 }
356
357 if ('checkedKeys' in props) {
358 var _getCheckedKeys2 = getCheckedKeys(props, state.willReceiveProps, k2n, p2n),
359 checkedKeys = _getCheckedKeys2.checkedKeys;
360
361 st.checkedKeys = checkedKeys;
362 }
363
364 st.indeterminateKeys = props.checkStrictly ? props.checkedKeys && props.checkedKeys.indeterminate || [] : getIndeterminateKeys(st.checkedKeys || state.checkedKeys || [], props.checkStrictly, k2n, p2n);
365
366 return _extends({}, st, {
367 dataSource: dataSource,
368 _k2n: k2n,
369 _p2n: p2n
370 });
371 };
372
373 Tree.prototype.setFocusKey = function setFocusKey() {
374 var _state$selectedKeys = this.state.selectedKeys,
375 selectedKeys = _state$selectedKeys === undefined ? [] : _state$selectedKeys;
376
377 this.setState({
378 focusedKey: selectedKeys.length > 0 ? selectedKeys[0] : this.getFirstAvaliablelChildKey('0')
379 });
380 };
381
382 Tree.prototype.getAvailableKey = function getAvailableKey(pos, prev) {
383 var _this2 = this;
384
385 var ps = Object.keys(this.state._p2n).filter(function (p) {
386 return _this2.isAvailablePos(pos, p);
387 });
388 if (ps.length > 1) {
389 var index = ps.indexOf(pos);
390 var targetIndex = void 0;
391 if (prev) {
392 targetIndex = index === 0 ? ps.length - 1 : index - 1;
393 } else {
394 targetIndex = index === ps.length - 1 ? 0 : index + 1;
395 }
396
397 return this.state._p2n[ps[targetIndex]].key;
398 }
399
400 return null;
401 };
402
403 Tree.prototype.getFirstAvaliablelChildKey = function getFirstAvaliablelChildKey(parentPos) {
404 var _this3 = this;
405
406 var pos = Object.keys(this.state._p2n).find(function (p) {
407 return _this3.isAvailablePos(parentPos + '-0', p);
408 });
409 return pos ? this.state._p2n[pos].key : null;
410 };
411
412 Tree.prototype.isAvailablePos = function isAvailablePos(refPos, targetPos) {
413 var disabled = this.state._p2n[targetPos].disabled;
414
415
416 return this.isSibling(refPos, targetPos) && !disabled;
417 };
418
419 Tree.prototype.isSibling = function isSibling(currentPos, targetPos) {
420 var currentNums = currentPos.split('-').slice(0, -1);
421 var targetNums = targetPos.split('-').slice(0, -1);
422
423 return currentNums.length === targetNums.length && currentNums.every(function (num, index) {
424 return num === targetNums[index];
425 });
426 };
427
428 Tree.prototype.getParentKey = function getParentKey(pos) {
429 return this.state._p2n[pos.slice(0, pos.length - 2)].key;
430 };
431
432 Tree.prototype.processKey = function processKey(keys, key, add) {
433 var index = keys.indexOf(key);
434 if (add && index === -1) {
435 keys.push(key);
436 } else if (!add && index > -1) {
437 keys.splice(index, 1);
438 }
439 return keys;
440 };
441
442 /*eslint-disable max-statements*/
443
444
445 Tree.prototype.handleItemKeyDown = function handleItemKeyDown(key, item, e) {
446 if ([KEYCODE.UP, KEYCODE.DOWN, KEYCODE.RIGHT, KEYCODE.LEFT, KEYCODE.ENTER, KEYCODE.ESC, KEYCODE.SPACE].indexOf(e.keyCode) > -1) {
447 e.preventDefault();
448 e.stopPropagation();
449 }
450
451 var focusedKey = this.state.focusedKey;
452
453 var node = this.state._k2n[key];
454 var pos = this.state._k2n[key].pos;
455 var level = pos.split('-').length - 1;
456 switch (e.keyCode) {
457 case KEYCODE.UP:
458 {
459 var avaliableKey = this.getAvailableKey(pos, true);
460 if (avaliableKey) {
461 focusedKey = avaliableKey;
462 }
463 break;
464 }
465 case KEYCODE.DOWN:
466 {
467 var _avaliableKey = this.getAvailableKey(pos, false);
468 if (_avaliableKey) {
469 focusedKey = _avaliableKey;
470 }
471 break;
472 }
473 case KEYCODE.RIGHT:
474 {
475 this.handleExpand(true, key, node);
476 var _avaliableKey2 = this.getFirstAvaliablelChildKey(pos);
477 if (_avaliableKey2) {
478 focusedKey = _avaliableKey2;
479 }
480 break;
481 }
482 case KEYCODE.LEFT:
483 case KEYCODE.ESC:
484 {
485 if (level === 1) {
486 var _avaliableKey3 = this.getAvailableKey(pos, true);
487 if (_avaliableKey3) {
488 focusedKey = _avaliableKey3;
489 }
490 } else if (level > 1) {
491 var parentKey = this.getParentKey(pos);
492 this.handleExpand(false, parentKey, node);
493 focusedKey = parentKey;
494 }
495 break;
496 }
497
498 case KEYCODE.ENTER:
499 case KEYCODE.SPACE:
500 {
501 var checkable = 'checkable' in item.props ? item.props.checkable : this.props.checkable;
502 var selectable = 'selectable' in item.props ? item.props.selectable : this.props.selectable;
503
504 if (checkable) {
505 this.handleCheck(!item.props.checked, key, node);
506 } else if (selectable) {
507 this.handleSelect(!item.props.selected, key, node, e);
508 }
509 break;
510 }
511 case KEYCODE.TAB:
512 focusedKey = null;
513 break;
514 default:
515 break;
516 }
517
518 if (focusedKey !== this.state.focusedKey) {
519 if (!('focusedKey' in this.props)) {
520 this.setState({
521 focusedKey: focusedKey
522 });
523 }
524 }
525
526 this.props.onItemKeyDown(focusedKey, item, e);
527 this.props.onItemFocus(focusedKey, e);
528 };
529
530 Tree.prototype.handleBlur = function handleBlur(e) {
531 this.setState({
532 focusedKey: null
533 });
534
535 this.props.onBlur && this.props.onBlur(e);
536 };
537
538 Tree.prototype.handleExpand = function handleExpand(expand, key, node) {
539 var _this4 = this;
540
541 var _props = this.props,
542 onExpand = _props.onExpand,
543 loadData = _props.loadData;
544
545 var expandedKeys = this.state.expandedKeys; // 由于setState 是异步操作,所以去掉 [...this.state.expandedKeys]
546 this.processKey(expandedKeys, key, expand);
547 var setExpandedState = function setExpandedState() {
548 if (!('expandedKeys' in _this4.props)) {
549 _this4.setState({ expandedKeys: expandedKeys });
550 }
551 onExpand(expandedKeys, { expanded: expand, node: node });
552 };
553
554 if (expand && loadData) {
555 return loadData(node).then(setExpandedState);
556 } else {
557 setExpandedState();
558 }
559 };
560
561 Tree.prototype.handleSelect = function handleSelect(select, key, node, e) {
562 var _props2 = this.props,
563 multiple = _props2.multiple,
564 onSelect = _props2.onSelect;
565
566 var selectedKeys = [].concat(this.state.selectedKeys);
567 if (multiple) {
568 this.processKey(selectedKeys, key, select);
569 } else {
570 selectedKeys = select ? [key] : [];
571 }
572
573 if (!('selectedKeys' in this.props)) {
574 this.setState({ selectedKeys: selectedKeys });
575 }
576 onSelect(selectedKeys, {
577 selectedNodes: this.getNodes(selectedKeys),
578 node: node,
579 selected: select,
580 event: e
581 });
582 };
583
584 // eslint-disable-next-line max-statements
585
586
587 Tree.prototype.handleCheck = function handleCheck(check, key, node) {
588 var _this5 = this;
589
590 var _props3 = this.props,
591 checkStrictly = _props3.checkStrictly,
592 checkedStrategy = _props3.checkedStrategy,
593 onCheck = _props3.onCheck;
594 var _state = this.state,
595 _k2n = _state._k2n,
596 _p2n = _state._p2n;
597
598 var checkedKeys = [].concat(this.state.checkedKeys);
599
600 if (checkStrictly) {
601 this.processKey(checkedKeys, key, check);
602 var _newCheckedKeys = isPlainObject(this.props.checkedKeys) ? {
603 checked: checkedKeys,
604 indeterminate: this.state.indeterminateKeys
605 } : checkedKeys;
606
607 onCheck(_newCheckedKeys, {
608 checkedNodes: this.getNodes(checkedKeys),
609 checkedNodesPositions: checkedKeys.map(function (key) {
610 if (!_k2n[key]) return null;
611 var _k2n$key = _k2n[key],
612 node = _k2n$key.node,
613 pos = _k2n$key.pos;
614
615 return { node: node, pos: pos };
616 }).filter(function (v) {
617 return !!v;
618 }),
619 node: node,
620 indeterminateKeys: this.state.indeterminateKeys,
621 checked: check,
622 key: key
623 });
624
625 return;
626 }
627
628 var pos = _k2n[key].pos;
629
630 forEachEnableNode(_k2n[key], function (node) {
631 if (node.checkable === false) return;
632 _this5.processKey(checkedKeys, node.key, check);
633 });
634
635 var ps = Object.keys(_p2n);
636
637 var currentPos = pos;
638 var nums = pos.split('-');
639
640 for (var i = nums.length; i > 2; i--) {
641 var parentCheck = true;
642
643 var parentPos = nums.slice(0, i - 1).join('-');
644 if (_p2n[parentPos].disabled || _p2n[parentPos].checkboxDisabled || _p2n[parentPos].checkable === false) {
645 currentPos = parentPos;
646 continue;
647 }
648 var parentKey = _p2n[parentPos].key;
649 var parentChecked = checkedKeys.indexOf(parentKey) > -1;
650 if (!check && !parentChecked) {
651 break;
652 }
653
654 for (var j = 0; j < ps.length; j++) {
655 var p = ps[j];
656 var pnode = _p2n[p];
657 if (isSiblingOrSelf(currentPos, p) && !pnode.disabled && !pnode.checkboxDisabled) {
658 var k = pnode.key;
659 if (pnode.checkable === false) {
660 // eslint-disable-next-line max-depth
661 if (!pnode.children || pnode.children.length === 0) continue;
662
663 // eslint-disable-next-line max-depth
664 for (var m = 0; m < pnode.children.length; m++) {
665 if (!pnode.children.every(function (child) {
666 return isNodeChecked(child, checkedKeys);
667 })) {
668 parentCheck = false;
669 break;
670 }
671 }
672 } else if (checkedKeys.indexOf(k) === -1) {
673 parentCheck = false;
674 }
675
676 if (!parentCheck) break;
677 }
678 }
679
680 this.processKey(checkedKeys, parentKey, parentCheck);
681
682 currentPos = parentPos;
683 }
684
685 var indeterminateKeys = getIndeterminateKeys(checkedKeys, checkStrictly, _k2n, _p2n);
686 if (!('checkedKeys' in this.props)) {
687 this.setState({
688 checkedKeys: checkedKeys,
689 indeterminateKeys: indeterminateKeys
690 });
691 }
692
693 var newCheckedKeys = void 0;
694 switch (checkedStrategy) {
695 case 'parent':
696 newCheckedKeys = filterChildKey(checkedKeys, _k2n, _p2n);
697 break;
698 case 'child':
699 newCheckedKeys = filterParentKey(checkedKeys, _k2n, _p2n);
700 break;
701 default:
702 newCheckedKeys = checkedKeys;
703 break;
704 }
705
706 onCheck(newCheckedKeys, {
707 checkedNodes: this.getNodes(newCheckedKeys),
708 checkedNodesPositions: newCheckedKeys.map(function (key) {
709 if (!_k2n[key]) return null;
710 var _k2n$key2 = _k2n[key],
711 node = _k2n$key2.node,
712 pos = _k2n$key2.pos;
713
714 return { node: node, pos: pos };
715 }).filter(function (v) {
716 return !!v;
717 }),
718 node: node,
719 indeterminateKeys: indeterminateKeys,
720 checked: check,
721 key: key
722 });
723 };
724
725 Tree.prototype.getNodeProps = function getNodeProps(key) {
726 var prefix = this.props.prefix;
727 var _state2 = this.state,
728 expandedKeys = _state2.expandedKeys,
729 selectedKeys = _state2.selectedKeys,
730 checkedKeys = _state2.checkedKeys,
731 dragOverNodeKey = _state2.dragOverNodeKey,
732 _k2n = _state2._k2n,
733 indeterminateKeys = _state2.indeterminateKeys;
734 var _k2n$key3 = _k2n[key],
735 pos = _k2n$key3.pos,
736 isLeaf = _k2n$key3.isLeaf,
737 level = _k2n$key3.level;
738
739
740 return {
741 prefix: prefix,
742 root: this,
743 eventKey: key,
744 pos: pos,
745 isLeaf: isLeaf,
746 level: level,
747 expanded: expandedKeys.indexOf(key) > -1,
748 selected: selectedKeys.indexOf(key) > -1,
749 checked: checkedKeys.indexOf(key) > -1,
750 indeterminate: indeterminateKeys.indexOf(key) > -1,
751 dragOver: dragOverNodeKey === key && this.dropPosition === 0,
752 dragOverGapTop: dragOverNodeKey === key && this.dropPosition === -1,
753 dragOverGapBottom: dragOverNodeKey === key && this.dropPosition === 1
754 };
755 };
756
757 Tree.prototype.getNodes = function getNodes(keys) {
758 var _this6 = this;
759
760 return keys.map(function (key) {
761 return _this6.state._k2n[key] && _this6.state._k2n[key].node;
762 }).filter(function (v) {
763 return !!v;
764 });
765 };
766
767 Tree.prototype.handleDragStart = function handleDragStart(e, node) {
768 var _this7 = this;
769
770 var dragNodeKey = node.props.eventKey;
771 this.dragNode = node;
772 this.dragNodesKeys = Object.keys(this.state._k2n).filter(function (k) {
773 return isDescendantOrSelf(_this7.state._k2n[dragNodeKey].pos, _this7.state._k2n[k].pos);
774 });
775
776 var expandedKeys = this.processKey([].concat(this.state.expandedKeys), dragNodeKey, false);
777 this.setState({ expandedKeys: expandedKeys });
778
779 this.props.onDragStart({
780 event: e,
781 node: node,
782 expandedKeys: expandedKeys
783 });
784 };
785
786 Tree.prototype.handleDragEnter = function handleDragEnter(e, node) {
787 var dragOverNodeKey = node.props.eventKey;
788 this.dropPosition = this.getDropPosition(e, node);
789 if (this.dragNode && this.dragNode.props.eventKey === dragOverNodeKey && this.dropPosition === 0) {
790 this.setState({
791 dragOverNodeKey: null
792 });
793 return;
794 }
795
796 var expandedKeys = this.processKey([].concat(this.state.expandedKeys), dragOverNodeKey, true);
797 this.setState({
798 dragOverNodeKey: dragOverNodeKey,
799 expandedKeys: expandedKeys
800 });
801
802 this.props.onDragEnter({
803 event: e,
804 node: node,
805 expandedKeys: expandedKeys
806 });
807 };
808
809 Tree.prototype.getDropPosition = function getDropPosition(e, node) {
810 var labelWrapperNode = node.labelWrapperEl;
811 var offsetTop = getOffset(labelWrapperNode).top;
812 var offsetHeight = labelWrapperNode.offsetHeight;
813 var pageY = e.pageY;
814 var gapHeight = 2;
815
816 if (pageY > offsetTop + offsetHeight - gapHeight) {
817 return 1;
818 }
819 if (pageY < offsetTop + gapHeight) {
820 return -1;
821 }
822 return 0;
823 };
824
825 Tree.prototype.handleDragOver = function handleDragOver(e, node) {
826 var dragOverNodeKey = node.props.eventKey;
827 if (this.state.dragOverNodeKey !== dragOverNodeKey) {
828 this.setState({
829 dragOverNodeKey: dragOverNodeKey
830 });
831 }
832
833 this.props.onDragOver({ event: e, node: node });
834 };
835
836 Tree.prototype.handleDragLeave = function handleDragLeave(e, node) {
837 var eventKey = node.props.eventKey;
838 var _keyList = this.state._keyList;
839
840 var firstKey = _keyList[0];
841 var lastKey = _keyList[_keyList.length - 1];
842 // 只针对树的边界节点(第一个和最后一个)做处理
843 if (eventKey === firstKey || eventKey === lastKey) {
844 this.setState({
845 dragOverNodeKey: null
846 });
847 }
848 this.props.onDragLeave({ event: e, node: node });
849 };
850
851 Tree.prototype.handleDragEnd = function handleDragEnd(e, node) {
852 this.setState({
853 dragOverNodeKey: null
854 });
855
856 this.props.onDragEnd({ event: e, node: node });
857 };
858
859 Tree.prototype.handleDrop = function handleDrop(e, node) {
860 if (this.dragNode && isDescendantOrSelf(this.state._k2n[this.dragNode.props.eventKey].pos, this.state._k2n[node.props.eventKey].pos)) {
861 return;
862 }
863
864 this.setState({
865 dragOverNodeKey: null
866 });
867
868 var params = this.generateDropParams(node);
869 this.props.onDrop(_extends({
870 event: e
871 }, params));
872 };
873
874 Tree.prototype.canDrop = function canDrop(node) {
875 var params = this.generateDropParams(node);
876 return this.props.canDrop(params);
877 };
878
879 Tree.prototype.generateDropParams = function generateDropParams(node) {
880 return {
881 dragNode: this.dragNode,
882 dragNodesKeys: [].concat(this.dragNodesKeys),
883 node: node,
884 dropPosition: this.dropPosition
885 };
886 };
887
888 Tree.prototype.filterTreeNode = function filterTreeNode(node) {
889 return this.props.filterTreeNode.call(this, node);
890 };
891
892 Tree.prototype.shouldNodeShow = function shouldNodeShow(nodeData) {
893 var _state3 = this.state,
894 expandedKeys = _state3.expandedKeys,
895 _p2n = _state3._p2n;
896
897
898 return !(nodeData.style && nodeData.style.display === 'none') && getAllDescendantKeys(nodeData, _p2n).every(function (k) {
899 return expandedKeys.includes(k);
900 });
901 };
902
903 Tree.prototype.renderTreeNode = function renderTreeNode(props, childNodes) {
904 var _props4 = this.props,
905 rtl = _props4.rtl,
906 labelRender = _props4.labelRender;
907 var key = props.key;
908
909 var nodeProps = _extends({
910 _key: key
911 }, props, this.getNodeProps(key));
912
913 if (labelRender) {
914 nodeProps.label = labelRender(pickProps(treeNodeProps, props));
915 }
916
917 return React.createElement(
918 TreeNode,
919 _extends({ rtl: rtl, key: key }, nodeProps),
920 childNodes
921 );
922 };
923
924 Tree.prototype.renderNodeList = function renderNodeList(dataSource) {
925 var _this8 = this;
926
927 var nodeList = [];
928 var _k2n = this.state._k2n;
929
930 var drill = function drill(list) {
931 list.forEach(function (item) {
932 // 为了兼容之前的实现 保留非法节点
933 if (item.illegalFlag) {
934 nodeList.push(item);
935 return;
936 }
937
938 var children = item.children,
939 nodeProps = _objectWithoutProperties(item, ['children']);
940
941 if (!_this8.shouldNodeShow(item)) {
942 return;
943 }
944
945 nodeList.push(nodeProps);
946 children && children.length && drill(children);
947 });
948 };
949
950 drill(dataSource);
951
952 return nodeList.map(function (nodeProps, index) {
953 // 为了兼容之前的实现 保留非法节点
954 if (nodeProps.illegalFlag) {
955 return nodeProps.node;
956 }
957 // aria props
958 nodeProps.size = nodeList.length;
959 nodeProps.posinset = index + 1;
960
961 return _k2n[nodeProps.key].node = _this8.renderTreeNode(nodeProps);
962 });
963 };
964
965 Tree.prototype.renderWithCustomChildNodes = function renderWithCustomChildNodes(dataSource) {
966 var _this9 = this;
967
968 var renderChildNodes = this.props.renderChildNodes;
969 var _k2n = this.state._k2n;
970
971
972 var drill = function drill(list) {
973 return list.map(function (_ref, index) {
974 var children = _ref.children,
975 nodeProps = _objectWithoutProperties(_ref, ['children']);
976
977 var childNodes = void 0;
978
979 if (children && children.length) {
980 childNodes = renderChildNodes(drill(children));
981 }
982
983 // aria props
984 nodeProps.size = list.length;
985 nodeProps.posinset = index + 1;
986
987 return _k2n[nodeProps.key].node = _this9.renderTreeNode(nodeProps, childNodes);
988 });
989 };
990 return drill(dataSource);
991 };
992
993 Tree.prototype.renderByDataSource = function renderByDataSource(dataSource) {
994 var _this10 = this;
995
996 var drill = function drill(data) {
997 var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '0';
998
999 return data.map(function (item, index) {
1000 // 为了兼容之前的实现 保留非法节点
1001 if (item.illegalFlag) {
1002 return item.node;
1003 }
1004 var pos = prefix + '-' + index;
1005
1006 var _item$key = item.key,
1007 key = _item$key === undefined ? pos : _item$key,
1008 children = item.children,
1009 others = _objectWithoutProperties(item, ['key', 'children']);
1010
1011 var props = _extends({
1012 size: data.length
1013 }, others, _this10.getNodeProps('' + key), {
1014 _key: key,
1015 key: key
1016 });
1017
1018 if (children && children.length) {
1019 props.children = drill(children, pos);
1020 }
1021
1022 var node = _this10.renderTreeNode(props, props.children);
1023
1024 // eslint-disable-next-line
1025 _this10.state._k2n[key].node = node;
1026 return node;
1027 });
1028 };
1029
1030 return drill(dataSource);
1031 };
1032
1033 Tree.prototype.renderByChildren = function renderByChildren() {
1034 var _this11 = this;
1035
1036 var rtl = this.props.rtl;
1037 var _k2n = this.state._k2n;
1038
1039
1040 var loop = function loop(children) {
1041 var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '0';
1042
1043 return Children.map(children, function (child, index) {
1044 if (!React.isValidElement(child)) {
1045 return;
1046 }
1047 var pos = prefix + '-' + index;
1048 var key = child.key || pos;
1049 var props = _this11.getNodeProps('' + key);
1050 if (child.props.children) {
1051 props.children = loop(child.props.children, pos);
1052 }
1053
1054 props._key = key;
1055 props.rtl = rtl;
1056 props.size = Children.count(children);
1057
1058 var node = cloneElement(child, props);
1059 _k2n[key].node = node;
1060 return node;
1061 });
1062 };
1063
1064 return loop(this.props.children);
1065 };
1066
1067 Tree.prototype.render = function render() {
1068 var _cx,
1069 _this12 = this;
1070
1071 var _props5 = this.props,
1072 prefix = _props5.prefix,
1073 rtl = _props5.rtl,
1074 className = _props5.className,
1075 showLine = _props5.showLine,
1076 isNodeBlock = _props5.isNodeBlock,
1077 isLabelBlock = _props5.isLabelBlock,
1078 multiple = _props5.multiple,
1079 useVirtual = _props5.useVirtual,
1080 renderChildNodes = _props5.renderChildNodes;
1081 var dataSource = this.state.dataSource;
1082
1083 var _pickOthers = pickOthers(Object.keys(Tree.propTypes), this.props),
1084 style = _pickOthers.style,
1085 others = _objectWithoutProperties(_pickOthers, ['style']);
1086
1087 if (rtl) {
1088 others.dir = 'rtl';
1089 }
1090
1091 var newClassName = cx((_cx = {}, _cx[prefix + 'tree'] = true, _cx[prefix + 'label-block'] = isLabelBlock, _cx[prefix + 'node-block'] = isNodeBlock, _cx[prefix + 'node-indent'] = !isNodeBlock, _cx[prefix + 'show-line'] = !isNodeBlock && showLine, _cx[className] = !!className, _cx));
1092
1093 var treeRender = function treeRender(items, ref) {
1094 return React.createElement(
1095 'ul',
1096 _extends({
1097 role: 'tree',
1098 ref: ref,
1099 'aria-multiselectable': multiple,
1100 onBlur: _this12.handleBlur,
1101 className: newClassName,
1102 style: useVirtual ? null : style
1103 }, others),
1104 items
1105 );
1106 };
1107
1108 var virtualTreeRender = function virtualTreeRender(dataSource) {
1109 return React.createElement(
1110 'div',
1111 { className: prefix + 'virtual-tree-container', style: style },
1112 React.createElement(
1113 VirtualList,
1114 { itemsRenderer: function itemsRenderer(items, ref) {
1115 return treeRender(items, ref);
1116 } },
1117 _this12.renderNodeList(dataSource)
1118 )
1119 );
1120 };
1121
1122 return useVirtual ? virtualTreeRender(dataSource) : renderChildNodes ? treeRender(this.renderWithCustomChildNodes(dataSource)) : !this.props.dataSource ? treeRender(this.renderByChildren()) : treeRender(this.renderByDataSource(dataSource));
1123 };
1124
1125 return Tree;
1126}(Component), _class.propTypes = {
1127 prefix: PropTypes.string,
1128 rtl: PropTypes.bool,
1129 pure: PropTypes.bool,
1130 className: PropTypes.string,
1131 /**
1132 * 树节点
1133 */
1134 children: PropTypes.node,
1135 /**
1136 * 数据源,该属性优先级高于 children
1137 */
1138 dataSource: PropTypes.array,
1139 /**
1140 * 是否显示树的线
1141 */
1142 showLine: PropTypes.bool,
1143 /**
1144 * 是否支持选中节点
1145 */
1146 selectable: PropTypes.bool,
1147 /**
1148 * (用于受控)当前选中节点 key 的数组
1149 */
1150 selectedKeys: PropTypes.arrayOf(PropTypes.string),
1151 /**
1152 * (用于非受控)默认选中节点 key 的数组
1153 */
1154 defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string),
1155 /**
1156 * 选中或取消选中节点时触发的回调函数
1157 * @param {Array} selectedKeys 选中节点key的数组
1158 * @param {Object} extra 额外参数
1159 * @param {Array} extra.selectedNodes 选中节点的数组
1160 * @param {Object} extra.node 当前操作的节点
1161 * @param {Boolean} extra.selected 当前操作是否是选中
1162 */
1163 onSelect: PropTypes.func,
1164 /**
1165 * 是否支持多选
1166 */
1167 multiple: PropTypes.bool,
1168 /**
1169 * 是否支持勾选节点的复选框
1170 */
1171 checkable: PropTypes.bool,
1172 /**
1173 * (用于受控)当前勾选复选框节点 key 的数组或 `{checked: Array, indeterminate: Array}` 的对象
1174 */
1175 checkedKeys: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.object]),
1176 /**
1177 * (用于非受控)默认勾选复选框节点 key 的数组
1178 */
1179 defaultCheckedKeys: PropTypes.arrayOf(PropTypes.string),
1180 /**
1181 * 勾选节点复选框是否完全受控(父子节点选中状态不再关联)
1182 */
1183 checkStrictly: PropTypes.bool,
1184 /**
1185 * 定义选中时回填的方式
1186 * @enumdesc 返回所有选中的节点, 父子节点都选中时只返回父节点, 父子节点都选中时只返回子节点
1187 */
1188 checkedStrategy: PropTypes.oneOf(['all', 'parent', 'child']),
1189 /**
1190 * 勾选或取消勾选复选框时触发的回调函数
1191 * @param {Array} checkedKeys 勾选复选框节点key的数组
1192 * @param {Object} extra 额外参数
1193 * @param {Array} extra.checkedNodes 勾选复选框节点的数组
1194 * @param {Array} extra.checkedNodesPositions 包含有勾选复选框节点和其位置的对象的数组
1195 * @param {Array} extra.indeterminateKeys 半选复选框节点 key 的数组
1196 * @param {Object} extra.node 当前操作的节点
1197 * @param {Boolean} extra.checked 当前操作是否是勾选
1198 */
1199 onCheck: PropTypes.func,
1200 /**
1201 * (用于受控)当前展开的节点 key 的数组
1202 */
1203 expandedKeys: PropTypes.arrayOf(PropTypes.string),
1204 /**
1205 * (用于非受控)默认展开的节点 key 的数组
1206 */
1207 defaultExpandedKeys: PropTypes.arrayOf(PropTypes.string),
1208 /**
1209 * 是否默认展开所有节点
1210 */
1211 defaultExpandAll: PropTypes.bool,
1212 /**
1213 * 是否自动展开父节点,建议受控时设置为false
1214 */
1215 autoExpandParent: PropTypes.bool,
1216 /**
1217 * 展开或收起节点时触发的回调函数
1218 * @param {Array} expandedKeys 展开的节点key的数组
1219 * @param {Object} extra 额外参数
1220 * @param {Object} extra.node 当前操作的节点
1221 * @param {Boolean} extra.expanded 当前操作是否是展开
1222 */
1223 onExpand: PropTypes.func,
1224 /**
1225 * 是否支持编辑节点内容
1226 */
1227 editable: PropTypes.bool,
1228 /**
1229 * 编辑节点内容完成时触发的回调函数
1230 * @param {String} key 编辑节点的 key
1231 * @param {String} label 编辑节点完成时节点的文本
1232 * @param {Object} node 当前编辑的节点
1233 */
1234 onEditFinish: PropTypes.func,
1235 /**
1236 * 是否支持拖拽节点
1237 */
1238 draggable: PropTypes.bool,
1239 /**
1240 * 开始拖拽节点时触发的回调函数
1241 * @param {Object} info 拖拽信息
1242 * @param {Object} info.event 事件对象
1243 * @param {Object} info.node 拖拽的节点
1244 */
1245 onDragStart: PropTypes.func,
1246 /**
1247 * 拖拽节点进入目标节点时触发的回调函数
1248 * @param {Object} info 拖拽信息
1249 * @param {Object} info.event 事件对象
1250 * @param {Object} info.node 目标节点
1251 * @param {Array} info.expandedKeys 当前展开的节点key的数组
1252 */
1253 onDragEnter: PropTypes.func,
1254 /**
1255 * 拖拽节点在目标节点上移动的时候触发的回调函数
1256 * @param {Object} info 拖拽信息
1257 * @param {Object} info.event 事件对象
1258 * @param {Object} info.node 目标节点
1259 */
1260 onDragOver: PropTypes.func,
1261 /**
1262 * 拖拽节点离开目标节点时触发的回调函数
1263 * @param {Object} info 拖拽信息
1264 * @param {Object} info.event 事件对象
1265 * @param {Object} info.node 目标节点
1266 */
1267 onDragLeave: PropTypes.func,
1268 /**
1269 * 拖拽节点拖拽结束时触发的回调函数
1270 * @param {Object} info 拖拽信息
1271 * @param {Object} info.event 事件对象
1272 * @param {Object} info.node 目标节点
1273 */
1274 onDragEnd: PropTypes.func,
1275 /**
1276 * 拖拽节点放入目标节点内或前后触发的回调函数
1277 * @param {Object} info 拖拽信息
1278 * @param {Object} info.event 事件对象
1279 * @param {Object} info.node 目标节点
1280 * @param {Object} info.dragNode 拖拽的节点
1281 * @param {Array} info.dragNodesKeys 拖拽的节点和其子节点 key 的数组
1282 * @param {Number} info.dropPosition 放置位置,-1代表当前节点前,0代表当前节点里,1代表当前节点后
1283 */
1284 onDrop: PropTypes.func,
1285 /**
1286 * 节点是否可被作为拖拽的目标节点
1287 * @param {Object} info 拖拽信息
1288 * @param {Object} info.node 目标节点
1289 * @param {Object} info.dragNode 拖拽的节点
1290 * @param {Array} info.dragNodesKeys 拖拽的节点和其子节点 key 的数组
1291 * @param {Number} info.dropPosition 放置位置,-1代表当前节点前,0代表当前节点里,1代表当前节点后
1292 * @return {Boolean} 是否可以被当作目标节点
1293 */
1294 canDrop: PropTypes.func,
1295 /**
1296 * 异步加载数据的函数
1297 * @param {Object} node 被点击展开的节点
1298 */
1299 loadData: PropTypes.func,
1300 /**
1301 * 按需筛选高亮节点
1302 * @param {Object} node 待筛选的节点
1303 * @return {Boolean} 是否被筛选中
1304 */
1305 filterTreeNode: PropTypes.func,
1306 /**
1307 * 右键点击节点时触发的回调函数
1308 * @param {Object} info 信息对象
1309 * @param {Object} info.event 事件对象
1310 * @param {Object} info.node 点击的节点
1311 */
1312 onRightClick: PropTypes.func,
1313 /**
1314 * 设置节点是否占满剩余空间,一般用于统一在各节点右侧添加元素(借助 flex 实现,暂时只支持 ie10+)
1315 */
1316 isLabelBlock: PropTypes.bool,
1317 /**
1318 * 设置节点是否占满一行
1319 */
1320 isNodeBlock: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
1321 /**
1322 * 是否开启展开收起动画
1323 */
1324 animation: PropTypes.bool,
1325 /**
1326 * 当前获得焦点的子菜单或菜单项 key 值
1327 */
1328 focusedKey: PropTypes.string,
1329 /**
1330 * 渲染子节点
1331 * @param {Array<ReactNode>} nodes 所有的子节点
1332 * @return {ReactNode} 返回节点
1333 */
1334 renderChildNodes: PropTypes.func,
1335 focusable: PropTypes.bool,
1336 autoFocus: PropTypes.bool,
1337 onItemFocus: PropTypes.func,
1338 onBlur: PropTypes.func,
1339 onItemKeyDown: PropTypes.func,
1340 /**
1341 * 自定义渲染单个子节点
1342 * @param {Object} node 节点数据
1343 * @return {ReactNode} 返回节点
1344 * @version 1.25
1345 */
1346 labelRender: PropTypes.func,
1347 /**
1348 * 是否开启虚拟滚动
1349 */
1350 useVirtual: PropTypes.bool,
1351 /**
1352 * 是否是不可变数据
1353 * @version 1.23
1354 */
1355 immutable: PropTypes.bool
1356}, _class.defaultProps = {
1357 prefix: 'next-',
1358 rtl: false,
1359 pure: false,
1360 showLine: false,
1361 selectable: true,
1362 editable: false,
1363 multiple: false,
1364 checkable: false,
1365 checkStrictly: false,
1366 checkedStrategy: 'all',
1367 draggable: false,
1368 autoExpandParent: true,
1369 defaultExpandAll: false,
1370 defaultExpandedKeys: [],
1371 defaultCheckedKeys: [],
1372 defaultSelectedKeys: [],
1373 onExpand: noop,
1374 onCheck: noop,
1375 onSelect: noop,
1376 onDragStart: noop,
1377 onDragEnter: noop,
1378 onDragOver: noop,
1379 onDragLeave: noop,
1380 onDragEnd: noop,
1381 onDrop: noop,
1382 canDrop: function canDrop() {
1383 return true;
1384 },
1385 onEditFinish: noop,
1386 onRightClick: noop,
1387 isLabelBlock: false,
1388 isNodeBlock: false,
1389 animation: true,
1390 focusable: true,
1391 autoFocus: false,
1392 onItemFocus: noop,
1393 onItemKeyDown: noop,
1394 useVirtual: false,
1395 immutable: false
1396}, _temp);
1397Tree.displayName = 'Tree';
1398
1399
1400export default polyfill(Tree);
\No newline at end of file