@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
@@ -0,0 +1,128 @@
1
+ import 'core-js/modules/esnext.async-iterator.filter.js';
2
+ import 'core-js/modules/esnext.iterator.filter.js';
3
+ import _jsx from '@babel/runtime/helpers/esm/jsx';
4
+ import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
5
+ import 'core-js/modules/web.dom-collections.iterator.js';
6
+ import 'core-js/modules/esnext.async-iterator.map.js';
7
+ import 'core-js/modules/esnext.iterator.map.js';
8
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
9
+ import 'core-js/modules/esnext.iterator.constructor.js';
10
+ import 'core-js/modules/esnext.iterator.for-each.js';
11
+ import 'core-js/modules/esnext.async-iterator.find.js';
12
+ import 'core-js/modules/esnext.iterator.find.js';
13
+ import React, { useContext, useMemo, useCallback } from 'react';
14
+ import { DndContext, DragOverlay } from '@dnd-kit/core';
15
+ import { SortableContext } from '@dnd-kit/sortable';
16
+ import { useTreeDndkitConfig } from '@elliemae/ds-drag-and-drop';
17
+ import TreeViewContext from '../TreeViewContext.js';
18
+ import { TreeItem } from '../parts/TreeItem.js';
19
+ import { DnDTreeContext } from './DnDTreeContext.js';
20
+ import { jsxs, jsx } from 'react/jsx-runtime';
21
+
22
+ 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; }
23
+
24
+ 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) { _defineProperty(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; }
25
+
26
+ const ensure = function (argument) {
27
+ let message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'This should never happen';
28
+
29
+ if (argument === undefined || argument === null) {
30
+ throw new TypeError(message);
31
+ }
32
+
33
+ return argument;
34
+ }; // only wraps in "DnDContext" and "DnDTreeContext" if any Drag and Drop functionality is requested
35
+
36
+
37
+ const withConditionalDnDRowContext = Component => props => {
38
+ const [lastActiveId, setLastActiveId] = React.useState('');
39
+ const {
40
+ props: {
41
+ data,
42
+ onOrderChange,
43
+ getIsDropValid
44
+ },
45
+ flattenedItems,
46
+ visibleItems: flattenedVisibleTree,
47
+ withDragAndDrop
48
+ } = useContext(TreeViewContext);
49
+ const flattenedVisibleTreeForDnD = useMemo(() => flattenedVisibleTree.map((item, index) => {
50
+ var _item$treeDepth, _item$children$length, _item$children, _item$node$parent$mod, _item$node$parent, _item$node$parent$mod2, _item$node$parent$mod3;
51
+
52
+ return {
53
+ uid: item.id.toString(),
54
+ depth: ((_item$treeDepth = item.treeDepth) !== null && _item$treeDepth !== void 0 ? _item$treeDepth : 1) - 1,
55
+ realIndex: index,
56
+ childrenCount: (_item$children$length = (_item$children = item.children) === null || _item$children === void 0 ? void 0 : _item$children.length) !== null && _item$children$length !== void 0 ? _item$children$length : 0,
57
+ parentId: (_item$node$parent$mod = (_item$node$parent = item.node.parent) === null || _item$node$parent === void 0 ? void 0 : (_item$node$parent$mod2 = _item$node$parent.model) === null || _item$node$parent$mod2 === void 0 ? void 0 : (_item$node$parent$mod3 = _item$node$parent$mod2.id) === null || _item$node$parent$mod3 === void 0 ? void 0 : _item$node$parent$mod3.toString()) !== null && _item$node$parent$mod !== void 0 ? _item$node$parent$mod : null,
58
+ original: item
59
+ };
60
+ }), [flattenedVisibleTree]);
61
+ const onReorder = useCallback((tree, indexes) => {
62
+ // Pull the row's original data into an object
63
+ const nodes = {};
64
+ tree.forEach(item => {
65
+ const originalItem = item.original;
66
+ originalItem.children = [];
67
+ nodes[item.uid] = item.original;
68
+ });
69
+ const newUserTree = [];
70
+ tree.forEach(item => {
71
+ // If row has parent, insert it to it's subrows
72
+ // otherwise append it to the new user data
73
+ if (item.parentId !== null && item.parentId !== undefined && item.parentId !== '__ds_tree_root') {
74
+ var _parentNode$children;
75
+
76
+ const parentNode = nodes[item.parentId];
77
+ (_parentNode$children = parentNode.children) === null || _parentNode$children === void 0 ? void 0 : _parentNode$children.push(item.original);
78
+ } else if (item.uid !== '__ds_tree_root') newUserTree.push(item.original);
79
+ }); // Tell the user that the order has change, he can chose to commit it or not
80
+
81
+ onOrderChange(newUserTree, data, flattenedItems[indexes.fromIndex]);
82
+ }, [onOrderChange, data, flattenedItems]);
83
+ const {
84
+ dndContextProps,
85
+ sortableContextProps,
86
+ activeId,
87
+ activeIndex,
88
+ depth,
89
+ dropIndicatorPosition,
90
+ visibleItems,
91
+ isDropValid
92
+ } = useTreeDndkitConfig({
93
+ flattenedItems,
94
+ visibleItems: flattenedVisibleTreeForDnD,
95
+ isHorizontalDnD: false,
96
+ isExpandable: true,
97
+ onReorder,
98
+ getIsDropValid,
99
+ maxDragAndDropLevel: Infinity
100
+ });
101
+ if (lastActiveId !== activeId && activeId) setLastActiveId(activeId);
102
+ if (withDragAndDrop) return /*#__PURE__*/jsxs(DndContext, _objectSpread(_objectSpread({}, dndContextProps), {}, {
103
+ children: [/*#__PURE__*/jsx(SortableContext, _objectSpread(_objectSpread({}, sortableContextProps), {}, {
104
+ children: /*#__PURE__*/_jsx(DnDTreeContext.Provider, {
105
+ value: {
106
+ activeIndex,
107
+ depth,
108
+ visibleItems: visibleItems.map(item => item.original),
109
+ dropIndicatorPosition,
110
+ lastActiveId,
111
+ setLastActiveId,
112
+ isDropValid
113
+ }
114
+ }, void 0, /*#__PURE__*/jsx(Component, _objectSpread({}, props)))
115
+ })), /*#__PURE__*/_jsx(DragOverlay, {
116
+ style: {
117
+ width: 'auto'
118
+ }
119
+ }, void 0, activeId ? /*#__PURE__*/_jsx(TreeItem, {
120
+ itemIndex: activeIndex,
121
+ item: ensure(flattenedVisibleTree.find(item => item.id.toString() === activeId)),
122
+ isDragOverlay: true
123
+ }) : null)]
124
+ }));
125
+ return /*#__PURE__*/jsx(Component, _objectSpread({}, props));
126
+ };
127
+
128
+ export { withConditionalDnDRowContext };
@@ -0,0 +1,61 @@
1
+ import 'core-js/modules/esnext.async-iterator.filter.js';
2
+ import 'core-js/modules/esnext.iterator.constructor.js';
3
+ import 'core-js/modules/esnext.iterator.filter.js';
4
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
5
+ import 'core-js/modules/esnext.iterator.for-each.js';
6
+ import _jsx from '@babel/runtime/helpers/esm/jsx';
7
+ import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
8
+ import { useContext, useMemo } from 'react';
9
+ import { useSortable } from '@dnd-kit/sortable';
10
+ import { SortableItemContext } from './SortableItemContext.js';
11
+ import TreeViewContext from '../TreeViewContext.js';
12
+ import { DnDTreeContext } from './DnDTreeContext.js';
13
+ import { jsx } from 'react/jsx-runtime';
14
+
15
+ 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; }
16
+
17
+ 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) { _defineProperty(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; }
18
+ const withDnDSortableItemContext = Component => props => {
19
+ const {
20
+ withDragAndDrop
21
+ } = useContext(TreeViewContext);
22
+ const {
23
+ dropIndicatorPosition,
24
+ lastActiveId,
25
+ setLastActiveId,
26
+ isDropValid
27
+ } = useContext(DnDTreeContext);
28
+ const id = props.item.id.toString(); // onMount generate unique options, so everyting is only ran once
29
+
30
+ const draggableOptions = useMemo(() => ({
31
+ id
32
+ }), [id]);
33
+ const useSortableHelpers = useSortable(draggableOptions); // calculate all the "useSortable" values as per required
34
+
35
+ const draggableProps = useMemo(() => {
36
+ if (!withDragAndDrop) return false;
37
+ const {
38
+ index,
39
+ overIndex
40
+ } = useSortableHelpers;
41
+ return _objectSpread(_objectSpread({}, useSortableHelpers), {}, {
42
+ shouldShowDropIndicatorPosition: overIndex === index,
43
+ dropIndicatorPosition,
44
+ lastActiveId,
45
+ setLastActiveId,
46
+ isDropValid
47
+ });
48
+ }, [withDragAndDrop, useSortableHelpers, dropIndicatorPosition, lastActiveId, setLastActiveId, isDropValid]); // we use a context so we can easly access information wherever without bubbling down
49
+ // this context is all Memoized so as long as component is not re-mounted,
50
+ // the context won't trigger un-required renders per-se...
51
+
52
+ const ctx = useMemo(() => ({
53
+ draggableProps
54
+ }), [draggableProps]); // we always add the context, if draggableProps===false we don't have the DnD enabled.
55
+
56
+ return /*#__PURE__*/_jsx(SortableItemContext.Provider, {
57
+ value: ctx
58
+ }, void 0, /*#__PURE__*/jsx(Component, _objectSpread({}, props)));
59
+ };
60
+
61
+ export { withDnDSortableItemContext };
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { TreeView, TreeViewWithSchema } from './TreeView.js';
2
- export { TreeDnD, TreeDndPlugin } from './plugins/dnd/TreeDndPlugin.js';
2
+ export { TreeDndPlugin } from './plugins/dnd/TreeDndPlugin.js';
3
3
  export { TreeRovingPlugin } from './plugins/roving/TreeRovingPlugin.js';
4
4
  export { SelectablePluginTree } from './plugins/selectable/SelectablePluginTree.js';
5
5
  export { TreeToolbarPlugin } from './plugins/toolbar/TreeToolbarPlugin.js';
@@ -0,0 +1,38 @@
1
+ import 'core-js/modules/esnext.async-iterator.filter.js';
2
+ import 'core-js/modules/esnext.iterator.constructor.js';
3
+ import 'core-js/modules/esnext.iterator.filter.js';
4
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
5
+ import 'core-js/modules/esnext.iterator.for-each.js';
6
+ import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
7
+ import { useContext, createElement } from 'react';
8
+ import { GripperVertical } from '@elliemae/ds-icons';
9
+ import { SortableItemContext } from '../hoc/SortableItemContext.js';
10
+
11
+ 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; }
12
+
13
+ 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) { _defineProperty(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; }
14
+ const DnDHandle = _ref => {
15
+ let {
16
+ id,
17
+ isDragOverlay
18
+ } = _ref;
19
+ const {
20
+ draggableProps
21
+ } = useContext(SortableItemContext);
22
+ const isDragging = draggableProps && draggableProps.isDragging;
23
+ return /*#__PURE__*/createElement(GripperVertical, _objectSpread(_objectSpread({
24
+ role: "button"
25
+ }, draggableProps && _objectSpread(_objectSpread({}, draggableProps.listeners), draggableProps.attributes)), {}, {
26
+ "data-testid": "drag-handle",
27
+ "data-isactive": draggableProps && !!draggableProps.active,
28
+ "data-isdragoverlay": isDragOverlay,
29
+ id: "".concat(id, "-drag-handle"),
30
+ key: "".concat(id, "-drag-handle"),
31
+ className: "drag-handle ".concat(isDragging ? '' : 'focuseable'),
32
+ color: ['brand-primary', '800'],
33
+ size: "s",
34
+ tabIndex: 0
35
+ }));
36
+ };
37
+
38
+ export { DnDHandle };
@@ -0,0 +1,68 @@
1
+ import _jsx from '@babel/runtime/helpers/esm/jsx';
2
+ import 'react';
3
+ import styled from 'styled-components';
4
+ import { DropIndicatorPosition } from '../hoc/SortableItemContext.js';
5
+ import { jsxs, Fragment } from 'react/jsx-runtime';
6
+
7
+ const getPositionStyles = _ref => {
8
+ let {
9
+ dropIndicatorPosition
10
+ } = _ref;
11
+ return "\n top: ".concat(dropIndicatorPosition === DropIndicatorPosition.Before ? '0' : 'unset', ";\n bottom: ").concat(dropIndicatorPosition === DropIndicatorPosition.After ? '0' : 'unset', ";\n left: -2px;\n ");
12
+ };
13
+
14
+ const getCircleStyles = _ref2 => {
15
+ let {
16
+ dropIndicatorPosition
17
+ } = _ref2;
18
+ return {
19
+ position: 'absolute',
20
+ zIndex: 20,
21
+ top: dropIndicatorPosition === DropIndicatorPosition.After ? 'unset' : '-2px',
22
+ bottom: dropIndicatorPosition === DropIndicatorPosition.Before ? 'unset' : '-2px',
23
+ left: '0px',
24
+ opacity: 1
25
+ };
26
+ };
27
+
28
+ const StyledIndicator = /*#__PURE__*/styled.div.withConfig({
29
+ componentId: "sc-1812zh0-0"
30
+ })(["position:absolute;", " box-sizing:border-box;width:", ";height:", ";background-color:", ";z-index:20;"], getPositionStyles, props => props.vertical ? '2px' : '100%', props => props.vertical ? '100%' : '2px', _ref3 => {
31
+ let {
32
+ isDropValid,
33
+ theme
34
+ } = _ref3;
35
+ return isDropValid ? theme.colors.brand[600] : theme.colors.danger[900];
36
+ });
37
+
38
+ const CircleIndicator = (style, isDropValid) => /*#__PURE__*/_jsx("svg", {
39
+ height: "6",
40
+ width: "6",
41
+ style: style
42
+ }, void 0, /*#__PURE__*/_jsx("circle", {
43
+ cx: "3",
44
+ cy: "3",
45
+ r: "3",
46
+ strokeWidth: "0",
47
+ fill: isDropValid ? '#1E79C2' : '#C64252'
48
+ }));
49
+
50
+ const DropIndicator = _ref4 => {
51
+ let {
52
+ dropIndicatorPosition,
53
+ isLast,
54
+ isDropValid
55
+ } = _ref4;
56
+ if (![DropIndicatorPosition.After, DropIndicatorPosition.Before].includes(dropIndicatorPosition)) return null;
57
+ const safeDropIndicatorPosition = isLast ? DropIndicatorPosition.Before : dropIndicatorPosition;
58
+ return /*#__PURE__*/jsxs(Fragment, {
59
+ children: [CircleIndicator(getCircleStyles({
60
+ dropIndicatorPosition: safeDropIndicatorPosition
61
+ }), isDropValid), /*#__PURE__*/_jsx(StyledIndicator, {
62
+ dropIndicatorPosition: safeDropIndicatorPosition,
63
+ isDropValid: isDropValid
64
+ })]
65
+ });
66
+ };
67
+
68
+ export { DropIndicator as default };
@@ -1,15 +1,12 @@
1
- import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
2
- import _jsx from '@babel/runtime/helpers/esm/jsx';
3
- import 'core-js/modules/web.dom-collections.iterator.js';
4
1
  import 'core-js/modules/esnext.async-iterator.filter.js';
5
2
  import 'core-js/modules/esnext.iterator.constructor.js';
6
3
  import 'core-js/modules/esnext.iterator.filter.js';
7
4
  import 'core-js/modules/esnext.async-iterator.for-each.js';
8
5
  import 'core-js/modules/esnext.iterator.for-each.js';
9
- import { useRef, useState, useContext, useMemo, useCallback } from 'react';
10
- import { SortableHandle, SortableElement } from '@elliemae/react-sortable-hoc';
6
+ import _jsx from '@babel/runtime/helpers/esm/jsx';
7
+ import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
8
+ import { useContext, useMemo, useCallback } from 'react';
11
9
  import { aggregatedClasses } from '@elliemae/ds-classnames';
12
- import { GripperVertical } from '@elliemae/ds-icons';
13
10
  import RadioSelectable from './RadioSelectable.js';
14
11
  import CheckboxSelectable from './CheckboxSelectable.js';
15
12
  import TreeViewContext from '../TreeViewContext.js';
@@ -20,6 +17,10 @@ import { Icon } from './Icon.js';
20
17
  import { ExpandCaret } from './ExpandCaret.js';
21
18
  import { TreeItemText } from './TreeItemText.js';
22
19
  import { treeItemBlockName, DSTreeViewPrefix } from '../config/cssClassesConstants.js';
20
+ import { DnDHandle } from './DnDHandle.js';
21
+ import { withDnDSortableItemContext } from '../hoc/WithDnDSortableItemContext.js';
22
+ import { SortableItemContext, DropIndicatorPosition } from '../hoc/SortableItemContext.js';
23
+ import DropIndicator from './DropIndicator.js';
23
24
  import { jsxs } from 'react/jsx-runtime';
24
25
 
25
26
  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; }
