@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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # @splicetree/plugin-dnd
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 拖拽插件增强:
8
+ - 新增 `configuration.dnd.handle`:仅在指定句柄元素上允许拖拽(如 `.handle`);未设置时整个节点可拖拽
9
+ - 新增 `configuration.dnd.color`:统一占位(ghost)颜色配置
10
+
3
11
  ## 1.1.0
4
12
 
5
13
  ## 1.0.0
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 { autoExpandOnDrop = true, autoUpdateParent = true, readonly = false } = ctx.options?.configuration?.dnd ?? {};
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: "var(--vp-code-color)",
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: "var(--vp-code-color)",
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: "var(--vp-code-color)",
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": "1.1.0",
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": "1.1.0"
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: 'var(--vp-code-color)', borderRadius: '2px' }, 'data-drop-position': -1 }
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: 'var(--vp-code-color)', borderRadius: '2px' }, 'data-drop-position': 1 }
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: 'var(--vp-code-color)', opacity: 0.15, borderRadius: '4px' }, 'data-drop-position': 0 }
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 {
package/src/types.ts CHANGED
@@ -26,4 +26,8 @@ export interface DndOptions {
26
26
  autoExpandOnDrop?: boolean
27
27
  /** 全局只读,禁用所有拖拽与排序 */
28
28
  readonly?: boolean
29
+ /** 统一占位(ghost)指示颜色,默认 '#4224da' */
30
+ color?: string
31
+ /** 仅在匹配的句柄元素上允许拖拽(如 '.handle') */
32
+ handle?: string
29
33
  }