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