@@ -32,23 +33,6 @@ const TreeListItem = aggregatedClasses('li', {
32
33
  })(treeItemBlockName);
33
34
  const TreeListItemAddonsWrapper = aggregatedClasses('div')(treeItemBlockName, 'addons' // temp fix untill we move to styled components
34
35
  );
35
- const DnDHandle = SortableHandle(_ref => {
36
- let {
37
- id
38
- } = _ref;
39
- return /*#__PURE__*/_jsx(GripperVertical, {
40
- "data-testid": "drag-handle",
41
- className: "drag-handle",
42
- size: "s",
43
- onMouseDown: e => {
44
- // prevent focusing the drag-handle to avoid borders
45
- if (e) {
46
- e.preventDefault();
47
- }
48
- },
49
- tabIndex: "0"
50
- }, "".concat(id, "-drag-handle"));
51
- });
52
36
  const TreeItem = props => {
53
37
  const {
54
38
  item,
@@ -56,7 +40,7 @@ const TreeItem = props => {
56
40
  itemWrapperStyle = {},
57
41
  virtualItemRef,
58
42
  spaceForNestingLevel = 1.5,
59
- onMouseDragOverItem
43
+ isDragOverlay = false
60
44
  } = props;
61
45
  const {
62
46
  id,
@@ -65,9 +49,10 @@ const TreeItem = props => {
65
49
  const {
66
50
  nodeItemRef
67
51
  } = node.model;
68
- const openFolderOnHoverTimeout = useRef(null);
69
- const [isDraggingOverThis, setIsDraggingOverThis] = useState(false);
70
- const onItemKeyDown = useOnItemKeyDown(item);
52
+ const {
53
+ draggableProps
54
+ } = useContext(SortableItemContext);
55
+ const onItemKeyDown = useOnItemKeyDown(item, draggableProps);
71
56
  const ctx = useContext(TreeViewContext);
72
57
  const {
73
58
  props: {
@@ -78,14 +63,12 @@ const TreeItem = props => {
78
63
  rowSize,
79
64
  labelOverflow
80
65
  },
81
- relativeMouseCord,
82
66
  withRadioChecks,
83
67
  withCheckboxChecks,
84
68
  withDragAndDrop,
85
69
  selectedItem,
86
70
  selectedCheckboxes,
87
71
  hoverItem,
88
- isDragging,
89
72
  virtualListHelpers: {
90
73
  scrollToIndex
91
74
  },
@@ -95,24 +78,27 @@ const TreeItem = props => {
95
78
  } = ctx; // Sortable Items needs to update
96
79
  // - the virtual list ref (for react-virtual requirement)
97
80
  // - nodeItemRef which is a prop avaiable in the TreeModel nodes
81
+ // - the drag and drop node reference
98
82
 
99
83
  const setItemRefs = ref => {
100
- setMultipleRefs(virtualItemRef, nodeItemRef)(ref);
84
+ setMultipleRefs(virtualItemRef, !isDragOverlay && nodeItemRef, !isDragOverlay && draggableProps && draggableProps.setNodeRef)(ref);
101
85
  };
102
86
 
87
+ const dropIndicatorPosition = draggableProps && draggableProps.shouldShowDropIndicatorPosition && draggableProps.dropIndicatorPosition;
88
+ const isDropIndicatorPositionInside = dropIndicatorPosition === DropIndicatorPosition.Inside;
89
+ const isDragging = draggableProps && draggableProps.isDragging;
90
+ const isDropValid = draggableProps && draggableProps.isDropValid;
103
91
  const dropPreviewClassName = useMemo(() => {
104
- if (!withDragAndDrop || !relativeMouseCord || !isDraggingOverThis) return '';
105
- const {
106
- isBefore,
107
- isAfter,
108
- isValid
109
- } = relativeMouseCord;
110
- let className = "".concat(DSTreeViewPrefix, "-").concat(treeItemBlockName).concat(isValid ? '--valid' : '--invalid');
111
- if (isBefore) className += '-drop-before';else if (isAfter) className += '-drop-after';else className += '-drop-in';
112
- return className;
113
- }, [withDragAndDrop, relativeMouseCord, isDraggingOverThis]);
114
- const selectedClassName = useMemo(() => (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) === item.id ? 'selected' : '', [item.id, selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id]);
115
- const hoverClassName = 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]);
92
+ if (isDropIndicatorPositionInside) {
93
+ const className = "".concat(DSTreeViewPrefix, "-").concat(treeItemBlockName).concat(isDropValid ? '--valid' : '--invalid', "-drop-in");
94
+ return className;
95
+ }
96
+
97
+ return '';
98
+ }, [isDropIndicatorPositionInside, isDropValid]);
99
+ const dragOverlayClassName = useMemo(() => isDragOverlay ? 'drag-overlay' : '', [isDragOverlay]);
100
+ const selectedClassName = 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]);
101
+ const hoverClassName = 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]);
116
102
  const fixedHeightClassname = useMemo(() => {
117
103
  if (labelOverflow === 'truncate') {
118
104
  if (rowSize === 'compact') return "".concat(DSTreeViewPrefix, "-").concat(treeItemBlockName, "--fixed-height-compact");
@@ -121,7 +107,7 @@ const TreeItem = props => {
121
107
 
122
108
  return '';
123
109
  }, [labelOverflow, rowSize]);
124
- const finalClassName = useMemo(() => "".concat(dropPreviewClassName, " ").concat(fixedHeightClassname, " ").concat(selectedClassName, " ").concat(hoverClassName), [dropPreviewClassName, selectedClassName, hoverClassName, fixedHeightClassname]);
110
+ const finalClassName = useMemo(() => "".concat(dropPreviewClassName, " ").concat(fixedHeightClassname, " ").concat(selectedClassName, " ").concat(hoverClassName, " ").concat(dragOverlayClassName), [dropPreviewClassName, selectedClassName, hoverClassName, fixedHeightClassname, dragOverlayClassName]);
125
111
  const handleItemClick = useCallback(e => {
126
112
  onItemClick(item, e);
127
113
  setFocusedItem(item);
@@ -140,23 +126,7 @@ const TreeItem = props => {
140
126
  }, [item, scrollToIndex, onItemClick, onItemFocus, setSelectedItem, setFocusedItem]);
141
127
  return /*#__PURE__*/jsxs(TreeListItem, {
142
128
  tabIndex: 0,
143
- onMouseMove: event => {
144
- if (withDragAndDrop && onMouseDragOverItem) {
145
- onMouseDragOverItem({
146
- event,
147
- item,
148
- itemIndex,
149
- setIsDraggingOverThis,
150
- openFolderOnHoverTimeout
151
- });
152
- }
153
- },
154
129
  onMouseLeave: () => {
155
- if (withDragAndDrop) {
156
- setIsDraggingOverThis(false);
157
- if (openFolderOnHoverTimeout !== null && openFolderOnHoverTimeout !== void 0 && openFolderOnHoverTimeout.current) clearTimeout(openFolderOnHoverTimeout.current);
158
- }
159
-
160
130
  if ((hoverItem === null || hoverItem === void 0 ? void 0 : hoverItem.id) === item.id) {
161
131
  setHoverItem(null);
162
132
  }
@@ -165,6 +135,7 @@ const TreeItem = props => {
165
135
  setHoverItem(item);
166
136
  },
167
137
  onClick: handleItemClick,
138
+ onBlur: () => setFocusedItem(null),
168
139
  ref: setItemRefs,
169
140
  style: _objectSpread({}, itemWrapperStyle),
170
141
  className: finalClassName,
@@ -174,25 +145,29 @@ const TreeItem = props => {
174
145
  "data-index": item.virtualIndex,
175
146
  onKeyDown: onItemKeyDown,
176
147
  children: [/*#__PURE__*/_jsx(TreeListItemAddonsWrapper, {}, void 0, withDragAndDrop ? /*#__PURE__*/_jsx(DnDHandle, {
177
- id: id
178
- }) : null, withRadioChecks ? /*#__PURE__*/_jsx(RadioSelectable, {
148
+ id: id,
149
+ isDragOverlay: isDragOverlay
150
+ }) : null, withRadioChecks && !isDragOverlay ? /*#__PURE__*/_jsx(RadioSelectable, {
179
151
  item: item,
180
152
  itemIndex: itemIndex
181
- }) : null, withCheckboxChecks ? /*#__PURE__*/_jsx(CheckboxSelectable, {
153
+ }) : null, withCheckboxChecks && !isDragOverlay ? /*#__PURE__*/_jsx(CheckboxSelectable, {
182
154
  item: item,
183
155
  itemIndex: itemIndex
184
- }) : null, /*#__PURE__*/_jsx(NestingSpace, {
156
+ }) : null, !isDragOverlay && /*#__PURE__*/_jsx(NestingSpace, {
185
157
  item: item,
186
158
  spaceForNestingLevel: spaceForNestingLevel
187
- }), /*#__PURE__*/_jsx(ExpandCaret, {
159
+ }), !isDragOverlay && /*#__PURE__*/_jsx(ExpandCaret, {
188
160
  item: item
189
161
  }), !disableIcons ? /*#__PURE__*/_jsx(Icon, {
190
162
  item: item
191
163
  }) : null), /*#__PURE__*/_jsx(TreeItemText, {
192
164
  item: item
193
- }), rightAddons && /*#__PURE__*/_jsx(TreeListItemAddonsWrapper, {}, void 0, typeof rightAddons === 'function' ? rightAddons(item) : rightAddons)]
165
+ }), rightAddons && /*#__PURE__*/_jsx(TreeListItemAddonsWrapper, {}, void 0, typeof rightAddons === 'function' ? rightAddons(item) : rightAddons), /*#__PURE__*/_jsx(DropIndicator, {
166
+ dropIndicatorPosition: dropIndicatorPosition,
167
+ isDropValid: isDropValid
168
+ })]
194
169
  });
195
170
  };
196
- const DragAndDropTreeItem = SortableElement(TreeItem);
171
+ var TreeItem$1 = withDnDSortableItemContext(TreeItem);
197
172
 
198
- export { DragAndDropTreeItem, TreeItem, TreeListItem, TreeListItemAddonsWrapper };
173
+ export { TreeItem, TreeListItem, TreeListItemAddonsWrapper, TreeItem$1 as default };
@@ -8,12 +8,13 @@ import 'core-js/modules/esnext.iterator.filter.js';
8
8
  import 'core-js/modules/esnext.async-iterator.for-each.js';
9
9
  import 'core-js/modules/esnext.iterator.for-each.js';
10
10
  import { useContext } from 'react';
11
- import { SortableContainer } from '@elliemae/react-sortable-hoc';
12
11
  import { aggregatedClasses } from '@elliemae/ds-classnames';
13
12
  import { DSCircularProgressIndicator } from '@elliemae/ds-circular-progress-indicator';
14
13
  import TreeViewContext from '../TreeViewContext.js';
15
14
  import { treeListBlockName, DSTreeViewPrefix } from '../config/cssClassesConstants.js';
16
- import { DragAndDropTreeItem, TreeItem } from './TreeItem.js';
15
+ import TreeItem from './TreeItem.js';
16
+ import { withConditionalDnDRowContext } from '../hoc/WithConditionalDnDContext.js';
17
+ import { DnDTreeContext } from '../hoc/DnDTreeContext.js';
17
18
  import { jsxs, jsx } from 'react/jsx-runtime';
18
19
 
19
20
  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; }
