@canlooks/can-ui 0.0.95 → 0.0.97
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/dist/cjs/components/accordion/accordion.style.d.ts +1 -1
- package/dist/cjs/components/alert/alert.style.d.ts +3 -3
- package/dist/cjs/components/button/button.style.d.ts +1 -1
- package/dist/cjs/components/checkboxBase/checkboxBase.style.d.ts +2 -2
- package/dist/cjs/components/clickAway/clickAway.d.ts +27 -27
- package/dist/cjs/components/dataGrid/dataGrid.style.d.ts +1 -1
- package/dist/cjs/components/descriptions/descriptions.style.d.ts +1 -1
- package/dist/cjs/components/dialog/dialog.style.d.ts +3 -3
- package/dist/cjs/components/drawer/drawer.d.ts +3 -1
- package/dist/cjs/components/drawer/drawer.js +2 -2
- package/dist/cjs/components/inputBase/inputBase.style.d.ts +2 -2
- package/dist/cjs/components/menuItem/menuItem.d.ts +4 -0
- package/dist/cjs/components/menuItem/menuItem.style.d.ts +2 -2
- package/dist/cjs/components/optionsBase/optionsBase.js +2 -1
- package/dist/cjs/components/palette/palette.style.d.ts +1 -1
- package/dist/cjs/components/pickerDialog/pickerDialog.style.d.ts +1 -1
- package/dist/cjs/components/progress/progress.js +2 -1
- package/dist/cjs/components/progress/progress.style.d.ts +1 -1
- package/dist/cjs/components/resizable/resizable.style.d.ts +1 -1
- package/dist/cjs/components/segmented/segmented.style.d.ts +1 -1
- package/dist/cjs/components/selectionContext/selectionContext.d.ts +2 -0
- package/dist/cjs/components/selectionContext/selectionHook.js +2 -1
- package/dist/cjs/components/snackbarBase/snackbarBase.style.d.ts +1 -1
- package/dist/cjs/components/status/status.style.d.ts +1 -1
- package/dist/cjs/components/tabs/tabs.style.d.ts +4 -4
- package/dist/cjs/components/tag/tag.style.d.ts +2 -2
- package/dist/cjs/components/transfer/transfer.style.d.ts +2 -2
- package/dist/cjs/components/tree/tree.d.ts +2 -2
- package/dist/cjs/components/tree/tree.js +15 -13
- package/dist/cjs/components/tree/tree.style.d.ts +5 -9
- package/dist/cjs/components/tree/tree.style.js +96 -206
- package/dist/cjs/components/tree/treeDnd.d.ts +3 -7
- package/dist/cjs/components/tree/treeDnd.js +7 -19
- package/dist/cjs/components/tree/treeDnd.style.d.ts +15 -0
- package/dist/cjs/components/tree/treeDnd.style.js +191 -0
- package/dist/cjs/components/tree/treeNode.d.ts +4 -4
- package/dist/cjs/components/tree/treeNode.js +82 -69
- package/dist/cjs/components/upload/upload.style.d.ts +1 -1
- package/dist/cjs/utils/dnd.d.ts +11 -3
- package/dist/cjs/utils/dnd.js +45 -2
- package/dist/esm/components/accordion/accordion.style.d.ts +1 -1
- package/dist/esm/components/alert/alert.style.d.ts +3 -3
- package/dist/esm/components/button/button.style.d.ts +1 -1
- package/dist/esm/components/checkboxBase/checkboxBase.style.d.ts +2 -2
- package/dist/esm/components/clickAway/clickAway.d.ts +27 -27
- package/dist/esm/components/dataGrid/dataGrid.style.d.ts +1 -1
- package/dist/esm/components/descriptions/descriptions.style.d.ts +1 -1
- package/dist/esm/components/dialog/dialog.style.d.ts +3 -3
- package/dist/esm/components/drawer/drawer.d.ts +3 -1
- package/dist/esm/components/drawer/drawer.js +2 -2
- package/dist/esm/components/inputBase/inputBase.style.d.ts +2 -2
- package/dist/esm/components/menuItem/menuItem.d.ts +4 -0
- package/dist/esm/components/menuItem/menuItem.style.d.ts +2 -2
- package/dist/esm/components/optionsBase/optionsBase.js +2 -1
- package/dist/esm/components/palette/palette.style.d.ts +1 -1
- package/dist/esm/components/pickerDialog/pickerDialog.style.d.ts +1 -1
- package/dist/esm/components/progress/progress.js +2 -1
- package/dist/esm/components/progress/progress.style.d.ts +1 -1
- package/dist/esm/components/resizable/resizable.style.d.ts +1 -1
- package/dist/esm/components/segmented/segmented.style.d.ts +1 -1
- package/dist/esm/components/selectionContext/selectionContext.d.ts +2 -0
- package/dist/esm/components/selectionContext/selectionHook.js +2 -1
- package/dist/esm/components/snackbarBase/snackbarBase.style.d.ts +1 -1
- package/dist/esm/components/status/status.style.d.ts +1 -1
- package/dist/esm/components/tabs/tabs.style.d.ts +4 -4
- package/dist/esm/components/tag/tag.style.d.ts +2 -2
- package/dist/esm/components/transfer/transfer.style.d.ts +2 -2
- package/dist/esm/components/tree/tree.d.ts +2 -2
- package/dist/esm/components/tree/tree.js +18 -16
- package/dist/esm/components/tree/tree.style.d.ts +5 -9
- package/dist/esm/components/tree/tree.style.js +95 -206
- package/dist/esm/components/tree/treeDnd.d.ts +3 -7
- package/dist/esm/components/tree/treeDnd.js +8 -20
- package/dist/esm/components/tree/treeDnd.style.d.ts +15 -0
- package/dist/esm/components/tree/treeDnd.style.js +186 -0
- package/dist/esm/components/tree/treeNode.d.ts +4 -4
- package/dist/esm/components/tree/treeNode.js +82 -69
- package/dist/esm/components/upload/upload.style.d.ts +1 -1
- package/dist/esm/utils/dnd.d.ts +11 -3
- package/dist/esm/utils/dnd.js +44 -2
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { defineInnerClasses, useCss } from '../../utils';
|
|
2
|
+
import { css } from '@emotion/react';
|
|
3
|
+
import { classes } from './tree.style';
|
|
4
|
+
import Color from 'color';
|
|
5
|
+
export const treeDndClasses = defineInnerClasses('tree-dnd', [
|
|
6
|
+
'levelBlock',
|
|
7
|
+
'dragHandle',
|
|
8
|
+
'mask',
|
|
9
|
+
'predecessor',
|
|
10
|
+
'sibling',
|
|
11
|
+
'siblingPrev',
|
|
12
|
+
'siblingNext',
|
|
13
|
+
'child'
|
|
14
|
+
]);
|
|
15
|
+
export function useStyle({ indent }) {
|
|
16
|
+
return useCss(({ mode, spacing, gray, colors }) => css `
|
|
17
|
+
.${classes.node} {
|
|
18
|
+
position: relative;
|
|
19
|
+
|
|
20
|
+
&[data-dragging=true] {
|
|
21
|
+
background-color: ${Color(colors.primary.main).alpha(mode === 'light' ? .13 : .23).string()} !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&[data-active=true] {
|
|
25
|
+
outline: 2px solid ${colors.primary.main};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.${treeDndClasses.dragHandle} {
|
|
30
|
+
width: 20px;
|
|
31
|
+
margin-right: ${spacing[3]}px;
|
|
32
|
+
text-align: center;
|
|
33
|
+
color: ${gray(.12)};
|
|
34
|
+
cursor: grab;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.${treeDndClasses.mask} {
|
|
38
|
+
display: flex;
|
|
39
|
+
position: absolute;
|
|
40
|
+
inset: 0;
|
|
41
|
+
z-index: 1;
|
|
42
|
+
|
|
43
|
+
.${classes.indent}:after {
|
|
44
|
+
display: none;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.${treeDndClasses.predecessor} {
|
|
48
|
+
width: ${indent}px;
|
|
49
|
+
position: relative;
|
|
50
|
+
|
|
51
|
+
&:has(+ .${treeDndClasses.sibling}) {
|
|
52
|
+
width: 29px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&[data-active=true] {
|
|
56
|
+
&:before, &:after {
|
|
57
|
+
content: '';
|
|
58
|
+
position: absolute;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&:before {
|
|
62
|
+
width: 8px;
|
|
63
|
+
height: 8px;
|
|
64
|
+
border-radius: 50%;
|
|
65
|
+
border: 2px solid ${colors.primary.main};
|
|
66
|
+
left: 0;
|
|
67
|
+
bottom: -4px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
&:after {
|
|
71
|
+
width: calc(100% - 8px);
|
|
72
|
+
height: 2px;
|
|
73
|
+
background: ${colors.primary.main};
|
|
74
|
+
left: 8px;
|
|
75
|
+
bottom: -1px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
& ~ * {
|
|
79
|
+
&:after {
|
|
80
|
+
content: '';
|
|
81
|
+
width: 100%;
|
|
82
|
+
height: 2px;
|
|
83
|
+
background: ${colors.primary.main};
|
|
84
|
+
position: absolute;
|
|
85
|
+
left: 0;
|
|
86
|
+
bottom: -1px;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.${treeDndClasses.sibling} {
|
|
93
|
+
width: ${indent * 2}px;
|
|
94
|
+
flex: 1;
|
|
95
|
+
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
position: relative;
|
|
98
|
+
|
|
99
|
+
.${treeDndClasses.siblingPrev}, .${treeDndClasses.siblingNext} {
|
|
100
|
+
flex: 1;
|
|
101
|
+
position: relative;
|
|
102
|
+
|
|
103
|
+
&[data-active=true] {
|
|
104
|
+
&:before, &:after {
|
|
105
|
+
content: '';
|
|
106
|
+
position: absolute;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&:before {
|
|
110
|
+
width: 8px;
|
|
111
|
+
height: 8px;
|
|
112
|
+
border-radius: 50%;
|
|
113
|
+
border: 2px solid ${colors.primary.main};
|
|
114
|
+
left: 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
&:after {
|
|
118
|
+
width: calc(100% - 8px);
|
|
119
|
+
height: 2px;
|
|
120
|
+
background: ${colors.primary.main};
|
|
121
|
+
left: 8px;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.${treeDndClasses.siblingPrev} {
|
|
127
|
+
&:before {
|
|
128
|
+
top: -4px
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
&:after {
|
|
132
|
+
top: -1px;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.${treeDndClasses.siblingNext} {
|
|
137
|
+
&:before {
|
|
138
|
+
bottom: -4px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
&:after {
|
|
142
|
+
bottom: -1px;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.${treeDndClasses.child} {
|
|
147
|
+
width: calc(100% - ${indent * 2}px);
|
|
148
|
+
height: 50%;
|
|
149
|
+
position: absolute;
|
|
150
|
+
right: 0;
|
|
151
|
+
bottom: 0;
|
|
152
|
+
|
|
153
|
+
&[data-active=true] {
|
|
154
|
+
&:before, &:after {
|
|
155
|
+
content: '';
|
|
156
|
+
position: absolute;
|
|
157
|
+
bottom: -1px;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
&:before {
|
|
161
|
+
width: 8px;
|
|
162
|
+
height: 8px;
|
|
163
|
+
border-left: 2px solid ${colors.primary.main};
|
|
164
|
+
border-bottom: 2px solid ${colors.primary.main};
|
|
165
|
+
left: 0;
|
|
166
|
+
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
&:after {
|
|
170
|
+
width: calc(100% - 12px);
|
|
171
|
+
height: 2px;
|
|
172
|
+
background: ${colors.primary.main};
|
|
173
|
+
left: 12px;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.${treeDndClasses.levelBlock} {
|
|
181
|
+
&[data-active=true] {
|
|
182
|
+
outline: 1px dashed ${colors.primary.main};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
`, [indent]);
|
|
186
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { DivProps, Id } from '../../types';
|
|
3
|
-
export interface TreeNodeProps extends Omit<DivProps, 'prefix'> {
|
|
4
|
-
|
|
3
|
+
export interface TreeNodeProps extends Omit<DivProps, 'id' | 'prefix'> {
|
|
4
|
+
id: Id;
|
|
5
5
|
label?: ReactNode;
|
|
6
6
|
prefix?: ReactNode;
|
|
7
7
|
suffix?: ReactNode;
|
|
8
8
|
disabled?: boolean;
|
|
9
|
-
/** @private
|
|
9
|
+
/** @private 表明该节点的层级 */
|
|
10
10
|
_level?: number;
|
|
11
11
|
}
|
|
12
|
-
export declare const TreeNode: React.MemoExoticComponent<({
|
|
12
|
+
export declare const TreeNode: React.MemoExoticComponent<({ id, label, prefix, suffix, disabled, _level, ...props }: TreeNodeProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
|
|
@@ -11,114 +11,127 @@ import { Icon } from '../icon';
|
|
|
11
11
|
import { faChevronRight } from '@fortawesome/free-solid-svg-icons/faChevronRight';
|
|
12
12
|
import { faGripVertical } from '@fortawesome/free-solid-svg-icons';
|
|
13
13
|
import { useTreeDndContext } from './treeDnd';
|
|
14
|
-
|
|
14
|
+
import { treeDndClasses } from './treeDnd.style';
|
|
15
|
+
export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0, ...props }) => {
|
|
15
16
|
const { expandedSet, toggleExpanded, indent, renderExpandIcon, showCheckbox, readOnly, clickLabelToExpand, ...context } = useTreeContext();
|
|
16
17
|
disabled ??= context.disabled;
|
|
17
|
-
const { selectionStatus, toggleSelected } = useSelectionContext();
|
|
18
|
-
const currentExpanded = expandedSet.has(
|
|
19
|
-
const status = selectionStatus.get(
|
|
18
|
+
const { optionsMap: nodesMap, selectionStatus, toggleSelected } = useSelectionContext();
|
|
19
|
+
const currentExpanded = expandedSet.has(id);
|
|
20
|
+
const status = selectionStatus.get(id);
|
|
20
21
|
const clickHandler = () => {
|
|
21
|
-
!readOnly && !disabled && toggleSelected(
|
|
22
|
-
clickLabelToExpand && toggleExpanded(
|
|
22
|
+
!readOnly && !disabled && toggleSelected(id);
|
|
23
|
+
clickLabelToExpand && toggleExpanded(id);
|
|
23
24
|
};
|
|
24
25
|
const hasChildren = !!props.children && (!Array.isArray(props.children) || props.children.length > 0);
|
|
25
26
|
/**
|
|
26
27
|
* ---------------------------------------------------------------------
|
|
27
28
|
* 拖拽部分
|
|
28
29
|
*/
|
|
29
|
-
const { sortable, showDragHandle, onSort,
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
!showCheckbox && clickHandler();
|
|
33
|
-
};
|
|
30
|
+
const { sortable, showDragHandle, onSort, dragging: [dragging, setDragging], overing, placement } = useTreeDndContext();
|
|
31
|
+
const isDraggingNode = dragging === id;
|
|
32
|
+
const nodeRef = useRef(null);
|
|
34
33
|
const dragHandleProps = useDraggable({
|
|
35
34
|
disabled: !sortable,
|
|
36
|
-
onDragStart(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
currentExpanded && toggleExpanded(
|
|
40
|
-
},
|
|
41
|
-
onDrag({ diff: [diffX] }) {
|
|
42
|
-
setIsOffsetSatisfied(diffX > indent * 2);
|
|
35
|
+
onDragStart() {
|
|
36
|
+
overing.current = void 0;
|
|
37
|
+
setDragging(id);
|
|
38
|
+
currentExpanded && toggleExpanded(id);
|
|
43
39
|
},
|
|
44
40
|
onDragEnd() {
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
overing.current && placement.current && onSort?.({
|
|
42
|
+
source: dragging,
|
|
43
|
+
destination: overing.current,
|
|
44
|
+
placement: placement.current
|
|
45
|
+
});
|
|
47
46
|
setDragging(void 0);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
source: dragging,
|
|
51
|
-
destination: overing,
|
|
52
|
-
placement: isOffsetSatisfied ? 'child' : placement.current
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
onClick
|
|
47
|
+
inactiveBlock();
|
|
48
|
+
}
|
|
57
49
|
});
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
const pointerEnterMaskArea = (e, _placement) => {
|
|
51
|
+
if (!isDraggingNode) {
|
|
52
|
+
activeBlock(e.currentTarget, _placement);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const pointerLeaveMaskArea = (e) => {
|
|
56
|
+
!isDraggingNode && inactiveBlock(e.currentTarget);
|
|
57
|
+
};
|
|
58
|
+
const pointerEnterPredecessor = (e, upLevel) => {
|
|
59
|
+
activeBlock(e.currentTarget, 'parent', upLevel);
|
|
60
|
+
};
|
|
61
|
+
const pointerLeavePredecessor = (e) => {
|
|
62
|
+
inactiveBlock(e.currentTarget);
|
|
63
|
+
};
|
|
64
|
+
const activeBlock = (el, _placement, upLevel = 0) => {
|
|
65
|
+
if (_placement === 'parent') {
|
|
66
|
+
let i = upLevel;
|
|
67
|
+
let parentId = id;
|
|
68
|
+
do {
|
|
69
|
+
const currentNode = nodesMap.get(parentId);
|
|
70
|
+
if (!currentNode._isLast) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
parentId = currentNode._parentId;
|
|
74
|
+
} while (--i && parentId);
|
|
75
|
+
overing.current = parentId;
|
|
76
|
+
placement.current = 'after';
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
overing.current = id;
|
|
80
|
+
placement.current = _placement;
|
|
81
|
+
}
|
|
82
|
+
el.dataset.active = 'true';
|
|
83
|
+
_placement !== 'child' && findPredecessor(el, parent => {
|
|
84
|
+
if (parent.classList.contains(treeDndClasses.levelBlock) && !upLevel--) {
|
|
63
85
|
parent.dataset.active = 'true';
|
|
86
|
+
const parentNode = parent.previousElementSibling;
|
|
87
|
+
if (parentNode && parentNode.classList.contains(classes.node)) {
|
|
88
|
+
parentNode.dataset.active = 'true';
|
|
89
|
+
}
|
|
64
90
|
return true;
|
|
65
91
|
}
|
|
66
92
|
});
|
|
67
93
|
};
|
|
68
|
-
const
|
|
69
|
-
|
|
94
|
+
const inactiveBlock = (el) => {
|
|
95
|
+
if (el) {
|
|
70
96
|
el.dataset.active = 'false';
|
|
71
|
-
};
|
|
72
|
-
fn(containerRef.current);
|
|
73
|
-
containerRef.current.querySelectorAll('.' + classes.levelBlock).forEach(fn);
|
|
74
|
-
};
|
|
75
|
-
const overingMask = (e) => {
|
|
76
|
-
if (hasChildren && !expandedSet.has(value)) {
|
|
77
|
-
overingTimer.current ||= setTimeout(() => {
|
|
78
|
-
toggleExpanded(value);
|
|
79
|
-
placement.current === 'after' && inactiveParentBlock();
|
|
80
|
-
}, 800);
|
|
81
97
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
setPlacement(placement);
|
|
90
|
-
activeParentBlock(e.currentTarget);
|
|
91
|
-
};
|
|
92
|
-
const onPointerLeave = () => {
|
|
93
|
-
setOvering(void 0);
|
|
94
|
-
inactiveParentBlock();
|
|
98
|
+
document.querySelectorAll('.' + treeDndClasses.levelBlock).forEach(el => {
|
|
99
|
+
el.dataset.active = 'false';
|
|
100
|
+
});
|
|
101
|
+
document.querySelectorAll('.' + classes.node).forEach(el => {
|
|
102
|
+
el.dataset.active = 'false';
|
|
103
|
+
});
|
|
104
|
+
overing.current = void 0;
|
|
95
105
|
};
|
|
96
106
|
/**
|
|
97
107
|
* ---------------------------------------------------------------------
|
|
98
108
|
* 渲染部分
|
|
99
109
|
*/
|
|
100
110
|
const renderedIndents = useMemo(() => {
|
|
101
|
-
return Array(_level).fill(void 0).map((_, i) => _jsx("div", { className: classes.indent
|
|
102
|
-
}, [_level
|
|
103
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { ...props, ref: cloneRef(nodeRef, props.ref), className: clsx(classes.node, props.className), "data-selected": status === 2, "data-read-only": readOnly, "data-disabled": disabled, "data-dragging":
|
|
111
|
+
return Array(_level).fill(void 0).map((_, i) => _jsx("div", { className: classes.indent }, i));
|
|
112
|
+
}, [_level]);
|
|
113
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { ...props, ref: cloneRef(nodeRef, props.ref), className: clsx(classes.node, props.className), "data-selected": status === 2, "data-read-only": readOnly, "data-disabled": disabled, "data-dragging": isDraggingNode, onClick: clickHandler, ...!showDragHandle && dragHandleProps, children: [renderedIndents, _jsx(Button, { className: classes.expand, variant: "plain", color: "text.secondary", onClick: e => {
|
|
104
114
|
e.stopPropagation();
|
|
105
|
-
toggleExpanded(
|
|
115
|
+
toggleExpanded(id);
|
|
106
116
|
}, onPointerDown: e => e.stopPropagation(), children: renderExpandIcon
|
|
107
|
-
? renderExpandIcon(
|
|
117
|
+
? renderExpandIcon(id, currentExpanded, [...expandedSet])
|
|
108
118
|
: hasChildren &&
|
|
109
119
|
_jsx(Icon, { icon: faChevronRight, className: classes.icon, style: {
|
|
110
120
|
rotate: currentExpanded ? '90deg' : '0deg'
|
|
111
121
|
} }) }), _jsxs("div", { className: classes.contentWrap, children: [sortable && showDragHandle &&
|
|
112
|
-
_jsx("div", { className:
|
|
122
|
+
_jsx("div", { className: treeDndClasses.dragHandle, ...dragHandleProps, onClick: e => e.stopPropagation(), children: _jsx(Icon, { icon: faGripVertical }) }), showCheckbox &&
|
|
113
123
|
_jsx(Checkbox, { className: classes.checkbox, checked: status === 2, indeterminate: status === 1, onClick: e => {
|
|
114
124
|
e.stopPropagation();
|
|
115
125
|
clickHandler();
|
|
116
126
|
} }), !!prefix &&
|
|
117
127
|
_jsx("div", { className: classes.prefix, children: prefix }), _jsx("div", { className: classes.label, children: label }), !!suffix &&
|
|
118
|
-
_jsx("div", { className: classes.suffix, children: suffix }), typeof dragging !== 'undefined' &&
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
_jsx("div", { className: classes.suffix, children: suffix })] }), typeof dragging !== 'undefined' &&
|
|
129
|
+
_jsxs("div", { className: treeDndClasses.mask, children: [Array(_level + 1).fill(void 0).map((_, i) => _jsx("div", { className: treeDndClasses.predecessor, ...i && {
|
|
130
|
+
onPointerEnter: e => pointerEnterPredecessor(e, _level + 1 - i),
|
|
131
|
+
onPointerLeave: pointerLeavePredecessor
|
|
132
|
+
} }, i)), _jsxs("div", { className: treeDndClasses.sibling, children: [_jsx("div", { className: treeDndClasses.siblingPrev, onPointerEnter: e => pointerEnterMaskArea(e, 'before'), onPointerLeave: pointerLeaveMaskArea }), _jsx("div", { className: treeDndClasses.siblingNext, onPointerEnter: e => pointerEnterMaskArea(e, 'after'), onPointerLeave: pointerLeaveMaskArea }), !hasChildren &&
|
|
133
|
+
_jsx("div", { className: treeDndClasses.child, onPointerEnter: e => pointerEnterMaskArea(e, 'child'), onPointerLeave: pointerLeaveMaskArea })] })] })] }), hasChildren &&
|
|
134
|
+
_jsx(Collapse, { className: treeDndClasses.levelBlock, in: currentExpanded, children: Children.map(props.children, child => {
|
|
122
135
|
return isValidElement(child)
|
|
123
136
|
? cloneElement(child, { _level: _level + 1 })
|
|
124
137
|
: child;
|
package/dist/esm/utils/dnd.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { DragEndEvent } from '@dnd-kit/core';
|
|
2
|
-
import { Obj } from '../types';
|
|
2
|
+
import { Id, Obj } from '../types';
|
|
3
|
+
import { NodeType, SortInfo } from '../components/tree';
|
|
3
4
|
/**
|
|
4
5
|
* 默认提供给@dnd-kit的sensors属性
|
|
5
6
|
*/
|
|
6
7
|
export declare function useDndSensors(): import("@dnd-kit/core").SensorDescriptor<import("@dnd-kit/core").SensorOptions>[];
|
|
7
8
|
/**
|
|
8
9
|
* <DndContext>组件通用的onDragEnd方法
|
|
9
|
-
* @param e
|
|
10
|
+
* @param e 事件
|
|
10
11
|
* @param prevState 传入需要排序的数组
|
|
11
|
-
* @param primaryKey
|
|
12
|
+
* @param primaryKey 索引用的主键,默认为`id`
|
|
12
13
|
*/
|
|
13
14
|
export declare function onDndDragEnd<S extends Obj>(e: DragEndEvent, prevState: S[], primaryKey?: string): S[] | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* <Tree>组件通用的onSort方法,注意:该方法会原地修改{@link treeNodes}
|
|
17
|
+
* @param info 信息
|
|
18
|
+
* @param treeNodes 树节点
|
|
19
|
+
* @param primaryKey 索引用的主键,默认为`id`
|
|
20
|
+
*/
|
|
21
|
+
export declare function onTreeNodeSort<N extends NodeType<V>, V extends Id = Id>(info: SortInfo<V>, treeNodes: N[], primaryKey?: string): N[];
|
package/dist/esm/utils/dnd.js
CHANGED
|
@@ -12,9 +12,9 @@ export function useDndSensors() {
|
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* <DndContext>组件通用的onDragEnd方法
|
|
15
|
-
* @param e
|
|
15
|
+
* @param e 事件
|
|
16
16
|
* @param prevState 传入需要排序的数组
|
|
17
|
-
* @param primaryKey
|
|
17
|
+
* @param primaryKey 索引用的主键,默认为`id`
|
|
18
18
|
*/
|
|
19
19
|
export function onDndDragEnd(e, prevState, primaryKey = 'id') {
|
|
20
20
|
const { active, over } = e;
|
|
@@ -26,3 +26,45 @@ export function onDndDragEnd(e, prevState, primaryKey = 'id') {
|
|
|
26
26
|
const newIndex = prevState.findIndex(v => v[primaryKey] === over.id);
|
|
27
27
|
return arrayMove(prevState, oldIndex, newIndex);
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* <Tree>组件通用的onSort方法,注意:该方法会原地修改{@link treeNodes}
|
|
31
|
+
* @param info 信息
|
|
32
|
+
* @param treeNodes 树节点
|
|
33
|
+
* @param primaryKey 索引用的主键,默认为`id`
|
|
34
|
+
*/
|
|
35
|
+
export function onTreeNodeSort(info, treeNodes, primaryKey = 'id') {
|
|
36
|
+
const find = (arr, id) => {
|
|
37
|
+
let target = null;
|
|
38
|
+
let targetIndex = -1;
|
|
39
|
+
let siblings = null;
|
|
40
|
+
const recurse = (arr) => {
|
|
41
|
+
return !!arr?.some((v, i, _siblings) => {
|
|
42
|
+
if (v[primaryKey] === id) {
|
|
43
|
+
target = v;
|
|
44
|
+
targetIndex = i;
|
|
45
|
+
siblings = _siblings;
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return v.children?.length && recurse(v.children);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
recurse(arr);
|
|
52
|
+
return target ? { target, targetIndex, siblings: siblings } : null;
|
|
53
|
+
};
|
|
54
|
+
const source = find(treeNodes, info.source);
|
|
55
|
+
source.siblings.splice(source.targetIndex, 1);
|
|
56
|
+
const destination = find(treeNodes, info.destination);
|
|
57
|
+
switch (info.placement) {
|
|
58
|
+
case 'before':
|
|
59
|
+
destination.siblings.splice(destination.targetIndex, 0, source.target);
|
|
60
|
+
break;
|
|
61
|
+
case 'after':
|
|
62
|
+
destination.siblings.splice(destination.targetIndex + 1, 0, source.target);
|
|
63
|
+
break;
|
|
64
|
+
default:
|
|
65
|
+
// children
|
|
66
|
+
destination.target.children ||= [];
|
|
67
|
+
destination.target.children.push(source.target);
|
|
68
|
+
}
|
|
69
|
+
return treeNodes;
|
|
70
|
+
}
|