@underverse-ui/underverse 1.0.157 → 1.0.158
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 +550 -210
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +554 -214
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5856,7 +5856,7 @@ var Modal = ({
|
|
|
5856
5856
|
const modalContent = /* @__PURE__ */ jsxs13(
|
|
5857
5857
|
"div",
|
|
5858
5858
|
{
|
|
5859
|
-
className: cn("fixed inset-0 z-9999 flex items-center justify-center p-4 md:p-6", overlayClassName),
|
|
5859
|
+
className: cn("fixed inset-0 z-[9999] flex items-center justify-center p-4 md:p-6", overlayClassName),
|
|
5860
5860
|
style: { overscrollBehavior: "contain" },
|
|
5861
5861
|
onMouseDown: handleOverlayMouseDown,
|
|
5862
5862
|
onMouseUp: handleOverlayMouseUp,
|
|
@@ -24707,7 +24707,7 @@ function useLocale2() {
|
|
|
24707
24707
|
}
|
|
24708
24708
|
|
|
24709
24709
|
// src/components/UEditor/UEditor.tsx
|
|
24710
|
-
import React83, { useEffect as useEffect38, useImperativeHandle as useImperativeHandle4, useMemo as
|
|
24710
|
+
import React83, { useEffect as useEffect38, useImperativeHandle as useImperativeHandle4, useMemo as useMemo25, useRef as useRef37 } from "react";
|
|
24711
24711
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
24712
24712
|
|
|
24713
24713
|
// src/components/UEditor/extensions.ts
|
|
@@ -27062,6 +27062,111 @@ import { useEffect as useEffect34, useRef as useRef29, useState as useState44 }
|
|
|
27062
27062
|
import Image4 from "@tiptap/extension-image";
|
|
27063
27063
|
import { mergeAttributes as mergeAttributes4 } from "@tiptap/core";
|
|
27064
27064
|
import { NodeViewWrapper as NodeViewWrapper4, ReactNodeViewRenderer as ReactNodeViewRenderer4 } from "@tiptap/react";
|
|
27065
|
+
|
|
27066
|
+
// src/components/UEditor/table-dom-utils.ts
|
|
27067
|
+
var MIN_TABLE_ROW_HEIGHT = 36;
|
|
27068
|
+
var COLUMN_RESIZE_LINE_THICKNESS = 2;
|
|
27069
|
+
var ROW_RESIZE_LINE_THICKNESS = 2;
|
|
27070
|
+
var UEDITOR_TABLE_LAYOUT_CHANGE_EVENT = "ueditor-table-layout-change";
|
|
27071
|
+
var TABLE_RESIZE_HIT_ZONE = 10;
|
|
27072
|
+
function findTableRowNodeInfo(view, rowElement) {
|
|
27073
|
+
const firstCell = rowElement.querySelector("th,td");
|
|
27074
|
+
if (!firstCell) return null;
|
|
27075
|
+
const cellPos = view.posAtDOM(firstCell, 0);
|
|
27076
|
+
const $pos = view.state.doc.resolve(cellPos);
|
|
27077
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
27078
|
+
const node = $pos.node(depth);
|
|
27079
|
+
if (node.type.name === "tableRow") {
|
|
27080
|
+
return {
|
|
27081
|
+
pos: $pos.before(depth),
|
|
27082
|
+
node
|
|
27083
|
+
};
|
|
27084
|
+
}
|
|
27085
|
+
}
|
|
27086
|
+
return null;
|
|
27087
|
+
}
|
|
27088
|
+
function resolveEventElement(target) {
|
|
27089
|
+
if (target instanceof Element) return target;
|
|
27090
|
+
if (target instanceof Node) return target.parentElement;
|
|
27091
|
+
return null;
|
|
27092
|
+
}
|
|
27093
|
+
function getSelectionTableCell(view) {
|
|
27094
|
+
const browserSelection = window.getSelection();
|
|
27095
|
+
const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
|
|
27096
|
+
const anchorCell = anchorElement?.closest?.("th,td");
|
|
27097
|
+
if (anchorCell instanceof HTMLElement) {
|
|
27098
|
+
return anchorCell;
|
|
27099
|
+
}
|
|
27100
|
+
const { from } = view.state.selection;
|
|
27101
|
+
const domAtPos = view.domAtPos(from);
|
|
27102
|
+
const element = resolveEventElement(domAtPos.node);
|
|
27103
|
+
const cell = element?.closest?.("th,td");
|
|
27104
|
+
return cell instanceof HTMLElement ? cell : null;
|
|
27105
|
+
}
|
|
27106
|
+
function isRowResizeHotspot(cell, clientX, clientY) {
|
|
27107
|
+
const rect = cell.getBoundingClientRect();
|
|
27108
|
+
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
27109
|
+
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
27110
|
+
return nearBottom && !nearRight;
|
|
27111
|
+
}
|
|
27112
|
+
function isColumnResizeHotspot(cell, clientX, clientY) {
|
|
27113
|
+
const rect = cell.getBoundingClientRect();
|
|
27114
|
+
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
27115
|
+
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
27116
|
+
return nearRight && !nearBottom;
|
|
27117
|
+
}
|
|
27118
|
+
function getRelativeBoundaryMetrics(surface, table, row, cell) {
|
|
27119
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
27120
|
+
const tableRect = table.getBoundingClientRect();
|
|
27121
|
+
const rowRect = row.getBoundingClientRect();
|
|
27122
|
+
const cellRect = cell.getBoundingClientRect();
|
|
27123
|
+
return {
|
|
27124
|
+
left: tableRect.left - surfaceRect.left + surface.scrollLeft,
|
|
27125
|
+
top: tableRect.top - surfaceRect.top + surface.scrollTop,
|
|
27126
|
+
width: tableRect.width,
|
|
27127
|
+
height: tableRect.height,
|
|
27128
|
+
rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
|
|
27129
|
+
columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
|
|
27130
|
+
};
|
|
27131
|
+
}
|
|
27132
|
+
function getRelativeCellMetrics(surface, cell) {
|
|
27133
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
27134
|
+
const cellRect = cell.getBoundingClientRect();
|
|
27135
|
+
return {
|
|
27136
|
+
left: cellRect.left - surfaceRect.left + surface.scrollLeft,
|
|
27137
|
+
top: cellRect.top - surfaceRect.top + surface.scrollTop,
|
|
27138
|
+
width: cellRect.width,
|
|
27139
|
+
height: cellRect.height
|
|
27140
|
+
};
|
|
27141
|
+
}
|
|
27142
|
+
function getRelativeSelectedCellsMetrics(surface) {
|
|
27143
|
+
const selectedCells = Array.from(
|
|
27144
|
+
surface.querySelectorAll("td.selectedCell, th.selectedCell")
|
|
27145
|
+
);
|
|
27146
|
+
if (selectedCells.length === 0) {
|
|
27147
|
+
return null;
|
|
27148
|
+
}
|
|
27149
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
27150
|
+
let left = Number.POSITIVE_INFINITY;
|
|
27151
|
+
let top = Number.POSITIVE_INFINITY;
|
|
27152
|
+
let right = Number.NEGATIVE_INFINITY;
|
|
27153
|
+
let bottom = Number.NEGATIVE_INFINITY;
|
|
27154
|
+
selectedCells.forEach((cell) => {
|
|
27155
|
+
const rect = cell.getBoundingClientRect();
|
|
27156
|
+
left = Math.min(left, rect.left);
|
|
27157
|
+
top = Math.min(top, rect.top);
|
|
27158
|
+
right = Math.max(right, rect.right);
|
|
27159
|
+
bottom = Math.max(bottom, rect.bottom);
|
|
27160
|
+
});
|
|
27161
|
+
return {
|
|
27162
|
+
left: left - surfaceRect.left + surface.scrollLeft,
|
|
27163
|
+
top: top - surfaceRect.top + surface.scrollTop,
|
|
27164
|
+
width: right - left,
|
|
27165
|
+
height: bottom - top
|
|
27166
|
+
};
|
|
27167
|
+
}
|
|
27168
|
+
|
|
27169
|
+
// src/components/UEditor/resizable-image.tsx
|
|
27065
27170
|
import { jsx as jsx82, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
27066
27171
|
var MIN_IMAGE_SIZE_PX = 40;
|
|
27067
27172
|
var IMAGE_LAYOUTS = /* @__PURE__ */ new Set(["block", "left", "right"]);
|
|
@@ -27143,6 +27248,7 @@ function ResizableImageNodeView(props) {
|
|
|
27143
27248
|
const { node, selected, updateAttributes, editor, getPos } = props;
|
|
27144
27249
|
const wrapperRef = useRef29(null);
|
|
27145
27250
|
const imgRef = useRef29(null);
|
|
27251
|
+
const resizePreviewRef = useRef29(null);
|
|
27146
27252
|
const [isHovered, setIsHovered] = useState44(false);
|
|
27147
27253
|
const [isResizing, setIsResizing] = useState44(false);
|
|
27148
27254
|
const widthAttr = toNullableNumber(node.attrs["width"]);
|
|
@@ -27150,11 +27256,59 @@ function ResizableImageNodeView(props) {
|
|
|
27150
27256
|
const textAlign = String(node.attrs["textAlign"] ?? "");
|
|
27151
27257
|
const imageLayout = parseImageLayout(node.attrs["imageLayout"]);
|
|
27152
27258
|
const dragStateRef = useRef29(null);
|
|
27259
|
+
const dispatchTableLayoutChange2 = () => {
|
|
27260
|
+
editor.view.dom.dispatchEvent(new CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, { bubbles: true }));
|
|
27261
|
+
};
|
|
27262
|
+
const getImageDisplayStyle = (width, height) => ({
|
|
27263
|
+
width: width ? `${width}px` : void 0,
|
|
27264
|
+
height: width && height ? "auto" : height ? `${height}px` : void 0,
|
|
27265
|
+
aspectRatio: width && height ? `${width} / ${height}` : void 0
|
|
27266
|
+
});
|
|
27267
|
+
const setResizePreviewStyle = (width, height, visible, resetBase = false) => {
|
|
27268
|
+
const preview = resizePreviewRef.current;
|
|
27269
|
+
if (!preview) return;
|
|
27270
|
+
const drag = dragStateRef.current;
|
|
27271
|
+
const baseW = resetBase || !drag ? Math.max(MIN_IMAGE_SIZE_PX, Math.round(width)) : drag.previewBaseW;
|
|
27272
|
+
const baseH = resetBase || !drag ? Math.max(MIN_IMAGE_SIZE_PX, Math.round(height)) : drag.previewBaseH;
|
|
27273
|
+
const scaleX = width / baseW;
|
|
27274
|
+
const scaleY = height / baseH;
|
|
27275
|
+
if (resetBase) {
|
|
27276
|
+
preview.style.width = `${baseW}px`;
|
|
27277
|
+
preview.style.height = `${baseH}px`;
|
|
27278
|
+
}
|
|
27279
|
+
preview.style.maxWidth = "none";
|
|
27280
|
+
preview.style.maxHeight = "none";
|
|
27281
|
+
preview.style.transform = visible ? `translateZ(0) scale(${scaleX}, ${scaleY})` : "translateZ(0) scale(1)";
|
|
27282
|
+
preview.style.display = visible ? "block" : "none";
|
|
27283
|
+
};
|
|
27284
|
+
const applyPendingResizeFrame = () => {
|
|
27285
|
+
const drag = dragStateRef.current;
|
|
27286
|
+
if (!drag) return;
|
|
27287
|
+
drag.frameId = null;
|
|
27288
|
+
setResizePreviewStyle(drag.pendingW, drag.pendingH, true);
|
|
27289
|
+
};
|
|
27290
|
+
const scheduleResizeFrame = () => {
|
|
27291
|
+
const drag = dragStateRef.current;
|
|
27292
|
+
if (!drag || drag.frameId !== null) return;
|
|
27293
|
+
drag.frameId = window.requestAnimationFrame(applyPendingResizeFrame);
|
|
27294
|
+
};
|
|
27295
|
+
useEffect34(() => {
|
|
27296
|
+
return () => {
|
|
27297
|
+
const drag = dragStateRef.current;
|
|
27298
|
+
if (drag && drag.frameId !== null) {
|
|
27299
|
+
window.cancelAnimationFrame(drag.frameId);
|
|
27300
|
+
}
|
|
27301
|
+
dragStateRef.current = null;
|
|
27302
|
+
document.body.style.cursor = "";
|
|
27303
|
+
};
|
|
27304
|
+
}, []);
|
|
27153
27305
|
useEffect34(() => {
|
|
27154
27306
|
const img = imgRef.current;
|
|
27155
27307
|
if (!img) return;
|
|
27156
|
-
|
|
27157
|
-
img.style.
|
|
27308
|
+
const displayStyle = getImageDisplayStyle(widthAttr, heightAttr);
|
|
27309
|
+
img.style.width = typeof displayStyle.width === "string" ? displayStyle.width : "";
|
|
27310
|
+
img.style.height = typeof displayStyle.height === "string" ? displayStyle.height : "";
|
|
27311
|
+
img.style.aspectRatio = typeof displayStyle.aspectRatio === "string" ? displayStyle.aspectRatio : "";
|
|
27158
27312
|
}, [widthAttr, heightAttr]);
|
|
27159
27313
|
const selectNode = () => {
|
|
27160
27314
|
const pos = typeof getPos === "function" ? getPos() : null;
|
|
@@ -27185,12 +27339,17 @@ function ResizableImageNodeView(props) {
|
|
|
27185
27339
|
startY: event.clientY,
|
|
27186
27340
|
startW,
|
|
27187
27341
|
startH,
|
|
27188
|
-
lastW: startW,
|
|
27189
|
-
lastH: startH,
|
|
27190
27342
|
aspect,
|
|
27191
|
-
maxW: Math.max(MIN_IMAGE_SIZE_PX, maxW)
|
|
27343
|
+
maxW: Math.max(MIN_IMAGE_SIZE_PX, maxW),
|
|
27344
|
+
previewBaseW: Math.max(MIN_IMAGE_SIZE_PX, Math.round(startW)),
|
|
27345
|
+
previewBaseH: Math.max(MIN_IMAGE_SIZE_PX, Math.round(startH)),
|
|
27346
|
+
pendingW: startW,
|
|
27347
|
+
pendingH: startH,
|
|
27348
|
+
frameId: null
|
|
27192
27349
|
};
|
|
27193
27350
|
setIsResizing(true);
|
|
27351
|
+
setResizePreviewStyle(startW, startH, true, true);
|
|
27352
|
+
document.body.style.cursor = "nwse-resize";
|
|
27194
27353
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
27195
27354
|
};
|
|
27196
27355
|
const onResizePointerMove = (event) => {
|
|
@@ -27203,19 +27362,33 @@ function ResizableImageNodeView(props) {
|
|
|
27203
27362
|
const nextSize = Math.abs(dx) >= Math.abs(dy) ? sizeFromWidth(drag.startW + dx, drag.aspect, drag.maxW) : sizeFromHeight(drag.startH + dy, drag.aspect, drag.maxW);
|
|
27204
27363
|
const nextW = nextSize.width;
|
|
27205
27364
|
const nextH = nextSize.height;
|
|
27206
|
-
drag.
|
|
27207
|
-
drag.
|
|
27208
|
-
|
|
27209
|
-
img.style.height = `${Math.round(nextH)}px`;
|
|
27365
|
+
drag.pendingW = nextW;
|
|
27366
|
+
drag.pendingH = nextH;
|
|
27367
|
+
scheduleResizeFrame();
|
|
27210
27368
|
};
|
|
27211
27369
|
const finishResize = () => {
|
|
27212
27370
|
const drag = dragStateRef.current;
|
|
27213
27371
|
dragStateRef.current = null;
|
|
27214
27372
|
setIsResizing(false);
|
|
27373
|
+
document.body.style.cursor = "";
|
|
27215
27374
|
if (!drag) return;
|
|
27375
|
+
if (drag.frameId !== null) {
|
|
27376
|
+
window.cancelAnimationFrame(drag.frameId);
|
|
27377
|
+
drag.frameId = null;
|
|
27378
|
+
}
|
|
27379
|
+
const img = imgRef.current;
|
|
27380
|
+
const nextW = Math.round(drag.pendingW);
|
|
27381
|
+
const nextH = Math.round(drag.pendingH);
|
|
27382
|
+
setResizePreviewStyle(nextW, nextH, false);
|
|
27383
|
+
if (img) {
|
|
27384
|
+
img.style.width = `${nextW}px`;
|
|
27385
|
+
img.style.height = "auto";
|
|
27386
|
+
img.style.aspectRatio = `${nextW} / ${nextH}`;
|
|
27387
|
+
}
|
|
27388
|
+
dispatchTableLayoutChange2();
|
|
27216
27389
|
updateAttributes({
|
|
27217
|
-
width:
|
|
27218
|
-
height:
|
|
27390
|
+
width: nextW,
|
|
27391
|
+
height: nextH,
|
|
27219
27392
|
imageWidthPreset: null
|
|
27220
27393
|
});
|
|
27221
27394
|
};
|
|
@@ -27264,9 +27437,30 @@ function ResizableImageNodeView(props) {
|
|
|
27264
27437
|
selected ? "ring-2 ring-primary/60 ring-offset-2 ring-offset-background" : "",
|
|
27265
27438
|
isResizing ? "select-none" : ""
|
|
27266
27439
|
].join(" "),
|
|
27440
|
+
style: getImageDisplayStyle(widthAttr, heightAttr)
|
|
27441
|
+
}
|
|
27442
|
+
),
|
|
27443
|
+
/* @__PURE__ */ jsx82(
|
|
27444
|
+
"div",
|
|
27445
|
+
{
|
|
27446
|
+
ref: resizePreviewRef,
|
|
27447
|
+
"aria-hidden": "true",
|
|
27448
|
+
"data-ueditor-image-resize-preview": "",
|
|
27449
|
+
className: [
|
|
27450
|
+
"pointer-events-none absolute left-0 top-0 z-20 hidden rounded-lg",
|
|
27451
|
+
"border border-primary/70 bg-background/30 bg-center bg-no-repeat bg-[length:100%_100%]",
|
|
27452
|
+
"opacity-45 shadow-md ring-2 ring-primary/25 will-change-transform",
|
|
27453
|
+
"select-none"
|
|
27454
|
+
].join(" "),
|
|
27267
27455
|
style: {
|
|
27268
27456
|
width: widthAttr ? `${widthAttr}px` : void 0,
|
|
27269
|
-
height: heightAttr ? `${heightAttr}px` : void 0
|
|
27457
|
+
height: heightAttr ? `${heightAttr}px` : void 0,
|
|
27458
|
+
maxWidth: "none",
|
|
27459
|
+
maxHeight: "none",
|
|
27460
|
+
backgroundImage: `url("${String(node.attrs["src"] ?? "").replace(/"/g, "%22")}")`,
|
|
27461
|
+
transform: "translateZ(0) scale(1)",
|
|
27462
|
+
transformOrigin: "top left",
|
|
27463
|
+
display: isResizing ? "block" : "none"
|
|
27270
27464
|
}
|
|
27271
27465
|
}
|
|
27272
27466
|
),
|
|
@@ -27274,6 +27468,7 @@ function ResizableImageNodeView(props) {
|
|
|
27274
27468
|
"div",
|
|
27275
27469
|
{
|
|
27276
27470
|
"aria-hidden": "true",
|
|
27471
|
+
"data-ueditor-image-resize-handle": "",
|
|
27277
27472
|
onPointerDown: onResizePointerDown,
|
|
27278
27473
|
onPointerMove: onResizePointerMove,
|
|
27279
27474
|
onPointerUp: onResizePointerUp,
|
|
@@ -27530,109 +27725,6 @@ var letter_spacing_default = LetterSpacing;
|
|
|
27530
27725
|
import { Table as Table3 } from "@tiptap/extension-table";
|
|
27531
27726
|
import { Plugin as Plugin4 } from "@tiptap/pm/state";
|
|
27532
27727
|
|
|
27533
|
-
// src/components/UEditor/table-dom-utils.ts
|
|
27534
|
-
var MIN_TABLE_ROW_HEIGHT = 36;
|
|
27535
|
-
var COLUMN_RESIZE_LINE_THICKNESS = 2;
|
|
27536
|
-
var ROW_RESIZE_LINE_THICKNESS = 2;
|
|
27537
|
-
var UEDITOR_TABLE_LAYOUT_CHANGE_EVENT = "ueditor-table-layout-change";
|
|
27538
|
-
var TABLE_RESIZE_HIT_ZONE = 10;
|
|
27539
|
-
function findTableRowNodeInfo(view, rowElement) {
|
|
27540
|
-
const firstCell = rowElement.querySelector("th,td");
|
|
27541
|
-
if (!firstCell) return null;
|
|
27542
|
-
const cellPos = view.posAtDOM(firstCell, 0);
|
|
27543
|
-
const $pos = view.state.doc.resolve(cellPos);
|
|
27544
|
-
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
27545
|
-
const node = $pos.node(depth);
|
|
27546
|
-
if (node.type.name === "tableRow") {
|
|
27547
|
-
return {
|
|
27548
|
-
pos: $pos.before(depth),
|
|
27549
|
-
node
|
|
27550
|
-
};
|
|
27551
|
-
}
|
|
27552
|
-
}
|
|
27553
|
-
return null;
|
|
27554
|
-
}
|
|
27555
|
-
function resolveEventElement(target) {
|
|
27556
|
-
if (target instanceof Element) return target;
|
|
27557
|
-
if (target instanceof Node) return target.parentElement;
|
|
27558
|
-
return null;
|
|
27559
|
-
}
|
|
27560
|
-
function getSelectionTableCell(view) {
|
|
27561
|
-
const browserSelection = window.getSelection();
|
|
27562
|
-
const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
|
|
27563
|
-
const anchorCell = anchorElement?.closest?.("th,td");
|
|
27564
|
-
if (anchorCell instanceof HTMLElement) {
|
|
27565
|
-
return anchorCell;
|
|
27566
|
-
}
|
|
27567
|
-
const { from } = view.state.selection;
|
|
27568
|
-
const domAtPos = view.domAtPos(from);
|
|
27569
|
-
const element = resolveEventElement(domAtPos.node);
|
|
27570
|
-
const cell = element?.closest?.("th,td");
|
|
27571
|
-
return cell instanceof HTMLElement ? cell : null;
|
|
27572
|
-
}
|
|
27573
|
-
function isRowResizeHotspot(cell, clientX, clientY) {
|
|
27574
|
-
const rect = cell.getBoundingClientRect();
|
|
27575
|
-
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
27576
|
-
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
27577
|
-
return nearBottom && !nearRight;
|
|
27578
|
-
}
|
|
27579
|
-
function isColumnResizeHotspot(cell, clientX, clientY) {
|
|
27580
|
-
const rect = cell.getBoundingClientRect();
|
|
27581
|
-
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
27582
|
-
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
27583
|
-
return nearRight && !nearBottom;
|
|
27584
|
-
}
|
|
27585
|
-
function getRelativeBoundaryMetrics(surface, table, row, cell) {
|
|
27586
|
-
const surfaceRect = surface.getBoundingClientRect();
|
|
27587
|
-
const tableRect = table.getBoundingClientRect();
|
|
27588
|
-
const rowRect = row.getBoundingClientRect();
|
|
27589
|
-
const cellRect = cell.getBoundingClientRect();
|
|
27590
|
-
return {
|
|
27591
|
-
left: tableRect.left - surfaceRect.left + surface.scrollLeft,
|
|
27592
|
-
top: tableRect.top - surfaceRect.top + surface.scrollTop,
|
|
27593
|
-
width: tableRect.width,
|
|
27594
|
-
height: tableRect.height,
|
|
27595
|
-
rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
|
|
27596
|
-
columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
|
|
27597
|
-
};
|
|
27598
|
-
}
|
|
27599
|
-
function getRelativeCellMetrics(surface, cell) {
|
|
27600
|
-
const surfaceRect = surface.getBoundingClientRect();
|
|
27601
|
-
const cellRect = cell.getBoundingClientRect();
|
|
27602
|
-
return {
|
|
27603
|
-
left: cellRect.left - surfaceRect.left + surface.scrollLeft,
|
|
27604
|
-
top: cellRect.top - surfaceRect.top + surface.scrollTop,
|
|
27605
|
-
width: cellRect.width,
|
|
27606
|
-
height: cellRect.height
|
|
27607
|
-
};
|
|
27608
|
-
}
|
|
27609
|
-
function getRelativeSelectedCellsMetrics(surface) {
|
|
27610
|
-
const selectedCells = Array.from(
|
|
27611
|
-
surface.querySelectorAll("td.selectedCell, th.selectedCell")
|
|
27612
|
-
);
|
|
27613
|
-
if (selectedCells.length === 0) {
|
|
27614
|
-
return null;
|
|
27615
|
-
}
|
|
27616
|
-
const surfaceRect = surface.getBoundingClientRect();
|
|
27617
|
-
let left = Number.POSITIVE_INFINITY;
|
|
27618
|
-
let top = Number.POSITIVE_INFINITY;
|
|
27619
|
-
let right = Number.NEGATIVE_INFINITY;
|
|
27620
|
-
let bottom = Number.NEGATIVE_INFINITY;
|
|
27621
|
-
selectedCells.forEach((cell) => {
|
|
27622
|
-
const rect = cell.getBoundingClientRect();
|
|
27623
|
-
left = Math.min(left, rect.left);
|
|
27624
|
-
top = Math.min(top, rect.top);
|
|
27625
|
-
right = Math.max(right, rect.right);
|
|
27626
|
-
bottom = Math.max(bottom, rect.bottom);
|
|
27627
|
-
});
|
|
27628
|
-
return {
|
|
27629
|
-
left: left - surfaceRect.left + surface.scrollLeft,
|
|
27630
|
-
top: top - surfaceRect.top + surface.scrollTop,
|
|
27631
|
-
width: right - left,
|
|
27632
|
-
height: bottom - top
|
|
27633
|
-
};
|
|
27634
|
-
}
|
|
27635
|
-
|
|
27636
27728
|
// src/components/UEditor/table-align-utils.ts
|
|
27637
27729
|
function findTableNodeInfoAtResolvedPos($pos) {
|
|
27638
27730
|
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
@@ -28472,6 +28564,9 @@ var HIGHLIGHT_COLOR_SWATCHES = [
|
|
|
28472
28564
|
function buildColorOptions(colors, prefix) {
|
|
28473
28565
|
return colors.map((color, index) => ({ name: `${prefix} ${index + 1}`, color }));
|
|
28474
28566
|
}
|
|
28567
|
+
function getSwatchCheckClass(color) {
|
|
28568
|
+
return /^#(?:fff|ffffff)$/i.test(color) ? "text-foreground" : "text-white drop-shadow-[0_1px_1px_rgba(0,0,0,0.8)]";
|
|
28569
|
+
}
|
|
28475
28570
|
var useEditorColors = () => {
|
|
28476
28571
|
const t = useSmartTranslations("UEditor");
|
|
28477
28572
|
const textColors = useMemo22(
|
|
@@ -28546,7 +28641,7 @@ var EditorColorPalette = ({
|
|
|
28546
28641
|
currentColor === c.color ? "border-primary ring-2 ring-primary/25" : "border-border/70"
|
|
28547
28642
|
),
|
|
28548
28643
|
style: { backgroundColor: c.color || "transparent" },
|
|
28549
|
-
children: currentColor === c.color && /* @__PURE__ */ jsx84("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx84(Check11, { className: "h-3.5 w-3.5
|
|
28644
|
+
children: currentColor === c.color && /* @__PURE__ */ jsx84("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx84(Check11, { className: cn("h-3.5 w-3.5", getSwatchCheckClass(c.color)) }) })
|
|
28550
28645
|
}
|
|
28551
28646
|
) }, `${c.name}-${c.color}`)) }),
|
|
28552
28647
|
/* @__PURE__ */ jsxs70(
|
|
@@ -30954,9 +31049,41 @@ function applyTableCellBackground(editor, color) {
|
|
|
30954
31049
|
}
|
|
30955
31050
|
editor.chain().focus().setCellAttribute("backgroundColor", value).run();
|
|
30956
31051
|
}
|
|
31052
|
+
function applyTableCellAttribute(editor, name, value, options = {}) {
|
|
31053
|
+
const shouldFocus = options.focus ?? true;
|
|
31054
|
+
const { state, view } = editor;
|
|
31055
|
+
const applied = setCellAttr2(name, value)(state, view.dispatch.bind(view));
|
|
31056
|
+
if (applied) {
|
|
31057
|
+
if (shouldFocus) view.focus();
|
|
31058
|
+
return;
|
|
31059
|
+
}
|
|
31060
|
+
const chain = editor.chain();
|
|
31061
|
+
if (shouldFocus) chain.focus();
|
|
31062
|
+
chain.setCellAttribute(name, value).run();
|
|
31063
|
+
}
|
|
31064
|
+
function BorderStylePreviewIcon({ style }) {
|
|
31065
|
+
const isNone = style === "none";
|
|
31066
|
+
return /* @__PURE__ */ jsx87(
|
|
31067
|
+
"span",
|
|
31068
|
+
{
|
|
31069
|
+
"aria-hidden": "true",
|
|
31070
|
+
className: cn(
|
|
31071
|
+
"relative inline-flex h-4 w-4 shrink-0 rounded-[2px]",
|
|
31072
|
+
isNone ? "border border-border/70 bg-muted/30" : "border text-current"
|
|
31073
|
+
),
|
|
31074
|
+
style: isNone ? void 0 : {
|
|
31075
|
+
borderStyle: style,
|
|
31076
|
+
borderWidth: style === "double" ? 3 : 2
|
|
31077
|
+
},
|
|
31078
|
+
children: isNone && /* @__PURE__ */ jsx87("span", { className: "absolute left-1/2 top-0 h-full w-px -translate-x-1/2 rotate-45 bg-muted-foreground/70" })
|
|
31079
|
+
}
|
|
31080
|
+
);
|
|
31081
|
+
}
|
|
30957
31082
|
var BubbleMenuContent = ({
|
|
30958
31083
|
editor,
|
|
30959
31084
|
onKeepOpenChange,
|
|
31085
|
+
onLinkInputOpenChange,
|
|
31086
|
+
onRequestClose,
|
|
30960
31087
|
fontSizes,
|
|
30961
31088
|
lineHeights,
|
|
30962
31089
|
initialShowLinkInput = false
|
|
@@ -30987,6 +31114,8 @@ var BubbleMenuContent = ({
|
|
|
30987
31114
|
const currentCellBgColor = normalizeStyleValue(editor.getAttributes("tableCell").backgroundColor || editor.getAttributes("tableHeader").backgroundColor) || "";
|
|
30988
31115
|
const currentCellFormula = normalizeStyleValue(editor.getAttributes("tableCell").formula || editor.getAttributes("tableHeader").formula) || "";
|
|
30989
31116
|
const currentCellNumberFormat = normalizeStyleValue(editor.getAttributes("tableCell").numberFormat || editor.getAttributes("tableHeader").numberFormat) || "text";
|
|
31117
|
+
const currentCellBorderStyle = editor.getAttributes("tableCell").borderStyle || editor.getAttributes("tableHeader").borderStyle || "solid";
|
|
31118
|
+
const currentCellBorderWidth = editor.getAttributes("tableCell").borderWidth || editor.getAttributes("tableHeader").borderWidth || "1px";
|
|
30990
31119
|
const isInTable2 = isSelectionInTable(editor.state);
|
|
30991
31120
|
const canMergeCells = isInTable2 && editor.can().mergeCells();
|
|
30992
31121
|
const canSplitCell = isInTable2 && editor.can().splitCell();
|
|
@@ -31000,6 +31129,15 @@ var BubbleMenuContent = ({
|
|
|
31000
31129
|
() => (lineHeights ?? getDefaultLineHeights()).filter((option) => ["1.2", "1.5", "1.75"].includes(option.value)),
|
|
31001
31130
|
[lineHeights]
|
|
31002
31131
|
);
|
|
31132
|
+
const borderColors = useMemo23(
|
|
31133
|
+
() => [
|
|
31134
|
+
highlightColors[0] ?? { name: t("colors.default"), color: "" },
|
|
31135
|
+
{ name: "Black", color: "#000000" },
|
|
31136
|
+
{ name: "White", color: "#ffffff" },
|
|
31137
|
+
...highlightColors.slice(1)
|
|
31138
|
+
],
|
|
31139
|
+
[highlightColors, t]
|
|
31140
|
+
);
|
|
31003
31141
|
useEffect36(() => {
|
|
31004
31142
|
setFontSizeDraft(currentFontSize.replace(/px$/i, ""));
|
|
31005
31143
|
}, [currentFontSize]);
|
|
@@ -31020,7 +31158,55 @@ var BubbleMenuContent = ({
|
|
|
31020
31158
|
};
|
|
31021
31159
|
useEffect36(() => {
|
|
31022
31160
|
onKeepOpenChange?.(showLinkInput);
|
|
31023
|
-
|
|
31161
|
+
onLinkInputOpenChange?.(showLinkInput);
|
|
31162
|
+
}, [onKeepOpenChange, onLinkInputOpenChange, showLinkInput]);
|
|
31163
|
+
useEffect36(() => {
|
|
31164
|
+
onKeepOpenChange?.(Boolean(activeColorPalette));
|
|
31165
|
+
}, [activeColorPalette, onKeepOpenChange]);
|
|
31166
|
+
const closeTransientPanels = useCallback22(() => {
|
|
31167
|
+
setActiveColorPalette(null);
|
|
31168
|
+
setShowLinkInput(false);
|
|
31169
|
+
onKeepOpenChange?.(false);
|
|
31170
|
+
onLinkInputOpenChange?.(false);
|
|
31171
|
+
onRequestClose?.();
|
|
31172
|
+
}, [onKeepOpenChange, onLinkInputOpenChange, onRequestClose]);
|
|
31173
|
+
const applyTableCellAttributeAndClose = useCallback22((name, value) => {
|
|
31174
|
+
applyTableCellAttribute(editor, name, value, { focus: false });
|
|
31175
|
+
closeTransientPanels();
|
|
31176
|
+
}, [closeTransientPanels, editor]);
|
|
31177
|
+
const clearTableCellBorderAndClose = useCallback22(() => {
|
|
31178
|
+
applyTableCellAttribute(editor, "borderColor", null, { focus: false });
|
|
31179
|
+
applyTableCellAttribute(editor, "borderStyle", null, { focus: false });
|
|
31180
|
+
applyTableCellAttribute(editor, "borderWidth", null, { focus: false });
|
|
31181
|
+
closeTransientPanels();
|
|
31182
|
+
}, [closeTransientPanels, editor]);
|
|
31183
|
+
const applyTableCellBorderColorAndClose = useCallback22((color) => {
|
|
31184
|
+
const value = color || null;
|
|
31185
|
+
applyTableCellAttribute(editor, "borderColor", value, { focus: false });
|
|
31186
|
+
closeTransientPanels();
|
|
31187
|
+
}, [closeTransientPanels, editor]);
|
|
31188
|
+
const closeColorPalette = useCallback22(() => {
|
|
31189
|
+
setActiveColorPalette(null);
|
|
31190
|
+
onKeepOpenChange?.(false);
|
|
31191
|
+
}, [onKeepOpenChange]);
|
|
31192
|
+
const applyInlineColorAndClose = useCallback22((color) => {
|
|
31193
|
+
if (activeColorPalette === "text") {
|
|
31194
|
+
if (color === "inherit") {
|
|
31195
|
+
editor.chain().focus().unsetColor().run();
|
|
31196
|
+
} else {
|
|
31197
|
+
editor.chain().focus().setColor(color).run();
|
|
31198
|
+
}
|
|
31199
|
+
} else if (activeColorPalette === "highlight") {
|
|
31200
|
+
if (color === "") {
|
|
31201
|
+
editor.chain().focus().unsetHighlight().run();
|
|
31202
|
+
} else {
|
|
31203
|
+
editor.chain().focus().toggleHighlight({ color }).run();
|
|
31204
|
+
}
|
|
31205
|
+
} else {
|
|
31206
|
+
applyTableCellBackground(editor, color);
|
|
31207
|
+
}
|
|
31208
|
+
closeColorPalette();
|
|
31209
|
+
}, [activeColorPalette, closeColorPalette, editor]);
|
|
31024
31210
|
useEffect36(() => {
|
|
31025
31211
|
if (!showLinkInput) return;
|
|
31026
31212
|
const close2 = () => setShowLinkInput(false);
|
|
@@ -31052,51 +31238,53 @@ var BubbleMenuContent = ({
|
|
|
31052
31238
|
const isTextPalette = activeColorPalette === "text";
|
|
31053
31239
|
const isHighlightPalette = activeColorPalette === "highlight";
|
|
31054
31240
|
if (activeColorPalette === "cell-border") {
|
|
31055
|
-
const currentBorderStyle = editor.getAttributes("tableCell").borderStyle || editor.getAttributes("tableHeader").borderStyle || "solid";
|
|
31056
|
-
const currentBorderWidth = editor.getAttributes("tableCell").borderWidth || editor.getAttributes("tableHeader").borderWidth || "1px";
|
|
31057
31241
|
const currentBorderColor = editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor || "currentColor";
|
|
31058
|
-
return /* @__PURE__ */ jsxs73("div", { className: "flex flex-col gap-2 p-2 w-56 text-sm", children: [
|
|
31242
|
+
return /* @__PURE__ */ jsxs73("div", { className: "flex flex-col gap-2 p-2 w-56 text-sm", "data-ueditor-keep-open": true, children: [
|
|
31059
31243
|
/* @__PURE__ */ jsx87("div", { className: "font-semibold text-xs text-muted-foreground uppercase tracking-wider mb-1", children: t("tableMenu.cellBorder") || "Cell Borders" }),
|
|
31060
31244
|
/* @__PURE__ */ jsxs73("div", { className: "flex flex-col gap-1", children: [
|
|
31061
31245
|
/* @__PURE__ */ jsx87("label", { className: "text-xs text-muted-foreground", children: t("tableMenu.borderStyle") || "Border Style" }),
|
|
31062
|
-
/* @__PURE__ */
|
|
31063
|
-
"
|
|
31246
|
+
/* @__PURE__ */ jsx87("div", { className: "grid grid-cols-3 gap-1", role: "group", "aria-label": t("tableMenu.borderStyle") || "Border Style", children: [
|
|
31247
|
+
["solid", "Solid"],
|
|
31248
|
+
["dashed", "Dashed"],
|
|
31249
|
+
["dotted", "Dotted"],
|
|
31250
|
+
["double", "Double"],
|
|
31251
|
+
["none", "None"]
|
|
31252
|
+
].map(([style, label]) => /* @__PURE__ */ jsxs73(
|
|
31253
|
+
"button",
|
|
31064
31254
|
{
|
|
31065
|
-
|
|
31066
|
-
|
|
31067
|
-
|
|
31068
|
-
|
|
31069
|
-
|
|
31070
|
-
|
|
31255
|
+
type: "button",
|
|
31256
|
+
"data-ueditor-close-on-select": true,
|
|
31257
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
31258
|
+
onClick: () => applyTableCellAttributeAndClose("borderStyle", style),
|
|
31259
|
+
className: cn(
|
|
31260
|
+
"inline-flex h-8 items-center justify-center gap-1.5 rounded-md px-2 text-xs font-medium transition-colors hover:bg-muted",
|
|
31261
|
+
currentCellBorderStyle === style ? "bg-primary/10 text-primary" : "bg-muted/40 text-foreground"
|
|
31262
|
+
),
|
|
31071
31263
|
children: [
|
|
31072
|
-
/* @__PURE__ */ jsx87(
|
|
31073
|
-
/* @__PURE__ */ jsx87("
|
|
31074
|
-
/* @__PURE__ */ jsx87("option", { value: "dotted", children: "Dotted" }),
|
|
31075
|
-
/* @__PURE__ */ jsx87("option", { value: "double", children: "Double" }),
|
|
31076
|
-
/* @__PURE__ */ jsx87("option", { value: "none", children: "None" })
|
|
31264
|
+
/* @__PURE__ */ jsx87(BorderStylePreviewIcon, { style }),
|
|
31265
|
+
/* @__PURE__ */ jsx87("span", { children: label })
|
|
31077
31266
|
]
|
|
31078
|
-
}
|
|
31079
|
-
|
|
31267
|
+
},
|
|
31268
|
+
style
|
|
31269
|
+
)) })
|
|
31080
31270
|
] }),
|
|
31081
31271
|
/* @__PURE__ */ jsxs73("div", { className: "flex flex-col gap-1", children: [
|
|
31082
31272
|
/* @__PURE__ */ jsx87("label", { className: "text-xs text-muted-foreground", children: t("tableMenu.borderWidth") || "Border Width" }),
|
|
31083
|
-
/* @__PURE__ */
|
|
31084
|
-
"
|
|
31273
|
+
/* @__PURE__ */ jsx87("div", { className: "grid grid-cols-4 gap-1", role: "group", "aria-label": t("tableMenu.borderWidth") || "Border Width", children: ["1px", "2px", "3px", "4px"].map((width) => /* @__PURE__ */ jsx87(
|
|
31274
|
+
"button",
|
|
31085
31275
|
{
|
|
31086
|
-
|
|
31087
|
-
|
|
31088
|
-
|
|
31089
|
-
|
|
31090
|
-
|
|
31091
|
-
|
|
31092
|
-
|
|
31093
|
-
|
|
31094
|
-
|
|
31095
|
-
|
|
31096
|
-
|
|
31097
|
-
|
|
31098
|
-
}
|
|
31099
|
-
)
|
|
31276
|
+
type: "button",
|
|
31277
|
+
"data-ueditor-close-on-select": true,
|
|
31278
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
31279
|
+
onClick: () => applyTableCellAttributeAndClose("borderWidth", width),
|
|
31280
|
+
className: cn(
|
|
31281
|
+
"h-8 rounded-md px-2 text-xs font-medium transition-colors hover:bg-muted",
|
|
31282
|
+
currentCellBorderWidth === width ? "bg-primary/10 text-primary" : "bg-muted/40 text-foreground"
|
|
31283
|
+
),
|
|
31284
|
+
children: width
|
|
31285
|
+
},
|
|
31286
|
+
width
|
|
31287
|
+
)) })
|
|
31100
31288
|
] }),
|
|
31101
31289
|
/* @__PURE__ */ jsxs73(
|
|
31102
31290
|
"button",
|
|
@@ -31118,70 +31306,36 @@ var BubbleMenuContent = ({
|
|
|
31118
31306
|
]
|
|
31119
31307
|
}
|
|
31120
31308
|
),
|
|
31121
|
-
/* @__PURE__ */
|
|
31122
|
-
|
|
31123
|
-
|
|
31124
|
-
|
|
31125
|
-
|
|
31126
|
-
|
|
31127
|
-
|
|
31128
|
-
|
|
31129
|
-
|
|
31130
|
-
|
|
31131
|
-
children: t("tableMenu.clearBorder") || "Clear Border"
|
|
31132
|
-
}
|
|
31133
|
-
),
|
|
31134
|
-
/* @__PURE__ */ jsx87(
|
|
31135
|
-
"button",
|
|
31136
|
-
{
|
|
31137
|
-
type: "button",
|
|
31138
|
-
onClick: () => setActiveColorPalette(null),
|
|
31139
|
-
className: "text-xs font-medium text-primary hover:underline",
|
|
31140
|
-
children: t("tableMenu.done") || "Done"
|
|
31141
|
-
}
|
|
31142
|
-
)
|
|
31143
|
-
] })
|
|
31309
|
+
/* @__PURE__ */ jsx87("div", { className: "flex items-center justify-between gap-2 mt-2 pt-2 border-t border-border", children: /* @__PURE__ */ jsx87(
|
|
31310
|
+
"button",
|
|
31311
|
+
{
|
|
31312
|
+
type: "button",
|
|
31313
|
+
"data-ueditor-close-on-select": true,
|
|
31314
|
+
onClick: clearTableCellBorderAndClose,
|
|
31315
|
+
className: "text-xs text-destructive hover:underline",
|
|
31316
|
+
children: t("tableMenu.clearBorder") || "Clear Border"
|
|
31317
|
+
}
|
|
31318
|
+
) })
|
|
31144
31319
|
] });
|
|
31145
31320
|
}
|
|
31146
31321
|
if (activeColorPalette === "cell-border-color") {
|
|
31147
31322
|
const currentBorderColor = normalizeStyleValue(editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor) || "";
|
|
31148
|
-
return /* @__PURE__ */ jsx87("div", { className: "w-56", children: /* @__PURE__ */ jsx87(
|
|
31323
|
+
return /* @__PURE__ */ jsx87("div", { className: "w-56", "data-ueditor-keep-open": true, children: /* @__PURE__ */ jsx87(
|
|
31149
31324
|
EditorColorPalette,
|
|
31150
31325
|
{
|
|
31151
|
-
colors:
|
|
31326
|
+
colors: borderColors,
|
|
31152
31327
|
currentColor: currentBorderColor,
|
|
31153
|
-
onSelect:
|
|
31154
|
-
const value = color || null;
|
|
31155
|
-
editor.chain().focus().setCellAttribute("borderColor", value).run();
|
|
31156
|
-
setActiveColorPalette("cell-border");
|
|
31157
|
-
},
|
|
31328
|
+
onSelect: applyTableCellBorderColorAndClose,
|
|
31158
31329
|
label: t("tableMenu.borderColor") || "Border Color"
|
|
31159
31330
|
}
|
|
31160
31331
|
) });
|
|
31161
31332
|
}
|
|
31162
|
-
return /* @__PURE__ */ jsx87("div", { className: "w-56", children: /* @__PURE__ */ jsx87(
|
|
31333
|
+
return /* @__PURE__ */ jsx87("div", { className: "w-56", "data-ueditor-keep-open": true, children: /* @__PURE__ */ jsx87(
|
|
31163
31334
|
EditorColorPalette,
|
|
31164
31335
|
{
|
|
31165
31336
|
colors: isTextPalette ? textColors : highlightColors,
|
|
31166
31337
|
currentColor: isTextPalette ? currentTextColor : isHighlightPalette ? currentHighlightColor : currentCellBgColor,
|
|
31167
|
-
onSelect:
|
|
31168
|
-
if (isTextPalette) {
|
|
31169
|
-
if (color === "inherit") {
|
|
31170
|
-
editor.chain().focus().unsetColor().run();
|
|
31171
|
-
} else {
|
|
31172
|
-
editor.chain().focus().setColor(color).run();
|
|
31173
|
-
}
|
|
31174
|
-
} else if (isHighlightPalette) {
|
|
31175
|
-
if (color === "") {
|
|
31176
|
-
editor.chain().focus().unsetHighlight().run();
|
|
31177
|
-
} else {
|
|
31178
|
-
editor.chain().focus().toggleHighlight({ color }).run();
|
|
31179
|
-
}
|
|
31180
|
-
} else {
|
|
31181
|
-
applyTableCellBackground(editor, color);
|
|
31182
|
-
}
|
|
31183
|
-
setActiveColorPalette(null);
|
|
31184
|
-
},
|
|
31338
|
+
onSelect: applyInlineColorAndClose,
|
|
31185
31339
|
label: isTextPalette ? t("colors.textColor") : isHighlightPalette ? t("colors.highlight") : t("tableMenu.cellBackground") || "Cell background"
|
|
31186
31340
|
}
|
|
31187
31341
|
) });
|
|
@@ -31506,6 +31660,9 @@ var BubbleMenuContent = ({
|
|
|
31506
31660
|
/* @__PURE__ */ jsx87(
|
|
31507
31661
|
ToolbarButton,
|
|
31508
31662
|
{
|
|
31663
|
+
onMouseDown: () => {
|
|
31664
|
+
onKeepOpenChange?.(true);
|
|
31665
|
+
},
|
|
31509
31666
|
onClick: () => setActiveColorPalette("cell-border"),
|
|
31510
31667
|
active: Boolean(
|
|
31511
31668
|
editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor || editor.getAttributes("tableCell").borderStyle || editor.getAttributes("tableHeader").borderStyle || editor.getAttributes("tableCell").borderWidth || editor.getAttributes("tableHeader").borderWidth
|
|
@@ -31587,14 +31744,27 @@ var CustomBubbleMenu = ({
|
|
|
31587
31744
|
const SHOW_DELAY_MS = 180;
|
|
31588
31745
|
const BUBBLE_MENU_OFFSET = 16;
|
|
31589
31746
|
const [isVisible, setIsVisible] = useState48(false);
|
|
31747
|
+
const [linkInputOpen, setLinkInputOpen] = useState48(false);
|
|
31590
31748
|
const [position, setPosition] = useState48({ top: 0, left: 0 });
|
|
31591
31749
|
const menuRef = useRef33(null);
|
|
31592
31750
|
const keepOpenRef = useRef33(false);
|
|
31593
31751
|
const showTimeoutRef = useRef33(null);
|
|
31752
|
+
const suppressShowUntilRef = useRef33(0);
|
|
31594
31753
|
const setKeepOpen = useCallback22((next) => {
|
|
31595
31754
|
keepOpenRef.current = next;
|
|
31755
|
+
if (!next) setLinkInputOpen(false);
|
|
31596
31756
|
if (next) setIsVisible(true);
|
|
31597
31757
|
}, []);
|
|
31758
|
+
const closeBubbleMenu = useCallback22(() => {
|
|
31759
|
+
suppressShowUntilRef.current = Date.now() + 1e3;
|
|
31760
|
+
keepOpenRef.current = false;
|
|
31761
|
+
setLinkInputOpen(false);
|
|
31762
|
+
setIsVisible(false);
|
|
31763
|
+
if (showTimeoutRef.current) {
|
|
31764
|
+
clearTimeout(showTimeoutRef.current);
|
|
31765
|
+
showTimeoutRef.current = null;
|
|
31766
|
+
}
|
|
31767
|
+
}, []);
|
|
31598
31768
|
useEffect36(() => {
|
|
31599
31769
|
const clearShowTimeout = () => {
|
|
31600
31770
|
if (showTimeoutRef.current) {
|
|
@@ -31606,6 +31776,11 @@ var CustomBubbleMenu = ({
|
|
|
31606
31776
|
const { state, view } = editor;
|
|
31607
31777
|
const { from, to, empty } = state.selection;
|
|
31608
31778
|
const isLinkActive = editor.isActive("link");
|
|
31779
|
+
if (Date.now() < suppressShowUntilRef.current) {
|
|
31780
|
+
clearShowTimeout();
|
|
31781
|
+
setIsVisible(false);
|
|
31782
|
+
return;
|
|
31783
|
+
}
|
|
31609
31784
|
if (!keepOpenRef.current && (empty && !isLinkActive || !view.hasFocus())) {
|
|
31610
31785
|
clearShowTimeout();
|
|
31611
31786
|
setIsVisible(false);
|
|
@@ -31617,6 +31792,11 @@ var CustomBubbleMenu = ({
|
|
|
31617
31792
|
start = view.coordsAtPos(from);
|
|
31618
31793
|
end = view.coordsAtPos(to);
|
|
31619
31794
|
} catch {
|
|
31795
|
+
if (keepOpenRef.current) {
|
|
31796
|
+
clearShowTimeout();
|
|
31797
|
+
setIsVisible(true);
|
|
31798
|
+
return;
|
|
31799
|
+
}
|
|
31620
31800
|
clearShowTimeout();
|
|
31621
31801
|
setIsVisible(false);
|
|
31622
31802
|
return;
|
|
@@ -31674,15 +31854,34 @@ var CustomBubbleMenu = ({
|
|
|
31674
31854
|
left: `${position.left}px`,
|
|
31675
31855
|
transform: "translate(-50%, -100%)"
|
|
31676
31856
|
},
|
|
31677
|
-
onMouseDown: (e) =>
|
|
31678
|
-
|
|
31857
|
+
onMouseDown: (e) => {
|
|
31858
|
+
const target = e.target;
|
|
31859
|
+
if (target?.closest?.("[data-ueditor-close-on-select]")) {
|
|
31860
|
+
keepOpenRef.current = false;
|
|
31861
|
+
} else if (target?.closest?.("[data-ueditor-keep-open]")) {
|
|
31862
|
+
keepOpenRef.current = true;
|
|
31863
|
+
}
|
|
31864
|
+
e.preventDefault();
|
|
31865
|
+
},
|
|
31866
|
+
children: editor.isActive("link") && !keepOpenRef.current && !linkInputOpen ? /* @__PURE__ */ jsx87(
|
|
31867
|
+
LinkPreviewContent,
|
|
31868
|
+
{
|
|
31869
|
+
editor,
|
|
31870
|
+
onEdit: () => {
|
|
31871
|
+
setLinkInputOpen(true);
|
|
31872
|
+
setKeepOpen(true);
|
|
31873
|
+
}
|
|
31874
|
+
}
|
|
31875
|
+
) : /* @__PURE__ */ jsx87(
|
|
31679
31876
|
BubbleMenuContent,
|
|
31680
31877
|
{
|
|
31681
31878
|
editor,
|
|
31682
31879
|
onKeepOpenChange: setKeepOpen,
|
|
31880
|
+
onLinkInputOpenChange: setLinkInputOpen,
|
|
31881
|
+
onRequestClose: closeBubbleMenu,
|
|
31683
31882
|
fontSizes,
|
|
31684
31883
|
lineHeights,
|
|
31685
|
-
initialShowLinkInput:
|
|
31884
|
+
initialShowLinkInput: linkInputOpen
|
|
31686
31885
|
}
|
|
31687
31886
|
)
|
|
31688
31887
|
}
|
|
@@ -38129,6 +38328,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
38129
38328
|
proseMirror.addEventListener("keyup", handleSelectionChange);
|
|
38130
38329
|
proseMirror.addEventListener("focusin", handleSelectionChange);
|
|
38131
38330
|
document.addEventListener("selectionchange", handleSelectionChange);
|
|
38331
|
+
surface?.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, handleActiveCellLayoutChange);
|
|
38132
38332
|
surface?.addEventListener("scroll", handleActiveCellLayoutChange, scrollListenerOptions);
|
|
38133
38333
|
window.addEventListener("resize", handleActiveCellLayoutChange);
|
|
38134
38334
|
document.addEventListener("pointermove", handlePointerMove);
|
|
@@ -38148,6 +38348,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
38148
38348
|
proseMirror.removeEventListener("keyup", handleSelectionChange);
|
|
38149
38349
|
proseMirror.removeEventListener("focusin", handleSelectionChange);
|
|
38150
38350
|
document.removeEventListener("selectionchange", handleSelectionChange);
|
|
38351
|
+
surface?.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, handleActiveCellLayoutChange);
|
|
38151
38352
|
surface?.removeEventListener("scroll", handleActiveCellLayoutChange, scrollListenerOptions);
|
|
38152
38353
|
window.removeEventListener("resize", handleActiveCellLayoutChange);
|
|
38153
38354
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
@@ -38179,7 +38380,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
38179
38380
|
}
|
|
38180
38381
|
|
|
38181
38382
|
// src/components/UEditor/menu-bar.tsx
|
|
38182
|
-
import React82, { useRef as useRef36, useState as useState49 } from "react";
|
|
38383
|
+
import React82, { useMemo as useMemo24, useRef as useRef36, useState as useState49 } from "react";
|
|
38183
38384
|
import { useEditorState as useEditorState3 } from "@tiptap/react";
|
|
38184
38385
|
import {
|
|
38185
38386
|
AlignCenter as AlignCenter4,
|
|
@@ -38210,6 +38411,144 @@ import {
|
|
|
38210
38411
|
Undo as UndoIcon2,
|
|
38211
38412
|
Upload as Upload4
|
|
38212
38413
|
} from "lucide-react";
|
|
38414
|
+
|
|
38415
|
+
// src/components/UEditor/preview-html.ts
|
|
38416
|
+
var DEFAULT_TABLE_COLUMN_WIDTH = 100;
|
|
38417
|
+
var TIPTAP_TABLE_MIN_COLUMN_WIDTH = 25;
|
|
38418
|
+
function parsePixelWidth2(value) {
|
|
38419
|
+
if (!value) return null;
|
|
38420
|
+
const match = String(value).match(/(?:^|[\s:])(\d+(?:\.\d+)?)px\b/i) ?? String(value).match(/^(\d+(?:\.\d+)?)$/);
|
|
38421
|
+
if (!match) return null;
|
|
38422
|
+
const parsed = Number.parseFloat(match[1] ?? match[0]);
|
|
38423
|
+
return Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed) : null;
|
|
38424
|
+
}
|
|
38425
|
+
function parseStyleWidth(style) {
|
|
38426
|
+
return parsePixelWidth2(style.width) ?? parsePixelWidth2(style.minWidth);
|
|
38427
|
+
}
|
|
38428
|
+
function parseStyleHeight(style) {
|
|
38429
|
+
return parsePixelWidth2(style.height) ?? parsePixelWidth2(style.minHeight);
|
|
38430
|
+
}
|
|
38431
|
+
function getCellColspan(cell) {
|
|
38432
|
+
return Math.max(1, cell.colSpan || Number.parseInt(cell.getAttribute("colspan") || "1", 10) || 1);
|
|
38433
|
+
}
|
|
38434
|
+
function getCellWidths(cell) {
|
|
38435
|
+
const dataColwidth = cell.getAttribute("data-colwidth") || cell.getAttribute("colwidth");
|
|
38436
|
+
if (dataColwidth) {
|
|
38437
|
+
const widths = dataColwidth.split(/[,\s]+/).map((part) => parsePixelWidth2(part)).filter((width2) => typeof width2 === "number");
|
|
38438
|
+
if (widths.length > 0) return widths;
|
|
38439
|
+
}
|
|
38440
|
+
const width = parsePixelWidth2(cell.getAttribute("width")) ?? parseStyleWidth(cell.style);
|
|
38441
|
+
if (!width) return null;
|
|
38442
|
+
const colspan = getCellColspan(cell);
|
|
38443
|
+
return Array.from({ length: colspan }, () => Math.max(DEFAULT_TABLE_COLUMN_WIDTH, Math.round(width / colspan)));
|
|
38444
|
+
}
|
|
38445
|
+
function getColumnCount(table) {
|
|
38446
|
+
const colCount = table.querySelectorAll("colgroup > col").length;
|
|
38447
|
+
if (colCount > 0) return colCount;
|
|
38448
|
+
return Math.max(
|
|
38449
|
+
0,
|
|
38450
|
+
...Array.from(table.rows).map(
|
|
38451
|
+
(row) => Array.from(row.cells).reduce((count, cell) => count + getCellColspan(cell), 0)
|
|
38452
|
+
)
|
|
38453
|
+
);
|
|
38454
|
+
}
|
|
38455
|
+
function resolveColumnWidths(table) {
|
|
38456
|
+
const columnCount = getColumnCount(table);
|
|
38457
|
+
if (columnCount <= 0) return [];
|
|
38458
|
+
const widths = Array.from({ length: columnCount }, () => DEFAULT_TABLE_COLUMN_WIDTH);
|
|
38459
|
+
const cols = Array.from(table.querySelectorAll("colgroup > col"));
|
|
38460
|
+
cols.slice(0, columnCount).forEach((col, index) => {
|
|
38461
|
+
const width = parsePixelWidth2(col.getAttribute("width")) ?? parseStyleWidth(col.style);
|
|
38462
|
+
if (width && width > TIPTAP_TABLE_MIN_COLUMN_WIDTH) {
|
|
38463
|
+
widths[index] = width;
|
|
38464
|
+
}
|
|
38465
|
+
});
|
|
38466
|
+
Array.from(table.rows).forEach((row) => {
|
|
38467
|
+
let columnIndex = 0;
|
|
38468
|
+
Array.from(row.cells).forEach((cell) => {
|
|
38469
|
+
const cellWidths = getCellWidths(cell);
|
|
38470
|
+
if (cellWidths) {
|
|
38471
|
+
cellWidths.slice(0, getCellColspan(cell)).forEach((width, offset) => {
|
|
38472
|
+
if (width > TIPTAP_TABLE_MIN_COLUMN_WIDTH && columnIndex + offset < widths.length) {
|
|
38473
|
+
widths[columnIndex + offset] = width;
|
|
38474
|
+
}
|
|
38475
|
+
});
|
|
38476
|
+
}
|
|
38477
|
+
columnIndex += getCellColspan(cell);
|
|
38478
|
+
});
|
|
38479
|
+
});
|
|
38480
|
+
return widths;
|
|
38481
|
+
}
|
|
38482
|
+
function setStyleProperty(element, property, value) {
|
|
38483
|
+
element.style.setProperty(property, value);
|
|
38484
|
+
}
|
|
38485
|
+
function resolveRowHeight(row) {
|
|
38486
|
+
const explicitRowHeight = parsePixelWidth2(row.getAttribute("data-row-height")) ?? parseStyleHeight(row.style);
|
|
38487
|
+
if (explicitRowHeight) return Math.max(MIN_TABLE_ROW_HEIGHT, explicitRowHeight);
|
|
38488
|
+
const cellHeight = Array.from(row.cells).reduce((maxHeight, cell) => {
|
|
38489
|
+
const height = parsePixelWidth2(cell.getAttribute("height")) ?? parseStyleHeight(cell.style);
|
|
38490
|
+
return height ? Math.max(maxHeight, height) : maxHeight;
|
|
38491
|
+
}, 0);
|
|
38492
|
+
return Math.max(MIN_TABLE_ROW_HEIGHT, cellHeight);
|
|
38493
|
+
}
|
|
38494
|
+
function normalizePreviewRowHeight(row) {
|
|
38495
|
+
const rowHeight = resolveRowHeight(row);
|
|
38496
|
+
row.style.height = `${rowHeight}px`;
|
|
38497
|
+
row.style.minHeight = `${rowHeight}px`;
|
|
38498
|
+
Array.from(row.cells).forEach((cell) => {
|
|
38499
|
+
cell.style.height = `${rowHeight}px`;
|
|
38500
|
+
cell.style.minHeight = `${rowHeight}px`;
|
|
38501
|
+
});
|
|
38502
|
+
}
|
|
38503
|
+
function normalizePreviewTable(table) {
|
|
38504
|
+
const widths = resolveColumnWidths(table);
|
|
38505
|
+
if (widths.length === 0) return;
|
|
38506
|
+
let colgroup = table.querySelector("colgroup");
|
|
38507
|
+
if (!colgroup) {
|
|
38508
|
+
colgroup = document.createElement("colgroup");
|
|
38509
|
+
table.insertBefore(colgroup, table.firstChild);
|
|
38510
|
+
}
|
|
38511
|
+
while (colgroup.children.length < widths.length) {
|
|
38512
|
+
colgroup.appendChild(document.createElement("col"));
|
|
38513
|
+
}
|
|
38514
|
+
Array.from(colgroup.children).forEach((child, index) => {
|
|
38515
|
+
if (child.tagName.toLowerCase() !== "col") return;
|
|
38516
|
+
const col = child;
|
|
38517
|
+
if (index >= widths.length) {
|
|
38518
|
+
child.remove();
|
|
38519
|
+
return;
|
|
38520
|
+
}
|
|
38521
|
+
col.style.width = `${widths[index]}px`;
|
|
38522
|
+
col.style.minWidth = `${widths[index]}px`;
|
|
38523
|
+
col.setAttribute("width", String(widths[index]));
|
|
38524
|
+
});
|
|
38525
|
+
const tableWidth = widths.reduce((sum, width) => sum + width, 0);
|
|
38526
|
+
setStyleProperty(table, "width", `${tableWidth}px`);
|
|
38527
|
+
setStyleProperty(table, "min-width", `${tableWidth}px`);
|
|
38528
|
+
setStyleProperty(table, "table-layout", "fixed");
|
|
38529
|
+
Array.from(table.rows).forEach((row) => {
|
|
38530
|
+
let columnIndex = 0;
|
|
38531
|
+
normalizePreviewRowHeight(row);
|
|
38532
|
+
Array.from(row.cells).forEach((cell) => {
|
|
38533
|
+
const colspan = getCellColspan(cell);
|
|
38534
|
+
const cellWidth = widths.slice(columnIndex, columnIndex + colspan).reduce((sum, width) => sum + width, 0);
|
|
38535
|
+
if (cellWidth > 0) {
|
|
38536
|
+
cell.style.width = `${cellWidth}px`;
|
|
38537
|
+
cell.style.minWidth = `${cellWidth}px`;
|
|
38538
|
+
}
|
|
38539
|
+
columnIndex += colspan;
|
|
38540
|
+
});
|
|
38541
|
+
});
|
|
38542
|
+
}
|
|
38543
|
+
function prepareUEditorPreviewHtml(html) {
|
|
38544
|
+
if (typeof document === "undefined" || !html) return html;
|
|
38545
|
+
const container = document.createElement("div");
|
|
38546
|
+
container.innerHTML = html;
|
|
38547
|
+
container.querySelectorAll("table").forEach((table) => normalizePreviewTable(table));
|
|
38548
|
+
return container.innerHTML;
|
|
38549
|
+
}
|
|
38550
|
+
|
|
38551
|
+
// src/components/UEditor/menu-bar.tsx
|
|
38213
38552
|
import { Fragment as Fragment35, jsx as jsx93, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
38214
38553
|
function MenuTableInsertGrid({
|
|
38215
38554
|
insertLabel,
|
|
@@ -38692,6 +39031,10 @@ var MenuBar = ({
|
|
|
38692
39031
|
const [showSourceDialog, setShowSourceDialog] = useState49(false);
|
|
38693
39032
|
const [sourceHtml, setSourceHtml] = useState49("");
|
|
38694
39033
|
const [showPreviewDialog, setShowPreviewDialog] = useState49(false);
|
|
39034
|
+
const previewHtml = useMemo24(
|
|
39035
|
+
() => showPreviewDialog ? prepareUEditorPreviewHtml(editor.getHTML()) : "",
|
|
39036
|
+
[editor, showPreviewDialog]
|
|
39037
|
+
);
|
|
38695
39038
|
const openSourceDialog = () => {
|
|
38696
39039
|
setSourceHtml(editor.getHTML());
|
|
38697
39040
|
setShowSourceDialog(true);
|
|
@@ -38700,10 +39043,7 @@ var MenuBar = ({
|
|
|
38700
39043
|
setShowPreviewDialog(true);
|
|
38701
39044
|
};
|
|
38702
39045
|
const handlePreview = () => {
|
|
38703
|
-
if (onPreview)
|
|
38704
|
-
onPreview();
|
|
38705
|
-
return;
|
|
38706
|
-
}
|
|
39046
|
+
if (onPreview?.(editor.getHTML()) === false) return;
|
|
38707
39047
|
openPreviewDialog();
|
|
38708
39048
|
};
|
|
38709
39049
|
const applySourceHtml = () => {
|
|
@@ -38938,12 +39278,12 @@ var MenuBar = ({
|
|
|
38938
39278
|
"div",
|
|
38939
39279
|
{
|
|
38940
39280
|
"data-testid": "preview-content",
|
|
38941
|
-
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain
|
|
39281
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain",
|
|
38942
39282
|
children: editor.isEmpty ? /* @__PURE__ */ jsx93("p", { className: "text-muted-foreground text-sm", children: t("menubar.previewEmpty") }) : /* @__PURE__ */ jsx93(
|
|
38943
39283
|
"div",
|
|
38944
39284
|
{
|
|
38945
39285
|
className: UEDITOR_PROSEMIRROR_CLASS_NAME,
|
|
38946
|
-
dangerouslySetInnerHTML: { __html:
|
|
39286
|
+
dangerouslySetInnerHTML: { __html: previewHtml }
|
|
38947
39287
|
}
|
|
38948
39288
|
)
|
|
38949
39289
|
}
|
|
@@ -39151,7 +39491,7 @@ var UEditor = React83.forwardRef(({
|
|
|
39151
39491
|
}
|
|
39152
39492
|
});
|
|
39153
39493
|
}, []);
|
|
39154
|
-
const resolvedUploadFile =
|
|
39494
|
+
const resolvedUploadFile = useMemo25(() => {
|
|
39155
39495
|
if (uploadFile) return uploadFile;
|
|
39156
39496
|
if (uploadFileForSave) {
|
|
39157
39497
|
return async (file) => {
|
|
@@ -39161,7 +39501,7 @@ var UEditor = React83.forwardRef(({
|
|
|
39161
39501
|
}
|
|
39162
39502
|
return uploadImage;
|
|
39163
39503
|
}, [uploadFile, uploadFileForSave, uploadImage]);
|
|
39164
|
-
const extensions =
|
|
39504
|
+
const extensions = useMemo25(
|
|
39165
39505
|
() => [
|
|
39166
39506
|
...buildUEditorExtensions({
|
|
39167
39507
|
placeholder: effectivePlaceholder,
|