@@ -38,16 +39,13 @@ const TreeListWrapper = aggregatedClasses('ul', {
38
39
  });
39
40
  const compactRowClass = "".concat(DSTreeViewPrefix, "-tv-row-size-compact");
40
41
  const normaRowClass = "".concat(DSTreeViewPrefix, "-tv-row-size-normal");
41
- const TreeList = props => {
42
- const {
43
- onMouseDragOverItem
44
- } = props;
42
+
43
+ const TreeListComp = () => {
45
44
  const ctx = useContext(TreeViewContext);
46
45
  const {
47
46
  virtualListRef,
48
47
  virtualListHelpers,
49
- visibleItems,
50
- withDragAndDrop,
48
+ visibleItems: flattenedVisibleItems,
51
49
  props: {
52
50
  width,
53
51
  height,
@@ -61,6 +59,9 @@ const TreeList = props => {
61
59
  virtualItems
62
60
  } = virtualListHelpers;
63
61
  const className = "".concat(rowSize === 'compact' ? "".concat(compactRowClass) : "".concat(normaRowClass));
62
+ const {
63
+ visibleItems
64
+ } = useContext(DnDTreeContext);
64
65
  return /*#__PURE__*/jsxs(TreeListWrapper, {
65
66
  ref: virtualListRef,
66
67
  className: className,
@@ -95,17 +96,17 @@ const TreeList = props => {
95
96
  measureRef,
96
97
  start
97
98
  } = virtualItem;
98
- const item = visibleItems[index];
99
+ const item = (visibleItems || flattenedVisibleItems)[index];
100
+ if (!item) return null;
99
101
  item.virtualIndex = index;
100
102
  const {
101
103
  id
102
104
  } = item;
103
105
  const style = {
104
106
  position: 'absolute',
105
- top: 0,
107
+ top: "".concat(start, "px"),
106
108
  left: 0,
107
- width: '100%',
108
- transform: "translateY(".concat(start, "px)")
109
+ width: '100%'
109
110
  };
110
111
  const listItemProps = {
111
112
  key: "DS-TreeView-List-Item-".concat(id),
@@ -116,13 +117,11 @@ const TreeList = props => {
116
117
  item,
117
118
  itemWrapperStyle: style
118
119
  };
119
- if (withDragAndDrop) return /*#__PURE__*/jsx(DragAndDropTreeItem, _objectSpread(_objectSpread({}, listItemProps), {}, {
120
- onMouseDragOverItem: onMouseDragOverItem
121
- }));
122
120
  return /*#__PURE__*/jsx(TreeItem, _objectSpread({}, listItemProps));
123
121
  })) : null]
124
122
  });
125
123
  };
