@underverse-ui/underverse 1.0.71 → 1.0.72
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/api-reference.json +1 -1
- package/dist/index.cjs +336 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +336 -107
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -29039,6 +29039,19 @@ var import_lucide_react47 = require("lucide-react");
|
|
|
29039
29039
|
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
29040
29040
|
var FALLBACK_TABLE_ROW_HEIGHT = 44;
|
|
29041
29041
|
var FALLBACK_TABLE_COLUMN_WIDTH = 160;
|
|
29042
|
+
var MENU_HOVER_PADDING = 18;
|
|
29043
|
+
var ROW_HANDLE_HOVER_WIDTH = 28;
|
|
29044
|
+
var COLUMN_HANDLE_HOVER_HEIGHT = 28;
|
|
29045
|
+
var ADD_COLUMN_HOVER_WIDTH = 24;
|
|
29046
|
+
var ADD_ROW_HOVER_HEIGHT = 24;
|
|
29047
|
+
var HANDLE_HOVER_RADIUS = 14;
|
|
29048
|
+
var DEFAULT_HOVER_STATE = {
|
|
29049
|
+
menuVisible: false,
|
|
29050
|
+
addColumnVisible: false,
|
|
29051
|
+
addRowVisible: false,
|
|
29052
|
+
rowHandleIndex: null,
|
|
29053
|
+
columnHandleIndex: null
|
|
29054
|
+
};
|
|
29042
29055
|
function resolveElement(target) {
|
|
29043
29056
|
if (target instanceof Element) return target;
|
|
29044
29057
|
if (target instanceof Node) return target.parentElement;
|
|
@@ -29164,6 +29177,12 @@ function buildLayout(editor, surface, cell) {
|
|
|
29164
29177
|
};
|
|
29165
29178
|
}
|
|
29166
29179
|
function getSelectedCell(editor) {
|
|
29180
|
+
const browserSelection = window.getSelection();
|
|
29181
|
+
const anchorElement = resolveElement(browserSelection?.anchorNode ?? null);
|
|
29182
|
+
const anchorCell = anchorElement?.closest?.("th,td");
|
|
29183
|
+
if (anchorCell instanceof HTMLTableCellElement) {
|
|
29184
|
+
return anchorCell;
|
|
29185
|
+
}
|
|
29167
29186
|
const domAtPos = editor.view.domAtPos(editor.state.selection.from);
|
|
29168
29187
|
return getCellFromTarget(domAtPos.node);
|
|
29169
29188
|
}
|
|
@@ -29192,6 +29211,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
29192
29211
|
const t = useSmartTranslations("UEditor");
|
|
29193
29212
|
const [layout, setLayout] = import_react52.default.useState(null);
|
|
29194
29213
|
const [dragPreview, setDragPreview] = import_react52.default.useState(null);
|
|
29214
|
+
const [hoverState, setHoverState] = import_react52.default.useState(DEFAULT_HOVER_STATE);
|
|
29195
29215
|
const layoutRef = import_react52.default.useRef(null);
|
|
29196
29216
|
const dragStateRef = import_react52.default.useRef(null);
|
|
29197
29217
|
import_react52.default.useEffect(() => {
|
|
@@ -29223,17 +29243,50 @@ function TableControls({ editor, containerRef }) {
|
|
|
29223
29243
|
setDragPreview(null);
|
|
29224
29244
|
document.body.style.cursor = "";
|
|
29225
29245
|
}, []);
|
|
29246
|
+
const updateHoverState = import_react52.default.useCallback((event) => {
|
|
29247
|
+
const activeLayout = layoutRef.current;
|
|
29248
|
+
const surface = containerRef.current;
|
|
29249
|
+
if (!activeLayout || !surface || dragStateRef.current) {
|
|
29250
|
+
setHoverState(DEFAULT_HOVER_STATE);
|
|
29251
|
+
return;
|
|
29252
|
+
}
|
|
29253
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
29254
|
+
const relativeX = event.clientX - surfaceRect.left + surface.scrollLeft;
|
|
29255
|
+
const relativeY = event.clientY - surfaceRect.top + surface.scrollTop;
|
|
29256
|
+
const rowHandleIndex = activeLayout.rowHandles.find((rowHandle) => relativeX >= activeLayout.tableLeft - ROW_HANDLE_HOVER_WIDTH && relativeX <= activeLayout.tableLeft && Math.abs(relativeY - rowHandle.center) <= HANDLE_HOVER_RADIUS)?.index ?? null;
|
|
29257
|
+
const columnHandleIndex = activeLayout.columnHandles.find((columnHandle) => relativeY >= activeLayout.tableTop - COLUMN_HANDLE_HOVER_HEIGHT && relativeY <= activeLayout.tableTop && Math.abs(relativeX - columnHandle.center) <= HANDLE_HOVER_RADIUS)?.index ?? null;
|
|
29258
|
+
const menuVisible = relativeX >= activeLayout.tableLeft - MENU_HOVER_PADDING && relativeX <= activeLayout.tableLeft + 42 && relativeY >= activeLayout.tableTop - COLUMN_HANDLE_HOVER_HEIGHT && relativeY <= activeLayout.tableTop + MENU_HOVER_PADDING;
|
|
29259
|
+
const addColumnVisible = relativeX >= activeLayout.tableLeft + activeLayout.tableWidth && relativeX <= activeLayout.tableLeft + activeLayout.tableWidth + ADD_COLUMN_HOVER_WIDTH && relativeY >= activeLayout.tableTop && relativeY <= activeLayout.tableTop + activeLayout.tableHeight;
|
|
29260
|
+
const addRowVisible = relativeY >= activeLayout.tableTop + activeLayout.tableHeight && relativeY <= activeLayout.tableTop + activeLayout.tableHeight + ADD_ROW_HOVER_HEIGHT && relativeX >= activeLayout.tableLeft && relativeX <= activeLayout.tableLeft + activeLayout.tableWidth;
|
|
29261
|
+
setHoverState((prev) => {
|
|
29262
|
+
if (prev.menuVisible === menuVisible && prev.addColumnVisible === addColumnVisible && prev.addRowVisible === addRowVisible && prev.rowHandleIndex === rowHandleIndex && prev.columnHandleIndex === columnHandleIndex) {
|
|
29263
|
+
return prev;
|
|
29264
|
+
}
|
|
29265
|
+
return {
|
|
29266
|
+
menuVisible,
|
|
29267
|
+
addColumnVisible,
|
|
29268
|
+
addRowVisible,
|
|
29269
|
+
rowHandleIndex,
|
|
29270
|
+
columnHandleIndex
|
|
29271
|
+
};
|
|
29272
|
+
});
|
|
29273
|
+
}, [containerRef]);
|
|
29226
29274
|
import_react52.default.useEffect(() => {
|
|
29227
29275
|
const proseMirror = editor.view.dom;
|
|
29228
29276
|
const surface = containerRef.current;
|
|
29229
29277
|
if (!surface) return void 0;
|
|
29230
29278
|
const handleMouseOver = (event) => {
|
|
29231
29279
|
if (dragStateRef.current) return;
|
|
29232
|
-
|
|
29280
|
+
const cell = getCellFromTarget(event.target);
|
|
29281
|
+
if (!cell) return;
|
|
29282
|
+
syncFromCell(cell);
|
|
29283
|
+
};
|
|
29284
|
+
const handleSurfaceMouseMove = (event) => {
|
|
29285
|
+
updateHoverState(event);
|
|
29233
29286
|
};
|
|
29234
29287
|
const handleMouseLeave = () => {
|
|
29235
29288
|
if (dragStateRef.current) return;
|
|
29236
|
-
|
|
29289
|
+
setHoverState(DEFAULT_HOVER_STATE);
|
|
29237
29290
|
};
|
|
29238
29291
|
const handleFocusIn = () => {
|
|
29239
29292
|
if (dragStateRef.current) return;
|
|
@@ -29242,6 +29295,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
29242
29295
|
proseMirror.addEventListener("mouseover", handleMouseOver);
|
|
29243
29296
|
proseMirror.addEventListener("mouseleave", handleMouseLeave);
|
|
29244
29297
|
proseMirror.addEventListener("focusin", handleFocusIn);
|
|
29298
|
+
surface.addEventListener("mousemove", handleSurfaceMouseMove);
|
|
29245
29299
|
surface.addEventListener("scroll", refreshCurrentLayout, { passive: true });
|
|
29246
29300
|
window.addEventListener("resize", refreshCurrentLayout);
|
|
29247
29301
|
editor.on("selectionUpdate", syncFromSelection);
|
|
@@ -29251,12 +29305,13 @@ function TableControls({ editor, containerRef }) {
|
|
|
29251
29305
|
proseMirror.removeEventListener("mouseover", handleMouseOver);
|
|
29252
29306
|
proseMirror.removeEventListener("mouseleave", handleMouseLeave);
|
|
29253
29307
|
proseMirror.removeEventListener("focusin", handleFocusIn);
|
|
29308
|
+
surface.removeEventListener("mousemove", handleSurfaceMouseMove);
|
|
29254
29309
|
surface.removeEventListener("scroll", refreshCurrentLayout);
|
|
29255
29310
|
window.removeEventListener("resize", refreshCurrentLayout);
|
|
29256
29311
|
editor.off("selectionUpdate", syncFromSelection);
|
|
29257
29312
|
editor.off("update", refreshCurrentLayout);
|
|
29258
29313
|
};
|
|
29259
|
-
}, [clearDrag, containerRef, editor, refreshCurrentLayout, syncFromCell, syncFromSelection]);
|
|
29314
|
+
}, [clearDrag, containerRef, editor, refreshCurrentLayout, syncFromCell, syncFromSelection, updateHoverState]);
|
|
29260
29315
|
const runAtCellPos = import_react52.default.useCallback((cellPos, command, options) => {
|
|
29261
29316
|
if (cellPos == null) return false;
|
|
29262
29317
|
focusCell(editor, cellPos);
|
|
@@ -29346,6 +29401,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
29346
29401
|
return true;
|
|
29347
29402
|
}, [runAtCornerCell, syncFromSelection]);
|
|
29348
29403
|
const canExpandTable = Boolean(layout);
|
|
29404
|
+
const controlsVisible = dragPreview !== null;
|
|
29349
29405
|
import_react52.default.useEffect(() => {
|
|
29350
29406
|
const handleMouseMove = (event) => {
|
|
29351
29407
|
const dragState = dragStateRef.current;
|
|
@@ -29557,107 +29613,147 @@ function TableControls({ editor, containerRef }) {
|
|
|
29557
29613
|
const expandPreviewHeight = dragPreview?.kind === "add-row" ? layout.tableHeight + dragPreview.previewRows * layout.avgRowHeight : layout.tableHeight;
|
|
29558
29614
|
const dragStatusText = dragPreview?.kind === "row" ? `${t("tableMenu.dragRow")} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview?.kind === "column" ? `${t("tableMenu.dragColumn")} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview?.kind === "add-row" ? `+${dragPreview.previewRows}R` : dragPreview?.kind === "add-column" ? `+${dragPreview.previewCols}C` : null;
|
|
29559
29615
|
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
|
|
29560
|
-
layout.rowHandles.map((rowHandle) =>
|
|
29561
|
-
|
|
29562
|
-
|
|
29563
|
-
|
|
29564
|
-
|
|
29565
|
-
|
|
29566
|
-
"
|
|
29567
|
-
{
|
|
29568
|
-
|
|
29569
|
-
|
|
29570
|
-
|
|
29571
|
-
|
|
29572
|
-
|
|
29573
|
-
|
|
29574
|
-
|
|
29575
|
-
|
|
29576
|
-
|
|
29577
|
-
|
|
29578
|
-
|
|
29579
|
-
|
|
29580
|
-
|
|
29581
|
-
|
|
29582
|
-
|
|
29583
|
-
|
|
29584
|
-
|
|
29585
|
-
|
|
29586
|
-
|
|
29587
|
-
|
|
29588
|
-
|
|
29589
|
-
|
|
29590
|
-
|
|
29591
|
-
|
|
29592
|
-
|
|
29593
|
-
|
|
29594
|
-
|
|
29595
|
-
|
|
29596
|
-
|
|
29597
|
-
|
|
29598
|
-
|
|
29599
|
-
|
|
29600
|
-
|
|
29601
|
-
|
|
29602
|
-
|
|
29603
|
-
|
|
29604
|
-
|
|
29605
|
-
|
|
29606
|
-
|
|
29607
|
-
|
|
29608
|
-
|
|
29609
|
-
|
|
29610
|
-
|
|
29611
|
-
|
|
29612
|
-
|
|
29613
|
-
|
|
29614
|
-
|
|
29615
|
-
|
|
29616
|
-
|
|
29617
|
-
|
|
29618
|
-
|
|
29619
|
-
|
|
29620
|
-
|
|
29621
|
-
|
|
29622
|
-
|
|
29623
|
-
|
|
29624
|
-
|
|
29625
|
-
|
|
29626
|
-
|
|
29627
|
-
|
|
29628
|
-
|
|
29629
|
-
|
|
29630
|
-
|
|
29631
|
-
|
|
29632
|
-
|
|
29633
|
-
|
|
29634
|
-
|
|
29635
|
-
|
|
29636
|
-
|
|
29637
|
-
|
|
29638
|
-
|
|
29639
|
-
|
|
29616
|
+
layout.rowHandles.map((rowHandle) => {
|
|
29617
|
+
const visible = controlsVisible || hoverState.rowHandleIndex === rowHandle.index;
|
|
29618
|
+
if (!visible) return null;
|
|
29619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29620
|
+
"div",
|
|
29621
|
+
{
|
|
29622
|
+
className: "absolute z-30",
|
|
29623
|
+
style: {
|
|
29624
|
+
top: Math.max(8, rowHandle.center - 12),
|
|
29625
|
+
left: rowHandleLeft
|
|
29626
|
+
},
|
|
29627
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29628
|
+
DropdownMenu,
|
|
29629
|
+
{
|
|
29630
|
+
placement: "right",
|
|
29631
|
+
items: getRowHandleMenuItems(rowHandle),
|
|
29632
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29633
|
+
"button",
|
|
29634
|
+
{
|
|
29635
|
+
type: "button",
|
|
29636
|
+
"aria-label": `${t("tableMenu.dragRow")} ${rowHandle.index + 1}`,
|
|
29637
|
+
title: `${t("tableMenu.dragRow")} ${rowHandle.index + 1}`,
|
|
29638
|
+
onMouseDown: (event) => {
|
|
29639
|
+
event.preventDefault();
|
|
29640
|
+
event.stopPropagation();
|
|
29641
|
+
dragStateRef.current = {
|
|
29642
|
+
kind: "row",
|
|
29643
|
+
originIndex: rowHandle.index,
|
|
29644
|
+
targetIndex: rowHandle.index,
|
|
29645
|
+
anchorPos: rowHandle.cellPos
|
|
29646
|
+
};
|
|
29647
|
+
setDragPreview({
|
|
29648
|
+
kind: "row",
|
|
29649
|
+
originIndex: rowHandle.index,
|
|
29650
|
+
targetIndex: rowHandle.index,
|
|
29651
|
+
targetStart: rowHandle.start,
|
|
29652
|
+
targetSize: rowHandle.size
|
|
29653
|
+
});
|
|
29654
|
+
document.body.style.cursor = "grabbing";
|
|
29655
|
+
},
|
|
29656
|
+
className: cn(
|
|
29657
|
+
"inline-flex h-6 w-6 items-center justify-center rounded-full",
|
|
29658
|
+
"border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
|
|
29659
|
+
"transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
|
|
29660
|
+
),
|
|
29661
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.GripVertical, { className: "h-3.5 w-3.5" })
|
|
29662
|
+
}
|
|
29663
|
+
)
|
|
29664
|
+
}
|
|
29665
|
+
)
|
|
29666
|
+
},
|
|
29667
|
+
`row-handle-${rowHandle.index}`
|
|
29668
|
+
);
|
|
29669
|
+
}),
|
|
29670
|
+
layout.columnHandles.map((columnHandle) => {
|
|
29671
|
+
const visible = controlsVisible || hoverState.columnHandleIndex === columnHandle.index;
|
|
29672
|
+
if (!visible) return null;
|
|
29673
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29674
|
+
"div",
|
|
29675
|
+
{
|
|
29676
|
+
className: "absolute z-30",
|
|
29677
|
+
style: {
|
|
29678
|
+
top: columnHandleTop,
|
|
29679
|
+
left: Math.max(8, columnHandle.center - 12)
|
|
29680
|
+
},
|
|
29681
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29682
|
+
DropdownMenu,
|
|
29683
|
+
{
|
|
29684
|
+
placement: "bottom-start",
|
|
29685
|
+
items: getColumnHandleMenuItems(columnHandle),
|
|
29686
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29687
|
+
"button",
|
|
29688
|
+
{
|
|
29689
|
+
type: "button",
|
|
29690
|
+
"aria-label": `${t("tableMenu.dragColumn")} ${columnHandle.index + 1}`,
|
|
29691
|
+
title: `${t("tableMenu.dragColumn")} ${columnHandle.index + 1}`,
|
|
29692
|
+
onMouseDown: (event) => {
|
|
29693
|
+
event.preventDefault();
|
|
29694
|
+
event.stopPropagation();
|
|
29695
|
+
dragStateRef.current = {
|
|
29696
|
+
kind: "column",
|
|
29697
|
+
originIndex: columnHandle.index,
|
|
29698
|
+
targetIndex: columnHandle.index,
|
|
29699
|
+
anchorPos: columnHandle.cellPos
|
|
29700
|
+
};
|
|
29701
|
+
setDragPreview({
|
|
29702
|
+
kind: "column",
|
|
29703
|
+
originIndex: columnHandle.index,
|
|
29704
|
+
targetIndex: columnHandle.index,
|
|
29705
|
+
targetStart: columnHandle.start,
|
|
29706
|
+
targetSize: columnHandle.size
|
|
29707
|
+
});
|
|
29708
|
+
document.body.style.cursor = "grabbing";
|
|
29709
|
+
},
|
|
29710
|
+
className: cn(
|
|
29711
|
+
"inline-flex h-6 w-6 items-center justify-center rounded-full",
|
|
29712
|
+
"border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
|
|
29713
|
+
"transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
|
|
29714
|
+
),
|
|
29715
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.GripHorizontal, { className: "h-3.5 w-3.5" })
|
|
29716
|
+
}
|
|
29717
|
+
)
|
|
29718
|
+
}
|
|
29719
|
+
)
|
|
29720
|
+
},
|
|
29721
|
+
`column-handle-${columnHandle.index}`
|
|
29722
|
+
);
|
|
29723
|
+
}),
|
|
29724
|
+
(controlsVisible || hoverState.menuVisible) && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29725
|
+
"div",
|
|
29640
29726
|
{
|
|
29641
|
-
|
|
29642
|
-
|
|
29643
|
-
|
|
29644
|
-
|
|
29727
|
+
className: "absolute z-30",
|
|
29728
|
+
style: {
|
|
29729
|
+
top: menuTop,
|
|
29730
|
+
left: menuLeft
|
|
29731
|
+
},
|
|
29732
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29733
|
+
DropdownMenu,
|
|
29645
29734
|
{
|
|
29646
|
-
|
|
29647
|
-
|
|
29648
|
-
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
|
|
29652
|
-
|
|
29653
|
-
|
|
29654
|
-
|
|
29655
|
-
|
|
29735
|
+
placement: "bottom-start",
|
|
29736
|
+
items: menuItems,
|
|
29737
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29738
|
+
"button",
|
|
29739
|
+
{
|
|
29740
|
+
type: "button",
|
|
29741
|
+
"aria-label": t("tableMenu.openControls"),
|
|
29742
|
+
title: t("tableMenu.openControls"),
|
|
29743
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
29744
|
+
className: cn(
|
|
29745
|
+
"pointer-events-auto inline-flex h-7 w-7 items-center justify-center rounded-full",
|
|
29746
|
+
"border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
|
|
29747
|
+
"transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
|
|
29748
|
+
),
|
|
29749
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.MoreHorizontal, { className: "h-4 w-4" })
|
|
29750
|
+
}
|
|
29751
|
+
)
|
|
29656
29752
|
}
|
|
29657
29753
|
)
|
|
29658
29754
|
}
|
|
29659
|
-
)
|
|
29660
|
-
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29755
|
+
),
|
|
29756
|
+
(controlsVisible || hoverState.addColumnVisible) && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29661
29757
|
"button",
|
|
29662
29758
|
{
|
|
29663
29759
|
type: "button",
|
|
@@ -29675,13 +29771,18 @@ function TableControls({ editor, containerRef }) {
|
|
|
29675
29771
|
className: cn(
|
|
29676
29772
|
"absolute z-30 inline-flex items-center justify-center rounded-md",
|
|
29677
29773
|
"border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
|
|
29678
|
-
"transition-colors hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
|
|
29774
|
+
"transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
|
|
29679
29775
|
),
|
|
29680
|
-
style: {
|
|
29776
|
+
style: {
|
|
29777
|
+
top: columnRailTop,
|
|
29778
|
+
left: columnRailLeft,
|
|
29779
|
+
width: 18,
|
|
29780
|
+
height: layout.tableHeight
|
|
29781
|
+
},
|
|
29681
29782
|
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "text-sm font-medium leading-none", children: "+" })
|
|
29682
29783
|
}
|
|
29683
29784
|
),
|
|
29684
|
-
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29785
|
+
(controlsVisible || hoverState.addRowVisible) && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
29685
29786
|
"button",
|
|
29686
29787
|
{
|
|
29687
29788
|
type: "button",
|
|
@@ -29699,9 +29800,14 @@ function TableControls({ editor, containerRef }) {
|
|
|
29699
29800
|
className: cn(
|
|
29700
29801
|
"absolute z-30 inline-flex items-center justify-center rounded-md",
|
|
29701
29802
|
"border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
|
|
29702
|
-
"transition-colors hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
|
|
29803
|
+
"transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
|
|
29703
29804
|
),
|
|
29704
|
-
style: {
|
|
29805
|
+
style: {
|
|
29806
|
+
top: rowRailTop,
|
|
29807
|
+
left: rowRailLeft,
|
|
29808
|
+
width: layout.tableWidth,
|
|
29809
|
+
height: 16
|
|
29810
|
+
},
|
|
29705
29811
|
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "text-sm font-medium leading-none", children: "+" })
|
|
29706
29812
|
}
|
|
29707
29813
|
),
|
|
@@ -29836,6 +29942,19 @@ function resolveEventElement(target) {
|
|
|
29836
29942
|
if (target instanceof Node) return target.parentElement;
|
|
29837
29943
|
return null;
|
|
29838
29944
|
}
|
|
29945
|
+
function getSelectionTableCell(view) {
|
|
29946
|
+
const browserSelection = window.getSelection();
|
|
29947
|
+
const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
|
|
29948
|
+
const anchorCell = anchorElement?.closest?.("th,td");
|
|
29949
|
+
if (anchorCell instanceof HTMLElement) {
|
|
29950
|
+
return anchorCell;
|
|
29951
|
+
}
|
|
29952
|
+
const { from } = view.state.selection;
|
|
29953
|
+
const domAtPos = view.domAtPos(from);
|
|
29954
|
+
const element = resolveEventElement(domAtPos.node);
|
|
29955
|
+
const cell = element?.closest?.("th,td");
|
|
29956
|
+
return cell instanceof HTMLElement ? cell : null;
|
|
29957
|
+
}
|
|
29839
29958
|
function isRowResizeHotspot(cell, clientX, clientY) {
|
|
29840
29959
|
const rect = cell.getBoundingClientRect();
|
|
29841
29960
|
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
@@ -29862,6 +29981,16 @@ function getRelativeBoundaryMetrics(surface, table, row, cell) {
|
|
|
29862
29981
|
columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
|
|
29863
29982
|
};
|
|
29864
29983
|
}
|
|
29984
|
+
function getRelativeCellMetrics(surface, cell) {
|
|
29985
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
29986
|
+
const cellRect = cell.getBoundingClientRect();
|
|
29987
|
+
return {
|
|
29988
|
+
left: cellRect.left - surfaceRect.left + surface.scrollLeft,
|
|
29989
|
+
top: cellRect.top - surfaceRect.top + surface.scrollTop,
|
|
29990
|
+
width: cellRect.width,
|
|
29991
|
+
height: cellRect.height
|
|
29992
|
+
};
|
|
29993
|
+
}
|
|
29865
29994
|
var UEditor = import_react53.default.forwardRef(({
|
|
29866
29995
|
content = "",
|
|
29867
29996
|
onChange,
|
|
@@ -29889,6 +30018,9 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
29889
30018
|
const editorContentRef = (0, import_react53.useRef)(null);
|
|
29890
30019
|
const tableColumnGuideRef = (0, import_react53.useRef)(null);
|
|
29891
30020
|
const tableRowGuideRef = (0, import_react53.useRef)(null);
|
|
30021
|
+
const activeTableCellHighlightRef = (0, import_react53.useRef)(null);
|
|
30022
|
+
const hoveredTableCellRef = (0, import_react53.useRef)(null);
|
|
30023
|
+
const activeTableCellRef = (0, import_react53.useRef)(null);
|
|
29892
30024
|
const rowResizeStateRef = (0, import_react53.useRef)(null);
|
|
29893
30025
|
const setEditorResizeCursor = import_react53.default.useCallback((cursor) => {
|
|
29894
30026
|
const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
|
|
@@ -29915,6 +30047,36 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
29915
30047
|
hideColumnGuide();
|
|
29916
30048
|
hideRowGuide();
|
|
29917
30049
|
}, [hideColumnGuide, hideRowGuide, setEditorResizeCursor]);
|
|
30050
|
+
const updateActiveCellHighlight = import_react53.default.useCallback((cell) => {
|
|
30051
|
+
const surface = editorContentRef.current;
|
|
30052
|
+
const highlight = activeTableCellHighlightRef.current;
|
|
30053
|
+
if (!highlight) return;
|
|
30054
|
+
if (!surface || !cell) {
|
|
30055
|
+
highlight.style.display = "none";
|
|
30056
|
+
return;
|
|
30057
|
+
}
|
|
30058
|
+
const metrics = getRelativeCellMetrics(surface, cell);
|
|
30059
|
+
highlight.style.display = "block";
|
|
30060
|
+
highlight.style.left = `${metrics.left}px`;
|
|
30061
|
+
highlight.style.top = `${metrics.top}px`;
|
|
30062
|
+
highlight.style.width = `${metrics.width}px`;
|
|
30063
|
+
highlight.style.height = `${metrics.height}px`;
|
|
30064
|
+
}, []);
|
|
30065
|
+
const setActiveTableCell = import_react53.default.useCallback((cell) => {
|
|
30066
|
+
if (activeTableCellRef.current === cell) return;
|
|
30067
|
+
activeTableCellRef.current = cell;
|
|
30068
|
+
updateActiveCellHighlight(activeTableCellRef.current);
|
|
30069
|
+
}, [updateActiveCellHighlight]);
|
|
30070
|
+
const clearActiveTableCell = import_react53.default.useCallback(() => {
|
|
30071
|
+
activeTableCellRef.current = null;
|
|
30072
|
+
updateActiveCellHighlight(null);
|
|
30073
|
+
}, [updateActiveCellHighlight]);
|
|
30074
|
+
const setHoveredTableCell = import_react53.default.useCallback((cell) => {
|
|
30075
|
+
hoveredTableCellRef.current = cell;
|
|
30076
|
+
}, []);
|
|
30077
|
+
const clearHoveredTableCell = import_react53.default.useCallback(() => {
|
|
30078
|
+
hoveredTableCellRef.current = null;
|
|
30079
|
+
}, []);
|
|
29918
30080
|
const showColumnGuide = import_react53.default.useCallback((table, row, cell) => {
|
|
29919
30081
|
const surface = editorContentRef.current;
|
|
29920
30082
|
const guide = tableColumnGuideRef.current;
|
|
@@ -30096,6 +30258,10 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30096
30258
|
onJsonChange?.(editor2.getJSON());
|
|
30097
30259
|
}
|
|
30098
30260
|
});
|
|
30261
|
+
const syncActiveTableCellFromSelection = import_react53.default.useCallback(() => {
|
|
30262
|
+
if (!editor) return;
|
|
30263
|
+
setActiveTableCell(getSelectionTableCell(editor.view));
|
|
30264
|
+
}, [editor, setActiveTableCell]);
|
|
30099
30265
|
(0, import_react53.useImperativeHandle)(
|
|
30100
30266
|
ref,
|
|
30101
30267
|
() => ({
|
|
@@ -30128,9 +30294,27 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30128
30294
|
(0, import_react53.useEffect)(() => {
|
|
30129
30295
|
if (!editor) return void 0;
|
|
30130
30296
|
const proseMirror = editor.view.dom;
|
|
30297
|
+
const surface = editorContentRef.current;
|
|
30298
|
+
let selectionSyncTimeoutId = 0;
|
|
30299
|
+
const scheduleActiveCellSync = (fallbackCell = null) => {
|
|
30300
|
+
requestAnimationFrame(() => {
|
|
30301
|
+
setActiveTableCell(getSelectionTableCell(editor.view) ?? fallbackCell);
|
|
30302
|
+
});
|
|
30303
|
+
window.clearTimeout(selectionSyncTimeoutId);
|
|
30304
|
+
selectionSyncTimeoutId = window.setTimeout(() => {
|
|
30305
|
+
setActiveTableCell(getSelectionTableCell(editor.view) ?? fallbackCell);
|
|
30306
|
+
}, 0);
|
|
30307
|
+
};
|
|
30308
|
+
const handleSelectionChange = () => {
|
|
30309
|
+
scheduleActiveCellSync();
|
|
30310
|
+
};
|
|
30311
|
+
const handleActiveCellLayoutChange = () => {
|
|
30312
|
+
updateActiveCellHighlight(activeTableCellRef.current);
|
|
30313
|
+
};
|
|
30131
30314
|
const handleEditorMouseMove = (event) => {
|
|
30132
30315
|
const activeRowResize = rowResizeStateRef.current;
|
|
30133
30316
|
if (activeRowResize) {
|
|
30317
|
+
setHoveredTableCell(activeRowResize.cellElement);
|
|
30134
30318
|
showRowGuide(activeRowResize.tableElement, activeRowResize.rowElement, activeRowResize.cellElement);
|
|
30135
30319
|
return;
|
|
30136
30320
|
}
|
|
@@ -30141,12 +30325,15 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30141
30325
|
}
|
|
30142
30326
|
const cell = target.closest("th,td");
|
|
30143
30327
|
if (!(cell instanceof HTMLElement)) {
|
|
30328
|
+
clearHoveredTableCell();
|
|
30144
30329
|
clearAllTableResizeHover();
|
|
30145
30330
|
return;
|
|
30146
30331
|
}
|
|
30332
|
+
setHoveredTableCell(cell);
|
|
30147
30333
|
const row = cell.closest("tr");
|
|
30148
30334
|
const table = cell.closest("table");
|
|
30149
30335
|
if (!(row instanceof HTMLTableRowElement) || !(table instanceof HTMLTableElement)) {
|
|
30336
|
+
clearHoveredTableCell();
|
|
30150
30337
|
clearAllTableResizeHover();
|
|
30151
30338
|
return;
|
|
30152
30339
|
}
|
|
@@ -30165,6 +30352,7 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30165
30352
|
clearAllTableResizeHover();
|
|
30166
30353
|
};
|
|
30167
30354
|
const handleEditorMouseLeave = () => {
|
|
30355
|
+
clearHoveredTableCell();
|
|
30168
30356
|
if (!rowResizeStateRef.current) {
|
|
30169
30357
|
clearAllTableResizeHover();
|
|
30170
30358
|
}
|
|
@@ -30172,15 +30360,24 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30172
30360
|
const handleEditorMouseDown = (event) => {
|
|
30173
30361
|
if (event.button !== 0) return;
|
|
30174
30362
|
const target = resolveEventElement(event.target);
|
|
30175
|
-
if (!(target instanceof Element))
|
|
30363
|
+
if (!(target instanceof Element)) {
|
|
30364
|
+
clearActiveTableCell();
|
|
30365
|
+
return;
|
|
30366
|
+
}
|
|
30176
30367
|
const cell = target.closest("th,td");
|
|
30177
|
-
if (!(cell instanceof HTMLTableCellElement))
|
|
30368
|
+
if (!(cell instanceof HTMLTableCellElement)) {
|
|
30369
|
+
clearActiveTableCell();
|
|
30370
|
+
return;
|
|
30371
|
+
}
|
|
30372
|
+
setActiveTableCell(cell);
|
|
30373
|
+
scheduleActiveCellSync(cell);
|
|
30178
30374
|
const row = cell.closest("tr");
|
|
30179
30375
|
const table = cell.closest("table");
|
|
30180
30376
|
if (!(row instanceof HTMLTableRowElement) || !(table instanceof HTMLTableElement)) return;
|
|
30181
30377
|
if (!isRowResizeHotspot(cell, event.clientX, event.clientY)) {
|
|
30182
30378
|
return;
|
|
30183
30379
|
}
|
|
30380
|
+
setHoveredTableCell(cell);
|
|
30184
30381
|
const rowInfo = findTableRowNodeInfo(editor.view, row);
|
|
30185
30382
|
if (!rowInfo) return;
|
|
30186
30383
|
rowResizeStateRef.current = {
|
|
@@ -30241,6 +30438,7 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30241
30438
|
clearPreviewRowHeight(state.rowElement);
|
|
30242
30439
|
rowResizeStateRef.current = null;
|
|
30243
30440
|
document.body.style.cursor = "";
|
|
30441
|
+
clearHoveredTableCell();
|
|
30244
30442
|
clearAllTableResizeHover();
|
|
30245
30443
|
};
|
|
30246
30444
|
const handleWindowBlur = () => {
|
|
@@ -30249,30 +30447,53 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30249
30447
|
clearPreviewRowHeight(state.rowElement);
|
|
30250
30448
|
rowResizeStateRef.current = null;
|
|
30251
30449
|
document.body.style.cursor = "";
|
|
30450
|
+
clearHoveredTableCell();
|
|
30252
30451
|
clearAllTableResizeHover();
|
|
30253
30452
|
};
|
|
30254
30453
|
proseMirror.addEventListener("mousemove", handleEditorMouseMove);
|
|
30255
30454
|
proseMirror.addEventListener("mouseleave", handleEditorMouseLeave);
|
|
30256
30455
|
proseMirror.addEventListener("mousedown", handleEditorMouseDown);
|
|
30456
|
+
proseMirror.addEventListener("click", handleSelectionChange);
|
|
30457
|
+
proseMirror.addEventListener("mouseup", handleSelectionChange);
|
|
30458
|
+
proseMirror.addEventListener("keyup", handleSelectionChange);
|
|
30459
|
+
proseMirror.addEventListener("focusin", handleSelectionChange);
|
|
30460
|
+
document.addEventListener("selectionchange", handleSelectionChange);
|
|
30461
|
+
surface?.addEventListener("scroll", handleActiveCellLayoutChange, { passive: true });
|
|
30462
|
+
window.addEventListener("resize", handleActiveCellLayoutChange);
|
|
30257
30463
|
window.addEventListener("mousemove", handlePointerMove);
|
|
30258
30464
|
document.addEventListener("pointermove", handlePointerMove);
|
|
30259
30465
|
window.addEventListener("mouseup", handlePointerUp);
|
|
30260
30466
|
document.addEventListener("pointerup", handlePointerUp);
|
|
30261
30467
|
window.addEventListener("blur", handleWindowBlur);
|
|
30468
|
+
editor.on("selectionUpdate", syncActiveTableCellFromSelection);
|
|
30469
|
+
editor.on("focus", syncActiveTableCellFromSelection);
|
|
30470
|
+
syncActiveTableCellFromSelection();
|
|
30262
30471
|
return () => {
|
|
30263
30472
|
proseMirror.removeEventListener("mousemove", handleEditorMouseMove);
|
|
30264
30473
|
proseMirror.removeEventListener("mouseleave", handleEditorMouseLeave);
|
|
30265
30474
|
proseMirror.removeEventListener("mousedown", handleEditorMouseDown);
|
|
30475
|
+
proseMirror.removeEventListener("click", handleSelectionChange);
|
|
30476
|
+
proseMirror.removeEventListener("mouseup", handleSelectionChange);
|
|
30477
|
+
proseMirror.removeEventListener("keyup", handleSelectionChange);
|
|
30478
|
+
proseMirror.removeEventListener("focusin", handleSelectionChange);
|
|
30479
|
+
document.removeEventListener("selectionchange", handleSelectionChange);
|
|
30480
|
+
surface?.removeEventListener("scroll", handleActiveCellLayoutChange);
|
|
30481
|
+
window.removeEventListener("resize", handleActiveCellLayoutChange);
|
|
30266
30482
|
window.removeEventListener("mousemove", handlePointerMove);
|
|
30267
30483
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
30268
30484
|
window.removeEventListener("mouseup", handlePointerUp);
|
|
30269
30485
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
30270
30486
|
window.removeEventListener("blur", handleWindowBlur);
|
|
30487
|
+
editor.off("selectionUpdate", syncActiveTableCellFromSelection);
|
|
30488
|
+
editor.off("focus", syncActiveTableCellFromSelection);
|
|
30489
|
+
window.clearTimeout(selectionSyncTimeoutId);
|
|
30271
30490
|
document.body.style.cursor = "";
|
|
30491
|
+
clearActiveTableCell();
|
|
30492
|
+
clearHoveredTableCell();
|
|
30272
30493
|
clearAllTableResizeHover();
|
|
30273
30494
|
rowResizeStateRef.current = null;
|
|
30274
30495
|
};
|
|
30275
|
-
}, [clearAllTableResizeHover, editor, hideColumnGuide, hideRowGuide, showColumnGuide, showRowGuide]);
|
|
30496
|
+
}, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editor, hideColumnGuide, hideRowGuide, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
|
|
30276
30497
|
if (!editor) {
|
|
30277
30498
|
return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
|
|
30278
30499
|
"div",
|
|
@@ -30324,6 +30545,14 @@ var UEditor = import_react53.default.forwardRef(({
|
|
|
30324
30545
|
className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
|
|
30325
30546
|
}
|
|
30326
30547
|
),
|
|
30548
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
|
|
30549
|
+
"span",
|
|
30550
|
+
{
|
|
30551
|
+
ref: activeTableCellHighlightRef,
|
|
30552
|
+
"aria-hidden": "true",
|
|
30553
|
+
className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-[#2383e2] bg-[#2383e2]/[0.06] transition-[left,top,width,height] duration-100"
|
|
30554
|
+
}
|
|
30555
|
+
),
|
|
30327
30556
|
editable && /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(TableControls, { editor, containerRef: editorContentRef }),
|
|
30328
30557
|
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
|
|
30329
30558
|
import_react54.EditorContent,
|