@react-fabric/data 1.0.0-beta.0
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.
- package/LICENSE +21 -0
- package/README.md +10 -0
- package/dist/cjs/histogram/Histogram.js +89 -0
- package/dist/cjs/histogram/Histogram.module.css +1 -0
- package/dist/cjs/hooks/useFilteredList.js +56 -0
- package/dist/cjs/hooks/usePagination.js +85 -0
- package/dist/cjs/i18n/ar.json.js +56 -0
- package/dist/cjs/i18n/en.json.js +56 -0
- package/dist/cjs/i18n/index.js +33 -0
- package/dist/cjs/index.js +24 -0
- package/dist/cjs/json/JsonViewer.js +246 -0
- package/dist/cjs/pagination/Pagination.js +100 -0
- package/dist/cjs/table/BodyCell.js +47 -0
- package/dist/cjs/table/HeaderCell.js +79 -0
- package/dist/cjs/table/Table.js +133 -0
- package/dist/cjs/table/useTableColumns.js +26 -0
- package/dist/cjs/table/useVirtualTable.js +56 -0
- package/dist/cjs/tree/TreeNode.js +107 -0
- package/dist/cjs/tree/TreePanel.js +136 -0
- package/dist/cjs/tree/types.js +30 -0
- package/dist/cjs/tree/useTree.js +181 -0
- package/dist/cjs/tree/utils.js +145 -0
- package/dist/cjs/virtual/Gallery.js +229 -0
- package/dist/cjs/virtual/List.js +218 -0
- package/dist/cjs/virtual/Scroller.js +77 -0
- package/dist/esm/histogram/Histogram.js +89 -0
- package/dist/esm/histogram/Histogram.module.css +1 -0
- package/dist/esm/hooks/useFilteredList.js +56 -0
- package/dist/esm/hooks/usePagination.js +85 -0
- package/dist/esm/i18n/ar.json.js +47 -0
- package/dist/esm/i18n/en.json.js +47 -0
- package/dist/esm/i18n/index.js +33 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/json/JsonViewer.js +246 -0
- package/dist/esm/pagination/Pagination.js +100 -0
- package/dist/esm/table/BodyCell.js +47 -0
- package/dist/esm/table/HeaderCell.js +79 -0
- package/dist/esm/table/Table.js +133 -0
- package/dist/esm/table/useTableColumns.js +26 -0
- package/dist/esm/table/useVirtualTable.js +56 -0
- package/dist/esm/tree/TreeNode.js +107 -0
- package/dist/esm/tree/TreePanel.js +136 -0
- package/dist/esm/tree/types.js +29 -0
- package/dist/esm/tree/useTree.js +181 -0
- package/dist/esm/tree/utils.js +140 -0
- package/dist/esm/virtual/Gallery.js +229 -0
- package/dist/esm/virtual/List.js +218 -0
- package/dist/esm/virtual/Scroller.js +77 -0
- package/dist/types/histogram/Histogram.d.ts +41 -0
- package/dist/types/hooks/useFilteredList.d.ts +7 -0
- package/dist/types/hooks/usePagination.d.ts +25 -0
- package/dist/types/i18n/index.d.ts +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/json/JsonViewer.d.ts +59 -0
- package/dist/types/pagination/Pagination.d.ts +24 -0
- package/dist/types/table/BodyCell.d.ts +5 -0
- package/dist/types/table/HeaderCell.d.ts +2 -0
- package/dist/types/table/Table.d.ts +2 -0
- package/dist/types/table/types.d.ts +26 -0
- package/dist/types/table/useTableColumns.d.ts +8 -0
- package/dist/types/table/useVirtualTable.d.ts +8 -0
- package/dist/types/tree/TreeNode.d.ts +2 -0
- package/dist/types/tree/TreePanel.d.ts +2 -0
- package/dist/types/tree/types.d.ts +138 -0
- package/dist/types/tree/useTree.d.ts +20 -0
- package/dist/types/tree/utils.d.ts +10 -0
- package/dist/types/virtual/Gallery.d.ts +55 -0
- package/dist/types/virtual/List.d.ts +59 -0
- package/dist/types/virtual/Scroller.d.ts +8 -0
- package/package.json +55 -0
- package/src/histogram/Histogram.module.css +57 -0
- package/src/histogram/Histogram.tsx +176 -0
- package/src/hooks/useFilteredList.tsx +78 -0
- package/src/hooks/usePagination.tsx +135 -0
- package/src/i18n/ar.json +36 -0
- package/src/i18n/en.json +36 -0
- package/src/i18n/index.ts +28 -0
- package/src/index.ts +35 -0
- package/src/json/JsonViewer.tsx +381 -0
- package/src/pagination/Pagination.tsx +157 -0
- package/src/table/BodyCell.tsx +54 -0
- package/src/table/HeaderCell.tsx +70 -0
- package/src/table/Table.tsx +143 -0
- package/src/table/types.ts +65 -0
- package/src/table/useTableColumns.ts +52 -0
- package/src/table/useVirtualTable.ts +54 -0
- package/src/tree/TreeNode.tsx +163 -0
- package/src/tree/TreePanel.tsx +157 -0
- package/src/tree/types.ts +181 -0
- package/src/tree/useTree.ts +227 -0
- package/src/tree/utils.ts +185 -0
- package/src/virtual/Gallery.tsx +349 -0
- package/src/virtual/List.tsx +351 -0
- package/src/virtual/Scroller.tsx +81 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
4
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
5
|
+
import { useDebounce } from '@react-fabric/core';
|
|
6
|
+
import { EMPTY_ARRAY } from '@react-fabric/utilities';
|
|
7
|
+
import memoizeOne from 'memoize-one';
|
|
8
|
+
import { useRef, useReducer, useEffect, useCallback } from 'react';
|
|
9
|
+
import { refactorTree, makeTreeMap, flattenTree, filterTree, updateSelection, updateChecked } from './utils.js';
|
|
10
|
+
|
|
11
|
+
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
|
+
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; }
|
|
13
|
+
var createItemList = memoizeOne(function (items) {
|
|
14
|
+
return items;
|
|
15
|
+
});
|
|
16
|
+
var useTree = function useTree(_ref) {
|
|
17
|
+
var _ref$items = _ref.items,
|
|
18
|
+
items = _ref$items === void 0 ? EMPTY_ARRAY : _ref$items,
|
|
19
|
+
_ref$checked = _ref.checked,
|
|
20
|
+
checked = _ref$checked === void 0 ? EMPTY_ARRAY : _ref$checked,
|
|
21
|
+
selected = _ref.selected,
|
|
22
|
+
matcher = _ref.matcher,
|
|
23
|
+
onSelect = _ref.onSelect,
|
|
24
|
+
onChecked = _ref.onChecked;
|
|
25
|
+
var componentEvents = useRef({
|
|
26
|
+
onSelect: onSelect,
|
|
27
|
+
onChecked: onChecked
|
|
28
|
+
});
|
|
29
|
+
var itemList = createItemList(items);
|
|
30
|
+
var _useReducer = useReducer(function (state, action) {
|
|
31
|
+
if (action.type === "load") {
|
|
32
|
+
state.items = refactorTree(action.items);
|
|
33
|
+
state.itemMap = makeTreeMap(state.items);
|
|
34
|
+
state.tree = flattenTree(state.items);
|
|
35
|
+
return _objectSpread({}, state);
|
|
36
|
+
}
|
|
37
|
+
if (action.type === "toggleExpand") {
|
|
38
|
+
var node = state.itemMap.get(action.id);
|
|
39
|
+
node && (node.open = !node.open);
|
|
40
|
+
state.tree = flattenTree(state.items);
|
|
41
|
+
return _objectSpread({}, state);
|
|
42
|
+
}
|
|
43
|
+
if (action.type === "expand") {
|
|
44
|
+
// TODO: check if children available, if not call onLoad to fetch node children
|
|
45
|
+
var _node = state.itemMap.get(action.id);
|
|
46
|
+
_node && (_node.open = true);
|
|
47
|
+
state.tree = flattenTree(state.items);
|
|
48
|
+
return _objectSpread({}, state);
|
|
49
|
+
}
|
|
50
|
+
if (action.type === "expandAll") {
|
|
51
|
+
// TODO: prevent opening dynamic nodes that dont have children
|
|
52
|
+
state.itemMap.forEach(function (node) {
|
|
53
|
+
!node.leaf && (node.open = true);
|
|
54
|
+
});
|
|
55
|
+
state.tree = flattenTree(state.items);
|
|
56
|
+
return _objectSpread({}, state);
|
|
57
|
+
}
|
|
58
|
+
if (action.type === "collapseAll") {
|
|
59
|
+
state.itemMap.forEach(function (node) {
|
|
60
|
+
!node.leaf && (node.open = false);
|
|
61
|
+
});
|
|
62
|
+
state.tree = flattenTree(state.items);
|
|
63
|
+
return _objectSpread({}, state);
|
|
64
|
+
}
|
|
65
|
+
if (action.type === "filter") {
|
|
66
|
+
filterTree(state.itemMap, action.query, matcher);
|
|
67
|
+
state.tree = flattenTree(state.items);
|
|
68
|
+
return _objectSpread({}, state);
|
|
69
|
+
}
|
|
70
|
+
if (action.type === "select") {
|
|
71
|
+
var _componentEvents$curr, _componentEvents$curr2;
|
|
72
|
+
if (state.selected) {
|
|
73
|
+
updateSelection(state.itemMap, state.selected);
|
|
74
|
+
}
|
|
75
|
+
updateSelection(state.itemMap, action.id, true);
|
|
76
|
+
state.tree = flattenTree(state.items);
|
|
77
|
+
(_componentEvents$curr = (_componentEvents$curr2 = componentEvents.current).onSelect) === null || _componentEvents$curr === void 0 || _componentEvents$curr.call(_componentEvents$curr2, action.id);
|
|
78
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
79
|
+
selected: action.id
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (action.type === "toggleCheck") {
|
|
83
|
+
var _componentEvents$curr3, _componentEvents$curr4;
|
|
84
|
+
updateChecked(state.itemMap, action.id);
|
|
85
|
+
var checkList = [[], []];
|
|
86
|
+
Array.from(state.itemMap.values()).filter(function (node) {
|
|
87
|
+
return node.checked === 1;
|
|
88
|
+
}).forEach(function (node) {
|
|
89
|
+
return checkList[node.leaf ? 0 : 1].push(node.id);
|
|
90
|
+
});
|
|
91
|
+
(_componentEvents$curr3 = (_componentEvents$curr4 = componentEvents.current).onChecked) === null || _componentEvents$curr3 === void 0 || _componentEvents$curr3.call(_componentEvents$curr4, checkList[0], checkList[1]);
|
|
92
|
+
return _objectSpread({}, state);
|
|
93
|
+
}
|
|
94
|
+
if (action.type === "checked") {
|
|
95
|
+
action.id.forEach(function (id) {
|
|
96
|
+
return updateChecked(state.itemMap, id);
|
|
97
|
+
});
|
|
98
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
99
|
+
checked: action.id
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return state;
|
|
103
|
+
}, {
|
|
104
|
+
itemMap: new Map(),
|
|
105
|
+
items: [],
|
|
106
|
+
tree: [],
|
|
107
|
+
checked: []
|
|
108
|
+
}),
|
|
109
|
+
_useReducer2 = _slicedToArray(_useReducer, 2),
|
|
110
|
+
state = _useReducer2[0],
|
|
111
|
+
dispatch = _useReducer2[1];
|
|
112
|
+
useEffect(function () {
|
|
113
|
+
componentEvents.current = {
|
|
114
|
+
onSelect: onSelect,
|
|
115
|
+
onChecked: onChecked
|
|
116
|
+
};
|
|
117
|
+
}, [onSelect, onChecked]);
|
|
118
|
+
useEffect(function () {
|
|
119
|
+
dispatch({
|
|
120
|
+
type: "load",
|
|
121
|
+
items: itemList
|
|
122
|
+
});
|
|
123
|
+
}, [itemList]);
|
|
124
|
+
useEffect(function () {
|
|
125
|
+
selected && dispatch({
|
|
126
|
+
type: "select",
|
|
127
|
+
id: selected
|
|
128
|
+
});
|
|
129
|
+
}, [selected]);
|
|
130
|
+
useEffect(function () {
|
|
131
|
+
checked && dispatch({
|
|
132
|
+
type: "checked",
|
|
133
|
+
id: checked
|
|
134
|
+
});
|
|
135
|
+
}, [checked]);
|
|
136
|
+
var toggleExpand = useCallback(function (id) {
|
|
137
|
+
dispatch({
|
|
138
|
+
type: "toggleExpand",
|
|
139
|
+
id: id
|
|
140
|
+
});
|
|
141
|
+
}, []);
|
|
142
|
+
var toggleCheck = useCallback(function (id) {
|
|
143
|
+
dispatch({
|
|
144
|
+
type: "toggleCheck",
|
|
145
|
+
id: id
|
|
146
|
+
});
|
|
147
|
+
}, []);
|
|
148
|
+
var select = useCallback(function (id) {
|
|
149
|
+
dispatch({
|
|
150
|
+
type: "select",
|
|
151
|
+
id: id
|
|
152
|
+
});
|
|
153
|
+
}, []);
|
|
154
|
+
var expandAll = useCallback(function () {
|
|
155
|
+
dispatch({
|
|
156
|
+
type: "expandAll"
|
|
157
|
+
});
|
|
158
|
+
}, []);
|
|
159
|
+
var collapseAll = useCallback(function () {
|
|
160
|
+
dispatch({
|
|
161
|
+
type: "collapseAll"
|
|
162
|
+
});
|
|
163
|
+
}, []);
|
|
164
|
+
var onFilter = useDebounce(function (query) {
|
|
165
|
+
dispatch({
|
|
166
|
+
type: "filter",
|
|
167
|
+
query: query
|
|
168
|
+
});
|
|
169
|
+
}, []);
|
|
170
|
+
return {
|
|
171
|
+
tree: state.tree,
|
|
172
|
+
toggleExpand: toggleExpand,
|
|
173
|
+
expandAll: expandAll,
|
|
174
|
+
collapseAll: collapseAll,
|
|
175
|
+
toggleCheck: toggleCheck,
|
|
176
|
+
select: select,
|
|
177
|
+
onFilter: onFilter
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export { useTree };
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
4
|
+
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
|
|
5
|
+
import { isString, matchString, compareValues } from '@react-fabric/utilities';
|
|
6
|
+
|
|
7
|
+
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; }
|
|
8
|
+
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; }
|
|
9
|
+
var sorter = function sorter(a, b) {
|
|
10
|
+
if (!!a.leaf !== !!b.leaf) return a.leaf ? 1 : -1;
|
|
11
|
+
return compareValues()(a.label, b.label);
|
|
12
|
+
};
|
|
13
|
+
var getChildren = function getChildren() {
|
|
14
|
+
var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
15
|
+
return list.map(function (item) {
|
|
16
|
+
return [item].concat(_toConsumableArray(getChildren(item.children)));
|
|
17
|
+
}).flat(99).filter(Boolean);
|
|
18
|
+
};
|
|
19
|
+
var getIntermediate = function getIntermediate() {
|
|
20
|
+
var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
21
|
+
var checks = list.map(function (item) {
|
|
22
|
+
return item.checked;
|
|
23
|
+
});
|
|
24
|
+
var someOff = checks.includes(0);
|
|
25
|
+
var someInt = checks.includes(2);
|
|
26
|
+
var someOn = checks.includes(1);
|
|
27
|
+
return someOff && someOn || someInt ? 2 : someOn ? 1 : 0;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// convert node item to internal node used by the tree
|
|
31
|
+
var refactorTree = function refactorTree(nodes) {
|
|
32
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
33
|
+
level: 0,
|
|
34
|
+
parent: undefined
|
|
35
|
+
};
|
|
36
|
+
var list = [];
|
|
37
|
+
nodes.sort(sorter).forEach(function (node) {
|
|
38
|
+
list.push(_objectSpread(_objectSpread({
|
|
39
|
+
open: false,
|
|
40
|
+
level: options.level,
|
|
41
|
+
parent: options.parent,
|
|
42
|
+
checked: 0,
|
|
43
|
+
loaded: false,
|
|
44
|
+
loading: false,
|
|
45
|
+
filtered: false,
|
|
46
|
+
lines: []
|
|
47
|
+
}, node), {}, {
|
|
48
|
+
leaf: !!node.leaf,
|
|
49
|
+
children: node.children && refactorTree(node.children, {
|
|
50
|
+
level: options.level + 1,
|
|
51
|
+
parent: node.id
|
|
52
|
+
})
|
|
53
|
+
}));
|
|
54
|
+
});
|
|
55
|
+
return list;
|
|
56
|
+
};
|
|
57
|
+
var makeTreeMap = function makeTreeMap(nodes) {
|
|
58
|
+
var map = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Map();
|
|
59
|
+
nodes.forEach(function (node) {
|
|
60
|
+
if (map.has(node.id)) throw new Error("Node with id [".concat(node.id, "] already exists, please make sure all ids are unique"));
|
|
61
|
+
map.set(node.id, node);
|
|
62
|
+
node.children && makeTreeMap(node.children, map);
|
|
63
|
+
});
|
|
64
|
+
return map;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// make flat list to be rendered by virtual list
|
|
68
|
+
var flattenTree = function flattenTree(nodes) {
|
|
69
|
+
var lines = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
70
|
+
var list = [];
|
|
71
|
+
var filtered = nodes.filter(function (node) {
|
|
72
|
+
return !node.filtered;
|
|
73
|
+
});
|
|
74
|
+
filtered.forEach(function (node, idx) {
|
|
75
|
+
node.lines = [].concat(_toConsumableArray(lines), [idx === filtered.length - 1 ? 2 : 3]);
|
|
76
|
+
list.push(node);
|
|
77
|
+
(node.open || node.childFiltered) && node.children && list.push.apply(list, _toConsumableArray(flattenTree(node.children.filter(function (child) {
|
|
78
|
+
return !child.filtered;
|
|
79
|
+
}), [].concat(_toConsumableArray(lines), [idx === filtered.length - 1 ? 0 : 1]))));
|
|
80
|
+
});
|
|
81
|
+
return list;
|
|
82
|
+
};
|
|
83
|
+
var updateSelection = function updateSelection(nodes, id, selected) {
|
|
84
|
+
var node = nodes.get(id);
|
|
85
|
+
if (node) {
|
|
86
|
+
// change selection
|
|
87
|
+
node.selected = selected;
|
|
88
|
+
// update all parent childSelected flag
|
|
89
|
+
var parent = node.parent;
|
|
90
|
+
while (parent) {
|
|
91
|
+
var parentNode = nodes.get(parent);
|
|
92
|
+
parentNode && (parentNode.childSelected = selected);
|
|
93
|
+
selected && parentNode && (parentNode.open = true);
|
|
94
|
+
parent = parentNode === null || parentNode === void 0 ? void 0 : parentNode.parent;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
var updateChecked = function updateChecked(list, id) {
|
|
99
|
+
var node = list.get(id);
|
|
100
|
+
if (node) {
|
|
101
|
+
node.checked = node.checked === 1 ? 0 : 1;
|
|
102
|
+
// check all children
|
|
103
|
+
node.children && getChildren(node.children).forEach(function (child) {
|
|
104
|
+
return child.checked = node.checked;
|
|
105
|
+
});
|
|
106
|
+
var parent = node.parent;
|
|
107
|
+
while (parent) {
|
|
108
|
+
var parentNode = list.get(parent);
|
|
109
|
+
parentNode && (parentNode.checked = getIntermediate(parentNode.children));
|
|
110
|
+
parent = parentNode === null || parentNode === void 0 ? void 0 : parentNode.parent;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var filterTree = function filterTree(nodes, query, matcher) {
|
|
115
|
+
nodes.forEach(function (node) {
|
|
116
|
+
if (query) {
|
|
117
|
+
if (node.parentFiltered) return;
|
|
118
|
+
node.filtered = !(matcher ? matcher(node.data, query) : isString(node.queryable) ? matchString(node.queryable, query) : isString(node.label) && matchString(node.label, query));
|
|
119
|
+
if (!node.filtered) {
|
|
120
|
+
var parent = node.parent;
|
|
121
|
+
while (parent) {
|
|
122
|
+
var parentNode = nodes.get(parent);
|
|
123
|
+
parentNode && (parentNode.filtered = false);
|
|
124
|
+
parentNode && (parentNode.childFiltered = true);
|
|
125
|
+
parent = parentNode === null || parentNode === void 0 ? void 0 : parentNode.parent;
|
|
126
|
+
}
|
|
127
|
+
node.children && getChildren(node.children).forEach(function (child) {
|
|
128
|
+
child.parentFiltered = true;
|
|
129
|
+
child.filtered = false;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
node.filtered = false;
|
|
134
|
+
node.childFiltered = undefined;
|
|
135
|
+
node.parentFiltered = undefined;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export { filterTree, flattenTree, makeTreeMap, refactorTree, updateChecked, updateSelection };
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
4
|
+
import { useEffectDebugger, useDebounce, Skeleton } from '@react-fabric/core';
|
|
5
|
+
import { debounce } from '@react-fabric/utilities';
|
|
6
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
7
|
+
import classNames from 'classnames';
|
|
8
|
+
import memoizeOne from 'memoize-one';
|
|
9
|
+
import { useDeferredValue, useMemo, useRef, useState, useEffect, useCallback, useLayoutEffect, useImperativeHandle, memo } from 'react';
|
|
10
|
+
import { Scroller } from './Scroller.js';
|
|
11
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
12
|
+
|
|
13
|
+
var createItemList = memoizeOne(function (items) {
|
|
14
|
+
return items;
|
|
15
|
+
});
|
|
16
|
+
var _VirtualGallery = function _VirtualGallery(_ref) {
|
|
17
|
+
var _virtualItems$3;
|
|
18
|
+
var items = _ref.items,
|
|
19
|
+
children = _ref.children,
|
|
20
|
+
columns = _ref.columns,
|
|
21
|
+
_ref$padding = _ref.padding,
|
|
22
|
+
padding = _ref$padding === void 0 ? "md" : _ref$padding,
|
|
23
|
+
_ref$defaultHeight = _ref.defaultHeight,
|
|
24
|
+
height = _ref$defaultHeight === void 0 ? 48 : _ref$defaultHeight,
|
|
25
|
+
_ref$defaultWidth = _ref.defaultWidth,
|
|
26
|
+
width = _ref$defaultWidth === void 0 ? 48 : _ref$defaultWidth,
|
|
27
|
+
hideScroller = _ref.hideScroller,
|
|
28
|
+
initialScroll = _ref.initialScroll,
|
|
29
|
+
loading = _ref.loading,
|
|
30
|
+
onLoadMore = _ref.onLoadMore,
|
|
31
|
+
onScroll = _ref.onScroll,
|
|
32
|
+
galleryRef = _ref.galleryRef;
|
|
33
|
+
var count = useDeferredValue(items.length);
|
|
34
|
+
var extraSize = useMemo(function () {
|
|
35
|
+
return onLoadMore ? 64 : 0;
|
|
36
|
+
}, [onLoadMore]);
|
|
37
|
+
var itemList = createItemList(items.map(function (item, idx) {
|
|
38
|
+
return {
|
|
39
|
+
index: idx,
|
|
40
|
+
data: item,
|
|
41
|
+
isLast: idx + 1 === items.length
|
|
42
|
+
};
|
|
43
|
+
}));
|
|
44
|
+
var scrollerRef = useRef(null);
|
|
45
|
+
var _useState = useState(1),
|
|
46
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
47
|
+
columnCount = _useState2[0],
|
|
48
|
+
setColumnCount = _useState2[1];
|
|
49
|
+
var columnMap = useMemo(function () {
|
|
50
|
+
return new Array(columnCount).fill(0).map(function (_, idx) {
|
|
51
|
+
return idx;
|
|
52
|
+
});
|
|
53
|
+
}, [columnCount]);
|
|
54
|
+
useEffectDebugger(function () {
|
|
55
|
+
if (scrollerRef.current) {
|
|
56
|
+
var el = scrollerRef.current;
|
|
57
|
+
var handler = function handler() {
|
|
58
|
+
var _el$offsetWidth;
|
|
59
|
+
setColumnCount(columns !== null && columns !== void 0 ? columns : Math.max(1, Math.floor((((_el$offsetWidth = el === null || el === void 0 ? void 0 : el.offsetWidth) !== null && _el$offsetWidth !== void 0 ? _el$offsetWidth : 800) - 32) / width)));
|
|
60
|
+
};
|
|
61
|
+
var ob = new ResizeObserver(handler);
|
|
62
|
+
handler();
|
|
63
|
+
ob.observe(el);
|
|
64
|
+
return function () {
|
|
65
|
+
ob.unobserve(el);
|
|
66
|
+
ob.disconnect();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}, [scrollerRef.current, columns, width], "virtualGallery recalculate view count");
|
|
70
|
+
var virtualizer = useVirtualizer({
|
|
71
|
+
count: Math.ceil(count / columnCount),
|
|
72
|
+
getScrollElement: function getScrollElement() {
|
|
73
|
+
return scrollerRef.current;
|
|
74
|
+
},
|
|
75
|
+
estimateSize: function estimateSize() {
|
|
76
|
+
return height;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
var virtualItems = virtualizer.getVirtualItems();
|
|
80
|
+
var currentIndex = useRef(0);
|
|
81
|
+
useEffect(function () {
|
|
82
|
+
var _virtualItems$1$index, _virtualItems$;
|
|
83
|
+
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;
|
|
84
|
+
if (scrollerRef.current && virtualItems[0] && scrollerRef.current.scrollTop < virtualItems[0].size) currentIndex.current = 0;
|
|
85
|
+
}, [virtualItems]);
|
|
86
|
+
var calculateActiveScroll = useCallback(function () {
|
|
87
|
+
var _scrollerRef$current;
|
|
88
|
+
var _ref2 = (_scrollerRef$current = scrollerRef.current) !== null && _scrollerRef$current !== void 0 ? _scrollerRef$current : {},
|
|
89
|
+
_ref2$scrollTop = _ref2.scrollTop,
|
|
90
|
+
scrollTop = _ref2$scrollTop === void 0 ? 0 : _ref2$scrollTop,
|
|
91
|
+
_ref2$scrollHeight = _ref2.scrollHeight,
|
|
92
|
+
scrollHeight = _ref2$scrollHeight === void 0 ? 0 : _ref2$scrollHeight,
|
|
93
|
+
_ref2$offsetHeight = _ref2.offsetHeight,
|
|
94
|
+
offsetHeight = _ref2$offsetHeight === void 0 ? 0 : _ref2$offsetHeight;
|
|
95
|
+
if (scrollHeight === offsetHeight) return 0;
|
|
96
|
+
if (scrollTop === 0) return 1;
|
|
97
|
+
if (scrollTop >= scrollHeight - offsetHeight - extraSize * 2) return 2;
|
|
98
|
+
return 3;
|
|
99
|
+
}, []);
|
|
100
|
+
var _useState3 = useState(0),
|
|
101
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
102
|
+
scrollActive = _useState4[0],
|
|
103
|
+
setScrollActive = _useState4[1];
|
|
104
|
+
var fireScrollEvent = useDebounce(function (idx) {
|
|
105
|
+
return onScroll === null || onScroll === void 0 ? void 0 : onScroll(currentIndex.current * idx);
|
|
106
|
+
}, [onScroll]);
|
|
107
|
+
var handleScroll = useCallback(function () {
|
|
108
|
+
setScrollActive(calculateActiveScroll());
|
|
109
|
+
fireScrollEvent(columnCount);
|
|
110
|
+
}, [columnCount, onLoadMore]);
|
|
111
|
+
useEffect(function () {
|
|
112
|
+
setScrollActive(calculateActiveScroll());
|
|
113
|
+
}, [count, calculateActiveScroll]);
|
|
114
|
+
useEffect(function () {
|
|
115
|
+
var db = debounce(function () {
|
|
116
|
+
var lastItem = virtualItems === null || virtualItems === void 0 ? void 0 : virtualItems.slice(-1).pop();
|
|
117
|
+
if (lastItem && !loading && lastItem.index * columnCount + columnCount >= count - 1) onLoadMore === null || onLoadMore === void 0 || onLoadMore();
|
|
118
|
+
});
|
|
119
|
+
db();
|
|
120
|
+
return function () {
|
|
121
|
+
return db.cancel();
|
|
122
|
+
};
|
|
123
|
+
}, [onLoadMore, loading, itemList, virtualItems, count, columnCount]);
|
|
124
|
+
useEffect(function () {
|
|
125
|
+
var _virtualItems$2;
|
|
126
|
+
var firstItem = (_virtualItems$2 = virtualItems[0]) === null || _virtualItems$2 === void 0 ? void 0 : _virtualItems$2.index;
|
|
127
|
+
if (onLoadMore && firstItem !== undefined && items[firstItem * columnCount] === null) {
|
|
128
|
+
var db = debounce(onLoadMore);
|
|
129
|
+
db(firstItem * columnCount);
|
|
130
|
+
return function () {
|
|
131
|
+
return db.cancel();
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}, [onLoadMore, items, columnCount, virtualItems, count]);
|
|
135
|
+
useLayoutEffect(function () {
|
|
136
|
+
setTimeout(function () {
|
|
137
|
+
initialScroll && virtualizer.scrollToIndex(Math.floor(initialScroll / columnCount), {
|
|
138
|
+
align: "start"
|
|
139
|
+
});
|
|
140
|
+
}, 100);
|
|
141
|
+
}, [columnCount]);
|
|
142
|
+
useImperativeHandle(galleryRef, function () {
|
|
143
|
+
return {
|
|
144
|
+
scrollToItem: function scrollToItem(index) {
|
|
145
|
+
virtualizer.scrollToIndex(Math.floor(index / columnCount), {
|
|
146
|
+
align: "start"
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
hilight: function hilight(index) {
|
|
150
|
+
var _scrollerRef$current2;
|
|
151
|
+
(_scrollerRef$current2 = scrollerRef.current) === null || _scrollerRef$current2 === void 0 || (_scrollerRef$current2 = _scrollerRef$current2.querySelector(".hilight")) === null || _scrollerRef$current2 === void 0 || _scrollerRef$current2.classList.remove("hilight", "ring-1");
|
|
152
|
+
virtualizer.scrollToIndex(Math.floor(index / columnCount), {
|
|
153
|
+
align: "start"
|
|
154
|
+
});
|
|
155
|
+
setTimeout(function () {
|
|
156
|
+
var _scrollerRef$current3;
|
|
157
|
+
(_scrollerRef$current3 = scrollerRef.current) === null || _scrollerRef$current3 === void 0 || (_scrollerRef$current3 = _scrollerRef$current3.querySelector("[data-index=\"".concat(index, "\"]"))) === null || _scrollerRef$current3 === void 0 || _scrollerRef$current3.classList.add("hilight", "ring-1");
|
|
158
|
+
}, 100);
|
|
159
|
+
},
|
|
160
|
+
unhilight: function unhilight() {
|
|
161
|
+
var _scrollerRef$current4;
|
|
162
|
+
(_scrollerRef$current4 = scrollerRef.current) === null || _scrollerRef$current4 === void 0 || (_scrollerRef$current4 = _scrollerRef$current4.querySelector(".hilight")) === null || _scrollerRef$current4 === void 0 || _scrollerRef$current4.classList.remove("hilight", "ring-1");
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}, [virtualizer, columnCount]);
|
|
166
|
+
return /*#__PURE__*/jsx("div", {
|
|
167
|
+
ref: scrollerRef,
|
|
168
|
+
onScroll: handleScroll,
|
|
169
|
+
className: classNames("area-content bg-base overflow-auto contain-strict"),
|
|
170
|
+
children: /*#__PURE__*/jsxs("div", {
|
|
171
|
+
className: classNames("inline-flex flex-nowrap gap-2 justify-center min-h-full min-w-full"),
|
|
172
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
173
|
+
className: classNames("box-content", padding === "sm" && "p-1", padding === "md" && "p-2", padding === "lg" && "p-4"),
|
|
174
|
+
children: /*#__PURE__*/jsxs("div", {
|
|
175
|
+
style: {
|
|
176
|
+
height: virtualizer.getTotalSize()
|
|
177
|
+
},
|
|
178
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
179
|
+
style: {
|
|
180
|
+
height: (_virtualItems$3 = virtualItems[0]) === null || _virtualItems$3 === void 0 ? void 0 : _virtualItems$3.start
|
|
181
|
+
}
|
|
182
|
+
}), virtualItems.map(function (_ref3) {
|
|
183
|
+
var key = _ref3.key,
|
|
184
|
+
index = _ref3.index,
|
|
185
|
+
measureElement = _ref3.measureElement;
|
|
186
|
+
return /*#__PURE__*/jsx("div", {
|
|
187
|
+
className: "flex",
|
|
188
|
+
"data-index": index,
|
|
189
|
+
ref: measureElement,
|
|
190
|
+
children: columnMap.map(function (col) {
|
|
191
|
+
return /*#__PURE__*/jsx("div", {
|
|
192
|
+
"data-index": index * columnCount + col,
|
|
193
|
+
className: classNames("grid rounded-capped"),
|
|
194
|
+
children: itemList[index * columnCount + col] && children(itemList[index * columnCount + col])
|
|
195
|
+
}, "".concat(key, ":").concat(col));
|
|
196
|
+
})
|
|
197
|
+
}, key);
|
|
198
|
+
}), onLoadMore && /*#__PURE__*/jsx("div", {
|
|
199
|
+
className: "h-16",
|
|
200
|
+
children: loading && /*#__PURE__*/jsx(Skeleton, {})
|
|
201
|
+
})]
|
|
202
|
+
})
|
|
203
|
+
}), !hideScroller && /*#__PURE__*/jsx("div", {
|
|
204
|
+
className: classNames("self-end sticky bottom-2"),
|
|
205
|
+
children: /*#__PURE__*/jsx(Scroller, {
|
|
206
|
+
vertical: true,
|
|
207
|
+
scrollActive: scrollActive,
|
|
208
|
+
onStart: function onStart() {
|
|
209
|
+
return virtualizer.scrollToIndex(0);
|
|
210
|
+
},
|
|
211
|
+
onPrevious: function onPrevious() {
|
|
212
|
+
return scrollerRef.current && virtualizer.scrollBy(-scrollerRef.current.offsetHeight);
|
|
213
|
+
},
|
|
214
|
+
onNext: function onNext() {
|
|
215
|
+
return scrollerRef.current && virtualizer.scrollBy(scrollerRef.current.offsetHeight);
|
|
216
|
+
},
|
|
217
|
+
onEnd: function onEnd() {
|
|
218
|
+
return virtualizer.scrollToIndex(count - 1);
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
})]
|
|
222
|
+
})
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
_VirtualGallery.displayName = "VirtualGallery";
|
|
226
|
+
var GenericMemo = memo;
|
|
227
|
+
var VirtualGallery = GenericMemo(_VirtualGallery);
|
|
228
|
+
|
|
229
|
+
export { VirtualGallery };
|