126
- const DragAndDropTreeList = SortableContainer(TreeList);
127
124
 
128
- export { DragAndDropTreeList, TreeList, TreeListNoItems, TreeListWrapper, treeListNoItemsBn };
125
+ const TreeList = withConditionalDnDRowContext(TreeListComp);
126
+
127
+ export { TreeList, TreeListNoItems, TreeListWrapper, treeListNoItemsBn };
@@ -1,35 +1,3 @@
1
- import _jsx from '@babel/runtime/helpers/esm/jsx';
2
- import { useContext } from 'react';
3
- import { DragAndDropTreeList } from '../../parts/TreeList.js';
4
- import { useDnDHelpers } from '../../utils/useDnDHelpers.js';
5
- import { keyCodes } from '../../utils/dnd-helpers.js';
6
- import TreeViewContext from '../../TreeViewContext.js';
7
-
8
- const TreeDnD = () => {
9
- const {
10
- updateBeforeSortStart,
11
- onSortStart,
12
- onMouseDragOverItem,
13
- onSortEnd
14
- } = useDnDHelpers();
15
- const ctx = useContext(TreeViewContext);
16
- const {
17
- virtualListRef
18
- } = ctx;
19
- return /*#__PURE__*/_jsx(DragAndDropTreeList, {
20
- useDragHandle: true,
21
- transitionDuration: 0,
22
- keyboardSortingTransitionDuration: 0,
23
- hideSortableGhost: false,
24
- disableAnimation: true,
25
- updateBeforeSortStart: updateBeforeSortStart,
26
- onSortStart: onSortStart,
27
- onMouseDragOverItem: onMouseDragOverItem,
28
- onSortEnd: onSortEnd,
29
- getContainer: () => virtualListRef === null || virtualListRef === void 0 ? void 0 : virtualListRef.current,
30
- keyCodes: keyCodes
31
- });
32
- };
33
1
  const TreeDndPlugin = 'tree-dnd';
