NodeList.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _typeof = require("@babel/runtime/helpers/typeof");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = exports.MotionEntity = exports.MOTION_KEY = void 0;
  8. exports.getMinimumRangeTransitionRange = getMinimumRangeTransitionRange;
  9. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  10. var _objectDestructuringEmpty2 = _interopRequireDefault(require("@babel/runtime/helpers/objectDestructuringEmpty"));
  11. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  12. var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
  13. var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect"));
  14. var _rcVirtualList = _interopRequireDefault(require("rc-virtual-list"));
  15. var React = _interopRequireWildcard(require("react"));
  16. var _MotionTreeNode = _interopRequireDefault(require("./MotionTreeNode"));
  17. var _diffUtil = require("./utils/diffUtil");
  18. var _treeUtil = require("./utils/treeUtil");
  19. var _excluded = ["prefixCls", "data", "selectable", "checkable", "expandedKeys", "selectedKeys", "checkedKeys", "loadedKeys", "loadingKeys", "halfCheckedKeys", "keyEntities", "disabled", "dragging", "dragOverNodeKey", "dropPosition", "motion", "height", "itemHeight", "virtual", "scrollWidth", "focusable", "activeItem", "focused", "tabIndex", "onKeyDown", "onFocus", "onBlur", "onActiveChange", "onListChangeStart", "onListChangeEnd"];
  20. /**
  21. * Handle virtual list of the TreeNodes.
  22. */
  23. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
  24. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  25. var HIDDEN_STYLE = {
  26. width: 0,
  27. height: 0,
  28. display: 'flex',
  29. overflow: 'hidden',
  30. opacity: 0,
  31. border: 0,
  32. padding: 0,
  33. margin: 0
  34. };
  35. var noop = function noop() {};
  36. var MOTION_KEY = exports.MOTION_KEY = "RC_TREE_MOTION_".concat(Math.random());
  37. var MotionNode = {
  38. key: MOTION_KEY
  39. };
  40. var MotionEntity = exports.MotionEntity = {
  41. key: MOTION_KEY,
  42. level: 0,
  43. index: 0,
  44. pos: '0',
  45. node: MotionNode,
  46. nodes: [MotionNode]
  47. };
  48. var MotionFlattenData = {
  49. parent: null,
  50. children: [],
  51. pos: MotionEntity.pos,
  52. data: MotionNode,
  53. title: null,
  54. key: MOTION_KEY,
  55. /** Hold empty list here since we do not use it */
  56. isStart: [],
  57. isEnd: []
  58. };
  59. /**
  60. * We only need get visible content items to play the animation.
  61. */
  62. function getMinimumRangeTransitionRange(list, virtual, height, itemHeight) {
  63. if (virtual === false || !height) {
  64. return list;
  65. }
  66. return list.slice(0, Math.ceil(height / itemHeight) + 1);
  67. }
  68. function itemKey(item) {
  69. var key = item.key,
  70. pos = item.pos;
  71. return (0, _treeUtil.getKey)(key, pos);
  72. }
  73. function getAccessibilityPath(item) {
  74. var path = String(item.data.key);
  75. var current = item;
  76. while (current.parent) {
  77. current = current.parent;
  78. path = "".concat(current.data.key, " > ").concat(path);
  79. }
  80. return path;
  81. }
  82. var NodeList = /*#__PURE__*/React.forwardRef(function (props, ref) {
  83. var prefixCls = props.prefixCls,
  84. data = props.data,
  85. selectable = props.selectable,
  86. checkable = props.checkable,
  87. expandedKeys = props.expandedKeys,
  88. selectedKeys = props.selectedKeys,
  89. checkedKeys = props.checkedKeys,
  90. loadedKeys = props.loadedKeys,
  91. loadingKeys = props.loadingKeys,
  92. halfCheckedKeys = props.halfCheckedKeys,
  93. keyEntities = props.keyEntities,
  94. disabled = props.disabled,
  95. dragging = props.dragging,
  96. dragOverNodeKey = props.dragOverNodeKey,
  97. dropPosition = props.dropPosition,
  98. motion = props.motion,
  99. height = props.height,
  100. itemHeight = props.itemHeight,
  101. virtual = props.virtual,
  102. scrollWidth = props.scrollWidth,
  103. focusable = props.focusable,
  104. activeItem = props.activeItem,
  105. focused = props.focused,
  106. tabIndex = props.tabIndex,
  107. onKeyDown = props.onKeyDown,
  108. onFocus = props.onFocus,
  109. onBlur = props.onBlur,
  110. onActiveChange = props.onActiveChange,
  111. onListChangeStart = props.onListChangeStart,
  112. onListChangeEnd = props.onListChangeEnd,
  113. domProps = (0, _objectWithoutProperties2.default)(props, _excluded);
  114. // =============================== Ref ================================
  115. var listRef = React.useRef(null);
  116. var indentMeasurerRef = React.useRef(null);
  117. React.useImperativeHandle(ref, function () {
  118. return {
  119. scrollTo: function scrollTo(scroll) {
  120. listRef.current.scrollTo(scroll);
  121. },
  122. getIndentWidth: function getIndentWidth() {
  123. return indentMeasurerRef.current.offsetWidth;
  124. }
  125. };
  126. });
  127. // ============================== Motion ==============================
  128. var _React$useState = React.useState(expandedKeys),
  129. _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
  130. prevExpandedKeys = _React$useState2[0],
  131. setPrevExpandedKeys = _React$useState2[1];
  132. var _React$useState3 = React.useState(data),
  133. _React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
  134. prevData = _React$useState4[0],
  135. setPrevData = _React$useState4[1];
  136. var _React$useState5 = React.useState(data),
  137. _React$useState6 = (0, _slicedToArray2.default)(_React$useState5, 2),
  138. transitionData = _React$useState6[0],
  139. setTransitionData = _React$useState6[1];
  140. var _React$useState7 = React.useState([]),
  141. _React$useState8 = (0, _slicedToArray2.default)(_React$useState7, 2),
  142. transitionRange = _React$useState8[0],
  143. setTransitionRange = _React$useState8[1];
  144. var _React$useState9 = React.useState(null),
  145. _React$useState10 = (0, _slicedToArray2.default)(_React$useState9, 2),
  146. motionType = _React$useState10[0],
  147. setMotionType = _React$useState10[1];
  148. // When motion end but data change, this will makes data back to previous one
  149. var dataRef = React.useRef(data);
  150. dataRef.current = data;
  151. function onMotionEnd() {
  152. var latestData = dataRef.current;
  153. setPrevData(latestData);
  154. setTransitionData(latestData);
  155. setTransitionRange([]);
  156. setMotionType(null);
  157. onListChangeEnd();
  158. }
  159. // Do animation if expanded keys changed
  160. // layoutEffect here to avoid blink of node removing
  161. (0, _useLayoutEffect.default)(function () {
  162. setPrevExpandedKeys(expandedKeys);
  163. var diffExpanded = (0, _diffUtil.findExpandedKeys)(prevExpandedKeys, expandedKeys);
  164. if (diffExpanded.key !== null) {
  165. if (diffExpanded.add) {
  166. var keyIndex = prevData.findIndex(function (_ref) {
  167. var key = _ref.key;
  168. return key === diffExpanded.key;
  169. });
  170. var rangeNodes = getMinimumRangeTransitionRange((0, _diffUtil.getExpandRange)(prevData, data, diffExpanded.key), virtual, height, itemHeight);
  171. var newTransitionData = prevData.slice();
  172. newTransitionData.splice(keyIndex + 1, 0, MotionFlattenData);
  173. setTransitionData(newTransitionData);
  174. setTransitionRange(rangeNodes);
  175. setMotionType('show');
  176. } else {
  177. var _keyIndex = data.findIndex(function (_ref2) {
  178. var key = _ref2.key;
  179. return key === diffExpanded.key;
  180. });
  181. var _rangeNodes = getMinimumRangeTransitionRange((0, _diffUtil.getExpandRange)(data, prevData, diffExpanded.key), virtual, height, itemHeight);
  182. var _newTransitionData = data.slice();
  183. _newTransitionData.splice(_keyIndex + 1, 0, MotionFlattenData);
  184. setTransitionData(_newTransitionData);
  185. setTransitionRange(_rangeNodes);
  186. setMotionType('hide');
  187. }
  188. } else if (prevData !== data) {
  189. // If whole data changed, we just refresh the list
  190. setPrevData(data);
  191. setTransitionData(data);
  192. }
  193. }, [expandedKeys, data]);
  194. // We should clean up motion if is changed by dragging
  195. React.useEffect(function () {
  196. if (!dragging) {
  197. onMotionEnd();
  198. }
  199. }, [dragging]);
  200. var mergedData = motion ? transitionData : data;
  201. var treeNodeRequiredProps = {
  202. expandedKeys: expandedKeys,
  203. selectedKeys: selectedKeys,
  204. loadedKeys: loadedKeys,
  205. loadingKeys: loadingKeys,
  206. checkedKeys: checkedKeys,
  207. halfCheckedKeys: halfCheckedKeys,
  208. dragOverNodeKey: dragOverNodeKey,
  209. dropPosition: dropPosition,
  210. keyEntities: keyEntities
  211. };
  212. return /*#__PURE__*/React.createElement(React.Fragment, null, focused && activeItem && /*#__PURE__*/React.createElement("span", {
  213. style: HIDDEN_STYLE,
  214. "aria-live": "assertive"
  215. }, getAccessibilityPath(activeItem)), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("input", {
  216. style: HIDDEN_STYLE,
  217. disabled: focusable === false || disabled,
  218. tabIndex: focusable !== false ? tabIndex : null,
  219. onKeyDown: onKeyDown,
  220. onFocus: onFocus,
  221. onBlur: onBlur,
  222. value: "",
  223. onChange: noop,
  224. "aria-label": "for screen reader"
  225. })), /*#__PURE__*/React.createElement("div", {
  226. className: "".concat(prefixCls, "-treenode"),
  227. "aria-hidden": true,
  228. style: {
  229. position: 'absolute',
  230. pointerEvents: 'none',
  231. visibility: 'hidden',
  232. height: 0,
  233. overflow: 'hidden',
  234. border: 0,
  235. padding: 0
  236. }
  237. }, /*#__PURE__*/React.createElement("div", {
  238. className: "".concat(prefixCls, "-indent")
  239. }, /*#__PURE__*/React.createElement("div", {
  240. ref: indentMeasurerRef,
  241. className: "".concat(prefixCls, "-indent-unit")
  242. }))), /*#__PURE__*/React.createElement(_rcVirtualList.default, (0, _extends2.default)({}, domProps, {
  243. data: mergedData,
  244. itemKey: itemKey,
  245. height: height,
  246. fullHeight: false,
  247. virtual: virtual,
  248. itemHeight: itemHeight,
  249. scrollWidth: scrollWidth,
  250. prefixCls: "".concat(prefixCls, "-list"),
  251. ref: listRef,
  252. role: "tree",
  253. onVisibleChange: function onVisibleChange(originList) {
  254. // The best match is using `fullList` - `originList` = `restList`
  255. // and check the `restList` to see if has the MOTION_KEY node
  256. // but this will cause performance issue for long list compare
  257. // we just check `originList` and repeat trigger `onMotionEnd`
  258. if (originList.every(function (item) {
  259. return itemKey(item) !== MOTION_KEY;
  260. })) {
  261. onMotionEnd();
  262. }
  263. }
  264. }), function (treeNode) {
  265. var pos = treeNode.pos,
  266. restProps = Object.assign({}, ((0, _objectDestructuringEmpty2.default)(treeNode.data), treeNode.data)),
  267. title = treeNode.title,
  268. key = treeNode.key,
  269. isStart = treeNode.isStart,
  270. isEnd = treeNode.isEnd;
  271. var mergedKey = (0, _treeUtil.getKey)(key, pos);
  272. delete restProps.key;
  273. delete restProps.children;
  274. var treeNodeProps = (0, _treeUtil.getTreeNodeProps)(mergedKey, treeNodeRequiredProps);
  275. return /*#__PURE__*/React.createElement(_MotionTreeNode.default, (0, _extends2.default)({}, restProps, treeNodeProps, {
  276. title: title,
  277. active: !!activeItem && key === activeItem.key,
  278. pos: pos,
  279. data: treeNode.data,
  280. isStart: isStart,
  281. isEnd: isEnd,
  282. motion: motion,
  283. motionNodes: key === MOTION_KEY ? transitionRange : null,
  284. motionType: motionType,
  285. onMotionStart: onListChangeStart,
  286. onMotionEnd: onMotionEnd,
  287. treeNodeRequiredProps: treeNodeRequiredProps,
  288. onMouseMove: function onMouseMove() {
  289. onActiveChange(null);
  290. }
  291. }));
  292. }));
  293. });
  294. if (process.env.NODE_ENV !== 'production') {
  295. NodeList.displayName = 'NodeList';
  296. }
  297. var _default = exports.default = NodeList;