@zidian-primitive/cascader 0.2.1 → 0.3.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/esm/components/node/CascaderNode.js +27 -18
- package/esm/components/root/CascaderRoot.js +2 -4
- package/esm/context/index.js +1 -2
- package/esm/hooks/useCascader.js +95 -34
- package/esm/index.js +1 -3
- package/esm/utils/data.js +14 -22
- package/esm/utils/logic.js +38 -6
- package/lib/components/index.d.ts +0 -2
- package/lib/components/root/CascaderRoot.d.ts +2 -2
- package/lib/context/index.d.ts +2 -2
- package/lib/hooks/useCascader.d.ts +4 -4
- package/lib/index.d.ts +2 -1
- package/lib/types/index.d.ts +20 -9
- package/lib/utils/data.d.ts +12 -0
- package/lib/utils/logic.d.ts +15 -3
- package/package.json +1 -1
- package/src/index.ts +2 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { useContext, useRef, useCallback, useEffect } from 'react';
|
|
2
|
+
import { memo, useContext, useRef, useCallback, useEffect } from 'react';
|
|
3
3
|
import { CascaderContext, CascaderPanelContext } from '../../context/index.js';
|
|
4
|
+
import { getNextStatus } from '../../utils/logic.js';
|
|
4
5
|
|
|
5
|
-
const CascaderNode = (props) => {
|
|
6
|
+
const CascaderNode = memo((props) => {
|
|
6
7
|
const {
|
|
7
8
|
node,
|
|
8
9
|
isLeaf,
|
|
@@ -12,7 +13,7 @@ const CascaderNode = (props) => {
|
|
|
12
13
|
render,
|
|
13
14
|
...elementProps
|
|
14
15
|
} = props;
|
|
15
|
-
const {
|
|
16
|
+
const { setNodeCheckStatus } = useContext(CascaderContext);
|
|
16
17
|
const { showIndicator, registerNode } = useContext(CascaderPanelContext);
|
|
17
18
|
const nodeRef = useRef(null);
|
|
18
19
|
const handleRef = useCallback((el) => {
|
|
@@ -24,26 +25,34 @@ const CascaderNode = (props) => {
|
|
|
24
25
|
const handleClick = (event) => {
|
|
25
26
|
if (isLeaf) {
|
|
26
27
|
if (onClick) onClick(node);
|
|
27
|
-
if (onTrigger) onTrigger(node.level, node.indices);
|
|
28
|
-
} else {
|
|
29
|
-
if (onTrigger) onTrigger(node.level, node.indices);
|
|
30
28
|
}
|
|
29
|
+
if (onTrigger) onTrigger(node.level, node.indices);
|
|
31
30
|
};
|
|
32
31
|
useEffect(() => {
|
|
33
|
-
if (isActive
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
if (!isActive || !nodeRef.current) return;
|
|
33
|
+
const node2 = nodeRef.current;
|
|
34
|
+
const parent = node2.parentElement;
|
|
35
|
+
if (!parent) return;
|
|
36
|
+
const nodeTop = node2.offsetTop;
|
|
37
|
+
const nodeBottom = nodeTop + node2.offsetHeight;
|
|
38
|
+
const viewTop = parent.scrollTop;
|
|
39
|
+
const viewBottom = viewTop + parent.clientHeight;
|
|
40
|
+
if (nodeTop < viewTop) {
|
|
41
|
+
parent.scrollTo({
|
|
42
|
+
top: nodeTop,
|
|
43
|
+
behavior: "smooth"
|
|
44
|
+
});
|
|
45
|
+
} else if (nodeBottom > viewBottom) {
|
|
46
|
+
parent.scrollTo({
|
|
47
|
+
top: nodeBottom - parent.clientHeight,
|
|
48
|
+
behavior: "smooth"
|
|
42
49
|
});
|
|
43
|
-
return () => cancelAnimationFrame(timer);
|
|
44
50
|
}
|
|
45
51
|
}, [isActive]);
|
|
46
|
-
return /* @__PURE__ */ jsx("div", { ref: handleRef, onClick: handleClick, "data-active": isActive, ...elementProps, children: render ? render({
|
|
52
|
+
return /* @__PURE__ */ jsx("div", { ref: handleRef, onClick: handleClick, "data-active": isActive ? isActive : void 0, ...elementProps, children: render ? render({
|
|
53
|
+
node,
|
|
54
|
+
handleToggleSelect: (node?.checkStatus || node.checkStatus === 0) && setNodeCheckStatus ? (nodeIdx) => setNodeCheckStatus(nodeIdx, getNextStatus(node.checkStatus)) : void 0
|
|
55
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
47
56
|
/* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: node.label }),
|
|
48
57
|
!isLeaf && /* @__PURE__ */ jsx(
|
|
49
58
|
"svg",
|
|
@@ -58,7 +67,7 @@ const CascaderNode = (props) => {
|
|
|
58
67
|
}
|
|
59
68
|
)
|
|
60
69
|
] }) });
|
|
61
|
-
};
|
|
70
|
+
});
|
|
62
71
|
CascaderNode.displayName = "CascaderNode";
|
|
63
72
|
|
|
64
73
|
export { CascaderNode };
|
|
@@ -5,15 +5,13 @@ import { CascaderContext } from '../../context/index.js';
|
|
|
5
5
|
const CascaderRoot = forwardRef((props, ref) => {
|
|
6
6
|
const {
|
|
7
7
|
isSelected = false,
|
|
8
|
-
selectType,
|
|
9
|
-
onSelectChange,
|
|
10
8
|
children,
|
|
9
|
+
setNodeCheckStatus,
|
|
11
10
|
...elementProps
|
|
12
11
|
} = props;
|
|
13
12
|
return /* @__PURE__ */ jsx(CascaderContext.Provider, { value: {
|
|
14
13
|
isSelected,
|
|
15
|
-
|
|
16
|
-
onSelectChange
|
|
14
|
+
setNodeCheckStatus
|
|
17
15
|
}, children: /* @__PURE__ */ jsx("div", { ref, ...elementProps, children }) });
|
|
18
16
|
});
|
|
19
17
|
CascaderRoot.displayName = "CascaderRoot";
|
package/esm/context/index.js
CHANGED
package/esm/hooks/useCascader.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useMemo, useCallback, useState, useEffect } from 'react';
|
|
2
|
+
import { changeMultipleNodeStatus, CHECK_ALL, changeSelected, changeNodeStatus } from '../utils/logic.js';
|
|
2
3
|
import { buildCascaderEngine, getShowPath, getCascadeColumns, changeShowPath } from '../utils/data.js';
|
|
3
|
-
import { setMultipleNodeStatus, setNodeCheckStatus } from '../utils/logic.js';
|
|
4
4
|
|
|
5
5
|
function useCascader(options) {
|
|
6
|
-
const { data, handleDataConfig, selectOption,
|
|
6
|
+
const { data, handleDataConfig, selectOption, pathOption } = options;
|
|
7
7
|
const sortedData = useMemo(() => {
|
|
8
8
|
return [...data].sort((a, b) => {
|
|
9
9
|
for (const field of handleDataConfig.levels) {
|
|
@@ -16,48 +16,109 @@ function useCascader(options) {
|
|
|
16
16
|
const sourceNodeData = useMemo(() => {
|
|
17
17
|
return buildCascaderEngine(sortedData, handleDataConfig);
|
|
18
18
|
}, [sortedData, handleDataConfig]);
|
|
19
|
-
const
|
|
19
|
+
const showConfig = useMemo(() => {
|
|
20
|
+
return pathOption?.showConfig ? pathOption.showConfig : { depth: handleDataConfig.levels.length - 1, showType: "label" };
|
|
21
|
+
}, [pathOption?.showConfig]);
|
|
22
|
+
const selectValueType = useMemo(() => selectOption?.valueType ?? "label", [selectOption?.valueType]);
|
|
23
|
+
const getStatusByOption = useCallback((sourceNodeData2, selected) => {
|
|
20
24
|
const statusArray = new Uint8Array(sourceNodeData2.length);
|
|
21
|
-
if (
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (selected) {
|
|
26
|
+
const levels = handleDataConfig.levels;
|
|
27
|
+
const selectIndices = [];
|
|
28
|
+
for (let node of sourceNodeData2) {
|
|
29
|
+
if (node.depth === levels.length - 1 && selected.includes(node[selectValueType])) {
|
|
30
|
+
selectIndices.push(node.index);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return changeMultipleNodeStatus(sourceNodeData2, selectIndices, CHECK_ALL, statusArray);
|
|
28
34
|
}
|
|
29
35
|
return statusArray;
|
|
30
|
-
}, [
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}, [
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
}, [selectValueType, handleDataConfig]);
|
|
37
|
+
const getPathByOption = useCallback((sourceNodeData2, value) => {
|
|
38
|
+
return getShowPath(
|
|
39
|
+
sourceNodeData2,
|
|
40
|
+
sourceNodeData2.find((node) => showConfig.depth === node.depth && node[showConfig.showType] === value)
|
|
41
|
+
);
|
|
42
|
+
}, [showConfig]);
|
|
43
|
+
const isControlled = useMemo(() => pathOption?.showValue || pathOption?.showValue === 0, [pathOption?.showValue]);
|
|
44
|
+
const initialPath = useMemo(() => getPathByOption(
|
|
45
|
+
sourceNodeData,
|
|
46
|
+
pathOption?.showValue ?? pathOption?.defaultShowValue
|
|
47
|
+
), [sourceNodeData, pathOption?.defaultShowValue, pathOption?.showValue]);
|
|
48
|
+
const initialSelected = useMemo(() => new Set(
|
|
49
|
+
selectOption?.selected ?? selectOption?.defaultSelected
|
|
50
|
+
), [selectOption?.selected, selectOption?.defaultSelected]);
|
|
51
|
+
const initialStatusArray = useMemo(() => getStatusByOption(
|
|
52
|
+
sourceNodeData,
|
|
53
|
+
selectOption?.selected ?? selectOption?.defaultSelected
|
|
54
|
+
), [sourceNodeData]);
|
|
55
|
+
const [internalPath, setInternalPath] = useState(initialPath);
|
|
56
|
+
const [internalSelected, setInternalSelected] = useState(initialSelected);
|
|
57
|
+
const [checkStatusArray, setCheckStatusArray] = useState(initialStatusArray);
|
|
58
|
+
const path = useMemo(() => isControlled ? initialPath : internalPath, [sourceNodeData, internalPath, isControlled]);
|
|
59
|
+
const columns = useMemo(() => getCascadeColumns(sourceNodeData, path), [sourceNodeData, initialPath, path]);
|
|
60
|
+
const handleChangePath = useCallback((depth, index) => {
|
|
61
|
+
if (pathOption?.onShowValueChange && depth === showConfig.depth) {
|
|
62
|
+
pathOption.onShowValueChange(sourceNodeData[index][showConfig.showType], depth);
|
|
63
|
+
}
|
|
64
|
+
if (pathOption?.showValue !== 0 && !pathOption?.showValue) {
|
|
65
|
+
setInternalPath(changeShowPath(
|
|
66
|
+
sourceNodeData,
|
|
67
|
+
{ oldPath: path, action: { depth, nodeIdx: index } }
|
|
68
|
+
));
|
|
69
|
+
}
|
|
70
|
+
}, [pathOption, sourceNodeData]);
|
|
71
|
+
const handleChangeCheckStatus = useCallback((nodeIdx, checkStatus) => {
|
|
72
|
+
if (selectOption) {
|
|
73
|
+
if (selectOption?.selected) {
|
|
74
|
+
const newSelectSet = changeSelected(
|
|
75
|
+
checkStatus,
|
|
76
|
+
sourceNodeData,
|
|
77
|
+
nodeIdx,
|
|
78
|
+
initialSelected,
|
|
79
|
+
selectValueType
|
|
80
|
+
);
|
|
81
|
+
if (selectOption?.onSelectedChange) selectOption.onSelectedChange(Array.from(newSelectSet));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (selectOption?.defaultSelected) {
|
|
85
|
+
const newSelectSet = changeSelected(
|
|
86
|
+
checkStatus,
|
|
87
|
+
sourceNodeData,
|
|
88
|
+
nodeIdx,
|
|
89
|
+
internalSelected,
|
|
90
|
+
selectValueType
|
|
91
|
+
);
|
|
92
|
+
setInternalSelected(newSelectSet);
|
|
93
|
+
setCheckStatusArray(changeNodeStatus(sourceNodeData, checkStatusArray, nodeIdx, checkStatus));
|
|
94
|
+
if (selectOption?.onSelectedChange) selectOption.onSelectedChange(Array.from(newSelectSet));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}, [selectOption, sourceNodeData, checkStatusArray, selectValueType]);
|
|
47
98
|
useEffect(() => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
99
|
+
setInternalPath(initialPath);
|
|
100
|
+
setInternalSelected(initialSelected);
|
|
101
|
+
setCheckStatusArray(initialStatusArray);
|
|
51
102
|
}, [data]);
|
|
52
103
|
useEffect(() => {
|
|
53
|
-
if (
|
|
54
|
-
|
|
104
|
+
if (selectOption?.selected) {
|
|
105
|
+
setCheckStatusArray(initialStatusArray);
|
|
106
|
+
}
|
|
107
|
+
}, [selectOption?.selected]);
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (pathOption?.defaultShowValue) {
|
|
110
|
+
setInternalPath(initialPath);
|
|
111
|
+
}
|
|
112
|
+
}, [pathOption?.defaultShowValue]);
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (selectOption?.defaultSelected) {
|
|
115
|
+
setInternalSelected(initialSelected);
|
|
55
116
|
}
|
|
56
|
-
}, [
|
|
117
|
+
}, [selectOption?.defaultSelected]);
|
|
57
118
|
return {
|
|
119
|
+
path,
|
|
58
120
|
nodes: sourceNodeData,
|
|
59
121
|
columns,
|
|
60
|
-
path,
|
|
61
122
|
checkStatusArray,
|
|
62
123
|
handleChangePath,
|
|
63
124
|
handleChangeCheckStatus
|
package/esm/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export { CascaderRoot } from './components/root/CascaderRoot.js';
|
|
2
2
|
export { CascaderNode } from './components/node/CascaderNode.js';
|
|
3
|
-
export { CascaderNodeCheck } from './components/node/CascaderNodeCheck.js';
|
|
4
3
|
export { CascaderPanel } from './components/panel/CascaderPanel.js';
|
|
5
|
-
export { CascaderPanelHeader } from './components/panel/CascaderPanelHeader.js';
|
|
6
4
|
export { CascaderPanelIndicator } from './components/panel/CascaderPanelIndicator.js';
|
|
7
5
|
export { useCascader } from './hooks/useCascader.js';
|
|
8
6
|
export { buildCascaderEngine, changeShowPath, getCascadeColumns, getShowPath } from './utils/data.js';
|
|
9
|
-
export {
|
|
7
|
+
export { CHECK_ALL, CHECK_INDETERMINATE, CHECK_NONE, changeMultipleNodeStatus, changeNodeStatus, changeSelected, changeSelectedPatch, getNextStatus } from './utils/logic.js';
|
package/esm/utils/data.js
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
function createCascaderNode(option) {
|
|
2
|
-
const { depth, currentIndex, parentIndex, row, label, value, pathId } = option;
|
|
3
|
-
return {
|
|
4
|
-
depth,
|
|
5
|
-
index: currentIndex,
|
|
6
|
-
parentIndex,
|
|
7
|
-
range: [currentIndex, currentIndex],
|
|
8
|
-
childrenIndices: [],
|
|
9
|
-
pathId,
|
|
10
|
-
label,
|
|
11
|
-
value,
|
|
12
|
-
raw: row
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
1
|
function buildCascaderEngine(data, config) {
|
|
16
2
|
let currentIndex = 0;
|
|
17
3
|
const currentConfig = config;
|
|
@@ -39,16 +25,17 @@ function buildCascaderEngine(data, config) {
|
|
|
39
25
|
if (nodeIdx === void 0) {
|
|
40
26
|
nodeIdx = currentIndex++;
|
|
41
27
|
nodeMap.set(currentPathId, nodeIdx);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
parentIndex,
|
|
45
|
-
currentIndex: nodeIdx,
|
|
46
|
-
pathId: currentPathId,
|
|
47
|
-
depth: levelIndex,
|
|
28
|
+
nodes[nodeIdx] = {
|
|
29
|
+
nodeId: currentPathId,
|
|
48
30
|
label,
|
|
49
31
|
value,
|
|
50
|
-
|
|
51
|
-
|
|
32
|
+
index: nodeIdx,
|
|
33
|
+
parentIndex,
|
|
34
|
+
depth: levelIndex,
|
|
35
|
+
range: [nodeIdx, nodeIdx],
|
|
36
|
+
childrenIndices: [],
|
|
37
|
+
data: item
|
|
38
|
+
};
|
|
52
39
|
if (parentIndex !== -1) {
|
|
53
40
|
nodes[parentIndex].childrenIndices.push(nodeIdx);
|
|
54
41
|
}
|
|
@@ -94,11 +81,16 @@ function getShowPath(nodes, targetNode) {
|
|
|
94
81
|
let showPath = [];
|
|
95
82
|
if (targetNode) {
|
|
96
83
|
let parentNode = targetNode;
|
|
84
|
+
let childNode = targetNode.childrenIndices[0] ? nodes[targetNode.childrenIndices[0]] : null;
|
|
97
85
|
showPath = new Array((targetNode?.depth ?? 0) + 1);
|
|
98
86
|
while (parentNode) {
|
|
99
87
|
showPath[parentNode.depth] = parentNode.index;
|
|
100
88
|
parentNode = parentNode.parentIndex !== -1 ? nodes[parentNode.parentIndex] : void 0;
|
|
101
89
|
}
|
|
90
|
+
while (childNode) {
|
|
91
|
+
showPath[childNode.depth] = childNode.index;
|
|
92
|
+
childNode = childNode.childrenIndices[0] ? childNode : null;
|
|
93
|
+
}
|
|
102
94
|
return showPath;
|
|
103
95
|
}
|
|
104
96
|
while (currentNode) {
|
package/esm/utils/logic.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const CHECK_NONE = 0;
|
|
2
2
|
const CHECK_ALL = 1;
|
|
3
3
|
const CHECK_INDETERMINATE = 2;
|
|
4
|
+
const getNextStatus = (curCheckStatus) => {
|
|
5
|
+
return curCheckStatus === CHECK_ALL ? CHECK_NONE : curCheckStatus === CHECK_INDETERMINATE ? CHECK_NONE : CHECK_ALL;
|
|
6
|
+
};
|
|
4
7
|
function propagateToChildren(statusArray, range, status) {
|
|
5
8
|
const [start, end] = range;
|
|
6
9
|
statusArray.fill(status, start, end + 1);
|
|
@@ -29,11 +32,10 @@ function propagateToParents(nodes, statusArray, childIndex) {
|
|
|
29
32
|
propagateToParents(nodes, statusArray, parentIdx);
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
|
-
function
|
|
33
|
-
const nextStatus = new Uint8Array(currentStatusArray);
|
|
35
|
+
function changeNodeStatus(nodes, currentStatusArray, nodeIndex, checkStatus) {
|
|
34
36
|
const targetNode = nodes[nodeIndex];
|
|
35
|
-
const
|
|
36
|
-
propagateToChildren(nextStatus, targetNode.range,
|
|
37
|
+
const nextStatus = new Uint8Array(currentStatusArray);
|
|
38
|
+
propagateToChildren(nextStatus, targetNode.range, checkStatus);
|
|
37
39
|
propagateToParents(nodes, nextStatus, nodeIndex);
|
|
38
40
|
return nextStatus;
|
|
39
41
|
}
|
|
@@ -57,7 +59,7 @@ function syncUpPath(nodes, statusArray, parentIdx) {
|
|
|
57
59
|
currIdx = node.parentIndex;
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
|
-
function
|
|
62
|
+
function changeMultipleNodeStatus(nodes, indices, targetStatus, currentStatusArray) {
|
|
61
63
|
const nextStatus = new Uint8Array(currentStatusArray);
|
|
62
64
|
const parentsToSync = /* @__PURE__ */ new Set();
|
|
63
65
|
indices.forEach((index) => {
|
|
@@ -75,5 +77,35 @@ function setMultipleNodeStatus(nodes, currentStatusArray, indices, targetStatus)
|
|
|
75
77
|
});
|
|
76
78
|
return nextStatus;
|
|
77
79
|
}
|
|
80
|
+
function changeSelectedPatch(nodes, indices, isChecked, currentSet) {
|
|
81
|
+
const nextSet = new Set(currentSet);
|
|
82
|
+
indices.forEach((idx) => {
|
|
83
|
+
const node = nodes[idx];
|
|
84
|
+
const [start, end] = node.range;
|
|
85
|
+
for (let i = start; i <= end; i++) {
|
|
86
|
+
if (nodes[i].childrenIndices.length === 0) {
|
|
87
|
+
if (isChecked) nextSet.add(nodes[i].index);
|
|
88
|
+
else nextSet.delete(nodes[i].index);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return nextSet;
|
|
93
|
+
}
|
|
94
|
+
function changeSelected(checkStatus, nodes, nodeIdx, currentSet, selectValueType) {
|
|
95
|
+
const nextSet = new Set(currentSet);
|
|
96
|
+
const targetNode = nodes[nodeIdx];
|
|
97
|
+
const [start, end] = targetNode.range;
|
|
98
|
+
for (let i = start; i <= end; i++) {
|
|
99
|
+
const node = nodes[i];
|
|
100
|
+
if (node.childrenIndices.length === 0) {
|
|
101
|
+
if (checkStatus === CHECK_ALL) {
|
|
102
|
+
nextSet.add(node[selectValueType]);
|
|
103
|
+
} else if (checkStatus === CHECK_NONE) {
|
|
104
|
+
nextSet.delete(node[selectValueType]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return nextSet;
|
|
109
|
+
}
|
|
78
110
|
|
|
79
|
-
export {
|
|
111
|
+
export { CHECK_ALL, CHECK_INDETERMINATE, CHECK_NONE, changeMultipleNodeStatus, changeNodeStatus, changeSelected, changeSelectedPatch, getNextStatus };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ComponentProps } from "react";
|
|
2
|
+
import { CheckStatus } from "../../types";
|
|
2
3
|
export interface CascaderRootProps extends ComponentProps<'div'> {
|
|
3
4
|
isSelected?: boolean;
|
|
4
|
-
|
|
5
|
-
onSelectChange?: (nodeIdx: number) => void;
|
|
5
|
+
setNodeCheckStatus?: (nodeIdx: number, nodeCheckStatus: CheckStatus) => void;
|
|
6
6
|
}
|
|
7
7
|
export declare const CascaderRoot: import("react").ForwardRefExoticComponent<Omit<CascaderRootProps, "ref"> & import("react").RefAttributes<unknown>>;
|
package/lib/context/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CSSProperties } from "react";
|
|
2
|
+
import { CheckStatus } from "../types";
|
|
2
3
|
export declare const CascaderContext: import("react").Context<{
|
|
3
4
|
isSelected: boolean;
|
|
4
|
-
|
|
5
|
-
onSelectChange: ((nodeIdx: number) => void) | undefined;
|
|
5
|
+
setNodeCheckStatus: ((nodeIdx: number, nodeCheckStatus: CheckStatus) => void) | undefined;
|
|
6
6
|
}>;
|
|
7
7
|
export declare const CascaderPanelContext: import("react").Context<{
|
|
8
8
|
showIndicator: boolean;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { CascaderNodeType, CascaderSelectOption, FlatDataConfig } from "../types";
|
|
1
|
+
import { CascaderNodeType, CascaderPathOption, CascaderSelectOption, CheckStatus, FlatDataConfig } from "../types";
|
|
2
2
|
export type CascaderHookOption<T> = {
|
|
3
3
|
data: T[];
|
|
4
4
|
handleDataConfig: FlatDataConfig;
|
|
5
|
+
pathOption?: CascaderPathOption;
|
|
5
6
|
selectOption?: CascaderSelectOption;
|
|
6
|
-
curShow?: string | number;
|
|
7
7
|
};
|
|
8
8
|
export declare function useCascader<T extends Record<string, any>>(options: CascaderHookOption<T>): {
|
|
9
|
+
path: number[];
|
|
9
10
|
nodes: CascaderNodeType<T>[];
|
|
10
11
|
columns: CascaderNodeType<T>[][];
|
|
11
|
-
path: number[];
|
|
12
12
|
checkStatusArray: Uint8Array<ArrayBufferLike>;
|
|
13
13
|
handleChangePath: (depth: number, index: number) => void;
|
|
14
|
-
handleChangeCheckStatus: (nodeIdx: number) => void;
|
|
14
|
+
handleChangeCheckStatus: (nodeIdx: number, checkStatus: CheckStatus) => void;
|
|
15
15
|
};
|
package/lib/index.d.ts
CHANGED
package/lib/types/index.d.ts
CHANGED
|
@@ -4,15 +4,15 @@ export type CheckStatus = 0 | 1 | 2;
|
|
|
4
4
|
* Data
|
|
5
5
|
*---------------------------------------------**/
|
|
6
6
|
export interface CascaderNodeType<T = any> {
|
|
7
|
+
label: string;
|
|
8
|
+
value: string | number;
|
|
9
|
+
nodeId: string;
|
|
7
10
|
depth: number;
|
|
8
11
|
index: number;
|
|
9
12
|
parentIndex: number;
|
|
10
|
-
range: [number, number];
|
|
11
13
|
childrenIndices: number[];
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
value: string | number;
|
|
15
|
-
raw: T | null;
|
|
14
|
+
range: [number, number];
|
|
15
|
+
data: T | null;
|
|
16
16
|
}
|
|
17
17
|
export interface CascaderItem<T> {
|
|
18
18
|
indices: number;
|
|
@@ -20,7 +20,7 @@ export interface CascaderItem<T> {
|
|
|
20
20
|
field: string;
|
|
21
21
|
label: string;
|
|
22
22
|
value: string | number;
|
|
23
|
-
|
|
23
|
+
data?: T;
|
|
24
24
|
checkStatus?: CheckStatus;
|
|
25
25
|
}
|
|
26
26
|
/**--------------------------------------------
|
|
@@ -42,9 +42,20 @@ export type GetCascaderColumnsOption = {
|
|
|
42
42
|
/**--------------------------------------------
|
|
43
43
|
* Other
|
|
44
44
|
*---------------------------------------------**/
|
|
45
|
+
export type CascaderPathOption = {
|
|
46
|
+
showConfig?: {
|
|
47
|
+
depth: number;
|
|
48
|
+
showType: "label" | "value";
|
|
49
|
+
};
|
|
50
|
+
showValue?: string | number;
|
|
51
|
+
defaultShowValue?: string | number;
|
|
52
|
+
onShowValueChange?: (value: string | number, depth: number) => void;
|
|
53
|
+
};
|
|
45
54
|
export type CascaderSelectOption = {
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
valueType?: "label" | "value";
|
|
56
|
+
selected?: (string | number)[];
|
|
57
|
+
defaultSelected?: (string | number)[];
|
|
58
|
+
onSelectedChange?: (selected: (string | number)[]) => void;
|
|
48
59
|
};
|
|
49
60
|
/**--------------------------------------------
|
|
50
61
|
* Slot
|
|
@@ -56,5 +67,5 @@ export type PanelHeaderSlot = (props: {
|
|
|
56
67
|
export type PanelIndicatorSlot = (props?: any) => ReactNode;
|
|
57
68
|
export type NodeSlotType = (props: {
|
|
58
69
|
node: CascaderItem<any>;
|
|
59
|
-
|
|
70
|
+
handleToggleSelect?: (nodeIdx: number) => void;
|
|
60
71
|
}) => ReactNode;
|
package/lib/utils/data.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { CascaderNodeType, FlatDataConfig, GetShowIndicesOption } from '../types/index.js';
|
|
2
|
+
/**--------------------------------------------
|
|
3
|
+
* 创建级连线性数组
|
|
4
|
+
*---------------------------------------------**/
|
|
2
5
|
export declare function buildCascaderEngine<T extends Record<string, any>>(data: T[], config: FlatDataConfig): CascaderNodeType<T>[];
|
|
6
|
+
/**--------------------------------------------
|
|
7
|
+
* 根据选中路径生成展示列表
|
|
8
|
+
*---------------------------------------------**/
|
|
3
9
|
export declare function getCascadeColumns<T>(nodes: CascaderNodeType<T>[], path: number[]): CascaderNodeType<T>[][];
|
|
10
|
+
/**--------------------------------------------
|
|
11
|
+
* 改变级联选择器的显示路径
|
|
12
|
+
*---------------------------------------------**/
|
|
4
13
|
export declare function changeShowPath<T>(nodes: CascaderNodeType<T>[], option: GetShowIndicesOption): number[];
|
|
14
|
+
/**--------------------------------------------
|
|
15
|
+
* 获取级联选择器的显示路径
|
|
16
|
+
*---------------------------------------------**/
|
|
5
17
|
export declare function getShowPath<T>(nodes: CascaderNodeType<T>[], targetNode?: CascaderNodeType): number[];
|
package/lib/utils/logic.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
import { CascaderNodeType } from "src/types";
|
|
2
|
-
export declare
|
|
3
|
-
export declare
|
|
1
|
+
import { CascaderNodeType, CheckStatus } from "src/types";
|
|
2
|
+
export declare const CHECK_NONE: CheckStatus;
|
|
3
|
+
export declare const CHECK_ALL: CheckStatus;
|
|
4
|
+
export declare const CHECK_INDETERMINATE: CheckStatus;
|
|
5
|
+
/**--------------------------------------------
|
|
6
|
+
* 获取切换节点状态
|
|
7
|
+
*---------------------------------------------**/
|
|
8
|
+
export declare const getNextStatus: (curCheckStatus: CheckStatus) => CheckStatus;
|
|
9
|
+
export declare function changeNodeStatus<T>(nodes: CascaderNodeType<T>[], currentStatusArray: Uint8Array, nodeIndex: number, checkStatus: CheckStatus): Uint8Array;
|
|
10
|
+
export declare function changeMultipleNodeStatus<T>(nodes: CascaderNodeType<T>[], indices: number[], targetStatus: CheckStatus, currentStatusArray: Uint8Array): Uint8Array;
|
|
11
|
+
/**--------------------------------------------
|
|
12
|
+
* 获取选中状态的所有叶子节点数据
|
|
13
|
+
*---------------------------------------------**/
|
|
14
|
+
export declare function changeSelectedPatch<T>(nodes: CascaderNodeType<T>[], indices: number[], isChecked: boolean, currentSet: Set<string | number>): Set<string | number>;
|
|
15
|
+
export declare function changeSelected<T>(checkStatus: CheckStatus, nodes: CascaderNodeType<T>[], nodeIdx: number, currentSet: Set<string | number>, selectValueType: "label" | "value"): Set<string | number>;
|
package/package.json
CHANGED