@splicetree/plugin-dnd 1.1.0 → 2.0.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/CHANGELOG.md +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +26 -7
- package/package.json +2 -2
- package/src/index.ts +30 -3
- package/src/types.ts +4 -0
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,10 @@ interface DndOptions {
|
|
|
25
25
|
autoExpandOnDrop?: boolean;
|
|
26
26
|
/** 全局只读,禁用所有拖拽与排序 */
|
|
27
27
|
readonly?: boolean;
|
|
28
|
+
/** 统一占位(ghost)指示颜色,默认 '#4224da' */
|
|
29
|
+
color?: string;
|
|
30
|
+
/** 仅在匹配的句柄元素上允许拖拽(如 '.handle') */
|
|
31
|
+
handle?: string;
|
|
28
32
|
}
|
|
29
33
|
//#endregion
|
|
30
34
|
//#region src/index.d.ts
|
|
@@ -71,8 +75,12 @@ declare module '@splicetree/core' {
|
|
|
71
75
|
dragProps: (id: string, behavior?: DragBehavior) => {
|
|
72
76
|
/** 是否可拖拽 */
|
|
73
77
|
draggable: boolean;
|
|
78
|
+
/** 鼠标按下,用于句柄检测 */
|
|
79
|
+
onMousedown: (e: MouseEvent) => void;
|
|
74
80
|
/** 原生拖拽开始事件处理 */
|
|
75
81
|
onDragstart: (e: DragEvent) => void;
|
|
82
|
+
/** 原生拖拽结束事件处理 */
|
|
83
|
+
onDragend: (e: DragEvent) => void;
|
|
76
84
|
/** 原生拖拽悬停事件处理 */
|
|
77
85
|
onDragover: (e: DragEvent) => void;
|
|
78
86
|
/** 原生拖拽离开事件处理 */
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,11 @@ function computePosition(targetId, el, e, src) {
|
|
|
24
24
|
const dnd = {
|
|
25
25
|
name: "dnd",
|
|
26
26
|
setup(ctx) {
|
|
27
|
-
const
|
|
27
|
+
const opts = ctx.options?.configuration?.dnd ?? {};
|
|
28
|
+
const { autoExpandOnDrop = true, autoUpdateParent = true, readonly = false } = opts;
|
|
29
|
+
const color = opts.color ?? "#4224da";
|
|
30
|
+
const handleSelector = opts.handle;
|
|
31
|
+
const handleActive = /* @__PURE__ */ new Set();
|
|
28
32
|
const parentField = ctx.tree.options?.configuration?.parentField ?? "parent";
|
|
29
33
|
let draggingId;
|
|
30
34
|
const hoverPositions = /* @__PURE__ */ new Map();
|
|
@@ -285,12 +289,26 @@ const dnd = {
|
|
|
285
289
|
const canDrag = behavior?.draggable === false ? false : !isDisabledById(id);
|
|
286
290
|
return {
|
|
287
291
|
draggable: canDrag,
|
|
292
|
+
onMousedown: (e) => {
|
|
293
|
+
if (!handleSelector) return;
|
|
294
|
+
if ((e.composedPath?.())?.some((el) => el?.matches?.(handleSelector)) ?? false) handleActive.add(id);
|
|
295
|
+
else handleActive.delete(id);
|
|
296
|
+
},
|
|
288
297
|
onDragstart: (e) => {
|
|
289
298
|
if (canDrag) {
|
|
299
|
+
if (handleSelector) {
|
|
300
|
+
if (!handleActive.has(id)) {
|
|
301
|
+
e.preventDefault();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
290
305
|
e.dataTransfer?.setData("text/plain", id);
|
|
291
306
|
onDragStart(id);
|
|
292
307
|
}
|
|
293
308
|
},
|
|
309
|
+
onDragend: (_e) => {
|
|
310
|
+
handleActive.delete(id);
|
|
311
|
+
},
|
|
294
312
|
onDragover: (e) => {
|
|
295
313
|
e.preventDefault();
|
|
296
314
|
const el = e.currentTarget;
|
|
@@ -302,13 +320,14 @@ const dnd = {
|
|
|
302
320
|
onDrop: (e) => {
|
|
303
321
|
e.preventDefault();
|
|
304
322
|
onDrop(id);
|
|
323
|
+
handleActive.delete(id);
|
|
305
324
|
}
|
|
306
325
|
};
|
|
307
326
|
};
|
|
308
|
-
const ghostStyle = (opts) => {
|
|
327
|
+
const ghostStyle = (opts$1) => {
|
|
309
328
|
if (!draggingId || ghostPos === void 0) return { style: { display: "none" } };
|
|
310
|
-
const usePadding = opts?.padding ?? true;
|
|
311
|
-
const useMargin = opts?.margin ?? true;
|
|
329
|
+
const usePadding = opts$1?.padding ?? true;
|
|
330
|
+
const useMargin = opts$1?.margin ?? true;
|
|
312
331
|
const leftInset = usePadding ? ghostInsetLeft : 0;
|
|
313
332
|
const rightInset = usePadding ? ghostInsetRight : 0;
|
|
314
333
|
const leftMargin = useMargin ? ghostMarginLeft : 0;
|
|
@@ -324,7 +343,7 @@ const dnd = {
|
|
|
324
343
|
...base,
|
|
325
344
|
top: `${ghostTop}px`,
|
|
326
345
|
height: "2px",
|
|
327
|
-
background:
|
|
346
|
+
background: color,
|
|
328
347
|
borderRadius: "2px"
|
|
329
348
|
},
|
|
330
349
|
"data-drop-position": -1
|
|
@@ -334,7 +353,7 @@ const dnd = {
|
|
|
334
353
|
...base,
|
|
335
354
|
top: `${ghostTop + ghostHeight}px`,
|
|
336
355
|
height: "2px",
|
|
337
|
-
background:
|
|
356
|
+
background: color,
|
|
338
357
|
borderRadius: "2px"
|
|
339
358
|
},
|
|
340
359
|
"data-drop-position": 1
|
|
@@ -344,7 +363,7 @@ const dnd = {
|
|
|
344
363
|
...base,
|
|
345
364
|
top: `${ghostTop}px`,
|
|
346
365
|
height: `${ghostHeight}px`,
|
|
347
|
-
background:
|
|
366
|
+
background: color,
|
|
348
367
|
opacity: .15,
|
|
349
368
|
borderRadius: "4px"
|
|
350
369
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@splicetree/plugin-dnd",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"email": "michael.cocova@gmail.com",
|
|
7
7
|
"name": "Michael Cocova"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@splicetree/core": "
|
|
26
|
+
"@splicetree/core": "2.0.0"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"dev": "tsdown --watch",
|
package/src/index.ts
CHANGED
|
@@ -43,8 +43,12 @@ declare module '@splicetree/core' {
|
|
|
43
43
|
dragProps: (id: string, behavior?: DragBehavior) => {
|
|
44
44
|
/** 是否可拖拽 */
|
|
45
45
|
draggable: boolean
|
|
46
|
+
/** 鼠标按下,用于句柄检测 */
|
|
47
|
+
onMousedown: (e: MouseEvent) => void
|
|
46
48
|
/** 原生拖拽开始事件处理 */
|
|
47
49
|
onDragstart: (e: DragEvent) => void
|
|
50
|
+
/** 原生拖拽结束事件处理 */
|
|
51
|
+
onDragend: (e: DragEvent) => void
|
|
48
52
|
/** 原生拖拽悬停事件处理 */
|
|
49
53
|
onDragover: (e: DragEvent) => void
|
|
50
54
|
/** 原生拖拽离开事件处理 */
|
|
@@ -85,6 +89,9 @@ export const dnd: SpliceTreePlugin = {
|
|
|
85
89
|
autoUpdateParent = true,
|
|
86
90
|
readonly = false,
|
|
87
91
|
} = opts
|
|
92
|
+
const color = opts.color ?? '#4224da'
|
|
93
|
+
const handleSelector = opts.handle
|
|
94
|
+
const handleActive = new Set<string>()
|
|
88
95
|
const parentField = ctx.tree.options?.configuration?.parentField ?? 'parent'
|
|
89
96
|
let draggingId: string | undefined
|
|
90
97
|
const hoverPositions = new Map<string, DropPosition>()
|
|
@@ -364,12 +371,31 @@ export const dnd: SpliceTreePlugin = {
|
|
|
364
371
|
const canDrag = behavior?.draggable === false ? false : !isDisabledById(id)
|
|
365
372
|
return {
|
|
366
373
|
draggable: canDrag,
|
|
374
|
+
onMousedown: (e: MouseEvent) => {
|
|
375
|
+
if (!handleSelector) return
|
|
376
|
+
const path = (e as any).composedPath?.() as Element[] | undefined
|
|
377
|
+
const allowed = path?.some(el => (el as Element)?.matches?.(handleSelector)) ?? false
|
|
378
|
+
if (allowed) {
|
|
379
|
+
handleActive.add(id)
|
|
380
|
+
} else {
|
|
381
|
+
handleActive.delete(id)
|
|
382
|
+
}
|
|
383
|
+
},
|
|
367
384
|
onDragstart: (e: DragEvent) => {
|
|
368
385
|
if (canDrag) {
|
|
386
|
+
if (handleSelector) {
|
|
387
|
+
if (!handleActive.has(id)) {
|
|
388
|
+
e.preventDefault()
|
|
389
|
+
return
|
|
390
|
+
}
|
|
391
|
+
}
|
|
369
392
|
e.dataTransfer?.setData('text/plain', id)
|
|
370
393
|
onDragStart(id)
|
|
371
394
|
}
|
|
372
395
|
},
|
|
396
|
+
onDragend: (_e: DragEvent) => {
|
|
397
|
+
handleActive.delete(id)
|
|
398
|
+
},
|
|
373
399
|
onDragover: (e: DragEvent) => {
|
|
374
400
|
e.preventDefault()
|
|
375
401
|
const el = e.currentTarget as HTMLElement
|
|
@@ -381,6 +407,7 @@ export const dnd: SpliceTreePlugin = {
|
|
|
381
407
|
onDrop: (e: DragEvent) => {
|
|
382
408
|
e.preventDefault()
|
|
383
409
|
onDrop(id)
|
|
410
|
+
handleActive.delete(id)
|
|
384
411
|
},
|
|
385
412
|
}
|
|
386
413
|
}
|
|
@@ -399,12 +426,12 @@ export const dnd: SpliceTreePlugin = {
|
|
|
399
426
|
const right = `${rightInset + rightMargin}px`
|
|
400
427
|
const base: Record<string, any> = { position: 'absolute', left, right, pointerEvents: 'none' }
|
|
401
428
|
if (ghostPos === DropPosition.BEFORE) {
|
|
402
|
-
return { 'style': { ...base, top: `${ghostTop}px`, height: '2px', background:
|
|
429
|
+
return { 'style': { ...base, top: `${ghostTop}px`, height: '2px', background: color, borderRadius: '2px' }, 'data-drop-position': -1 }
|
|
403
430
|
}
|
|
404
431
|
if (ghostPos === DropPosition.AFTER) {
|
|
405
|
-
return { 'style': { ...base, top: `${ghostTop + ghostHeight}px`, height: '2px', background:
|
|
432
|
+
return { 'style': { ...base, top: `${ghostTop + ghostHeight}px`, height: '2px', background: color, borderRadius: '2px' }, 'data-drop-position': 1 }
|
|
406
433
|
}
|
|
407
|
-
return { 'style': { ...base, top: `${ghostTop}px`, height: `${ghostHeight}px`, background:
|
|
434
|
+
return { 'style': { ...base, top: `${ghostTop}px`, height: `${ghostHeight}px`, background: color, opacity: 0.15, borderRadius: '4px' }, 'data-drop-position': 0 }
|
|
408
435
|
}
|
|
409
436
|
|
|
410
437
|
return {
|