@elliemae/ds-treeview 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/cjs/TreeView.js +2 -6
  2. package/cjs/TreeViewContext.js +2 -8
  3. package/cjs/config/useTreeview.js +3 -13
  4. package/cjs/hoc/DnDTreeContext.js +18 -0
  5. package/cjs/hoc/SortableItemContext.js +21 -0
  6. package/cjs/hoc/WithConditionalDnDContext.js +138 -0
  7. package/cjs/hoc/WithDnDSortableItemContext.js +70 -0
  8. package/cjs/index.js +0 -1
  9. package/cjs/parts/DnDHandle.js +46 -0
  10. package/cjs/parts/DropIndicator.js +75 -0
  11. package/cjs/parts/TreeItem.js +43 -68
  12. package/cjs/parts/TreeList.js +15 -17
  13. package/cjs/plugins/dnd/TreeDndPlugin.js +0 -37
  14. package/cjs/plugins/dnd/index.js +0 -1
  15. package/cjs/plugins/index.js +0 -1
  16. package/cjs/react-desc-prop-types.js +1 -0
  17. package/cjs/utils/keyboard-helpers.js +6 -5
  18. package/cjs/utils/tree-helpers.js +28 -2
  19. package/cjs/utils/useTree.js +4 -2
  20. package/esm/TreeView.js +2 -6
  21. package/esm/TreeViewContext.js +2 -8
  22. package/esm/config/useTreeview.js +4 -14
  23. package/esm/hoc/DnDTreeContext.js +14 -0
  24. package/esm/hoc/SortableItemContext.js +17 -0
  25. package/esm/hoc/WithConditionalDnDContext.js +128 -0
  26. package/esm/hoc/WithDnDSortableItemContext.js +61 -0
  27. package/esm/index.js +1 -1
  28. package/esm/parts/DnDHandle.js +38 -0
  29. package/esm/parts/DropIndicator.js +68 -0
  30. package/esm/parts/TreeItem.js +42 -67
  31. package/esm/parts/TreeList.js +16 -17
  32. package/esm/plugins/dnd/TreeDndPlugin.js +1 -33
  33. package/esm/plugins/dnd/index.js +1 -1
  34. package/esm/plugins/index.js +1 -1
  35. package/esm/react-desc-prop-types.js +1 -0
  36. package/esm/utils/keyboard-helpers.js +6 -5
  37. package/esm/utils/tree-helpers.js +28 -3
  38. package/esm/utils/useTree.js +5 -3
  39. package/package.json +34 -18
  40. package/types/hoc/DnDTreeContext.d.ts +14 -0
  41. package/types/hoc/SortableItemContext.d.ts +19 -0
  42. package/types/hoc/WithConditionalDnDContext.d.ts +4 -0
  43. package/types/hoc/WithDnDSortableItemContext.d.ts +4 -0
  44. package/types/parts/DnDHandle.d.ts +6 -0
  45. package/types/parts/DropIndicator.d.ts +10 -0
  46. package/types/parts/TreeItem.d.ts +4 -11
  47. package/types/parts/TreeList.d.ts +0 -4
  48. package/types/plugins/dnd/TreeDndPlugin.d.ts +0 -2
  49. package/types/react-desc-prop-types.d.ts +17 -3
  50. package/types/sharedTypes.d.ts +1 -8
  51. package/types/utils/keyboard-helpers.d.ts +2 -1
  52. package/types/utils/refs-helpers.d.ts +1 -1
  53. package/types/utils/tree-helpers.d.ts +4 -1
  54. package/types/utils/useTree.d.ts +1 -0
  55. package/cjs/utils/dnd-helpers.js +0 -140
  56. package/cjs/utils/useDnDHelpers.js +0 -220
  57. package/esm/utils/dnd-helpers.js +0 -132
  58. package/esm/utils/useDnDHelpers.js +0 -216
  59. package/types/utils/dnd-helpers.d.ts +0 -39
  60. package/types/utils/useDnDHelpers.d.ts +0 -26
@@ -2,18 +2,15 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var _defineProperty = require('@babel/runtime/helpers/defineProperty');
6
- var _jsx = require('@babel/runtime/helpers/jsx');
7
- require('core-js/modules/web.dom-collections.iterator.js');
8
5
  require('core-js/modules/esnext.async-iterator.filter.js');
9
6
  require('core-js/modules/esnext.iterator.constructor.js');
10
7
  require('core-js/modules/esnext.iterator.filter.js');
11
8
  require('core-js/modules/esnext.async-iterator.for-each.js');
12
9
  require('core-js/modules/esnext.iterator.for-each.js');
10
+ var _jsx = require('@babel/runtime/helpers/jsx');
11
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
13
12
  var React = require('react');
14
- var reactSortableHoc = require('@elliemae/react-sortable-hoc');
15
13
  var dsClassnames = require('@elliemae/ds-classnames');
16
- var dsIcons = require('@elliemae/ds-icons');
17
14
  var RadioSelectable = require('./RadioSelectable.js');
18
15
  var CheckboxSelectable = require('./CheckboxSelectable.js');
19
16
  var TreeViewContext = require('../TreeViewContext.js');
@@ -24,12 +21,16 @@ var Icon = require('./Icon.js');
24
21
  var ExpandCaret = require('./ExpandCaret.js');
