@react-fabric/data 1.0.0-beta.54 → 1.0.0-beta.56

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 (42) hide show
  1. package/dist/cjs/hooks/useFilteredList.js +68 -10
  2. package/dist/cjs/table/HeaderCell.js +3 -2
  3. package/dist/cjs/table/Table.js +7 -1
  4. package/dist/cjs/table/useVirtualTable.js +18 -0
  5. package/dist/cjs/tree/TreeNode.js +3 -2
  6. package/dist/cjs/tree/TreePanel.js +18 -4
  7. package/dist/cjs/tree/useTree.js +107 -39
  8. package/dist/cjs/tree/utils.js +5 -4
  9. package/dist/cjs/virtual/Gallery.js +2 -2
  10. package/dist/cjs/virtual/List.js +2 -2
  11. package/dist/esm/hooks/useFilteredList.js +69 -11
  12. package/dist/esm/table/HeaderCell.js +3 -2
  13. package/dist/esm/table/Table.js +7 -1
  14. package/dist/esm/table/useVirtualTable.js +19 -1
  15. package/dist/esm/tree/TreeNode.js +3 -2
  16. package/dist/esm/tree/TreePanel.js +19 -5
  17. package/dist/esm/tree/useTree.js +109 -41
  18. package/dist/esm/tree/utils.js +5 -4
  19. package/dist/esm/virtual/Gallery.js +2 -2
  20. package/dist/esm/virtual/List.js +2 -2
  21. package/dist/types/hooks/useFilteredList.d.ts +49 -6
  22. package/dist/types/table/HeaderCell.d.ts +1 -1
  23. package/dist/types/table/Table.d.ts +1 -1
  24. package/dist/types/table/types.d.ts +3 -0
  25. package/dist/types/table/useVirtualTable.d.ts +3 -0
  26. package/dist/types/tree/TreePanel.d.ts +1 -1
  27. package/dist/types/tree/types.d.ts +12 -13
  28. package/dist/types/tree/useTree.d.ts +3 -0
  29. package/dist/types/tree/utils.d.ts +2 -2
  30. package/package.json +5 -5
  31. package/src/hooks/useFilteredList.tsx +90 -9
  32. package/src/table/HeaderCell.tsx +3 -2
  33. package/src/table/Table.tsx +5 -0
  34. package/src/table/types.ts +4 -0
  35. package/src/table/useVirtualTable.ts +24 -1
  36. package/src/tree/TreeNode.tsx +4 -5
  37. package/src/tree/TreePanel.tsx +12 -4
  38. package/src/tree/types.ts +12 -13
  39. package/src/tree/useTree.ts +105 -35
  40. package/src/tree/utils.ts +11 -5
  41. package/src/virtual/Gallery.tsx +1 -1
  42. package/src/virtual/List.tsx +1 -1
@@ -1,20 +1,34 @@
1
1
  'use client';
2
2
 
3
3
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
4
- import { isString, matchString } from '@react-fabric/utilities';
4
+ import { isArray, matchString, isString } from '@react-fabric/utilities';
5
5
  import { useState, useDeferredValue, useTransition, useCallback, useEffect } from 'react';
6
6
 
