@haklex/rich-plugin-block-handle 0.0.4 → 0.0.6
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/BlockHandlePlugin.d.ts.map +1 -1
- package/dist/index.mjs +63 -15
- package/package.json +15 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockHandlePlugin.d.ts","sourceRoot":"","sources":["../src/BlockHandlePlugin.tsx"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAGV,YAAY,EACb,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"BlockHandlePlugin.d.ts","sourceRoot":"","sources":["../src/BlockHandlePlugin.tsx"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAGV,YAAY,EACb,MAAM,OAAO,CAAA;AAmqBd,wBAAgB,iBAAiB,IAAI,YAAY,CAGhD"}
|
package/dist/index.mjs
CHANGED
|
@@ -42,6 +42,54 @@ function getBlockElement(editor, target) {
|
|
|
42
42
|
}
|
|
43
43
|
return null;
|
|
44
44
|
}
|
|
45
|
+
function getNearestBlockByY(rootElement, clientY) {
|
|
46
|
+
const blocks = Array.from(rootElement.children).filter(
|
|
47
|
+
(child) => child instanceof HTMLElement
|
|
48
|
+
);
|
|
49
|
+
if (!blocks.length) return null;
|
|
50
|
+
let nearestBlock = null;
|
|
51
|
+
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
52
|
+
for (const block of blocks) {
|
|
53
|
+
const rect = block.getBoundingClientRect();
|
|
54
|
+
if (rect.height <= 0) continue;
|
|
55
|
+
if (clientY >= rect.top && clientY <= rect.bottom) return block;
|
|
56
|
+
const distance = clientY < rect.top ? rect.top - clientY : clientY - rect.bottom;
|
|
57
|
+
if (distance < nearestDistance) {
|
|
58
|
+
nearestDistance = distance;
|
|
59
|
+
nearestBlock = block;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return nearestBlock;
|
|
63
|
+
}
|
|
64
|
+
function getDropTargetBlock(editor, rootElement, event) {
|
|
65
|
+
const rootRect = rootElement.getBoundingClientRect();
|
|
66
|
+
if (rootRect.width <= 0 || rootRect.height <= 0) return null;
|
|
67
|
+
if (event.clientY < rootRect.top || event.clientY > rootRect.bottom) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const points = [
|
|
71
|
+
{ x: event.clientX, y: event.clientY }
|
|
72
|
+
];
|
|
73
|
+
const clampedX = Math.min(
|
|
74
|
+
rootRect.right - 1,
|
|
75
|
+
Math.max(rootRect.left + 1, event.clientX)
|
|
76
|
+
);
|
|
77
|
+
if (clampedX !== event.clientX) {
|
|
78
|
+
points.unshift({ x: clampedX, y: event.clientY });
|
|
79
|
+
}
|
|
80
|
+
for (const point of points) {
|
|
81
|
+
const element = document.elementFromPoint(point.x, point.y);
|
|
82
|
+
if (!(element instanceof HTMLElement)) continue;
|
|
83
|
+
const block = getBlockElement(editor, element);
|
|
84
|
+
if (block) return block;
|
|
85
|
+
}
|
|
86
|
+
const { target } = event;
|
|
87
|
+
if (target instanceof HTMLElement) {
|
|
88
|
+
const block = getBlockElement(editor, target);
|
|
89
|
+
if (block) return block;
|
|
90
|
+
}
|
|
91
|
+
return getNearestBlockByY(rootElement, event.clientY);
|
|
92
|
+
}
|
|
45
93
|
function toPagePosition(rect) {
|
|
46
94
|
return {
|
|
47
95
|
top: rect.top + window.scrollY,
|
|
@@ -353,20 +401,21 @@ function BlockHandleInner({
|
|
|
353
401
|
if (!event.dataTransfer?.types.includes(DRAG_DATA_KEY)) return false;
|
|
354
402
|
event.preventDefault();
|
|
355
403
|
event.dataTransfer.dropEffect = "move";
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const rootRect = rootElement.getBoundingClientRect();
|
|
361
|
-
const midY = rect.top + rect.height / 2;
|
|
362
|
-
const y = event.clientY < midY ? rect.top : rect.bottom;
|
|
363
|
-
setDropLine({
|
|
364
|
-
visible: true,
|
|
365
|
-
top: y + window.scrollY,
|
|
366
|
-
left: rootRect.left + window.scrollX,
|
|
367
|
-
width: rootRect.width
|
|
368
|
-
});
|
|
404
|
+
const block = getDropTargetBlock(editor, rootElement, event);
|
|
405
|
+
if (!block) {
|
|
406
|
+
setDropLine((s) => s.visible ? { ...s, visible: false } : s);
|
|
407
|
+
return true;
|
|
369
408
|
}
|
|
409
|
+
const rect = block.getBoundingClientRect();
|
|
410
|
+
const rootRect = rootElement.getBoundingClientRect();
|
|
411
|
+
const midY = rect.top + rect.height / 2;
|
|
412
|
+
const y = event.clientY < midY ? rect.top : rect.bottom;
|
|
413
|
+
setDropLine({
|
|
414
|
+
visible: true,
|
|
415
|
+
top: y + window.scrollY,
|
|
416
|
+
left: rootRect.left + window.scrollX,
|
|
417
|
+
width: rootRect.width
|
|
418
|
+
});
|
|
370
419
|
return true;
|
|
371
420
|
},
|
|
372
421
|
COMMAND_PRIORITY_HIGH
|
|
@@ -379,8 +428,7 @@ function BlockHandleInner({
|
|
|
379
428
|
event.preventDefault();
|
|
380
429
|
setDropLine((s) => ({ ...s, visible: false }));
|
|
381
430
|
clearDragVisualState();
|
|
382
|
-
const
|
|
383
|
-
const block = getBlockElement(editor, target);
|
|
431
|
+
const block = getDropTargetBlock(editor, rootElement, event);
|
|
384
432
|
if (!block) return false;
|
|
385
433
|
editor.update(() => {
|
|
386
434
|
const draggedNode = $getNodeByKey(draggedKey);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haklex/rich-plugin-block-handle",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Block handle plugin with add button and context menu",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -16,20 +16,20 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@haklex/rich-editor-ui": "0.0.
|
|
20
|
-
"@haklex/rich-style-token": "0.0.
|
|
19
|
+
"@haklex/rich-editor-ui": "0.0.6",
|
|
20
|
+
"@haklex/rich-style-token": "0.0.6"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@lexical/code": "^0.
|
|
24
|
-
"@lexical/list": "^0.
|
|
25
|
-
"@lexical/react": "^0.
|
|
26
|
-
"@lexical/rich-text": "^0.
|
|
27
|
-
"@lexical/selection": "^0.
|
|
23
|
+
"@lexical/code": "^0.40.0",
|
|
24
|
+
"@lexical/list": "^0.40.0",
|
|
25
|
+
"@lexical/react": "^0.40.0",
|
|
26
|
+
"@lexical/rich-text": "^0.40.0",
|
|
27
|
+
"@lexical/selection": "^0.40.0",
|
|
28
28
|
"@types/react": "^19.0.0",
|
|
29
29
|
"@types/react-dom": "^19.0.0",
|
|
30
30
|
"@vanilla-extract/css": "^1.17.1",
|
|
31
31
|
"@vanilla-extract/vite-plugin": "^4.0.20",
|
|
32
|
-
"lexical": "^0.
|
|
32
|
+
"lexical": "^0.40.0",
|
|
33
33
|
"lucide-react": "^0.574.0",
|
|
34
34
|
"react": "19.2.4",
|
|
35
35
|
"react-dom": "19.2.4",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"vite-plugin-dts": "^4.5.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@lexical/code": "^0.
|
|
42
|
-
"@lexical/list": "^0.
|
|
43
|
-
"@lexical/react": "^0.
|
|
44
|
-
"@lexical/rich-text": "^0.
|
|
45
|
-
"@lexical/selection": "^0.
|
|
46
|
-
"lexical": "^0.
|
|
41
|
+
"@lexical/code": "^0.40.0",
|
|
42
|
+
"@lexical/list": "^0.40.0",
|
|
43
|
+
"@lexical/react": "^0.40.0",
|
|
44
|
+
"@lexical/rich-text": "^0.40.0",
|
|
45
|
+
"@lexical/selection": "^0.40.0",
|
|
46
|
+
"lexical": "^0.40.0",
|
|
47
47
|
"lucide-react": "^0.574.0",
|
|
48
48
|
"react": ">=19",
|
|
49
49
|
"react-dom": ">=19"
|