form-driver 0.4.21 → 0.4.22
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/m3.css +116 -8
- package/dist/m3.js +1 -1
- package/es/m3.css +116 -8
- package/es/m3.js +486 -474
- package/lib/m3.css +116 -8
- package/lib/m3.js +485 -473
- package/package.json +4 -1
- package/src/ui/editor/basic/ARangePicker.tsx +15 -3
- package/src/ui/widget/EnhancedSortDrag.less +61 -0
- package/src/ui/widget/EnhancedSortDrag.tsx +294 -284
- package/src/ui/widget/SortDrag.less +78 -13
- package/src/ui/widget/SortDrag.tsx +119 -103
- package/types/ui/widget/EnhancedSortDrag.d.ts +3 -1
|
@@ -1,32 +1,97 @@
|
|
|
1
1
|
.sortDrag {
|
|
2
2
|
.dragItem {
|
|
3
3
|
display: flex;
|
|
4
|
+
align-items: center;
|
|
4
5
|
justify-content: space-between;
|
|
5
|
-
padding: 4px
|
|
6
|
+
padding: 0 4px;
|
|
6
7
|
background: #fff;
|
|
7
|
-
// border: 1px solid #d9d9d9;
|
|
8
|
-
// border-radius: 4px;
|
|
9
|
-
// box-shadow: 0 1px 2px #00000008;
|
|
10
8
|
font-size: 14px;
|
|
11
|
-
transition: background 0.
|
|
9
|
+
transition: background 0.15s ease, box-shadow 0.15s ease;
|
|
10
|
+
cursor: default;
|
|
11
|
+
user-select: none;
|
|
12
|
+
-webkit-user-select: none;
|
|
13
|
+
// 拖拽中占位符状态
|
|
14
|
+
&.dragging {
|
|
15
|
+
background: #fafafa;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.dragHandleWrapper {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
min-width: 36px;
|
|
24
|
+
min-height: 36px;
|
|
12
25
|
cursor: grab;
|
|
26
|
+
margin-left: 2px;
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
touch-action: none;
|
|
29
|
+
-webkit-touch-callout: none;
|
|
30
|
+
transition: background 0.15s ease;
|
|
13
31
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
background: #bae7ff;
|
|
17
|
-
box-shadow: 0 2px 8px #1890ff33;
|
|
32
|
+
&:hover {
|
|
33
|
+
background: #f5f5f5;
|
|
18
34
|
}
|
|
19
35
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
background: #
|
|
36
|
+
&:active {
|
|
37
|
+
cursor: grabbing;
|
|
38
|
+
background: #e8e8e8;
|
|
39
|
+
|
|
40
|
+
.dragHandleIcon {
|
|
41
|
+
color: #1890ff;
|
|
42
|
+
}
|
|
23
43
|
}
|
|
24
44
|
}
|
|
25
45
|
|
|
46
|
+
.dragHandleIcon {
|
|
47
|
+
font-size: 16px;
|
|
48
|
+
color: #bfbfbf;
|
|
49
|
+
transition: color 0.15s ease;
|
|
50
|
+
}
|
|
51
|
+
|
|
26
52
|
.dragBody {
|
|
27
53
|
flex: 1;
|
|
54
|
+
min-height: 0;
|
|
28
55
|
}
|
|
56
|
+
|
|
29
57
|
.dragHandle {
|
|
30
|
-
width:
|
|
58
|
+
width: 36px;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ========== 拖拽预览 — 简洁浮动卡片 ==========
|
|
63
|
+
.sortDrag-overlay {
|
|
64
|
+
.sortDrag-overlay-inner {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
justify-content: space-between;
|
|
68
|
+
padding: 4px 8px;
|
|
69
|
+
background: #ffffff;
|
|
70
|
+
border-radius: 8px;
|
|
71
|
+
box-shadow:
|
|
72
|
+
0 1px 3px rgba(0, 0, 0, 0.08),
|
|
73
|
+
0 8px 24px rgba(0, 0, 0, 0.12);
|
|
74
|
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
75
|
+
|
|
76
|
+
.dragBody {
|
|
77
|
+
flex: 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.sortDrag-overlay-handle {
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
width: 28px;
|
|
86
|
+
height: 28px;
|
|
87
|
+
border-radius: 4px;
|
|
88
|
+
background: #f0f0f0;
|
|
89
|
+
margin-left: 6px;
|
|
90
|
+
flex-shrink: 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.sortDrag-overlay-handleIcon {
|
|
94
|
+
font-size: 14px;
|
|
95
|
+
color: #8c8c8c;
|
|
31
96
|
}
|
|
32
97
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import React, { memo,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Button } from "antd";
|
|
1
|
+
import React, { memo, useState, useEffect, ReactNode } from "react";
|
|
2
|
+
import { DndContext, closestCenter, DragOverlay, DragStartEvent, DragEndEvent, PointerSensor, TouchSensor, KeyboardSensor, useSensor, useSensors } from "@dnd-kit/core";
|
|
3
|
+
import { SortableContext, useSortable, arrayMove, verticalListSortingStrategy, sortableKeyboardCoordinates } from "@dnd-kit/sortable";
|
|
4
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
6
5
|
import { HolderOutlined } from "@ant-design/icons";
|
|
7
6
|
import clsx from "clsx";
|
|
8
7
|
|
|
@@ -19,113 +18,130 @@ type SortDragProps = {
|
|
|
19
18
|
}>;
|
|
20
19
|
};
|
|
21
20
|
|
|
21
|
+
const SortableItem: React.FC<{
|
|
22
|
+
item: SortDragProps["sortList"][0];
|
|
23
|
+
}> = memo(({ item }) => {
|
|
24
|
+
const {
|
|
25
|
+
attributes,
|
|
26
|
+
listeners,
|
|
27
|
+
setNodeRef,
|
|
28
|
+
transform,
|
|
29
|
+
transition,
|
|
30
|
+
isDragging,
|
|
31
|
+
} = useSortable({
|
|
32
|
+
id: item.id,
|
|
33
|
+
disabled: !item.isChecked,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const style: React.CSSProperties = {
|
|
37
|
+
transform: CSS.Transform.toString(transform),
|
|
38
|
+
transition,
|
|
39
|
+
opacity: isDragging ? 0 : 1,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const itemClass = clsx("dragItem", {
|
|
43
|
+
dragging: isDragging,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
className={itemClass}
|
|
49
|
+
ref={setNodeRef}
|
|
50
|
+
style={style}
|
|
51
|
+
>
|
|
52
|
+
<div className="dragBody">{item.cpn}</div>
|
|
53
|
+
<div>
|
|
54
|
+
{item.isChecked ? (
|
|
55
|
+
<div
|
|
56
|
+
className="dragHandleWrapper"
|
|
57
|
+
{...attributes}
|
|
58
|
+
{...listeners}
|
|
59
|
+
>
|
|
60
|
+
<HolderOutlined className="dragHandleIcon" />
|
|
61
|
+
</div>
|
|
62
|
+
) : null}
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
SortableItem.displayName = "SortableItem";
|
|
69
|
+
|
|
22
70
|
const SortDrag: React.FC<SortDragProps> = memo((props) => {
|
|
23
71
|
const { sortList, changeOriginDataSource } = props;
|
|
24
72
|
const [items, setItems] = useState<SortDragProps["sortList"]>(sortList);
|
|
73
|
+
const [activeId, setActiveId] = useState<string | null>(null);
|
|
25
74
|
|
|
26
|
-
//
|
|
27
|
-
const [draggingId, setDraggingId] = useState<string | null>(null);
|
|
28
|
-
// 记录当前 hover 的 Id
|
|
29
|
-
const [droppingId, setDroppingId] = useState<string | null>(null);
|
|
30
|
-
// refs 用于绑定每个 item 的 DOM
|
|
31
|
-
const itemRefs = useRef<Record<string, HTMLDivElement | null>>({});
|
|
32
|
-
// 修改:为每个 item 单独管理 dragHandle ref
|
|
33
|
-
const dragHandleRefs = useRef<Record<string, HTMLSpanElement | null>>({});
|
|
34
|
-
|
|
35
|
-
// 注册拖拽和 drop target
|
|
75
|
+
// 同步外部 sortList 变化到内部状态
|
|
36
76
|
useEffect(() => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const fromIdx = items.findIndex((i) => i.id === source.data.id);
|
|
78
|
-
const toIdx = idx;
|
|
79
|
-
if (fromIdx === -1 || fromIdx === toIdx) return;
|
|
80
|
-
const newItems = [...items];
|
|
81
|
-
const [moved] = newItems.splice(fromIdx, 1);
|
|
82
|
-
newItems.splice(toIdx, 0, moved);
|
|
83
|
-
console.log("排序之后的数据", newItems);
|
|
84
|
-
setItems(newItems);
|
|
85
|
-
|
|
86
|
-
changeOriginDataSource(newItems);
|
|
87
|
-
setDroppingId(null);
|
|
88
|
-
},
|
|
89
|
-
})
|
|
90
|
-
);
|
|
91
|
-
});
|
|
92
|
-
// 监听全局拖拽,拖拽结束时清理 draggingId
|
|
93
|
-
const monitorCleanup = monitorForElements({
|
|
94
|
-
onDrop: () => setDraggingId(null),
|
|
95
|
-
});
|
|
96
|
-
cleanups.push(monitorCleanup);
|
|
97
|
-
return () => {
|
|
98
|
-
cleanups.forEach((fn) => fn());
|
|
99
|
-
};
|
|
100
|
-
}, [items]);
|
|
77
|
+
setItems(sortList);
|
|
78
|
+
}, [sortList]);
|
|
79
|
+
|
|
80
|
+
const sensors = useSensors(
|
|
81
|
+
useSensor(TouchSensor, {
|
|
82
|
+
activationConstraint: {
|
|
83
|
+
delay: 200,
|
|
84
|
+
tolerance: 5,
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
useSensor(PointerSensor, {
|
|
88
|
+
activationConstraint: {
|
|
89
|
+
distance: 10,
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
useSensor(KeyboardSensor, {
|
|
93
|
+
coordinateGetter: sortableKeyboardCoordinates,
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const handleDragStart = (event: DragStartEvent) => {
|
|
98
|
+
setActiveId(event.active.id as string);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const handleDragEnd = (event: DragEndEvent) => {
|
|
102
|
+
const { active, over } = event;
|
|
103
|
+
setActiveId(null);
|
|
104
|
+
|
|
105
|
+
if (!over || active.id === over.id) return;
|
|
106
|
+
|
|
107
|
+
const oldIndex = items.findIndex((item) => item.id === active.id);
|
|
108
|
+
const newIndex = items.findIndex((item) => item.id === over.id);
|
|
109
|
+
if (oldIndex === -1 || newIndex === -1) return;
|
|
110
|
+
|
|
111
|
+
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
112
|
+
setItems(newItems);
|
|
113
|
+
changeOriginDataSource(newItems);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const activeItem = items.find((item) => item.id === activeId);
|
|
101
117
|
|
|
102
118
|
return (
|
|
103
|
-
<
|
|
104
|
-
{
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
/>
|
|
123
|
-
|
|
119
|
+
<DndContext
|
|
120
|
+
sensors={sensors}
|
|
121
|
+
collisionDetection={closestCenter}
|
|
122
|
+
onDragStart={handleDragStart}
|
|
123
|
+
onDragEnd={handleDragEnd}
|
|
124
|
+
>
|
|
125
|
+
<SortableContext items={items} strategy={verticalListSortingStrategy}>
|
|
126
|
+
<div className="sortDrag">
|
|
127
|
+
{items.map((item) => (
|
|
128
|
+
<SortableItem key={item.id} item={item} />
|
|
129
|
+
))}
|
|
130
|
+
</div>
|
|
131
|
+
</SortableContext>
|
|
132
|
+
<DragOverlay dropAnimation={null}>
|
|
133
|
+
{activeItem ? (
|
|
134
|
+
<div className="sortDrag-overlay">
|
|
135
|
+
<div className="sortDrag-overlay-inner">
|
|
136
|
+
<div className="dragBody">{activeItem.cpn}</div>
|
|
137
|
+
<div className="sortDrag-overlay-handle">
|
|
138
|
+
<HolderOutlined className="sortDrag-overlay-handleIcon" />
|
|
139
|
+
</div>
|
|
124
140
|
</div>
|
|
125
141
|
</div>
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
</
|
|
142
|
+
) : null}
|
|
143
|
+
</DragOverlay>
|
|
144
|
+
</DndContext>
|
|
129
145
|
);
|
|
130
146
|
});
|
|
131
147
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React, { ReactNode } from "react";
|
|
2
|
+
import type { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities";
|
|
2
3
|
import "./EnhancedSortDrag.less";
|
|
4
|
+
type DndListeners = SyntheticListenerMap | undefined;
|
|
3
5
|
/**
|
|
4
6
|
* 拖拽项数据类型定义
|
|
5
7
|
*/
|
|
@@ -27,7 +29,7 @@ export interface EnhancedSortDragProps {
|
|
|
27
29
|
/** 拖拽失败回调 */
|
|
28
30
|
onDragFail?: (error: DragError) => void;
|
|
29
31
|
/** 自定义拖拽句柄渲染 */
|
|
30
|
-
renderDragHandle?: (item: DragItem, isDragging: boolean) => ReactNode;
|
|
32
|
+
renderDragHandle?: (item: DragItem, isDragging: boolean, listeners?: DndListeners) => ReactNode;
|
|
31
33
|
/** 拖拽预览内容 */
|
|
32
34
|
renderDragPreview?: (item: DragItem) => ReactNode;
|
|
33
35
|
/** 是否为表格行模式 */
|