7
7
  var filterList = function filterList(items) {
8
8
  var query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
9
- var matcher = arguments.length > 2 ? arguments[2] : undefined;
9
+ var matchAll = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
10
+ var matcher = arguments.length > 3 ? arguments[3] : undefined;
10
11
  var newList = [];
11
12
  items.forEach(function (item) {
12
13
  if (matcher) {
13
14
  return (matcher === null || matcher === void 0 ? void 0 : matcher(item, query)) && newList.push(item);
14
15
  }
15
- if (query && isString(query)) {
16
- var _item$label;
17
- if (matchString((_item$label = item.label) !== null && _item$label !== void 0 ? _item$label : item.toString(), query)) {
16
+ if (query && isArray(query) && query.length > 0) {
17
+ if (matchAll && query.every(function (q) {
18
+ var _item$label;
19
+ return matchString((_item$label = item.label) !== null && _item$label !== void 0 ? _item$label : item.toString(), q);
20
+ })) {
21
+ return newList.push(item);
22
+ }
23
+ if (!matchAll && query.some(function (q) {
24
+ var _item$label2;
25
+ return matchString((_item$label2 = item.label) !== null && _item$label2 !== void 0 ? _item$label2 : item.toString(), q);
26
+ })) {
27
+ return newList.push(item);
28
+ }
29
+ } else if (query && isString(query)) {
30
+ var _item$label3;
31
+ if (matchString((_item$label3 = item.label) !== null && _item$label3 !== void 0 ? _item$label3 : item.toString(), query)) {
18
32
  return newList.push(item);
19
33
  }
20
34
  } else {
@@ -24,6 +38,26 @@ var filterList = function filterList(items) {
24
38
  return newList;
25
39
  };
26
40
 
41
+ /**
42
+ * Custom hook to filter a list of items based on a query.
43
+ * It provides a way to search through the items and returns the filtered list.
44
+ * The hook uses a deferred value to optimize performance during transitions.
45
+ * It also allows for a custom matcher function to define how items should be matched against the query.
46
+ *
47
+ * @param items - The list of items to filter.
48
+ * @param matchAll - Match all phrases in the query list against the items.
49
+ * @returns An object containing the search function, current query, filtered list, and a boolean indicating if a search is in progress.
50
+ *
51
+ * @example
52
+ * ```jsx
53
+ * useFilteredList(items, (item, query) => {
54
+ * return item.name.includes(query);
55
+ * });
56
+ * ```
57
+ *
58
+ * @see {@link https://adarshpastakia.github.io/react-fabric/?path=/docs/data-usefilteredlist--docs}
59
+ */
60
+
27
61
  /**
28
62
  * Custom hook to filter a list of items based on a query.
29
63
  * It provides a way to search through the items and returns the filtered list.
@@ -43,7 +77,29 @@ var filterList = function filterList(items) {
43
77
  *
44
78
  * @see {@link https://adarshpastakia.github.io/react-fabric/?path=/docs/data-usefilteredlist--docs}
45
79
  */
46
- var useFilteredList = function useFilteredList(items, matcher) {
80
+
81
+ /**
82
+ * Custom hook to filter a list of items based on a query.
83
+ * It provides a way to search through the items and returns the filtered list.
84
+ * The hook uses a deferred value to optimize performance during transitions.
85
+ * It also allows for a custom matcher function to define how items should be matched against the query.
86
+ *
87
+ * @param items - The list of items to filter.
88
+ * @param matchAll - Match all phrases in the query list against the items.
89
+ * @param matcher - An optional function to match items against the query.
90
+ * @returns An object containing the search function, current query, filtered list, and a boolean indicating if a search is in progress.
91
+ *
92
+ * @example
93
+ * ```jsx
94
+ * useFilteredList(items, (item, query) => {
95
+ * return item.name.includes(query);
96
+ * });
97
+ * ```
98
+ *
99
+ * @see {@link https://adarshpastakia.github.io/react-fabric/?path=/docs/data-usefilteredlist--docs}
100
+ */
101
+
102
+ function useFilteredList(items, matchAll, matcher) {
47
103
  var _useState = useState(),
48
104
  _useState2 = _slicedToArray(_useState, 2),
49
105
  query = _useState2[0],
@@ -57,20 +113,22 @@ var useFilteredList = function useFilteredList(items, matcher) {
57
113
  _useTransition2 = _slicedToArray(_useTransition, 2),
58
114
  isSearching = _useTransition2[0],
59
115
  startTransition = _useTransition2[1];
60
- var filterItems = useCallback(function (items, query) {
116
+ var matchingAll = typeof matchAll === "boolean" ? matchAll : true;
117
+ var matcherFn = typeof matchAll === "function" ? matchAll : matcher;
118
+ var filterItems = useCallback(function (items, query, matchingAll) {
61
119
  return startTransition(function () {
62
- return setFilteredList(filterList(items, query, matcher));
120
+ return setFilteredList(filterList(items, query, matchingAll, matcherFn));
63
121
  });
64
122
  }, []);
65
123
  useEffect(function () {
66
- if (query) filterItems(_items, query);else setFilteredList(items);
67
- }, [query, _items]);
124
+ if (query) filterItems(_items, query, matchingAll);else setFilteredList(items);
125
+ }, [query, matchingAll, _items]);
68
126
  return {
69
127
  onSearch: setQuery,
70
128
  query: query,
71
129
  filteredList: filteredList,
72
130
  isSearching: isSearching
73
131
  };
74
- };
132
+ }
75
133
 
76
134
  export { useFilteredList };
@@ -11,6 +11,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
11
11
 
12
12
  var HeaderCell = function HeaderCell(_ref) {
13
13
  var id = _ref.id,
14
+ field = _ref.field,
14
15
  dataType = _ref.dataType,
15
16
  label = _ref.label,
16
17
  icon = _ref.icon,
@@ -56,7 +57,7 @@ var HeaderCell = function HeaderCell(_ref) {
56
57
  list: filterOptions,
57
58
  filter: filter,
58
59
  onFilter: function onFilter(value) {
59
- return _onFilter === null || _onFilter === void 0 ? void 0 : _onFilter(id, value);
60
+ return _onFilter === null || _onFilter === void 0 ? void 0 : _onFilter(field !== null && field !== void 0 ? field : id, value);
60
61
  }
61
62
  })
62
63
  }, "filters"));
@@ -87,7 +88,7 @@ var HeaderCell = function HeaderCell(_ref) {
87
88
  list: filterOptions,
88
89
  filter: filter,
89
90
  onFilter: function onFilter(value) {
90
- return _onFilter === null || _onFilter === void 0 ? void 0 : _onFilter(id, value);
91
+ return _onFilter === null || _onFilter === void 0 ? void 0 : _onFilter(field !== null && field !== void 0 ? field : id, value);
91
92
  }
92
93
  }, "filters")];
93
94
  }
@@ -40,7 +40,10 @@ var Table = function Table(_ref) {
40
40
  onFilter = _ref.onFilter,
41
41
  onScroll = _ref.onScroll,
42
42
  onRowClick = _ref.onRowClick,
43
- onCheckedChanged = _ref.onCheckedChanged;
43
+ onCheckedChanged = _ref.onCheckedChanged,
44
+ _ref$total = _ref.total,
45
+ total = _ref$total === void 0 ? 0 : _ref$total,
46
+ onLoadMore = _ref.onLoadMore;
44
47
  var _useTranslation = useTranslation("data"),
45
48
  t = _useTranslation.t;
46
49
  var fireCheckChanged = useDebounce(function (checkedIds) {
@@ -53,6 +56,9 @@ var Table = function Table(_ref) {
53
56
  checked: checked,
54
57
  keyProperty: keyProperty,
55
58
  groupProperty: groupProperty,
59
+ total: total,
60
+ loading: loading,
61
+ onLoadMore: onLoadMore,
56
62
  onCheckChanged: fireCheckChanged
57
63
  }),
58
64
  scrollerRef = _useVirtualTable.scrollerRef,
@@ -3,7 +3,7 @@
3
3
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
4
4
  import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
5
5
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
6
- import { groupBy, compareValues } from '@react-fabric/utilities';
6
+ import { groupBy, compareValues, debounce } from '@react-fabric/utilities';
7
7
  import { useVirtualizer, defaultRangeExtractor } from '@tanstack/react-virtual';
8
8
  import { useReducer, useRef, useMemo, useState, useCallback, useEffect } from 'react';
9
9
 
@@ -137,6 +137,24 @@ var useVirtualTable = function useVirtualTable(data, options) {
137
137
  checked: (_options$checked = options.checked) !== null && _options$checked !== void 0 ? _options$checked : []
138
138
  });
139
139
  }, [options.checked]);