34
2
 
35
- export { TreeDnD, TreeDndPlugin };
3
+ export { TreeDndPlugin };
@@ -1 +1 @@
1
- export { TreeDnD, TreeDndPlugin } from './TreeDndPlugin.js';
1
+ export { TreeDndPlugin } from './TreeDndPlugin.js';
@@ -1,4 +1,4 @@
1
- export { TreeDnD, TreeDndPlugin } from './dnd/TreeDndPlugin.js';
1
+ export { TreeDndPlugin } from './dnd/TreeDndPlugin.js';
2
2
  export { TreeRovingPlugin } from './roving/TreeRovingPlugin.js';
3
3
  export { SelectablePluginTree } from './selectable/SelectablePluginTree.js';
4
4
  export { TreeToolbarPlugin } from './toolbar/TreeToolbarPlugin.js';
@@ -26,6 +26,7 @@ const TreeViewPropTypes = {
26
26
  isMultiSelect: PropTypes.bool.description('whether the tree view is multi select or not').defaultValue(false),
27
27
  isSingleSelect: PropTypes.bool.description('wheter the tree view is single select or not').defaultValue(false),
28
28
  isLoading: PropTypes.bool.description('wheter the tree should show the loading state or not').defaultValue(false),
29
+ getIsDropValid: PropTypes.func.description("Function that returns true if the drop is valid and false if it's not").defaultValue('() => true'),
29
30
  restrictDragAndDrop: PropTypes.bool.description('whether to restrict DnD functionality or not').defaultValue(false),
30
31
  showChildrenAmount: PropTypes.bool.description('whether to show the amount of children or not').defaultValue(false),
31
32
  sortable: PropTypes.bool.description('whether the sortable functionality is active or not').defaultValue(false),