@trafica/editor 1.0.45 → 1.0.46
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/index.js +132 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +132 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -8034,6 +8034,7 @@ function EditorCore({
|
|
|
8034
8034
|
const isComposingRef = useRef(false);
|
|
8035
8035
|
const stateRef = useRef(engine.getState());
|
|
8036
8036
|
const [selectedImagePath, setSelectedImagePath] = useState(null);
|
|
8037
|
+
const [imageDragState, setImageDragState] = useState(null);
|
|
8037
8038
|
const [findReplaceOpen, setFindReplaceOpen] = useState(false);
|
|
8038
8039
|
const [findReplaceMode, setFindReplaceMode] = useState("find");
|
|
8039
8040
|
const [linkPopupOpen, setLinkPopupOpen] = useState(false);
|
|
@@ -8514,7 +8515,21 @@ function EditorCore({
|
|
|
8514
8515
|
const fig = target.closest("[data-image-path]");
|
|
8515
8516
|
if (fig == null ? void 0 : fig.dataset.imagePath) {
|
|
8516
8517
|
e.preventDefault();
|
|
8517
|
-
|
|
8518
|
+
const path = JSON.parse(fig.dataset.imagePath);
|
|
8519
|
+
setSelectedImagePath(path);
|
|
8520
|
+
if (path.length === 1) {
|
|
8521
|
+
const imgEl = fig.querySelector("img");
|
|
8522
|
+
const rect = imgEl == null ? void 0 : imgEl.getBoundingClientRect();
|
|
8523
|
+
imageDragRef.current = {
|
|
8524
|
+
imagePath: path,
|
|
8525
|
+
startX: e.clientX,
|
|
8526
|
+
startY: e.clientY,
|
|
8527
|
+
active: false,
|
|
8528
|
+
ghostW: Math.min((rect == null ? void 0 : rect.width) || 300, 320),
|
|
8529
|
+
ghostH: Math.min((rect == null ? void 0 : rect.height) || 200, 200),
|
|
8530
|
+
ghostSrc: (imgEl == null ? void 0 : imgEl.src) || ""
|
|
8531
|
+
};
|
|
8532
|
+
}
|
|
8518
8533
|
return;
|
|
8519
8534
|
}
|
|
8520
8535
|
setSelectedImagePath(null);
|
|
@@ -8567,6 +8582,7 @@ function EditorCore({
|
|
|
8567
8582
|
engine.dispatch(tr);
|
|
8568
8583
|
}, [engine]);
|
|
8569
8584
|
const imageResizeRef = useRef(null);
|
|
8585
|
+
const imageDragRef = useRef(null);
|
|
8570
8586
|
useEffect(() => {
|
|
8571
8587
|
const onMouseMove = (e) => {
|
|
8572
8588
|
const drag = imageResizeRef.current;
|
|
@@ -8599,6 +8615,48 @@ function EditorCore({
|
|
|
8599
8615
|
document.removeEventListener("mouseup", onMouseUp);
|
|
8600
8616
|
};
|
|
8601
8617
|
}, [engine]);
|
|
8618
|
+
useEffect(() => {
|
|
8619
|
+
const DRAG_THRESHOLD = 6;
|
|
8620
|
+
const onMouseMove = (e) => {
|
|
8621
|
+
const drag = imageDragRef.current;
|
|
8622
|
+
if (!drag) return;
|
|
8623
|
+
const dx = e.clientX - drag.startX;
|
|
8624
|
+
const dy = e.clientY - drag.startY;
|
|
8625
|
+
if (!drag.active && Math.sqrt(dx * dx + dy * dy) < DRAG_THRESHOLD) return;
|
|
8626
|
+
drag.active = true;
|
|
8627
|
+
const container = containerRef.current;
|
|
8628
|
+
const { dropIndex, indicatorClientY } = getImageDropTarget(container, e.clientY, drag.imagePath);
|
|
8629
|
+
setImageDragState({
|
|
8630
|
+
ghostX: e.clientX,
|
|
8631
|
+
ghostY: e.clientY,
|
|
8632
|
+
ghostW: drag.ghostW,
|
|
8633
|
+
ghostH: drag.ghostH,
|
|
8634
|
+
ghostSrc: drag.ghostSrc,
|
|
8635
|
+
dropIndicatorClientY: indicatorClientY,
|
|
8636
|
+
dropIndex,
|
|
8637
|
+
imagePath: drag.imagePath
|
|
8638
|
+
});
|
|
8639
|
+
};
|
|
8640
|
+
const onMouseUp = (e) => {
|
|
8641
|
+
const drag = imageDragRef.current;
|
|
8642
|
+
if (!drag) return;
|
|
8643
|
+
imageDragRef.current = null;
|
|
8644
|
+
if (!drag.active) {
|
|
8645
|
+
setImageDragState(null);
|
|
8646
|
+
return;
|
|
8647
|
+
}
|
|
8648
|
+
const container = containerRef.current;
|
|
8649
|
+
const { dropIndex } = getImageDropTarget(container, e.clientY, drag.imagePath);
|
|
8650
|
+
setImageDragState(null);
|
|
8651
|
+
moveImageInDoc(drag.imagePath, dropIndex, engine);
|
|
8652
|
+
};
|
|
8653
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
8654
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
8655
|
+
return () => {
|
|
8656
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
8657
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
8658
|
+
};
|
|
8659
|
+
}, [engine]);
|
|
8602
8660
|
useEffect(() => {
|
|
8603
8661
|
const container = containerRef.current;
|
|
8604
8662
|
if (!container) return;
|
|
@@ -8716,6 +8774,19 @@ function EditorCore({
|
|
|
8716
8774
|
].join(" ")
|
|
8717
8775
|
}
|
|
8718
8776
|
),
|
|
8777
|
+
imageDragState && (() => {
|
|
8778
|
+
const container = containerRef.current;
|
|
8779
|
+
if (!container) return null;
|
|
8780
|
+
const cr = container.getBoundingClientRect();
|
|
8781
|
+
const relY = imageDragState.dropIndicatorClientY - cr.top + container.scrollTop;
|
|
8782
|
+
return /* @__PURE__ */ jsx(
|
|
8783
|
+
"div",
|
|
8784
|
+
{
|
|
8785
|
+
className: "editor-image-drop-indicator",
|
|
8786
|
+
style: { top: relY }
|
|
8787
|
+
}
|
|
8788
|
+
);
|
|
8789
|
+
})(),
|
|
8719
8790
|
linkTooltip && /* @__PURE__ */ jsxs(
|
|
8720
8791
|
"div",
|
|
8721
8792
|
{
|
|
@@ -8776,6 +8847,26 @@ function EditorCore({
|
|
|
8776
8847
|
onClose: () => setSelectedImagePath(null)
|
|
8777
8848
|
}
|
|
8778
8849
|
),
|
|
8850
|
+
imageDragState && /* @__PURE__ */ jsx(
|
|
8851
|
+
"div",
|
|
8852
|
+
{
|
|
8853
|
+
className: "editor-image-drag-ghost",
|
|
8854
|
+
style: {
|
|
8855
|
+
left: imageDragState.ghostX,
|
|
8856
|
+
top: imageDragState.ghostY,
|
|
8857
|
+
width: imageDragState.ghostW,
|
|
8858
|
+
height: imageDragState.ghostH
|
|
8859
|
+
},
|
|
8860
|
+
children: /* @__PURE__ */ jsx(
|
|
8861
|
+
"img",
|
|
8862
|
+
{
|
|
8863
|
+
src: imageDragState.ghostSrc,
|
|
8864
|
+
alt: "",
|
|
8865
|
+
style: { width: "100%", height: "100%", objectFit: "contain", display: "block" }
|
|
8866
|
+
}
|
|
8867
|
+
)
|
|
8868
|
+
}
|
|
8869
|
+
),
|
|
8779
8870
|
!readOnly && /* @__PURE__ */ jsx(
|
|
8780
8871
|
"div",
|
|
8781
8872
|
{
|
|
@@ -8798,6 +8889,46 @@ function EditorCore({
|
|
|
8798
8889
|
}
|
|
8799
8890
|
);
|
|
8800
8891
|
}
|
|
8892
|
+
function getImageDropTarget(container, clientY, imagePath) {
|
|
8893
|
+
const fallback = { dropIndex: imagePath[0], indicatorClientY: clientY };
|
|
8894
|
+
if (!container) return fallback;
|
|
8895
|
+
const blocks = Array.from(
|
|
8896
|
+
container.querySelectorAll(":scope > [data-block-path]")
|
|
8897
|
+
);
|
|
8898
|
+
if (blocks.length === 0) return fallback;
|
|
8899
|
+
const gaps = [];
|
|
8900
|
+
gaps.push({ y: blocks[0].getBoundingClientRect().top, index: 0 });
|
|
8901
|
+
for (let i = 0; i < blocks.length - 1; i++) {
|
|
8902
|
+
const bottom = blocks[i].getBoundingClientRect().bottom;
|
|
8903
|
+
const top = blocks[i + 1].getBoundingClientRect().top;
|
|
8904
|
+
gaps.push({ y: (bottom + top) / 2, index: i + 1 });
|
|
8905
|
+
}
|
|
8906
|
+
gaps.push({ y: blocks[blocks.length - 1].getBoundingClientRect().bottom, index: blocks.length });
|
|
8907
|
+
let best = gaps[0];
|
|
8908
|
+
let bestDist = Math.abs(clientY - best.y);
|
|
8909
|
+
for (const gap of gaps) {
|
|
8910
|
+
const dist = Math.abs(clientY - gap.y);
|
|
8911
|
+
if (dist < bestDist) {
|
|
8912
|
+
bestDist = dist;
|
|
8913
|
+
best = gap;
|
|
8914
|
+
}
|
|
8915
|
+
}
|
|
8916
|
+
return { dropIndex: best.index, indicatorClientY: best.y };
|
|
8917
|
+
}
|
|
8918
|
+
function moveImageInDoc(imagePath, targetIndex, engine) {
|
|
8919
|
+
const state = engine.getState();
|
|
8920
|
+
const imageNode = getNodeAtPath(state.doc, imagePath);
|
|
8921
|
+
if (!imageNode) return;
|
|
8922
|
+
const oldIndex = imagePath[imagePath.length - 1];
|
|
8923
|
+
const parentPath = imagePath.slice(0, -1);
|
|
8924
|
+
let adj = targetIndex > oldIndex ? targetIndex - 1 : targetIndex;
|
|
8925
|
+
adj = Math.max(0, Math.min(state.doc.children.length - 1, adj));
|
|
8926
|
+
if (adj === oldIndex) return;
|
|
8927
|
+
const tr = createTransaction();
|
|
8928
|
+
tr.steps.push({ type: "delete_node", path: imagePath });
|
|
8929
|
+
tr.steps.push({ type: "insert_node", parentPath, index: adj, node: imageNode });
|
|
8930
|
+
engine.dispatch(tr);
|
|
8931
|
+
}
|
|
8801
8932
|
var BLOCK_TAGS = "p|h[1-6]|ul|ol|li|blockquote|pre|figure|table|thead|tbody|tr|th|td";
|
|
8802
8933
|
var _OPEN_ONLY_RE = new RegExp(`^<(${BLOCK_TAGS})(?:\\s[^>]*)?>$`, "i");
|
|
8803
8934
|
var _CLOSE_ONLY_RE = new RegExp(`^<\\/(${BLOCK_TAGS})>$`, "i");
|