UNPKG

@atlaskit/tree

Version:

A React Component for displaying expandable and sortable tree hierarchies

307 lines (305 loc) 15.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _reactBeautifulDndNext = require("react-beautiful-dnd-next"); var _cssBoxModel = require("css-box-model"); var _TreeUtils = require("./Tree-utils"); var _handy = require("../../utils/handy"); var _tree = require("../../utils/tree"); var _mutateTree = require("../../utils/mutateTree"); var _TreeItem = _interopRequireDefault(require("../TreeItem")); var _flatTree = require("../../utils/flat-tree"); var _delayedFunction = _interopRequireDefault(require("../../utils/delayed-function")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } var Tree = /*#__PURE__*/function (_Component) { (0, _inherits2.default)(Tree, _Component); var _super = _createSuper(Tree); function Tree() { var _this; (0, _classCallCheck2.default)(this, Tree); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _super.call.apply(_super, [this].concat(args)); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "state", { flattenedTree: [], draggedItemId: undefined }); // HTMLElement for each rendered item (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "itemsElement", {}); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "expandTimer", new _delayedFunction.default(500)); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDragStart", function (result) { var onDragStart = _this.props.onDragStart; _this.dragState = { source: result.source, destination: result.source, mode: result.mode }; _this.setState({ draggedItemId: result.draggableId }); if (onDragStart) { onDragStart(result.draggableId); } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDragUpdate", function (update) { var onExpand = _this.props.onExpand; var flattenedTree = _this.state.flattenedTree; if (!_this.dragState) { return; } _this.expandTimer.stop(); if (update.combine) { var draggableId = update.combine.draggableId; var item = (0, _flatTree.getItemById)(flattenedTree, draggableId); if (item && _this.isExpandable(item)) { _this.expandTimer.start(function () { return onExpand(draggableId, item.path); }); } } _this.dragState = _objectSpread(_objectSpread({}, _this.dragState), {}, { destination: update.destination, combine: update.combine }); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDropAnimating", function () { _this.expandTimer.stop(); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDragEnd", function (result) { var _this$props = _this.props, onDragEnd = _this$props.onDragEnd, tree = _this$props.tree; var flattenedTree = _this.state.flattenedTree; _this.expandTimer.stop(); var finalDragState = _objectSpread(_objectSpread({}, _this.dragState), {}, { source: result.source, destination: result.destination, combine: result.combine }); _this.setState({ draggedItemId: undefined }); var _calculateFinalDropPo = (0, _TreeUtils.calculateFinalDropPositions)(tree, flattenedTree, finalDragState), sourcePosition = _calculateFinalDropPo.sourcePosition, destinationPosition = _calculateFinalDropPo.destinationPosition; onDragEnd(sourcePosition, destinationPosition); _this.dragState = undefined; }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onPointerMove", function () { if (_this.dragState) { _this.dragState = _objectSpread(_objectSpread({}, _this.dragState), {}, { horizontalLevel: _this.getDroppedLevel() }); } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "calculateEffectivePath", function (flatItem, snapshot) { var _this$state = _this.state, flattenedTree = _this$state.flattenedTree, draggedItemId = _this$state.draggedItemId; if (_this.dragState && draggedItemId === flatItem.item.id && (_this.dragState.destination || _this.dragState.combine)) { var _this$dragState = _this.dragState, source = _this$dragState.source, destination = _this$dragState.destination, combine = _this$dragState.combine, horizontalLevel = _this$dragState.horizontalLevel, mode = _this$dragState.mode; // We only update the path when it's dragged by keyboard or drop is animated if (mode === 'SNAP' || snapshot.isDropAnimating) { if (destination) { // Between two items return (0, _flatTree.getDestinationPath)(flattenedTree, source.index, destination.index, horizontalLevel); } if (combine) { // Hover on other item while dragging return (0, _flatTree.getDestinationPath)(flattenedTree, source.index, (0, _flatTree.getIndexById)(flattenedTree, combine.draggableId), horizontalLevel); } } } return flatItem.path; }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "isExpandable", function (item) { return !!item.item.hasChildren && !item.item.isExpanded; }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getDroppedLevel", function () { var offsetPerLevel = _this.props.offsetPerLevel; var draggedItemId = _this.state.draggedItemId; if (!_this.dragState || !_this.containerElement) { return undefined; } var containerLeft = (0, _cssBoxModel.getBox)(_this.containerElement).contentBox.left; var itemElement = _this.itemsElement[draggedItemId]; if (itemElement) { var currentLeft = (0, _cssBoxModel.getBox)(itemElement).contentBox.left; var relativeLeft = Math.max(currentLeft - containerLeft, 0); return Math.floor((relativeLeft + offsetPerLevel / 2) / offsetPerLevel) + 1; } return undefined; }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "patchDroppableProvided", function (provided) { return _objectSpread(_objectSpread({}, provided), {}, { innerRef: function innerRef(el) { _this.containerElement = el; provided.innerRef(el); } }); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "setItemRef", function (itemId, el) { if (!!el) { _this.itemsElement[itemId] = el; } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "renderItems", function () { var flattenedTree = _this.state.flattenedTree; return flattenedTree.map(_this.renderItem); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "renderItem", function (flatItem, index) { var isDragEnabled = _this.props.isDragEnabled; // If drag and drop is explicitly disabled for all items, render TreeItem directly with stubbed provided and snapshot if (isDragEnabled === false) { return _this.renderTreeItem({ flatItem: flatItem, path: flatItem.path, provided: { draggableProps: { 'data-react-beautiful-dnd-draggable': '' }, innerRef: function innerRef() {}, dragHandleProps: null }, snapshot: { isDragging: false, isDropAnimating: false } }); } var isDragDisabled = typeof isDragEnabled === 'function' ? !isDragEnabled(flatItem.item) : !isDragEnabled; return /*#__PURE__*/_react.default.createElement(_reactBeautifulDndNext.Draggable, { key: flatItem.item.id, draggableId: flatItem.item.id.toString(), index: index, isDragDisabled: isDragDisabled }, _this.renderDraggableItem(flatItem)); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "renderDraggableItem", function (flatItem) { return function (provided, snapshot) { var currentPath = _this.calculateEffectivePath(flatItem, snapshot); if (snapshot.isDropAnimating) { _this.onDropAnimating(); } return _this.renderTreeItem({ flatItem: flatItem, path: currentPath, provided: provided, snapshot: snapshot }); }; }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "renderTreeItem", function (_ref) { var flatItem = _ref.flatItem, path = _ref.path, provided = _ref.provided, snapshot = _ref.snapshot; var _this$props2 = _this.props, renderItem = _this$props2.renderItem, onExpand = _this$props2.onExpand, onCollapse = _this$props2.onCollapse, offsetPerLevel = _this$props2.offsetPerLevel; return /*#__PURE__*/_react.default.createElement(_TreeItem.default, { key: flatItem.item.id, item: flatItem.item, path: path, onExpand: onExpand, onCollapse: onCollapse, renderItem: renderItem, provided: provided, snapshot: snapshot, itemRef: _this.setItemRef, offsetPerLevel: offsetPerLevel }); }); return _this; } (0, _createClass2.default)(Tree, [{ key: "render", value: function render() { var _this2 = this; var isNestingEnabled = this.props.isNestingEnabled; var renderedItems = this.renderItems(); return /*#__PURE__*/_react.default.createElement(_reactBeautifulDndNext.DragDropContext, { onDragStart: this.onDragStart, onDragEnd: this.onDragEnd, onDragUpdate: this.onDragUpdate }, /*#__PURE__*/_react.default.createElement(_reactBeautifulDndNext.Droppable, { droppableId: "tree", isCombineEnabled: isNestingEnabled, ignoreContainerClipping: true }, function (provided) { var finalProvided = _this2.patchDroppableProvided(provided); return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({ ref: finalProvided.innerRef, style: { pointerEvents: 'auto' }, onTouchMove: _this2.onPointerMove, onMouseMove: _this2.onPointerMove }, finalProvided.droppableProps), renderedItems, provided.placeholder); })); } }], [{ key: "getDerivedStateFromProps", value: function getDerivedStateFromProps(props, state) { var draggedItemId = state.draggedItemId; var tree = props.tree; var finalTree = Tree.closeParentIfNeeded(tree, draggedItemId); var flattenedTree = (0, _tree.flattenTree)(finalTree); return _objectSpread(_objectSpread({}, state), {}, { flattenedTree: flattenedTree }); } }, { key: "closeParentIfNeeded", value: function closeParentIfNeeded(tree, draggedItemId) { if (!!draggedItemId) { // Closing parent internally during dragging, because visually we can only move one item not a subtree return (0, _mutateTree.mutateTree)(tree, draggedItemId, { isExpanded: false }); } return tree; } }]); return Tree; }(_react.Component); exports.default = Tree; (0, _defineProperty2.default)(Tree, "defaultProps", { tree: { children: [] }, onExpand: _handy.noop, onCollapse: _handy.noop, onDragStart: _handy.noop, onDragEnd: _handy.noop, renderItem: _handy.noop, offsetPerLevel: 35, isDragEnabled: false, isNestingEnabled: false });