140
+ useEffect(function () {
141
+ if (options.onLoadMore) {
142
+ var _virtualItems$, _virtualItems$slice$p;
143
+ var firstItem = (_virtualItems$ = virtualItems[0]) === null || _virtualItems$ === void 0 ? void 0 : _virtualItems$.index;
144
+ var lastItem = virtualItems === null || virtualItems === void 0 || (_virtualItems$slice$p = virtualItems.slice(-1).pop()) === null || _virtualItems$slice$p === void 0 ? void 0 : _virtualItems$slice$p.index;
145
+ var canLoadPrevPage = firstItem !== undefined && state.items[firstItem] === null;
146
+ var canLoadNextPage = lastItem !== undefined && lastItem === state.items.length - 1 && state.items.length < options.total;
147
+ var db = debounce(options.onLoadMore);
148
+ if (canLoadPrevPage) {
149
+ db(firstItem);
150
+ } else if (!options.loading && canLoadNextPage) {
151
+ db(lastItem + 1);
152
+ }
153
+ return function () {
154
+ return db.cancel();
155
+ };
156
+ }
157
+ }, [options.onLoadMore, virtualItems]);
140
158
  return {
141
159
  scrollerRef: scrollerRef,
142
160
  items: virtualItems,
@@ -63,9 +63,10 @@ var TreeNode = function TreeNode(_ref) {
63
63
  return /*#__PURE__*/jsxs("div", {
64
64
  role: "treeitem",
65
65
  "aria-selected": node.selected,
66
- className: classNames("flex flex-nowrap items-center", node.className, node.leaf ? leafClassName : nodeClassName),
66
+ className: classNames("flex flex-nowrap items-center"),
67
67
  "data-testid": node["data-testid"],
68
68
  "data-test-value": node["data-test-value"],
69
+ "data-id": node.id,
69
70
  children: [filler, node.loading && /*#__PURE__*/jsx("div", {
70
71
  className: "flex-initial w-6",
71
72
  children: /*#__PURE__*/jsx(Icon, {
@@ -93,7 +94,7 @@ var TreeNode = function TreeNode(_ref) {
93
94
  })
94
95
  }), !node.empty && /*#__PURE__*/jsxs("div", {
95
96
  role: "none",
96
- className: classNames("group/tool data-[selected]:bg-primary-100 flex flex-nowrap flex-1 overflow-hidden select-none", node.childSelected && "font-medium", node.disabled && "text-muted opacity-65", !node.disabled && (canSelect || onClick) && "hover:bg-primary-50 cursor-pointer"),
97
+ className: classNames("group/tool data-[selected]:bg-primary-100 flex flex-nowrap flex-1 overflow-hidden select-none", node.childSelected && "font-medium", node.disabled && "text-muted opacity-65", node.className, node.leaf ? leafClassName : nodeClassName, !node.disabled && (canSelect || onClick) && "hover:bg-primary-50 cursor-pointer"),
97
98
  "data-selected": node.selected,
98
99
  onClick: node.disabled ? undefined : function () {
99
100
  onClick === null || onClick === void 0 || onClick(node.id, node.data);
@@ -5,13 +5,13 @@ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProper
5
5
  import { CoreIcons, Section, Header, Icon, ButtonGroup, Button } from '@react-fabric/core';
6
6
  import { Search } from '@react-fabric/form';
7
7
  import { useVirtualizer } from '@tanstack/react-virtual';
8
- import { useRef, useMemo, useImperativeHandle } from 'react';
8
+ import { useRef, useMemo, useImperativeHandle, useEffect } from 'react';
9
9
  import { TreeNode } from './TreeNode.js';
10
10
  import { iconExpandAll, iconCollapseAll } from './types.js';
11
11
  import { useTree } from './useTree.js';
12
12
  import { jsxs, jsx } from 'react/jsx-runtime';
13
13
 
14
- var _excluded = ["ref", "items", "selected", "checked", "checkable", "noLines", "renderer", "searchable", "selectable", "matcher", "filterPlaceholder", "defaultLeafIcon", "defaultNodeIcon", "expander", "onChecked", "onLoad", "onQuery", "onSelect", "onClick", "sorter", "makeLabel", "makeIcon", "defaultExpanded", "onExpandToggle", "leafClassName", "nodeClassName"];
14
+ var _excluded = ["ref", "items", "selected", "checked", "checkable", "noLines", "searchable", "selectable", "matcher", "filterPlaceholder", "defaultLeafIcon", "defaultNodeIcon", "expander", "onChecked", "onLoad", "onQuery", "onSelect", "onClick", "sorter", "makeLabel", "makeIcon", "defaultExpanded", "onExpandToggle", "leafClassName", "nodeClassName"];
15
15
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
16
16
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
17
17
  var TreePanel = function TreePanel(_ref) {
@@ -22,7 +22,6 @@ var TreePanel = function TreePanel(_ref) {
22
22
  checked = _ref.checked,
23
23
  checkable = _ref.checkable,
24
24
  noLines = _ref.noLines,
25
- renderer = _ref.renderer,
26
25
  searchable = _ref.searchable,
27
26
  selectable = _ref.selectable,
28
27
  matcher = _ref.matcher,
@@ -58,10 +57,13 @@ var TreePanel = function TreePanel(_ref) {
58
57
  onExpandToggle: onExpandToggle
59
58
  }),
60
59
  tree = _useTree.tree,
60
+ query = _useTree.query,
61
+ currentSelected = _useTree.selected,
61
62
  toggleExpand = _useTree.toggleExpand,
62
63
  toggleCheck = _useTree.toggleCheck,
63
64
  expandAll = _useTree.expandAll,
64
65
  collapseAll = _useTree.collapseAll,
66
+ expandAndLoad = _useTree.expandAndLoad,
65
67
  _select = _useTree.select,
66
68
  expand = _useTree.expand,
67
69
  onFilter = _useTree.onFilter;
@@ -87,16 +89,28 @@ var TreePanel = function TreePanel(_ref) {
87
89
  open: function open(id) {
88
90
  return expand(id);
89
91
  },
92
+ openAndLoad: function openAndLoad(list) {
93
+ return expandAndLoad(list);
94
+ },
90
95
  select: function select(id) {
91
96
  return _select(id);
92
97
  }
93
98
  };
94
99
  }, []);
100
+ useEffect(function () {
101
+ var index = tree.findIndex(function (n) {
102
+ return n.id === currentSelected;
103
+ });
104
+ virtualizer.scrollToIndex(index, {
105
+ align: "auto"
106
+ });
107
+ }, [currentSelected]);
95
108
  return /*#__PURE__*/jsxs(Section, {
96
109
  children: [/*#__PURE__*/jsxs(Header, {
97
110
  flex: true,
98
111
  className: "items-center p-px justify-end overflow-hidden border-b",
99
112
  children: [searchable && /*#__PURE__*/jsx(Search, {
113
+ value: query,
100
114
  onSearch: onFilter,
101
115
  allowClear: true,
102
116
  placeholder: filterPlaceholder,
@@ -134,7 +148,7 @@ var TreePanel = function TreePanel(_ref) {
134
148
  height: (_virtualItems$ = virtualItems[0]) === null || _virtualItems$ === void 0 ? void 0 : _virtualItems$.start
135
149
  }
136
150
  }), virtualItems.map(function (_ref2) {
137
- var _makeIcon, _ref3, _ref4;
151
+ var _makeIcon, _ref3;
138
152
  var index = _ref2.index,
139
153
  key = _ref2.key;
140
154
  return /*#__PURE__*/jsx("div", {
@@ -154,7 +168,7 @@ var TreePanel = function TreePanel(_ref) {
154
168
  onClick: onClick,
155
169
  leafClassName: leafClassName,
156
170
  nodeClassName: nodeClassName,
157
- children: (_ref3 = (_ref4 = tree[index].data && (renderer === null || renderer === void 0 ? void 0 : renderer(tree[index].data))) !== null && _ref4 !== void 0 ? _ref4 : makeLabel === null || makeLabel === void 0 ? void 0 : makeLabel(tree[index].data)) !== null && _ref3 !== void 0 ? _ref3 : tree[index].label
171
+ children: (_ref3 = tree[index].data && (makeLabel === null || makeLabel === void 0 ? void 0 : makeLabel(tree[index].data))) !== null && _ref3 !== void 0 ? _ref3 : tree[index].label
158
172
  })
159
173
  }, key);
160
174
  })]
@@ -2,11 +2,12 @@
2
2
 
3
3
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
4
4
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
5
+ import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
5
6
  import { useDebounce } from '@react-fabric/core';
6
- import { EMPTY_ARRAY } from '@react-fabric/utilities';
7
+ import { EMPTY_ARRAY, isEmpty } from '@react-fabric/utilities';
7
8
  import memoizeOne from 'memoize-one';
8
9
  import { useRef, useCallback, useReducer, useEffect } from 'react';
9
- import { refactorTree, makeTreeMap, flattenTree, updateSelection, filterTree, updateChecked } from './utils.js';
10
+ import { refactorTree, makeTreeMap, flattenTree, updateSelection, updateChecked, filterTree } from './utils.js';
10
11
 
11
12
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
12
13
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -31,7 +32,7 @@ var useTree = function useTree(_ref) {
31
32
  onSelect: onSelect,
32
33
  onChecked: onChecked
33
34
  });
34
- var intialExpand = useRef(defaultExpanded !== null && defaultExpanded !== void 0 ? defaultExpanded : EMPTY_ARRAY);
35
+ var intialExpand = useRef(_toConsumableArray(defaultExpanded !== null && defaultExpanded !== void 0 ? defaultExpanded : EMPTY_ARRAY));
35
36
  var itemList = createItemList(items);
36
37
  var fireExpandToggle = useCallback(function (itemMap) {
37
38
  var expandedList = itemMap.filter(function (node) {
@@ -47,26 +48,29 @@ var useTree = function useTree(_ref) {
47
48
  var _node$children;
48
49
  if (node.open && !node.leaf && !((_node$children = node.children) !== null && _node$children !== void 0 && _node$children.length)) {
49
50
  node.loading = true;
50
- void Promise.resolve(onLoad === null || onLoad === void 0 ? void 0 : onLoad(node.id)).then(function () {
51
- var resp = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EMPTY_ARRAY;
52
- node.children = refactorTree(resp, {
53
- sorter: sorter,
54
- defaultExpanded: defaultExpanded
55
- }, {
56
- level: node.level + 1,
57
- parent: node.id
58
- });
59
- })["finally"](function () {
60
- var _intialExpand$current;
61
- node.loading = false;
62
- dispatch({
63
- type: "loaded"
51
+ // delay onload callback to avoid state issues
52
+ setTimeout(function () {
53
+ void Promise.resolve(onLoad === null || onLoad === void 0 ? void 0 : onLoad(node.id)).then(function () {
54
+ var resp = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EMPTY_ARRAY;
55
+ node.children = refactorTree(resp, {
56
+ sorter: sorter,
57
+ defaultExpanded: defaultExpanded
58
+ }, {
59
+ level: node.level + 1,
60
+ parent: node.id
61
+ });
62
+ })["finally"](function () {
63
+ var _intialExpand$current;
64
+ node.loading = false;
65
+ dispatch({
66
+ type: "loaded"
67
+ });
68
+ ((_intialExpand$current = intialExpand.current) === null || _intialExpand$current === void 0 ? void 0 : _intialExpand$current.length) > 0 && dispatch({
69
+ type: "expand",
70
+ id: intialExpand.current.shift()
71
+ });
64
72
  });
65
- ((_intialExpand$current = intialExpand.current) === null || _intialExpand$current === void 0 ? void 0 : _intialExpand$current.length) > 0 && dispatch({
66
- type: "expand",
67
- id: intialExpand.current.shift()
68
- });
69
- });
73
+ }, 100);
70
74
  } else {
71
75
  var _intialExpand$current2;
72
76
  dispatch({
@@ -78,6 +82,17 @@ var useTree = function useTree(_ref) {
78
82
  });
79
83
  }
80
84
  }, [onLoad]);
85
+ var fireSelected = useDebounce(function (nodeId, data) {
86
+ var _componentEvents$curr, _componentEvents$curr2;
87
+ (_componentEvents$curr = (_componentEvents$curr2 = componentEvents.current).onSelect) === null || _componentEvents$curr === void 0 || _componentEvents$curr.call(_componentEvents$curr2, nodeId, data);
88
+ }, [onSelect]);
89
+ var fireChecked = useDebounce(function (leafs, nodes, partials) {
90
+ var _componentEvents$curr3, _componentEvents$curr4;
91
+ (_componentEvents$curr3 = (_componentEvents$curr4 = componentEvents.current).onChecked) === null || _componentEvents$curr3 === void 0 || _componentEvents$curr3.call(_componentEvents$curr4, leafs, nodes, partials);
92
+ }, [onChecked]);
93
+ var fireQuery = useDebounce(function (query) {
94
+ onQuery === null || onQuery === void 0 || onQuery(query);
95
+ }, [onQuery]);
81
96
  var _useReducer = useReducer(function (state, action) {
82
97
  if (action.type === "load") {
83
98
  state.items = refactorTree(action.items, {
@@ -86,6 +101,9 @@ var useTree = function useTree(_ref) {
86
101
  });
87
102
  state.itemMap = makeTreeMap(state.items);
88
103
  state.tree = flattenTree(state.items);
104
+ state.selected = undefined;
105
+ state.checked = undefined;
106
+ state.query = "";
89
107
  return _objectSpread({}, state);
90
108
  }
91
109
  if (action.type === "toggleExpand") {
@@ -97,10 +115,14 @@ var useTree = function useTree(_ref) {
97
115
  }
98
116
  }
99
117
  if (action.type === "loaded") {
118
+ var _state$checked;
100
119
  state.itemMap = makeTreeMap(state.items);
101
120
  fireExpandToggle(Array.from(state.itemMap.values()));
102
121
  state.tree = flattenTree(state.items);
103
- state.selected && updateSelection(state.itemMap, state.selected, true);
122
+ state.selected = updateSelection(state.itemMap, selected, true);
123
+ (_state$checked = state.checked) === null || _state$checked === void 0 || _state$checked.forEach(function (id) {
124
+ return updateChecked(state.itemMap, id, 1);
125
+ });
104
126
  return _objectSpread({}, state);
105
127
  }
106
128
  if (action.type === "expand") {
@@ -136,41 +158,66 @@ var useTree = function useTree(_ref) {
136
158
  }
137
159
  if (action.type === "filter") {
138
160
  if (onQuery) {
139
- var _action$query;
140
- onQuery((_action$query = action.query) !== null && _action$query !== void 0 ? _action$query : "");
161
+ // TODO: onQuery should provide new tree listing
162
+ // save current tree state as preQueryState
163
+ // on clearing filter restore preQueryState
164
+ if (!isEmpty(action.query)) {
165
+ // state.prevItems = state.items;
166
+ fireQuery(action.query);
167
+ }
141
168
  } else {
142
169
  filterTree(state.itemMap, action.query, matcher);
143
170
  state.tree = flattenTree(state.items);
144
- return _objectSpread({}, state);
145
171
  }
172
+ return _objectSpread(_objectSpread({}, state), {}, {
173
+ query: action.query
174
+ });
175
+ }
176
+ if (action.type === "toggleSelect") {
177
+ if (!onSelect) {
178
+ if (state.selected) {
179
+ updateSelection(state.itemMap, state.selected);
180
+ }
181
+ state.selected = updateSelection(state.itemMap, action.id, true);
182
+ state.tree = flattenTree(state.items);
183
+ } else {
184
+ var _state$itemMap$get;
185
+ fireSelected(action.id, (_state$itemMap$get = state.itemMap.get(action.id)) === null || _state$itemMap$get === void 0 ? void 0 : _state$itemMap$get.data);
186
+ }
187
+ return _objectSpread({}, state);
146
188
  }
147
189
  if (action.type === "select") {
148
- var _componentEvents$curr, _componentEvents$curr2, _state$itemMap$get;
149
190
  if (state.selected) {
150
191
  updateSelection(state.itemMap, state.selected);
151
192
  }
152
- updateSelection(state.itemMap, action.id, true);
193
+ state.selected = updateSelection(state.itemMap, action.id, true);
153
194
  state.tree = flattenTree(state.items);
154
- (_componentEvents$curr = (_componentEvents$curr2 = componentEvents.current).onSelect) === null || _componentEvents$curr === void 0 || _componentEvents$curr.call(_componentEvents$curr2, action.id, (_state$itemMap$get = state.itemMap.get(action.id)) === null || _state$itemMap$get === void 0 ? void 0 : _state$itemMap$get.data);
155
- return _objectSpread(_objectSpread({}, state), {}, {
156
- selected: action.id
157
- });
195
+ return _objectSpread({}, state);
158
196
  }
159
197
  if (action.type === "toggleCheck") {
160
- var _componentEvents$curr3, _componentEvents$curr4;
161
198
  updateChecked(state.itemMap, action.id);
162
- var checkList = [[], []];
199
+ var checkList = [[], [], []];
163
200
  Array.from(state.itemMap.values()).filter(function (node) {
164
- return node.checked === 1;
201
+ return node.checked !== 0;
165
202
  }).forEach(function (node) {
166
- return checkList[node.leaf ? 0 : 1].push(node.id);
203
+ return checkList[node.leaf ? 0 : node.checked].push(node.id);
204
+ });
205
+ fireChecked(checkList[0],
206
+ // leafs
207
+ checkList[1],
208
+ // nodes
209
+ checkList[2] // partials
210
+ );
211
+ return _objectSpread(_objectSpread({}, state), {}, {
212
+ checked: checkList[0]
167
213
  });
168
- (_componentEvents$curr3 = (_componentEvents$curr4 = componentEvents.current).onChecked) === null || _componentEvents$curr3 === void 0 || _componentEvents$curr3.call(_componentEvents$curr4, checkList[0], checkList[1]);
169
- return _objectSpread({}, state);
170
214
  }
171
215
  if (action.type === "checked") {
216
+ state.itemMap.forEach(function (item) {
217
+ return item.checked = 0;
218
+ });
172
219
  action.id.forEach(function (id) {
173
- return updateChecked(state.itemMap, id);
220
+ return updateChecked(state.itemMap, id, 1);
174
221
  });
175
222
  return _objectSpread(_objectSpread({}, state), {}, {
176
223
  checked: action.id
@@ -181,7 +228,8 @@ var useTree = function useTree(_ref) {
181
228
  itemMap: new Map(),
182
229
  items: [],
183
230
  tree: [],
184
- checked: []
231
+ checked: [],
232
+ query: ""
185
233
  }),
186
234
  _useReducer2 = _slicedToArray(_useReducer, 2),
187
235
  state = _useReducer2[0],
@@ -202,6 +250,14 @@ var useTree = function useTree(_ref) {
202
250
  type: "expand",
203
251
  id: intialExpand.current.shift()
204
252
  });
253
+ selected && dispatch({
254
+ type: "select",
255
+ id: selected
256
+ });
257
+ checked && dispatch({
258
+ type: "checked",
259
+ id: checked
260
+ });
205
261
  }, [itemList]);
206
262
  useEffect(function () {
207
263
  selected && dispatch({
@@ -229,7 +285,7 @@ var useTree = function useTree(_ref) {
229
285
  }, []);
230
286
  var select = useCallback(function (id) {
231
287
  dispatch({
232
- type: "select",
288
+ type: "toggleSelect",
233
289
  id: id
234
290
  });
235
291
  }, []);
@@ -239,6 +295,15 @@ var useTree = function useTree(_ref) {
239
295
  id: id
240
296
  });
241
297
  }, []);
298
+ var expandAndLoad = useCallback(function (expandList) {
299
+ if (expandList.length > 0) {
300
+ intialExpand.current = _toConsumableArray(expandList);
301
+ dispatch({
302
+ type: "expand",
303
+ id: intialExpand.current.shift()
304
+ });
305
+ }
306
+ }, []);
242
307
  var expandAll = useCallback(function () {
243
308
  dispatch({
244
309
  type: "expandAll"
@@ -257,10 +322,13 @@ var useTree = function useTree(_ref) {
257
322
  }, [], 300);
258
323
  return {
259
324
  tree: state.tree,
325
+ query: state.query,
326
+ selected: state.selected,
260
327
  toggleExpand: toggleExpand,
261
328
  expandAll: expandAll,
262
329
  collapseAll: collapseAll,
263
330
  toggleCheck: toggleCheck,
331
+ expandAndLoad: expandAndLoad,
264
332
  select: select,
265
333
  expand: expand,
266
334
  onFilter: onFilter
@@ -96,7 +96,7 @@ var flattenTree = function flattenTree(nodes) {
96
96
  return list;
97
97
  };
98
98
  var updateSelection = function updateSelection(nodes, id, selected) {
99
- var node = nodes.get(id);
99
+ var node = nodes.get(id !== null && id !== void 0 ? id : "");
100
100
  if (node) {
101
101
  // change selection
102
102
  node.selected = selected;
@@ -105,15 +105,16 @@ var updateSelection = function updateSelection(nodes, id, selected) {
105
105
  while (parent) {
106
106
  var parentNode = nodes.get(parent);
107
107
  parentNode && (parentNode.childSelected = selected);
108
- selected && parentNode && (parentNode.open = true);
108
+ // selected && parentNode && (parentNode.open = true);
109
109
  parent = parentNode === null || parentNode === void 0 ? void 0 : parentNode.parent;
110
110
  }
111
+ return id;
111
112
  }
112
113
  };
113
- var updateChecked = function updateChecked(list, id) {
114
+ var updateChecked = function updateChecked(list, id, checked) {
114
115
  var node = list.get(id);
115
116
  if (node) {
116
- node.checked = node.checked === 1 ? 0 : 1;
117
+ node.checked = checked === undefined ? node.checked === 0 ? 1 : 0 : checked;
117
118
  // check all children
118
119
  node.children && getChildren(node.children).forEach(function (child) {
119
120
  return child.checked = node.checked;
@@ -92,8 +92,8 @@ var _VirtualGallery = function _VirtualGallery(_ref) {
92
92
  var virtualItems = virtualizer.getVirtualItems();
93
93
  var currentIndex = useRef(0);
94
94
  useEffect(function () {
95
- var _virtualItems$1$index, _virtualItems$;
96
- currentIndex.current = (_virtualItems$1$index = (_virtualItems$ = virtualItems[1]) === null || _virtualItems$ === void 0 ? void 0 : _virtualItems$.index) !== null && _virtualItems$1$index !== void 0 ? _virtualItems$1$index : 0;
95
+ var _virtualItems$2$index, _virtualItems$;
96
+ currentIndex.current = (_virtualItems$2$index = (_virtualItems$ = virtualItems[2]) === null || _virtualItems$ === void 0 ? void 0 : _virtualItems$.index) !== null && _virtualItems$2$index !== void 0 ? _virtualItems$2$index : 0;
97
97
  if (scrollerRef.current && virtualItems[0] && scrollerRef.current.scrollTop < virtualItems[0].size) currentIndex.current = 0;
98
98
  }, [virtualItems]);
99
99
  var calculateActiveScroll = useCallback(function () {
@@ -68,8 +68,8 @@ var _VirtualList = function _VirtualList(_ref) {
68
68
  var virtualItems = virtualizer.getVirtualItems();
69
69
  var currentIndex = useRef(0);
70
70
  useEffect(function () {
71
- var _virtualItems$1$index, _virtualItems$;
72
- currentIndex.current = (_virtualItems$1$index = (_virtualItems$ = virtualItems[1]) === null || _virtualItems$ === void 0 ? void 0 : _virtualItems$.index) !== null && _virtualItems$1$index !== void 0 ? _virtualItems$1$index : 0;
71
+ var _virtualItems$2$index, _virtualItems$;
72
+ currentIndex.current = (_virtualItems$2$index = (_virtualItems$ = virtualItems[2]) === null || _virtualItems$ === void 0 ? void 0 : _virtualItems$.index) !== null && _virtualItems$2$index !== void 0 ? _virtualItems$2$index : 0;
73
73
  if (scrollerRef.current && virtualItems[0] && scrollerRef.current.scrollTop < virtualItems[0].size) currentIndex.current = 0;
74
74
  }, [virtualItems]);
75
75
  var calculateActiveScroll = useCallback(function () {