@trafica/editor 1.0.45 → 1.0.47
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 +135 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +135 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8036,6 +8036,7 @@ function EditorCore({
|
|
|
8036
8036
|
const isComposingRef = react.useRef(false);
|
|
8037
8037
|
const stateRef = react.useRef(engine.getState());
|
|
8038
8038
|
const [selectedImagePath, setSelectedImagePath] = react.useState(null);
|
|
8039
|
+
const [imageDragState, setImageDragState] = react.useState(null);
|
|
8039
8040
|
const [findReplaceOpen, setFindReplaceOpen] = react.useState(false);
|
|
8040
8041
|
const [findReplaceMode, setFindReplaceMode] = react.useState("find");
|
|
8041
8042
|
const [linkPopupOpen, setLinkPopupOpen] = react.useState(false);
|
|
@@ -8516,7 +8517,19 @@ function EditorCore({
|
|
|
8516
8517
|
const fig = target.closest("[data-image-path]");
|
|
8517
8518
|
if (fig == null ? void 0 : fig.dataset.imagePath) {
|
|
8518
8519
|
e.preventDefault();
|
|
8519
|
-
|
|
8520
|
+
const path = JSON.parse(fig.dataset.imagePath);
|
|
8521
|
+
setSelectedImagePath(path);
|
|
8522
|
+
const imgEl = fig.querySelector("img");
|
|
8523
|
+
const rect = imgEl == null ? void 0 : imgEl.getBoundingClientRect();
|
|
8524
|
+
imageDragRef.current = {
|
|
8525
|
+
imagePath: path,
|
|
8526
|
+
startX: e.clientX,
|
|
8527
|
+
startY: e.clientY,
|
|
8528
|
+
active: false,
|
|
8529
|
+
ghostW: Math.min((rect == null ? void 0 : rect.width) || 300, 320),
|
|
8530
|
+
ghostH: Math.min((rect == null ? void 0 : rect.height) || 200, 200),
|
|
8531
|
+
ghostSrc: (imgEl == null ? void 0 : imgEl.src) || ""
|
|
8532
|
+
};
|
|
8520
8533
|
return;
|
|
8521
8534
|
}
|
|
8522
8535
|
setSelectedImagePath(null);
|
|
@@ -8569,6 +8582,7 @@ function EditorCore({
|
|
|
8569
8582
|
engine.dispatch(tr);
|
|
8570
8583
|
}, [engine]);
|
|
8571
8584
|
const imageResizeRef = react.useRef(null);
|
|
8585
|
+
const imageDragRef = react.useRef(null);
|
|
8572
8586
|
react.useEffect(() => {
|
|
8573
8587
|
const onMouseMove = (e) => {
|
|
8574
8588
|
const drag = imageResizeRef.current;
|
|
@@ -8601,6 +8615,48 @@ function EditorCore({
|
|
|
8601
8615
|
document.removeEventListener("mouseup", onMouseUp);
|
|
8602
8616
|
};
|
|
8603
8617
|
}, [engine]);
|
|
8618
|
+
react.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]);
|
|
8604
8660
|
react.useEffect(() => {
|
|
8605
8661
|
const container = containerRef.current;
|
|
8606
8662
|
if (!container) return;
|
|
@@ -8718,6 +8774,19 @@ function EditorCore({
|
|
|
8718
8774
|
].join(" ")
|
|
8719
8775
|
}
|
|
8720
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__ */ jsxRuntime.jsx(
|
|
8783
|
+
"div",
|
|
8784
|
+
{
|
|
8785
|
+
className: "editor-image-drop-indicator",
|
|
8786
|
+
style: { top: relY }
|
|
8787
|
+
}
|
|
8788
|
+
);
|
|
8789
|
+
})(),
|
|
8721
8790
|
linkTooltip && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8722
8791
|
"div",
|
|
8723
8792
|
{
|
|
@@ -8778,6 +8847,26 @@ function EditorCore({
|
|
|
8778
8847
|
onClose: () => setSelectedImagePath(null)
|
|
8779
8848
|
}
|
|
8780
8849
|
),
|
|
8850
|
+
imageDragState && /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
|
|
8861
|
+
"img",
|
|
8862
|
+
{
|
|
8863
|
+
src: imageDragState.ghostSrc,
|
|
8864
|
+
alt: "",
|
|
8865
|
+
style: { width: "100%", height: "100%", objectFit: "contain", display: "block" }
|
|
8866
|
+
}
|
|
8867
|
+
)
|
|
8868
|
+
}
|
|
8869
|
+
),
|
|
8781
8870
|
!readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8782
8871
|
"div",
|
|
8783
8872
|
{
|
|
@@ -8800,6 +8889,51 @@ function EditorCore({
|
|
|
8800
8889
|
}
|
|
8801
8890
|
);
|
|
8802
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 isTopLevel = imagePath.length === 1;
|
|
8923
|
+
const topLevelIndex = imagePath[0];
|
|
8924
|
+
let adj = targetIndex;
|
|
8925
|
+
if (isTopLevel) {
|
|
8926
|
+
if (targetIndex > topLevelIndex) adj = targetIndex - 1;
|
|
8927
|
+
adj = Math.max(0, Math.min(state.doc.children.length - 1, adj));
|
|
8928
|
+
if (adj === topLevelIndex) return;
|
|
8929
|
+
} else {
|
|
8930
|
+
adj = Math.max(0, Math.min(state.doc.children.length, adj));
|
|
8931
|
+
}
|
|
8932
|
+
const tr = createTransaction();
|
|
8933
|
+
tr.steps.push({ type: "delete_node", path: imagePath });
|
|
8934
|
+
tr.steps.push({ type: "insert_node", parentPath: [], index: adj, node: imageNode });
|
|
8935
|
+
engine.dispatch(tr);
|
|
8936
|
+
}
|
|
8803
8937
|
var BLOCK_TAGS = "p|h[1-6]|ul|ol|li|blockquote|pre|figure|table|thead|tbody|tr|th|td";
|
|
8804
8938
|
var _OPEN_ONLY_RE = new RegExp(`^<(${BLOCK_TAGS})(?:\\s[^>]*)?>$`, "i");
|
|
8805
8939
|
var _CLOSE_ONLY_RE = new RegExp(`^<\\/(${BLOCK_TAGS})>$`, "i");
|