25
22
  var TreeItemText = require('./TreeItemText.js');
26
23
  var cssClassesConstants = require('../config/cssClassesConstants.js');
24
+ var DnDHandle = require('./DnDHandle.js');
25
+ var WithDnDSortableItemContext = require('../hoc/WithDnDSortableItemContext.js');
26
+ var SortableItemContext = require('../hoc/SortableItemContext.js');
27
+ var DropIndicator = require('./DropIndicator.js');
27
28
  var jsxRuntime = require('react/jsx-runtime');
28
29
 
29
30
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
30
31
 
31
- var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
32
32
  var _jsx__default = /*#__PURE__*/_interopDefaultLegacy(_jsx);
33
+ var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
33
34
 
34
35
  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; }
35
36
 
@@ -41,23 +42,6 @@ const TreeListItem = dsClassnames.aggregatedClasses('li', {
41
42
  })(cssClassesConstants.treeItemBlockName);
42
43
  const TreeListItemAddonsWrapper = dsClassnames.aggregatedClasses('div')(cssClassesConstants.treeItemBlockName, 'addons' // temp fix untill we move to styled components
43
44
  );
44
- const DnDHandle = reactSortableHoc.SortableHandle(_ref => {
45
- let {
46
- id
47
- } = _ref;
48
- return /*#__PURE__*/_jsx__default["default"](dsIcons.GripperVertical, {
49
- "data-testid": "drag-handle",
50
- className: "drag-handle",
51
- size: "s",
52
- onMouseDown: e => {
53
- // prevent focusing the drag-handle to avoid borders
54
- if (e) {
55
- e.preventDefault();
56
- }
57
- },
58
- tabIndex: "0"
59
- }, "".concat(id, "-drag-handle"));
60
- });
61
45
  const TreeItem = props => {
62
46
  const {
63
47
  item,
@@ -65,7 +49,7 @@ const TreeItem = props => {
65
49
  itemWrapperStyle = {},
66
50
  virtualItemRef,
67
51
  spaceForNestingLevel = 1.5,
68
- onMouseDragOverItem
52
+ isDragOverlay = false
69
53
  } = props;
70
54
  const {
71
55
  id,
@@ -74,9 +58,10 @@ const TreeItem = props => {
74
58
  const {
75
59
  nodeItemRef
76
60
  } = node.model;
77
- const openFolderOnHoverTimeout = React.useRef(null);
78
- const [isDraggingOverThis, setIsDraggingOverThis] = React.useState(false);
79
- const onItemKeyDown = keyboardHelpers.useOnItemKeyDown(item);
61
+ const {
62
+ draggableProps
63
+ } = React.useContext(SortableItemContext.SortableItemContext);
64
+ const onItemKeyDown = keyboardHelpers.useOnItemKeyDown(item, draggableProps);
80
65
  const ctx = React.useContext(TreeViewContext["default"]);
81
66
  const {
82
67
  props: {
@@ -87,14 +72,12 @@ const TreeItem = props => {
87
72
  rowSize,
88
73
  labelOverflow
89
74
  },
90
- relativeMouseCord,
91
75
  withRadioChecks,
92
76
  withCheckboxChecks,
93
77
  withDragAndDrop,
94
78
  selectedItem,
95
79
  selectedCheckboxes,
96
80
  hoverItem,
97
- isDragging,
98
81
  virtualListHelpers: {
99
82
  scrollToIndex
100
83
  },
@@ -104,24 +87,27 @@ const TreeItem = props => {
104
87
  } = ctx; // Sortable Items needs to update
105
88
  // - the virtual list ref (for react-virtual requirement)
106
89
  // - nodeItemRef which is a prop avaiable in the TreeModel nodes
90
+ // - the drag and drop node reference
107
91
 
108
92
  const setItemRefs = ref => {
109
- refsHelpers.setMultipleRefs(virtualItemRef, nodeItemRef)(ref);
93
+ refsHelpers.setMultipleRefs(virtualItemRef, !isDragOverlay && nodeItemRef, !isDragOverlay && draggableProps && draggableProps.setNodeRef)(ref);
110
94
  };
111
95
 
96
+ const dropIndicatorPosition = draggableProps && draggableProps.shouldShowDropIndicatorPosition && draggableProps.dropIndicatorPosition;
97
+ const isDropIndicatorPositionInside = dropIndicatorPosition === SortableItemContext.DropIndicatorPosition.Inside;
98
+ const isDragging = draggableProps && draggableProps.isDragging;
99
+ const isDropValid = draggableProps && draggableProps.isDropValid;
112
100
  const dropPreviewClassName = React.useMemo(() => {
113
- if (!withDragAndDrop || !relativeMouseCord || !isDraggingOverThis) return '';
114
- const {
115
- isBefore,
116
- isAfter,
117
- isValid
118
- } = relativeMouseCord;
119
- let className = "".concat(cssClassesConstants.DSTreeViewPrefix, "-").concat(cssClassesConstants.treeItemBlockName).concat(isValid ? '--valid' : '--invalid');
120
- if (isBefore) className += '-drop-before';else if (isAfter) className += '-drop-after';else className += '-drop-in';
121
- return className;
122
- }, [withDragAndDrop, relativeMouseCord, isDraggingOverThis]);
123
- const selectedClassName = React.useMemo(() => (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) === item.id ? 'selected' : '', [item.id, selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id]);
124
- const hoverClassName = React.useMemo(() => (hoverItem === null || hoverItem === void 0 ? void 0 : hoverItem.id) !== item.id || withDragAndDrop && isDragging ? '' : 'hover', [hoverItem === null || hoverItem === void 0 ? void 0 : hoverItem.id, item.id, withDragAndDrop, isDragging]);
101
+ if (isDropIndicatorPositionInside) {
102
+ const className = "".concat(cssClassesConstants.DSTreeViewPrefix, "-").concat(cssClassesConstants.treeItemBlockName).concat(isDropValid ? '--valid' : '--invalid', "-drop-in");
103
+ return className;
104
+ }
105
+
106
+ return '';
107
+ }, [isDropIndicatorPositionInside, isDropValid]);
108
+ const dragOverlayClassName = React.useMemo(() => isDragOverlay ? 'drag-overlay' : '', [isDragOverlay]);
109
+ const selectedClassName = React.useMemo(() => (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) === item.id && !isDragOverlay ? 'selected' : '', [isDragOverlay, item.id, selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id]);
110
+ const hoverClassName = React.useMemo(() => !isDragOverlay && ((hoverItem === null || hoverItem === void 0 ? void 0 : hoverItem.id) === item.id || isDragging) ? 'hover' : '', [isDragOverlay, hoverItem === null || hoverItem === void 0 ? void 0 : hoverItem.id, item.id, isDragging]);
125
111
  const fixedHeightClassname = React.useMemo(() => {
126
112
  if (labelOverflow === 'truncate') {
127
113
  if (rowSize === 'compact') return "".concat(cssClassesConstants.DSTreeViewPrefix, "-").concat(cssClassesConstants.treeItemBlockName, "--fixed-height-compact");
@@ -130,7 +116,7 @@ const TreeItem = props => {
130
116
 
131
117
  return '';
132
118
  }, [labelOverflow, rowSize]);
133
- const finalClassName = React.useMemo(() => "".concat(dropPreviewClassName, " ").concat(fixedHeightClassname, " ").concat(selectedClassName, " ").concat(hoverClassName), [dropPreviewClassName, selectedClassName, hoverClassName, fixedHeightClassname]);
119
+ const finalClassName = React.useMemo(() => "".concat(dropPreviewClassName, " ").concat(fixedHeightClassname, " ").concat(selectedClassName, " ").concat(hoverClassName, " ").concat(dragOverlayClassName), [dropPreviewClassName, selectedClassName, hoverClassName, fixedHeightClassname, dragOverlayClassName]);
134
120
  const handleItemClick = React.useCallback(e => {
135
121
  onItemClick(item, e);
136
122
  setFocusedItem(item);
@@ -149,23 +135,7 @@ const TreeItem = props => {
149
135
  }, [item, scrollToIndex, onItemClick, onItemFocus, setSelectedItem, setFocusedItem]);
150
136
  return /*#__PURE__*/jsxRuntime.jsxs(TreeListItem, {
151
137
  tabIndex: 0,
152
- onMouseMove: event => {
153
- if (withDragAndDrop && onMouseDragOverItem) {
154
- onMouseDragOverItem({
155
- event,
156
- item,
157
- itemIndex,
158
- setIsDraggingOverThis,
159
- openFolderOnHoverTimeout
160
- });
161
- }
162
- },
163
138
  onMouseLeave: () => {
164
- if (withDragAndDrop) {
165
- setIsDraggingOverThis(false);
166
- if (openFolderOnHoverTimeout !== null && openFolderOnHoverTimeout !== void 0 && openFolderOnHoverTimeout.current) clearTimeout(openFolderOnHoverTimeout.current);
167
- }
168
-
169
139
  if ((hoverItem === null || hoverItem === void 0 ? void 0 : hoverItem.id) === item.id) {
170
140
  setHoverItem(null);
171
141
  }
@@ -174,6 +144,7 @@ const TreeItem = props => {
174
144
  setHoverItem(item);
175
145
  },
176
146
  onClick: handleItemClick,
147
+ onBlur: () => setFocusedItem(null),
177
148
  ref: setItemRefs,
178
149
  style: _objectSpread({}, itemWrapperStyle),
179
150
  className: finalClassName,
@@ -182,29 +153,33 @@ const TreeItem = props => {
182
153
  "data-id": item.id,
183
154
  "data-index": item.virtualIndex,
184
155
  onKeyDown: onItemKeyDown,
185
- children: [/*#__PURE__*/_jsx__default["default"](TreeListItemAddonsWrapper, {}, void 0, withDragAndDrop ? /*#__PURE__*/_jsx__default["default"](DnDHandle, {
186
- id: id
187
- }) : null, withRadioChecks ? /*#__PURE__*/_jsx__default["default"](RadioSelectable, {
156
+ children: [/*#__PURE__*/_jsx__default["default"](TreeListItemAddonsWrapper, {}, void 0, withDragAndDrop ? /*#__PURE__*/_jsx__default["default"](DnDHandle.DnDHandle, {
157
+ id: id,
158
+ isDragOverlay: isDragOverlay
159
+ }) : null, withRadioChecks && !isDragOverlay ? /*#__PURE__*/_jsx__default["default"](RadioSelectable, {
188
160
  item: item,
189
161
  itemIndex: itemIndex
190
- }) : null, withCheckboxChecks ? /*#__PURE__*/_jsx__default["default"](CheckboxSelectable, {
162
+ }) : null, withCheckboxChecks && !isDragOverlay ? /*#__PURE__*/_jsx__default["default"](CheckboxSelectable, {
191
163
  item: item,
192
164
  itemIndex: itemIndex
193
- }) : null, /*#__PURE__*/_jsx__default["default"](NestingSpace.NestingSpace, {
165
+ }) : null, !isDragOverlay && /*#__PURE__*/_jsx__default["default"](NestingSpace.NestingSpace, {
194
166
  item: item,
195
167
  spaceForNestingLevel: spaceForNestingLevel
196
- }), /*#__PURE__*/_jsx__default["default"](ExpandCaret.ExpandCaret, {
168
+ }), !isDragOverlay && /*#__PURE__*/_jsx__default["default"](ExpandCaret.ExpandCaret, {
197
169
  item: item
198
170
  }), !disableIcons ? /*#__PURE__*/_jsx__default["default"](Icon.Icon, {
199
171
  item: item
200
172
  }) : null), /*#__PURE__*/_jsx__default["default"](TreeItemText.TreeItemText, {
201
173
  item: item
202
- }), rightAddons && /*#__PURE__*/_jsx__default["default"](TreeListItemAddonsWrapper, {}, void 0, typeof rightAddons === 'function' ? rightAddons(item) : rightAddons)]
174
+ }), rightAddons && /*#__PURE__*/_jsx__default["default"](TreeListItemAddonsWrapper, {}, void 0, typeof rightAddons === 'function' ? rightAddons(item) : rightAddons), /*#__PURE__*/_jsx__default["default"](DropIndicator, {
175
+ dropIndicatorPosition: dropIndicatorPosition,
176
+ isDropValid: isDropValid
177
+ })]
203
178
  });
204
179
  };
205
- const DragAndDropTreeItem = reactSortableHoc.SortableElement(TreeItem);
180
+ var TreeItem$1 = WithDnDSortableItemContext.withDnDSortableItemContext(TreeItem);
206
181
 
207
- exports.DragAndDropTreeItem = DragAndDropTreeItem;
208
182
  exports.TreeItem = TreeItem;
209
183
  exports.TreeListItem = TreeListItem;
210
184
  exports.TreeListItemAddonsWrapper = TreeListItemAddonsWrapper;
185
+ exports["default"] = TreeItem$1;
@@ -12,12 +12,13 @@ require('core-js/modules/esnext.iterator.filter.js');
12
12
  require('core-js/modules/esnext.async-iterator.for-each.js');
13
13
  require('core-js/modules/esnext.iterator.for-each.js');
14
14
  var React = require('react');
15
- var reactSortableHoc = require('@elliemae/react-sortable-hoc');
16
15
  var dsClassnames = require('@elliemae/ds-classnames');
17
16
  var dsCircularProgressIndicator = require('@elliemae/ds-circular-progress-indicator');
18
17
  var TreeViewContext = require('../TreeViewContext.js');
19
18
  var cssClassesConstants = require('../config/cssClassesConstants.js');
20
19
  var TreeItem = require('./TreeItem.js');
20
+ var WithConditionalDnDContext = require('../hoc/WithConditionalDnDContext.js');
21
+ var DnDTreeContext = require('../hoc/DnDTreeContext.js');
21
22
  var jsxRuntime = require('react/jsx-runtime');
22
23
 
23
24
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -47,16 +48,13 @@ const TreeListWrapper = dsClassnames.aggregatedClasses('ul', {
47
48
  });
48
49
  const compactRowClass = "".concat(cssClassesConstants.DSTreeViewPrefix, "-tv-row-size-compact");
49
50
  const normaRowClass = "".concat(cssClassesConstants.DSTreeViewPrefix, "-tv-row-size-normal");
50
- const TreeList = props => {
51
- const {
52
- onMouseDragOverItem
53
- } = props;
51
+
52
+ const TreeListComp = () => {
54
53
  const ctx = React.useContext(TreeViewContext["default"]);
55
54
  const {
56
55
  virtualListRef,
57
56
  virtualListHelpers,
58
- visibleItems,
59
- withDragAndDrop,
57
+ visibleItems: flattenedVisibleItems,
60
58
  props: {
61
59
  width,
62
60
  height,
@@ -70,6 +68,9 @@ const TreeList = props => {
70
68
  virtualItems
71
69
  } = virtualListHelpers;
72
70
  const className = "".concat(rowSize === 'compact' ? "".concat(compactRowClass) : "".concat(normaRowClass));
71
+ const {
72
+ visibleItems
73
+ } = React.useContext(DnDTreeContext.DnDTreeContext);
73
74
  return /*#__PURE__*/jsxRuntime.jsxs(TreeListWrapper, {
74
75
  ref: virtualListRef,
75
76
  className: className,
@@ -104,17 +105,17 @@ const TreeList = props => {
104
105
  measureRef,
105
106
  start
106
107
  } = virtualItem;
107
- const item = visibleItems[index];
108
+ const item = (visibleItems || flattenedVisibleItems)[index];
109
+ if (!item) return null;
108
110
  item.virtualIndex = index;
109
111
  const {
110
112
  id
111
113
  } = item;
112
114
  const style = {
113
115
  position: 'absolute',
114
- top: 0,
116
+ top: "".concat(start, "px"),
115
117
  left: 0,
116
- width: '100%',
117
- transform: "translateY(".concat(start, "px)")
118
+ width: '100%'
118
119
  };
119
120
  const listItemProps = {
120
121
  key: "DS-TreeView-List-Item-".concat(id),
@@ -125,16 +126,13 @@ const TreeList = props => {
125
126
  item,
126
127
  itemWrapperStyle: style
127
128
  };
128
- if (withDragAndDrop) return /*#__PURE__*/jsxRuntime.jsx(TreeItem.DragAndDropTreeItem, _objectSpread(_objectSpread({}, listItemProps), {}, {
129
- onMouseDragOverItem: onMouseDragOverItem
130
- }));
131
- return /*#__PURE__*/jsxRuntime.jsx(TreeItem.TreeItem, _objectSpread({}, listItemProps));
129
+ return /*#__PURE__*/jsxRuntime.jsx(TreeItem["default"], _objectSpread({}, listItemProps));
132
130
  })) : null]
133
131
  });
134
132
  };
135
- const DragAndDropTreeList = reactSortableHoc.SortableContainer(TreeList);
136
133
 
137
- exports.DragAndDropTreeList = DragAndDropTreeList;
134
+ const TreeList = WithConditionalDnDContext.withConditionalDnDRowContext(TreeListComp);
135
+
138
136
  exports.TreeList = TreeList;
139
137
  exports.TreeListNoItems = TreeListNoItems;
140
138
  exports.TreeListWrapper = TreeListWrapper;
@@ -2,43 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var _jsx = require('@babel/runtime/helpers/jsx');
6
- var React = require('react');
7
- var TreeList = require('../../parts/TreeList.js');
8
- var useDnDHelpers = require('../../utils/useDnDHelpers.js');
9
- var dndHelpers = require('../../utils/dnd-helpers.js');
10
- var TreeViewContext = require('../../TreeViewContext.js');
11
-
12
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
-
14
- var _jsx__default = /*#__PURE__*/_interopDefaultLegacy(_jsx);
15
-
16
- const TreeDnD = () => {
17
- const {
18
- updateBeforeSortStart,
19
- onSortStart,
20
- onMouseDragOverItem,
21
- onSortEnd
22
- } = useDnDHelpers.useDnDHelpers();
23
- const ctx = React.useContext(TreeViewContext["default"]);
24
- const {
25
- virtualListRef
26
- } = ctx;
27
- return /*#__PURE__*/_jsx__default["default"](TreeList.DragAndDropTreeList, {
28
- useDragHandle: true,
29
- transitionDuration: 0,
30
- keyboardSortingTransitionDuration: 0,
31
- hideSortableGhost: false,
32
- disableAnimation: true,
33
- updateBeforeSortStart: updateBeforeSortStart,
34
- onSortStart: onSortStart,
35
- onMouseDragOverItem: onMouseDragOverItem,
36
- onSortEnd: onSortEnd,
37
- getContainer: () => virtualListRef === null || virtualListRef === void 0 ? void 0 : virtualListRef.current,
38
- keyCodes: dndHelpers.keyCodes
39
- });
40
- };
41
5
  const TreeDndPlugin = 'tree-dnd';
42
6
 
43
- exports.TreeDnD = TreeDnD;
44
7
  exports.TreeDndPlugin = TreeDndPlugin;
@@ -6,5 +6,4 @@ var TreeDndPlugin = require('./TreeDndPlugin.js');
6
6
 
7
7
 
8
8
 
9
- exports.TreeDnD = TreeDndPlugin.TreeDnD;
10
9
  exports.TreeDndPlugin = TreeDndPlugin.TreeDndPlugin;
@@ -12,7 +12,6 @@ var SearchableTreePlugin = require('./searchable/SearchableTreePlugin.js');
12
12
 
13
13
 
14
14
 
15
- exports.TreeDnD = TreeDndPlugin.TreeDnD;
16
15
  exports.TreeDndPlugin = TreeDndPlugin.TreeDndPlugin;
17
16
  exports.TreeRovingPlugin = TreeRovingPlugin.TreeRovingPlugin;
18
17
  exports.SelectablePluginTree = SelectablePluginTree.SelectablePluginTree;
@@ -30,6 +30,7 @@ const TreeViewPropTypes = {
30
30
  isMultiSelect: reactDesc.PropTypes.bool.description('whether the tree view is multi select or not').defaultValue(false),
31
31
  isSingleSelect: reactDesc.PropTypes.bool.description('wheter the tree view is single select or not').defaultValue(false),
32
32
  isLoading: reactDesc.PropTypes.bool.description('wheter the tree should show the loading state or not').defaultValue(false),
33
+ getIsDropValid: reactDesc.PropTypes.func.description("Function that returns true if the drop is valid and false if it's not").defaultValue('() => true'),
33
34
  restrictDragAndDrop: reactDesc.PropTypes.bool.description('whether to restrict DnD functionality or not').defaultValue(false),
34
35
  showChildrenAmount: reactDesc.PropTypes.bool.description('whether to show the amount of children or not').defaultValue(false),
35
36
  sortable: reactDesc.PropTypes.bool.description('whether the sortable functionality is active or not').defaultValue(false),
@@ -19,14 +19,13 @@ var groupExpandsHelpers = require('./group-expands-helpers.js');
19
19
  // 36 home
20
20
  // 56 number 8
21
21
  // 106 (NumPad) *
22
- const useOnItemKeyDown = item => {
22
+ const useOnItemKeyDown = (item, draggableProps) => {
23
23
  const ctx = React.useContext(TreeViewContext["default"]);
24
24
  const {
25
25
  props: {
26
26
  onItemFocus
27
27
  },
28
28
  triggerTreeRerender,
29
- isDragging,
30
29
  visibleItems,
31
30
  setFocusedItem,
32
31
  setSelectedItem,
@@ -55,10 +54,12 @@ const useOnItemKeyDown = item => {
55
54
  keyCode
56
55
  } = e;
57
56
 
58
- if (!isDragging) {
57
+ if (!(draggableProps && draggableProps.active)) {
59
58
  if (keyCode !== 9) e.preventDefault(); // allow tab/shift+tab
60
59
 
61
- if (keyCode === 13 || keyCode === 32) setSelectedItem(item);
60
+ if ((keyCode === 13 || keyCode === 32) && e.target.tagName === 'LI') {
61
+ setSelectedItem(item);
62
+ }
62
63
 
63
64
  if (keyCode === 37) {
64
65
  if (isGroup && isExpanded) {
@@ -146,7 +147,7 @@ const useOnItemKeyDown = item => {
146
147
  }
147
148
  }
148
149
  }
149
- }, [isDragging, setSelectedItem, item, isGroup, isExpanded, triggerTreeRerender, scrollToIndex, setLatestToggledItem, visibleItems, setFocusedItem, onItemFocusCurry, updateUserExpandedState]);
150
+ }, [draggableProps, setSelectedItem, item, isGroup, isExpanded, triggerTreeRerender, updateUserExpandedState, scrollToIndex, setLatestToggledItem, visibleItems, setFocusedItem, onItemFocusCurry]);
150
151
  return onItemKeyDown;
151
152
  };
152
153
  const useGlobalKeyboardListener = func => {
@@ -132,7 +132,7 @@ const getChildrenMatchesSearchQuery = function (parentNode) {
132
132
  */
133
133
 
134
134
  const enrichNodeModelInPlace = function (node) {
135
- var _node$model, _node$model$children;
135
+ var _node$model$children$, _node$model, _node$model$children;
136
136
 
137
137
  let searchQuery = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
138
138
  let selection = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
@@ -148,7 +148,7 @@ const enrichNodeModelInPlace = function (node) {
148
148
  // this is useful to avoid having to always check both the flag and the children.length...
149
149
 
150
150
 
151
- if (typeof node.model.isGroup !== 'boolean' && ((_node$model = node.model) === null || _node$model === void 0 ? void 0 : (_node$model$children = _node$model.children) === null || _node$model$children === void 0 ? void 0 : _node$model$children.length) > 0) {
151
+ if (typeof node.model.isGroup !== 'boolean' && ((_node$model$children$ = (_node$model = node.model) === null || _node$model === void 0 ? void 0 : (_node$model$children = _node$model.children) === null || _node$model$children === void 0 ? void 0 : _node$model$children.length) !== null && _node$model$children$ !== void 0 ? _node$model$children$ : 0) > 0) {
152
152
  node.model.isGroup = true;
153
153
  }
154
154
 
@@ -180,9 +180,35 @@ const focusItem = item => {
180
180
 
181
181
  item === null || item === void 0 ? void 0 : (_item$nodeItemRef = item.nodeItemRef) === null || _item$nodeItemRef === void 0 ? void 0 : (_item$nodeItemRef$cur = _item$nodeItemRef.current) === null || _item$nodeItemRef$cur === void 0 ? void 0 : _item$nodeItemRef$cur.focus();
182
182
  };
183
+ const flattenTreeForDnD = function (data) {
184
+ let shouldDescend = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : () => true;
185
+ const flattenedTree = [];
186
+ let index = 0;
187
+
188
+ const doit = function (node) {
189
+ var _node$children$length, _node$children, _node$children2;
190
+
191
+ let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
192
+ let parentId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
193
+ flattenedTree.push({
194
+ uid: node.id.toString(),
195
+ depth,
196
+ realIndex: index,
197
+ childrenCount: (_node$children$length = (_node$children = node.children) === null || _node$children === void 0 ? void 0 : _node$children.length) !== null && _node$children$length !== void 0 ? _node$children$length : 0,
198
+ parentId: parentId !== null ? parentId.toString() : null,
199
+ original: node
200
+ });
201
+ index += 1;
202
+ if (shouldDescend(node)) (_node$children2 = node.children) === null || _node$children2 === void 0 ? void 0 : _node$children2.forEach(child => doit(child, depth + 1, node.id.toString()));
203
+ };
204
+
205
+ data.forEach(datum => doit(datum));
206
+ return flattenedTree;
207
+ };
183
208
 
184
209
  exports.cloneNode = cloneNode;
185
210
  exports.enrichNodeModelInPlace = enrichNodeModelInPlace;
211
+ exports.flattenTreeForDnD = flattenTreeForDnD;
186
212
  exports.focusItem = focusItem;
187
213
  exports.getChildrenMatchesSearchQuery = getChildrenMatchesSearchQuery;
188
214
  exports.getItemsParentNode = getItemsParentNode;
@@ -76,9 +76,9 @@ const useTree = (data, props, states) => {
76
76
  React.useEffect(() => {
77
77
  const parsedVisibleItems = [];
78
78
  const newExpandedHashMap = {};
79
- treeRoot.walk(node => {
80
- const shouldContinueWalking = true; // tree-model ask we return true if we want to continue walking
79
+ const shouldContinueWalking = true; // tree-model ask we return true if we want to continue walking
81
80
 
81
+ treeRoot.walk(node => {
82
82
  treeHelpers.enrichNodeModelInPlace(node, searchQuery, selection, expanded);
83
83
  if (node.model.id && node.model.isGroup && node.model.isExpanded) newExpandedHashMap[node.model.id] = true;
84
84
  return shouldContinueWalking;
@@ -93,8 +93,10 @@ const useTree = (data, props, states) => {
93
93
  setExpandedGroups(newExpandedHashMap); // eslint-disable-next-line react-hooks/exhaustive-deps
94
94
  }, [treeRoot, rerenderItems, searchQuery, highlightOnlyQuery, selection, expanded, setExpandedGroups // onVisibleItemsChange // evaluate potential performance hit?
95
95
  ]);
96
+ const flattenedItems = React.useMemo(() => treeHelpers.flattenTreeForDnD(data), [data]);
96
97
  return {
97
98
  visibleItems,
99
+ flattenedItems,
98
100
  tree,
99
101
  treeRoot,
100
102
  rerenderItems,
package/esm/TreeView.js CHANGED
@@ -3,21 +3,17 @@ import 'react';
3
3
  import { describe } from 'react-desc';
4
4
  import { TreeViewPropTypes } from './react-desc-prop-types.js';
5
5
  import TreeViewContext from './TreeViewContext.js';
6
- import { TreeDndPlugin, TreeDnD } from './plugins/dnd/TreeDndPlugin.js';
7
6
  import { useTreeview } from './config/useTreeview.js';
8
7
  import { TreeList } from './parts/TreeList.js';
9
8
 
10
- var _TreeDnD, _TreeList;
9
+ var _TreeList;
11
10
  function TreeView(props) {
12
- const {
13
- plugins
14
- } = props;
15
11
  const {
16
12
  ctx
17
13
  } = useTreeview(props);
18
14
  return /*#__PURE__*/_jsx(TreeViewContext.Provider, {
19
15
  value: ctx
20
- }, void 0, plugins !== null && plugins !== void 0 && plugins.includes(TreeDndPlugin) ? _TreeDnD || (_TreeDnD = /*#__PURE__*/_jsx(TreeDnD, {})) : _TreeList || (_TreeList = /*#__PURE__*/_jsx(TreeList, {})));
16
+ }, void 0, _TreeList || (_TreeList = /*#__PURE__*/_jsx(TreeList, {})));
21
17
  }
22
18
  const TreeViewWithSchema = describe(TreeView);
23
19
  TreeViewWithSchema.propTypes = TreeViewPropTypes;
@@ -14,6 +14,7 @@ const defaultProps = {
14
14
  fluid: false,
15
15
  isMultiSelect: false,
16
16
  isSingleSelect: false,
17
+ getIsDropValid: () => true,
17
18
  restrictDragAndDrop: false,
18
19
  showChildrenAmount: false,
19
20
  sortable: false,
@@ -54,11 +55,10 @@ const defaultRelativeMouseCoord = {
54
55
  const defaultContext = {
55
56
  props: defaultProps,
56
57
  visibleItems: [],
58
+ flattenedItems: [],
57
59
  withRadioChecks: false,
58
60
  withCheckboxChecks: false,
59
61
  withDragAndDrop: false,
60
- relativeMouseCord: defaultRelativeMouseCoord,
61
- setRelativeMouseCord: noop,
62
62
  triggerTreeRerender: noop,
63
63
  tree: undefined,
64
64
  treeRoot: undefined,
@@ -69,12 +69,6 @@ const defaultContext = {
69
69
  scrollToIndex: noop
70
70
  },
71
71
  virtualListRef: undefined,
72
- isDragging: false,
73
- setIsDragging: noop,
74
- isKeyboardDragging: false,
75
- setIsKeyboardDragging: noop,
76
- draggedItem: null,
77
- setDraggedItem: noop,
78
72
  uniqueTreeViewUUID: '',
79
73
  selectedItem: null,
80
74
  setSelectedItem: noop,
@@ -10,7 +10,7 @@ import { useVirtual } from 'react-virtual';
10
10
  import { useMemoMergePropsWithDefault, useValidateTypescriptPropTypes } from '@elliemae/ds-props-helpers';
11
11
  import { v4 } from 'uuid';
12
12
  import { TreeViewPropTypes } from '../react-desc-prop-types.js';
13
- import { defaultProps, defaultRelativeMouseCoord } from '../TreeViewContext.js';
13
+ import { defaultProps } from '../TreeViewContext.js';
14
14
  import { TreeDndPlugin } from '../plugins/dnd/TreeDndPlugin.js';
15
15
  import { useTree } from '../utils/useTree.js';
16
16
  import { toggleItemExpand, useNotifyExpandedChange } from '../utils/group-expands-helpers.js';
@@ -42,11 +42,7 @@ const useTreeview = props => {
42
42
  selection,
43
43
  onInstanceRefInitialized
44
44
  } = propsWithDefault;
45
- const [isDragging, setIsDragging] = useState(false);
46
- const [isKeyboardDragging, setIsKeyboardDragging] = useState(false);
47
- const [relativeMouseCord, setRelativeMouseCord] = useState(defaultRelativeMouseCoord);
48
45
  const [uniqueTreeViewUUID] = useState(v4());
49
- const [draggedItem, setDraggedItem] = useState(null);
50
46
  const [hoverItem, setHoverItem] = useState(null);
51
47
  const [latestToggledItem, setLatestToggledItem] = useState(null);
52
48
  const [selectedItem, setSelectedItem] = useState(null);
@@ -55,6 +51,7 @@ const useTreeview = props => {
55
51
  const [expandedGroups, setExpandedGroups] = useState({});
56
52
  const {
57
53
  visibleItems,
54
+ flattenedItems,
58
55
  tree,
59
56
  treeRoot,
60
57
  triggerTreeRerender,
@@ -76,20 +73,13 @@ const useTreeview = props => {
76
73
  const handleExpandGroup = useCallback(toggleItemExpand, []);
77
74
  const ctx = useMemo(() => ({
78
75
  props: propsWithDefault,
79
- setRelativeMouseCord,
80
- relativeMouseCord,
81
76
  virtualListHelpers,
82
77
  virtualListRef,
83
78
  tree,
84
79
  treeRoot,
85
80
  visibleItems,
81
+ flattenedItems,
86
82
  triggerTreeRerender,
87
- isDragging,
88
- setIsDragging,
89
- isKeyboardDragging,
90
- setIsKeyboardDragging,
91
- draggedItem,
92
- setDraggedItem,
93
83
  withRadioChecks,
94
84
  withCheckboxChecks,
95
85
  withDragAndDrop,
@@ -108,7 +98,7 @@ const useTreeview = props => {
108
98
  setHoverItem,
109
99
  handleExpandGroup,
110
100
  updateUserExpandedState
111
- }), [draggedItem, expandedGroups, focusedItem, handleExpandGroup, hoverItem, isDragging, isKeyboardDragging, latestToggledItem, propsWithDefault, relativeMouseCord, selectedCheckboxes, selectedItem, tree, treeRoot, triggerTreeRerender, uniqueTreeViewUUID, virtualListHelpers, visibleItems, withCheckboxChecks, withDragAndDrop, withRadioChecks, updateUserExpandedState]); // this hooks can't use the context because the context provider doesn't wrap this
101
+ }), [propsWithDefault, virtualListHelpers, tree, treeRoot, visibleItems, flattenedItems, triggerTreeRerender, withRadioChecks, withCheckboxChecks, withDragAndDrop, uniqueTreeViewUUID, selectedCheckboxes, selectedItem, expandedGroups, latestToggledItem, focusedItem, hoverItem, handleExpandGroup, updateUserExpandedState]); // this hooks can't use the context because the context provider doesn't wrap this
112
102
  // as such we manually pass the second parameter as fit
113
103
 
114
104
  if (instanceRef) instanceRef.current = treeRef.current;
@@ -0,0 +1,14 @@
1
+ import { createContext } from 'react';
2
+ import { DropIndicatorPosition } from './SortableItemContext.js';
3
+
4
+ const DnDTreeContext = /*#__PURE__*/createContext({
5
+ depth: undefined,
6
+ activeIndex: undefined,
7
+ visibleItems: undefined,
8
+ dropIndicatorPosition: DropIndicatorPosition.None,
9
+ lastActiveId: undefined,
10
+ setLastActiveId: undefined,
11
+ isDropValid: false
12
+ });
13
+
14
+ export { DnDTreeContext };
@@ -0,0 +1,17 @@
1
+ import { createContext } from 'react';
2
+
3
+ let DropIndicatorPosition;
4
+
5
+ (function (DropIndicatorPosition) {
6
+ DropIndicatorPosition[DropIndicatorPosition["None"] = 0] = "None";
7
+ DropIndicatorPosition[DropIndicatorPosition["Before"] = 1] = "Before";
8
+ DropIndicatorPosition[DropIndicatorPosition["After"] = 2] = "After";
9
+ DropIndicatorPosition[DropIndicatorPosition["Inside"] = 3] = "Inside";
10
+ })(DropIndicatorPosition || (DropIndicatorPosition = {}));
11
+
12
+ /** Context for cross component communication */
13
+ const SortableItemContext = /*#__PURE__*/createContext({
14
+ draggableProps: false
15
+ });
16
+
17
+ export { DropIndicatorPosition, SortableItemContext };