@underverse-ui/underverse 1.0.100 → 1.0.102
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 +578 -418
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +576 -416
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -23278,8 +23278,8 @@ function useLocale2() {
|
|
|
23278
23278
|
}
|
|
23279
23279
|
|
|
23280
23280
|
// src/components/UEditor/UEditor.tsx
|
|
23281
|
-
var
|
|
23282
|
-
var
|
|
23281
|
+
var import_react53 = __toESM(require("react"), 1);
|
|
23282
|
+
var import_react54 = require("@tiptap/react");
|
|
23283
23283
|
|
|
23284
23284
|
// src/components/UEditor/extensions.ts
|
|
23285
23285
|
var import_extension_document = __toESM(require("@tiptap/extension-document"), 1);
|
|
@@ -23653,6 +23653,49 @@ var SlashCommand = import_core.Extension.create({
|
|
|
23653
23653
|
// src/components/UEditor/clipboard-images.ts
|
|
23654
23654
|
var import_core2 = require("@tiptap/core");
|
|
23655
23655
|
var import_state = require("@tiptap/pm/state");
|
|
23656
|
+
|
|
23657
|
+
// src/components/UEditor/url-safety.ts
|
|
23658
|
+
var LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
23659
|
+
var IMAGE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
23660
|
+
function normalizeUrlInput(raw) {
|
|
23661
|
+
return raw.trim().replace(/[\u0000-\u001F\u007F\s]+/g, "");
|
|
23662
|
+
}
|
|
23663
|
+
function isProtocolRelativeUrl(value) {
|
|
23664
|
+
return value.startsWith("//");
|
|
23665
|
+
}
|
|
23666
|
+
function isRelativeUrl(value) {
|
|
23667
|
+
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("#");
|
|
23668
|
+
}
|
|
23669
|
+
function isDataImageUrl(value) {
|
|
23670
|
+
return /^data:image\/(?:png|jpe?g|gif|webp|svg\+xml|bmp|x-icon|avif);base64,/i.test(value);
|
|
23671
|
+
}
|
|
23672
|
+
function isSafeUEditorUrl(raw, kind) {
|
|
23673
|
+
const value = normalizeUrlInput(raw);
|
|
23674
|
+
if (!value) return false;
|
|
23675
|
+
if (kind === "image" && isDataImageUrl(value)) return true;
|
|
23676
|
+
if (isRelativeUrl(value)) return true;
|
|
23677
|
+
if (isProtocolRelativeUrl(value)) return false;
|
|
23678
|
+
try {
|
|
23679
|
+
const parsed = new URL(value);
|
|
23680
|
+
return kind === "image" ? IMAGE_PROTOCOLS.has(parsed.protocol) : LINK_PROTOCOLS.has(parsed.protocol);
|
|
23681
|
+
} catch {
|
|
23682
|
+
return false;
|
|
23683
|
+
}
|
|
23684
|
+
}
|
|
23685
|
+
function sanitizeUEditorUrl(raw, kind) {
|
|
23686
|
+
const value = raw.trim();
|
|
23687
|
+
if (!value) return "";
|
|
23688
|
+
if (isSafeUEditorUrl(value, kind)) return normalizeUrlInput(value);
|
|
23689
|
+
if (kind === "link" && !isProtocolRelativeUrl(value) && !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value)) {
|
|
23690
|
+
const withProtocol = `https://${value}`;
|
|
23691
|
+
return isSafeUEditorUrl(withProtocol, kind) ? withProtocol : "";
|
|
23692
|
+
}
|
|
23693
|
+
return "";
|
|
23694
|
+
}
|
|
23695
|
+
|
|
23696
|
+
// src/components/UEditor/clipboard-images.ts
|
|
23697
|
+
var DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
23698
|
+
var DEFAULT_UEDITOR_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"];
|
|
23656
23699
|
function getImageFiles(dataTransfer) {
|
|
23657
23700
|
if (!dataTransfer) return [];
|
|
23658
23701
|
const itemFiles = [];
|
|
@@ -23684,7 +23727,7 @@ async function resolveImageSrc(file, options) {
|
|
|
23684
23727
|
if (options.insertMode === "upload" && options.upload) {
|
|
23685
23728
|
try {
|
|
23686
23729
|
const result = await options.upload(file);
|
|
23687
|
-
const src = typeof result === "string" ? result : "";
|
|
23730
|
+
const src = typeof result === "string" ? sanitizeUEditorUrl(result, "image") : "";
|
|
23688
23731
|
if (src) return src;
|
|
23689
23732
|
} catch (err) {
|
|
23690
23733
|
if (!options.fallbackToDataUrl) throw err;
|
|
@@ -23696,8 +23739,8 @@ var ClipboardImages = import_core2.Extension.create({
|
|
|
23696
23739
|
name: "clipboardImages",
|
|
23697
23740
|
addOptions() {
|
|
23698
23741
|
return {
|
|
23699
|
-
maxFileSize:
|
|
23700
|
-
allowedMimeTypes:
|
|
23742
|
+
maxFileSize: DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
|
|
23743
|
+
allowedMimeTypes: DEFAULT_UEDITOR_IMAGE_MIME_TYPES,
|
|
23701
23744
|
upload: void 0,
|
|
23702
23745
|
fallbackToDataUrl: true,
|
|
23703
23746
|
insertMode: "base64"
|
|
@@ -24556,6 +24599,9 @@ function buildUEditorExtensions({
|
|
|
24556
24599
|
maxCharacters,
|
|
24557
24600
|
uploadImage,
|
|
24558
24601
|
imageInsertMode = "base64",
|
|
24602
|
+
maxImageFileSize,
|
|
24603
|
+
allowedImageMimeTypes,
|
|
24604
|
+
fallbackToDataUrl,
|
|
24559
24605
|
editable = true
|
|
24560
24606
|
}) {
|
|
24561
24607
|
return [
|
|
@@ -24609,12 +24655,20 @@ function buildUEditorExtensions({
|
|
|
24609
24655
|
import_extension_horizontal_rule.default,
|
|
24610
24656
|
import_extension_link.default.configure({
|
|
24611
24657
|
openOnClick: false,
|
|
24658
|
+
protocols: ["http", "https", "mailto", "tel"],
|
|
24659
|
+
isAllowedUri: (url) => isSafeUEditorUrl(url ?? "", "link"),
|
|
24612
24660
|
HTMLAttributes: {
|
|
24613
24661
|
class: "text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer"
|
|
24614
24662
|
}
|
|
24615
24663
|
}),
|
|
24616
24664
|
resizable_image_default,
|
|
24617
|
-
ClipboardImages.configure({
|
|
24665
|
+
ClipboardImages.configure({
|
|
24666
|
+
upload: uploadImage,
|
|
24667
|
+
insertMode: imageInsertMode,
|
|
24668
|
+
...maxImageFileSize !== void 0 ? { maxFileSize: maxImageFileSize } : {},
|
|
24669
|
+
...allowedImageMimeTypes ? { allowedMimeTypes: allowedImageMimeTypes } : {},
|
|
24670
|
+
...fallbackToDataUrl !== void 0 ? { fallbackToDataUrl } : {}
|
|
24671
|
+
}),
|
|
24618
24672
|
import_extension_text_style.TextStyle,
|
|
24619
24673
|
font_family_default,
|
|
24620
24674
|
font_size_default,
|
|
@@ -24833,11 +24887,7 @@ var import_react48 = require("react");
|
|
|
24833
24887
|
var import_lucide_react43 = require("lucide-react");
|
|
24834
24888
|
var import_jsx_runtime78 = require("react/jsx-runtime");
|
|
24835
24889
|
function normalizeUrl(raw) {
|
|
24836
|
-
|
|
24837
|
-
if (!url) return "";
|
|
24838
|
-
if (url.startsWith("#") || url.startsWith("/")) return url;
|
|
24839
|
-
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url)) return url;
|
|
24840
|
-
return `https://${url}`;
|
|
24890
|
+
return sanitizeUEditorUrl(raw, "link");
|
|
24841
24891
|
}
|
|
24842
24892
|
var LinkInput = ({
|
|
24843
24893
|
onSubmit,
|
|
@@ -24882,8 +24932,9 @@ var ImageInput = ({ onSubmit, onCancel }) => {
|
|
|
24882
24932
|
}, []);
|
|
24883
24933
|
const handleSubmit = (e) => {
|
|
24884
24934
|
e.preventDefault();
|
|
24885
|
-
|
|
24886
|
-
|
|
24935
|
+
const safeUrl = sanitizeUEditorUrl(url, "image");
|
|
24936
|
+
if (safeUrl) {
|
|
24937
|
+
onSubmit(safeUrl, alt);
|
|
24887
24938
|
}
|
|
24888
24939
|
};
|
|
24889
24940
|
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("form", { onSubmit: handleSubmit, className: "p-3 space-y-3", children: [
|
|
@@ -25069,6 +25120,8 @@ var EditorToolbar = ({
|
|
|
25069
25120
|
variant,
|
|
25070
25121
|
uploadImage,
|
|
25071
25122
|
imageInsertMode = "base64",
|
|
25123
|
+
maxImageFileSize = DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
|
|
25124
|
+
allowedImageMimeTypes = DEFAULT_UEDITOR_IMAGE_MIME_TYPES,
|
|
25072
25125
|
fontFamilies,
|
|
25073
25126
|
fontSizes,
|
|
25074
25127
|
lineHeights,
|
|
@@ -25136,10 +25189,13 @@ var EditorToolbar = ({
|
|
|
25136
25189
|
setImageUploadError(null);
|
|
25137
25190
|
for (const file of files) {
|
|
25138
25191
|
if (!file.type.startsWith("image/")) continue;
|
|
25192
|
+
if (file.size > maxImageFileSize) continue;
|
|
25193
|
+
if (allowedImageMimeTypes.length > 0 && !allowedImageMimeTypes.includes(file.type)) continue;
|
|
25139
25194
|
try {
|
|
25140
25195
|
const src = imageInsertMode === "upload" && uploadImage ? await uploadImage(file) : await fileToDataUrl2(file);
|
|
25141
|
-
|
|
25142
|
-
|
|
25196
|
+
const safeSrc = sanitizeUEditorUrl(src, "image");
|
|
25197
|
+
if (!safeSrc) continue;
|
|
25198
|
+
editor.chain().focus().setImage({ src: safeSrc, alt: file.name }).run();
|
|
25143
25199
|
editor.commands.createParagraphNear();
|
|
25144
25200
|
} catch {
|
|
25145
25201
|
setImageUploadError(t("imageInput.uploadError"));
|
|
@@ -26334,12 +26390,12 @@ var MIME_EXTENSION_MAP = {
|
|
|
26334
26390
|
"image/x-icon": "ico",
|
|
26335
26391
|
"image/avif": "avif"
|
|
26336
26392
|
};
|
|
26337
|
-
function
|
|
26393
|
+
function isDataImageUrl2(value) {
|
|
26338
26394
|
return /^data:image\//i.test(value.trim());
|
|
26339
26395
|
}
|
|
26340
26396
|
function parseDataImageUrl(dataUrl) {
|
|
26341
26397
|
const value = dataUrl.trim();
|
|
26342
|
-
if (!
|
|
26398
|
+
if (!isDataImageUrl2(value)) return null;
|
|
26343
26399
|
const commaIndex = value.indexOf(",");
|
|
26344
26400
|
if (commaIndex < 0) return null;
|
|
26345
26401
|
const header = value.slice(5, commaIndex);
|
|
@@ -26373,19 +26429,33 @@ function createFileFromDataImageUrl(dataUrl, index) {
|
|
|
26373
26429
|
}
|
|
26374
26430
|
function normalizeUploadResult(result) {
|
|
26375
26431
|
if (typeof result === "string") {
|
|
26376
|
-
const url2 = result
|
|
26432
|
+
const url2 = sanitizeUEditorUrl(result, "image");
|
|
26377
26433
|
if (!url2) throw new Error("Upload handler returned an empty URL.");
|
|
26378
26434
|
return { url: url2 };
|
|
26379
26435
|
}
|
|
26380
26436
|
if (!result || typeof result !== "object") {
|
|
26381
26437
|
throw new Error("Upload handler returned invalid result.");
|
|
26382
26438
|
}
|
|
26383
|
-
const url = typeof result.url === "string" ? result.url
|
|
26439
|
+
const url = typeof result.url === "string" ? sanitizeUEditorUrl(result.url, "image") : "";
|
|
26384
26440
|
if (!url) throw new Error("Upload handler object result is missing `url`.");
|
|
26385
26441
|
const { url: _ignoredUrl, ...rest } = result;
|
|
26386
26442
|
const meta = Object.keys(rest).length > 0 ? rest : void 0;
|
|
26387
26443
|
return { url, meta };
|
|
26388
26444
|
}
|
|
26445
|
+
async function runWithConcurrency(items, concurrency, worker) {
|
|
26446
|
+
const limit = Math.max(1, Math.floor(concurrency));
|
|
26447
|
+
const results = new Array(items.length);
|
|
26448
|
+
let nextIndex = 0;
|
|
26449
|
+
async function runNext() {
|
|
26450
|
+
while (nextIndex < items.length) {
|
|
26451
|
+
const currentIndex = nextIndex;
|
|
26452
|
+
nextIndex += 1;
|
|
26453
|
+
results[currentIndex] = await worker(items[currentIndex]);
|
|
26454
|
+
}
|
|
26455
|
+
}
|
|
26456
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, runNext));
|
|
26457
|
+
return results;
|
|
26458
|
+
}
|
|
26389
26459
|
function getErrorReason(error) {
|
|
26390
26460
|
if (error instanceof Error && error.message) return error.message;
|
|
26391
26461
|
if (typeof error === "string" && error.trim()) return error;
|
|
@@ -26397,7 +26467,7 @@ function decodeHtmlEntities(value) {
|
|
|
26397
26467
|
function normalizeImageUrl(url) {
|
|
26398
26468
|
const input = decodeHtmlEntities(url.trim());
|
|
26399
26469
|
if (!input) return "";
|
|
26400
|
-
if (
|
|
26470
|
+
if (isDataImageUrl2(input)) return input;
|
|
26401
26471
|
const isAbsolute = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(input);
|
|
26402
26472
|
if (!isAbsolute) {
|
|
26403
26473
|
return input.split("#")[0] ?? input;
|
|
@@ -26481,7 +26551,8 @@ var UEditorPrepareContentForSaveError = class extends Error {
|
|
|
26481
26551
|
};
|
|
26482
26552
|
async function prepareUEditorContentForSave({
|
|
26483
26553
|
html,
|
|
26484
|
-
uploadImageForSave
|
|
26554
|
+
uploadImageForSave,
|
|
26555
|
+
uploadConcurrency = 3
|
|
26485
26556
|
}) {
|
|
26486
26557
|
if (!html || !html.includes("<img")) {
|
|
26487
26558
|
return createResult({ html, uploaded: [], inlineUploaded: [], errors: [] });
|
|
@@ -26494,7 +26565,7 @@ async function prepareUEditorContentForSave({
|
|
|
26494
26565
|
for (const match of imgMatches) {
|
|
26495
26566
|
if (!match.srcAttr) continue;
|
|
26496
26567
|
const src = match.srcAttr.value.trim();
|
|
26497
|
-
if (!
|
|
26568
|
+
if (!isDataImageUrl2(src)) continue;
|
|
26498
26569
|
base64Candidates.push({
|
|
26499
26570
|
id: `${match.start}:${match.end}`,
|
|
26500
26571
|
match,
|
|
@@ -26520,8 +26591,10 @@ async function prepareUEditorContentForSave({
|
|
|
26520
26591
|
const inlineUploaded = [];
|
|
26521
26592
|
const errors = [];
|
|
26522
26593
|
const replacements = /* @__PURE__ */ new Map();
|
|
26523
|
-
const uploadResults = await
|
|
26524
|
-
base64Candidates
|
|
26594
|
+
const uploadResults = await runWithConcurrency(
|
|
26595
|
+
base64Candidates,
|
|
26596
|
+
uploadConcurrency,
|
|
26597
|
+
async (candidate) => {
|
|
26525
26598
|
try {
|
|
26526
26599
|
const file = createFileFromDataImageUrl(candidate.src, candidate.index);
|
|
26527
26600
|
const uploadResult = await uploadImageForSave(file);
|
|
@@ -26530,7 +26603,7 @@ async function prepareUEditorContentForSave({
|
|
|
26530
26603
|
} catch (error) {
|
|
26531
26604
|
return { candidate, error: getErrorReason(error) };
|
|
26532
26605
|
}
|
|
26533
|
-
}
|
|
26606
|
+
}
|
|
26534
26607
|
);
|
|
26535
26608
|
for (const item of uploadResults) {
|
|
26536
26609
|
if ("error" in item) {
|
|
@@ -30732,6 +30805,111 @@ var columnResizingPluginKey = new PluginKey3("tableColumnResizing");
|
|
|
30732
30805
|
|
|
30733
30806
|
// src/components/UEditor/table-controls.tsx
|
|
30734
30807
|
var import_lucide_react46 = require("lucide-react");
|
|
30808
|
+
|
|
30809
|
+
// src/components/UEditor/table-dom-utils.ts
|
|
30810
|
+
var MIN_TABLE_ROW_HEIGHT = 36;
|
|
30811
|
+
var COLUMN_RESIZE_LINE_THICKNESS = 2;
|
|
30812
|
+
var ROW_RESIZE_LINE_THICKNESS = 2;
|
|
30813
|
+
var UEDITOR_TABLE_LAYOUT_CHANGE_EVENT = "ueditor-table-layout-change";
|
|
30814
|
+
var TABLE_RESIZE_HIT_ZONE = 10;
|
|
30815
|
+
function findTableRowNodeInfo(view, rowElement) {
|
|
30816
|
+
const firstCell = rowElement.querySelector("th,td");
|
|
30817
|
+
if (!firstCell) return null;
|
|
30818
|
+
const cellPos = view.posAtDOM(firstCell, 0);
|
|
30819
|
+
const $pos = view.state.doc.resolve(cellPos);
|
|
30820
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
30821
|
+
const node = $pos.node(depth);
|
|
30822
|
+
if (node.type.name === "tableRow") {
|
|
30823
|
+
return {
|
|
30824
|
+
pos: $pos.before(depth),
|
|
30825
|
+
node
|
|
30826
|
+
};
|
|
30827
|
+
}
|
|
30828
|
+
}
|
|
30829
|
+
return null;
|
|
30830
|
+
}
|
|
30831
|
+
function resolveEventElement(target) {
|
|
30832
|
+
if (target instanceof Element) return target;
|
|
30833
|
+
if (target instanceof Node) return target.parentElement;
|
|
30834
|
+
return null;
|
|
30835
|
+
}
|
|
30836
|
+
function getSelectionTableCell(view) {
|
|
30837
|
+
const browserSelection = window.getSelection();
|
|
30838
|
+
const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
|
|
30839
|
+
const anchorCell = anchorElement?.closest?.("th,td");
|
|
30840
|
+
if (anchorCell instanceof HTMLElement) {
|
|
30841
|
+
return anchorCell;
|
|
30842
|
+
}
|
|
30843
|
+
const { from } = view.state.selection;
|
|
30844
|
+
const domAtPos = view.domAtPos(from);
|
|
30845
|
+
const element = resolveEventElement(domAtPos.node);
|
|
30846
|
+
const cell = element?.closest?.("th,td");
|
|
30847
|
+
return cell instanceof HTMLElement ? cell : null;
|
|
30848
|
+
}
|
|
30849
|
+
function isRowResizeHotspot(cell, clientX, clientY) {
|
|
30850
|
+
const rect = cell.getBoundingClientRect();
|
|
30851
|
+
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
30852
|
+
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
30853
|
+
return nearBottom && !nearRight;
|
|
30854
|
+
}
|
|
30855
|
+
function isColumnResizeHotspot(cell, clientX, clientY) {
|
|
30856
|
+
const rect = cell.getBoundingClientRect();
|
|
30857
|
+
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
30858
|
+
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
30859
|
+
return nearRight && !nearBottom;
|
|
30860
|
+
}
|
|
30861
|
+
function getRelativeBoundaryMetrics(surface, table, row, cell) {
|
|
30862
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
30863
|
+
const tableRect = table.getBoundingClientRect();
|
|
30864
|
+
const rowRect = row.getBoundingClientRect();
|
|
30865
|
+
const cellRect = cell.getBoundingClientRect();
|
|
30866
|
+
return {
|
|
30867
|
+
left: tableRect.left - surfaceRect.left + surface.scrollLeft,
|
|
30868
|
+
top: tableRect.top - surfaceRect.top + surface.scrollTop,
|
|
30869
|
+
width: tableRect.width,
|
|
30870
|
+
height: tableRect.height,
|
|
30871
|
+
rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
|
|
30872
|
+
columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
|
|
30873
|
+
};
|
|
30874
|
+
}
|
|
30875
|
+
function getRelativeCellMetrics(surface, cell) {
|
|
30876
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
30877
|
+
const cellRect = cell.getBoundingClientRect();
|
|
30878
|
+
return {
|
|
30879
|
+
left: cellRect.left - surfaceRect.left + surface.scrollLeft,
|
|
30880
|
+
top: cellRect.top - surfaceRect.top + surface.scrollTop,
|
|
30881
|
+
width: cellRect.width,
|
|
30882
|
+
height: cellRect.height
|
|
30883
|
+
};
|
|
30884
|
+
}
|
|
30885
|
+
function getRelativeSelectedCellsMetrics(surface) {
|
|
30886
|
+
const selectedCells = Array.from(
|
|
30887
|
+
surface.querySelectorAll("td.selectedCell, th.selectedCell")
|
|
30888
|
+
);
|
|
30889
|
+
if (selectedCells.length === 0) {
|
|
30890
|
+
return null;
|
|
30891
|
+
}
|
|
30892
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
30893
|
+
let left = Number.POSITIVE_INFINITY;
|
|
30894
|
+
let top = Number.POSITIVE_INFINITY;
|
|
30895
|
+
let right = Number.NEGATIVE_INFINITY;
|
|
30896
|
+
let bottom = Number.NEGATIVE_INFINITY;
|
|
30897
|
+
selectedCells.forEach((cell) => {
|
|
30898
|
+
const rect = cell.getBoundingClientRect();
|
|
30899
|
+
left = Math.min(left, rect.left);
|
|
30900
|
+
top = Math.min(top, rect.top);
|
|
30901
|
+
right = Math.max(right, rect.right);
|
|
30902
|
+
bottom = Math.max(bottom, rect.bottom);
|
|
30903
|
+
});
|
|
30904
|
+
return {
|
|
30905
|
+
left: left - surfaceRect.left + surface.scrollLeft,
|
|
30906
|
+
top: top - surfaceRect.top + surface.scrollTop,
|
|
30907
|
+
width: right - left,
|
|
30908
|
+
height: bottom - top
|
|
30909
|
+
};
|
|
30910
|
+
}
|
|
30911
|
+
|
|
30912
|
+
// src/components/UEditor/table-controls.tsx
|
|
30735
30913
|
var import_jsx_runtime83 = require("react/jsx-runtime");
|
|
30736
30914
|
var FALLBACK_TABLE_ROW_HEIGHT = 44;
|
|
30737
30915
|
var FALLBACK_TABLE_COLUMN_WIDTH = 160;
|
|
@@ -31031,6 +31209,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
31031
31209
|
surface.addEventListener("mouseover", handleSurfaceMouseMove);
|
|
31032
31210
|
surface.addEventListener("mousemove", handleSurfaceMouseMove);
|
|
31033
31211
|
surface.addEventListener("scroll", refreshCurrentLayout, { passive: true });
|
|
31212
|
+
surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
|
|
31034
31213
|
window.addEventListener("resize", refreshCurrentLayout);
|
|
31035
31214
|
editor.on("selectionUpdate", syncFromSelection);
|
|
31036
31215
|
editor.on("update", refreshCurrentLayout);
|
|
@@ -31042,6 +31221,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
31042
31221
|
surface.removeEventListener("mouseover", handleSurfaceMouseMove);
|
|
31043
31222
|
surface.removeEventListener("mousemove", handleSurfaceMouseMove);
|
|
31044
31223
|
surface.removeEventListener("scroll", refreshCurrentLayout);
|
|
31224
|
+
surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
|
|
31045
31225
|
window.removeEventListener("resize", refreshCurrentLayout);
|
|
31046
31226
|
editor.off("selectionUpdate", syncFromSelection);
|
|
31047
31227
|
editor.off("update", refreshCurrentLayout);
|
|
@@ -31725,163 +31905,163 @@ function TableControls({ editor, containerRef }) {
|
|
|
31725
31905
|
] });
|
|
31726
31906
|
}
|
|
31727
31907
|
|
|
31728
|
-
// src/components/UEditor/
|
|
31729
|
-
var
|
|
31730
|
-
|
|
31731
|
-
|
|
31732
|
-
|
|
31733
|
-
|
|
31734
|
-
|
|
31735
|
-
|
|
31736
|
-
|
|
31737
|
-
|
|
31738
|
-
|
|
31739
|
-
|
|
31740
|
-
|
|
31741
|
-
|
|
31742
|
-
|
|
31743
|
-
|
|
31744
|
-
|
|
31745
|
-
|
|
31746
|
-
|
|
31747
|
-
|
|
31748
|
-
|
|
31749
|
-
|
|
31750
|
-
|
|
31751
|
-
|
|
31752
|
-
|
|
31753
|
-
|
|
31754
|
-
|
|
31755
|
-
|
|
31756
|
-
|
|
31757
|
-
|
|
31758
|
-
|
|
31759
|
-
|
|
31760
|
-
|
|
31761
|
-
|
|
31762
|
-
|
|
31763
|
-
|
|
31764
|
-
|
|
31765
|
-
|
|
31766
|
-
|
|
31767
|
-
|
|
31768
|
-
|
|
31769
|
-
|
|
31770
|
-
|
|
31771
|
-
|
|
31772
|
-
|
|
31773
|
-
|
|
31774
|
-
|
|
31775
|
-
|
|
31776
|
-
|
|
31777
|
-
|
|
31778
|
-
|
|
31779
|
-
|
|
31780
|
-
|
|
31781
|
-
|
|
31782
|
-
|
|
31783
|
-
|
|
31784
|
-
|
|
31785
|
-
|
|
31786
|
-
|
|
31787
|
-
|
|
31788
|
-
|
|
31789
|
-
|
|
31790
|
-
|
|
31791
|
-
|
|
31792
|
-
|
|
31793
|
-
|
|
31794
|
-
|
|
31795
|
-
|
|
31796
|
-
|
|
31797
|
-
|
|
31798
|
-
|
|
31799
|
-
|
|
31800
|
-
|
|
31801
|
-
|
|
31802
|
-
|
|
31803
|
-
|
|
31804
|
-
|
|
31805
|
-
|
|
31806
|
-
|
|
31807
|
-
|
|
31808
|
-
|
|
31809
|
-
|
|
31810
|
-
|
|
31811
|
-
|
|
31812
|
-
|
|
31813
|
-
|
|
31814
|
-
|
|
31815
|
-
|
|
31816
|
-
|
|
31817
|
-
|
|
31818
|
-
|
|
31819
|
-
|
|
31820
|
-
|
|
31821
|
-
|
|
31822
|
-
|
|
31823
|
-
|
|
31824
|
-
|
|
31825
|
-
|
|
31826
|
-
|
|
31827
|
-
|
|
31828
|
-
|
|
31829
|
-
|
|
31830
|
-
|
|
31831
|
-
|
|
31832
|
-
|
|
31833
|
-
|
|
31834
|
-
|
|
31835
|
-
|
|
31836
|
-
|
|
31837
|
-
|
|
31838
|
-
|
|
31839
|
-
|
|
31840
|
-
|
|
31841
|
-
|
|
31842
|
-
|
|
31843
|
-
|
|
31844
|
-
|
|
31845
|
-
|
|
31846
|
-
|
|
31847
|
-
|
|
31848
|
-
|
|
31849
|
-
|
|
31850
|
-
|
|
31851
|
-
|
|
31852
|
-
|
|
31853
|
-
|
|
31854
|
-
|
|
31855
|
-
|
|
31856
|
-
|
|
31857
|
-
|
|
31858
|
-
|
|
31859
|
-
|
|
31860
|
-
|
|
31861
|
-
|
|
31862
|
-
|
|
31863
|
-
|
|
31864
|
-
|
|
31865
|
-
|
|
31866
|
-
|
|
31867
|
-
|
|
31868
|
-
|
|
31869
|
-
|
|
31870
|
-
|
|
31871
|
-
|
|
31872
|
-
|
|
31873
|
-
|
|
31874
|
-
|
|
31875
|
-
|
|
31876
|
-
|
|
31877
|
-
const inFlightPrepareRef = (0, import_react52.useRef)(null);
|
|
31878
|
-
const lastAppliedContentRef = (0, import_react52.useRef)(content ?? "");
|
|
31908
|
+
// src/components/UEditor/editor-styles.ts
|
|
31909
|
+
var UEDITOR_PROSEMIRROR_CLASS_NAME = cn(
|
|
31910
|
+
"prose prose-sm sm:prose dark:prose-invert max-w-none",
|
|
31911
|
+
"focus:outline-none",
|
|
31912
|
+
"px-4 py-4",
|
|
31913
|
+
"[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
|
|
31914
|
+
"[&_.is-editor-empty]:before:text-muted-foreground/50",
|
|
31915
|
+
"[&_.is-editor-empty]:before:float-left",
|
|
31916
|
+
"[&_.is-editor-empty]:before:pointer-events-none",
|
|
31917
|
+
"[&_.is-editor-empty]:before:h-0",
|
|
31918
|
+
"[&_ul[data-type='taskList']]:list-none",
|
|
31919
|
+
"[&_ul[data-type='taskList']]:pl-0",
|
|
31920
|
+
"[&_ul[data-type='taskList']_li]:flex",
|
|
31921
|
+
"[&_ul[data-type='taskList']_li]:items-start",
|
|
31922
|
+
"[&_ul[data-type='taskList']_li]:gap-2",
|
|
31923
|
+
"[&_ul[data-type='taskList']_li>label]:mt-0.5",
|
|
31924
|
+
"[&_ul[data-type='taskList']_li>label>input]:w-4",
|
|
31925
|
+
"[&_ul[data-type='taskList']_li>label>input]:h-4",
|
|
31926
|
+
"[&_ul[data-type='taskList']_li>label>input]:rounded",
|
|
31927
|
+
"[&_ul[data-type='taskList']_li>label>input]:border-2",
|
|
31928
|
+
"[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
|
|
31929
|
+
"[&_ul[data-type='taskList']_li>label>input]:accent-primary",
|
|
31930
|
+
"[&_pre]:bg-muted/40!",
|
|
31931
|
+
"[&_pre]:text-foreground!",
|
|
31932
|
+
"[&_pre]:border!",
|
|
31933
|
+
"[&_pre]:border-border/60!",
|
|
31934
|
+
"[&_pre_code]:bg-transparent!",
|
|
31935
|
+
"[&_.tableWrapper]:overflow-x-auto",
|
|
31936
|
+
"[&_.tableWrapper]:pb-1.5",
|
|
31937
|
+
"[&_.tableWrapper]:select-text",
|
|
31938
|
+
"[&_.tableWrapper]:[scrollbar-width:thin]",
|
|
31939
|
+
"[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
|
|
31940
|
+
"[&_.tableWrapper::-webkit-scrollbar]:h-2",
|
|
31941
|
+
"[&_.tableWrapper::-webkit-scrollbar]:w-2",
|
|
31942
|
+
"[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
|
|
31943
|
+
"[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
|
|
31944
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
|
|
31945
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
|
|
31946
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
|
|
31947
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
|
|
31948
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
|
|
31949
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
|
|
31950
|
+
"[&_table]:table-fixed",
|
|
31951
|
+
"[&_table]:overflow-hidden",
|
|
31952
|
+
"[&_table]:select-text",
|
|
31953
|
+
"[&_table[data-table-align]]:w-max",
|
|
31954
|
+
"[&_table[data-table-align]]:max-w-full",
|
|
31955
|
+
"[&_table[data-table-align='center']]:mx-auto",
|
|
31956
|
+
"[&_table[data-table-align='right']]:ml-auto",
|
|
31957
|
+
"[&_table[data-table-align='right']]:mr-0",
|
|
31958
|
+
"[&_td]:relative",
|
|
31959
|
+
"[&_td]:align-top",
|
|
31960
|
+
"[&_td]:box-border",
|
|
31961
|
+
"[&_td]:select-text",
|
|
31962
|
+
"[&_th]:relative",
|
|
31963
|
+
"[&_th]:align-top",
|
|
31964
|
+
"[&_th]:box-border",
|
|
31965
|
+
"[&_th]:select-text",
|
|
31966
|
+
"[&_.selectedCell]:after:content-['']",
|
|
31967
|
+
"[&_.selectedCell]:after:absolute",
|
|
31968
|
+
"[&_.selectedCell]:after:inset-0",
|
|
31969
|
+
"[&_.selectedCell]:after:z-[2]",
|
|
31970
|
+
"[&_.selectedCell]:after:bg-primary/15",
|
|
31971
|
+
"[&_.selectedCell]:after:pointer-events-none",
|
|
31972
|
+
"[&_.column-resize-handle]:pointer-events-auto",
|
|
31973
|
+
"[&_.column-resize-handle]:cursor-col-resize",
|
|
31974
|
+
"[&_.column-resize-handle]:absolute",
|
|
31975
|
+
"[&_.column-resize-handle]:top-[-1px]",
|
|
31976
|
+
"[&_.column-resize-handle]:bottom-[-1px]",
|
|
31977
|
+
"[&_.column-resize-handle]:right-[-5px]",
|
|
31978
|
+
"[&_.column-resize-handle]:z-10",
|
|
31979
|
+
"[&_.column-resize-handle]:w-2.5",
|
|
31980
|
+
"[&_.column-resize-handle]:bg-transparent",
|
|
31981
|
+
"[&_.column-resize-handle]:rounded-none",
|
|
31982
|
+
"[&_.column-resize-handle]:opacity-0",
|
|
31983
|
+
"[&_.column-resize-handle]:transition-opacity",
|
|
31984
|
+
"[&_.column-resize-handle]:after:absolute",
|
|
31985
|
+
"[&_.column-resize-handle]:after:top-0",
|
|
31986
|
+
"[&_.column-resize-handle]:after:bottom-0",
|
|
31987
|
+
"[&_.column-resize-handle]:after:left-1/2",
|
|
31988
|
+
"[&_.column-resize-handle]:after:w-0.5",
|
|
31989
|
+
"[&_.column-resize-handle]:after:-translate-x-1/2",
|
|
31990
|
+
"[&_.column-resize-handle]:after:rounded-full",
|
|
31991
|
+
"[&_.column-resize-handle]:after:bg-primary/75",
|
|
31992
|
+
"[&_.column-resize-handle]:after:content-['']",
|
|
31993
|
+
"[&.resize-cursor_.column-resize-handle]:opacity-100",
|
|
31994
|
+
"[&.resize-cursor_.column-resize-handle]:after:bg-primary",
|
|
31995
|
+
"[&.resize-cursor]:cursor-col-resize",
|
|
31996
|
+
"[&.resize-row-cursor]:cursor-row-resize",
|
|
31997
|
+
"[&_img.ProseMirror-selectednode]:ring-2",
|
|
31998
|
+
"[&_img.ProseMirror-selectednode]:ring-primary/60",
|
|
31999
|
+
"[&_img.ProseMirror-selectednode]:ring-offset-2",
|
|
32000
|
+
"[&_img.ProseMirror-selectednode]:ring-offset-background",
|
|
32001
|
+
"[&_hr]:border-t-2",
|
|
32002
|
+
"[&_hr]:border-primary/30",
|
|
32003
|
+
"[&_hr]:my-8",
|
|
32004
|
+
"[&_h1]:text-3xl",
|
|
32005
|
+
"[&_h1]:font-bold",
|
|
32006
|
+
"[&_h1]:mt-6",
|
|
32007
|
+
"[&_h1]:mb-4",
|
|
32008
|
+
"[&_h1]:text-foreground",
|
|
32009
|
+
"[&_h2]:text-2xl",
|
|
32010
|
+
"[&_h2]:font-semibold",
|
|
32011
|
+
"[&_h2]:mt-5",
|
|
32012
|
+
"[&_h2]:mb-3",
|
|
32013
|
+
"[&_h2]:text-foreground",
|
|
32014
|
+
"[&_h3]:text-xl",
|
|
32015
|
+
"[&_h3]:font-semibold",
|
|
32016
|
+
"[&_h3]:mt-4",
|
|
32017
|
+
"[&_h3]:mb-2",
|
|
32018
|
+
"[&_h3]:text-foreground",
|
|
32019
|
+
"[&_ul:not([data-type='taskList'])]:list-disc",
|
|
32020
|
+
"[&_ul:not([data-type='taskList'])]:pl-6",
|
|
32021
|
+
"[&_ul:not([data-type='taskList'])]:my-3",
|
|
32022
|
+
"[&_ol]:list-decimal",
|
|
32023
|
+
"[&_ol]:pl-6",
|
|
32024
|
+
"[&_ol]:my-3",
|
|
32025
|
+
"[&_li]:my-1",
|
|
32026
|
+
"[&_li]:pl-1",
|
|
32027
|
+
"[&_li_p]:my-0",
|
|
32028
|
+
"[&_blockquote]:border-l-4",
|
|
32029
|
+
"[&_blockquote]:border-primary",
|
|
32030
|
+
"[&_blockquote]:pl-4",
|
|
32031
|
+
"[&_blockquote]:py-2",
|
|
32032
|
+
"[&_blockquote]:my-4",
|
|
32033
|
+
"[&_blockquote]:bg-muted/30",
|
|
32034
|
+
"[&_blockquote]:rounded-r-lg",
|
|
32035
|
+
"[&_blockquote]:italic",
|
|
32036
|
+
"[&_blockquote]:text-muted-foreground",
|
|
32037
|
+
"[&_blockquote_p]:my-0",
|
|
32038
|
+
"[&_[data-image-layout='left']+p]:mt-1",
|
|
32039
|
+
"[&_[data-image-layout='left']+p]:min-h-[5rem]",
|
|
32040
|
+
"[&_[data-image-layout='right']+p]:mt-1",
|
|
32041
|
+
"[&_[data-image-layout='right']+p]:min-h-[5rem]",
|
|
32042
|
+
"max-md:[&_[data-image-layout='left']]:float-none",
|
|
32043
|
+
"max-md:[&_[data-image-layout='left']]:mr-0",
|
|
32044
|
+
"max-md:[&_[data-image-layout='left']]:ml-0",
|
|
32045
|
+
"max-md:[&_[data-image-layout='left']]:max-w-full",
|
|
32046
|
+
"max-md:[&_[data-image-layout='right']]:float-none",
|
|
32047
|
+
"max-md:[&_[data-image-layout='right']]:mr-0",
|
|
32048
|
+
"max-md:[&_[data-image-layout='right']]:ml-0",
|
|
32049
|
+
"max-md:[&_[data-image-layout='right']]:max-w-full",
|
|
32050
|
+
"max-md:[&_[data-image-layout='left']+p]:min-h-0",
|
|
32051
|
+
"max-md:[&_[data-image-layout='right']+p]:min-h-0"
|
|
32052
|
+
);
|
|
32053
|
+
|
|
32054
|
+
// src/components/UEditor/use-table-interactions.ts
|
|
32055
|
+
var import_react52 = __toESM(require("react"), 1);
|
|
32056
|
+
function useUEditorTableInteractions(editor) {
|
|
31879
32057
|
const editorContentRef = (0, import_react52.useRef)(null);
|
|
31880
32058
|
const tableColumnGuideRef = (0, import_react52.useRef)(null);
|
|
31881
32059
|
const tableRowGuideRef = (0, import_react52.useRef)(null);
|
|
31882
32060
|
const activeTableCellHighlightRef = (0, import_react52.useRef)(null);
|
|
31883
32061
|
const hoveredTableCellRef = (0, import_react52.useRef)(null);
|
|
31884
32062
|
const activeTableCellRef = (0, import_react52.useRef)(null);
|
|
32063
|
+
const tableLayoutSyncFrameRef = (0, import_react52.useRef)(null);
|
|
32064
|
+
const rowResizeCommitFrameRef = (0, import_react52.useRef)(null);
|
|
31885
32065
|
const rowResizeStateRef = (0, import_react52.useRef)(null);
|
|
31886
32066
|
const setEditorResizeCursor = import_react52.default.useCallback((cursor) => {
|
|
31887
32067
|
const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
|
|
@@ -31923,6 +32103,14 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
31923
32103
|
highlight.style.width = `${metrics.width}px`;
|
|
31924
32104
|
highlight.style.height = `${metrics.height}px`;
|
|
31925
32105
|
}, []);
|
|
32106
|
+
const scheduleTableLayoutSync = import_react52.default.useCallback(() => {
|
|
32107
|
+
if (tableLayoutSyncFrameRef.current !== null) return;
|
|
32108
|
+
tableLayoutSyncFrameRef.current = window.requestAnimationFrame(() => {
|
|
32109
|
+
tableLayoutSyncFrameRef.current = null;
|
|
32110
|
+
updateActiveCellHighlight(activeTableCellRef.current);
|
|
32111
|
+
editorContentRef.current?.dispatchEvent(new CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT));
|
|
32112
|
+
});
|
|
32113
|
+
}, [updateActiveCellHighlight]);
|
|
31926
32114
|
const setActiveTableCell = import_react52.default.useCallback((cell) => {
|
|
31927
32115
|
if (activeTableCellRef.current === cell) return;
|
|
31928
32116
|
activeTableCellRef.current = cell;
|
|
@@ -31964,228 +32152,49 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
31964
32152
|
surface.classList.add("resize-row-cursor");
|
|
31965
32153
|
setEditorResizeCursor("row-resize");
|
|
31966
32154
|
}, [setEditorResizeCursor]);
|
|
31967
|
-
const
|
|
31968
|
-
()
|
|
31969
|
-
|
|
31970
|
-
|
|
31971
|
-
|
|
31972
|
-
|
|
31973
|
-
|
|
31974
|
-
|
|
31975
|
-
|
|
31976
|
-
|
|
31977
|
-
editorProps: {
|
|
31978
|
-
handleDOMEvents: {
|
|
31979
|
-
keydown: (_view, event) => {
|
|
31980
|
-
if (!(event instanceof KeyboardEvent)) return false;
|
|
31981
|
-
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
31982
|
-
event.stopPropagation();
|
|
31983
|
-
}
|
|
31984
|
-
return false;
|
|
31985
|
-
},
|
|
31986
|
-
click: (view, event) => {
|
|
31987
|
-
if (!(event instanceof MouseEvent)) return false;
|
|
31988
|
-
if (event.button !== 0) return false;
|
|
31989
|
-
const target = resolveEventElement(event.target);
|
|
31990
|
-
const anchor = target?.closest?.("a[href]");
|
|
31991
|
-
const href = anchor?.getAttribute("href") ?? "";
|
|
31992
|
-
if (!href) return false;
|
|
31993
|
-
if (!view.state.selection.empty) return false;
|
|
31994
|
-
event.preventDefault();
|
|
31995
|
-
event.stopPropagation();
|
|
31996
|
-
window.open(href, "_blank", "noopener,noreferrer");
|
|
31997
|
-
return true;
|
|
31998
|
-
}
|
|
31999
|
-
},
|
|
32000
|
-
attributes: {
|
|
32001
|
-
class: cn(
|
|
32002
|
-
"prose prose-sm sm:prose dark:prose-invert max-w-none",
|
|
32003
|
-
"focus:outline-none",
|
|
32004
|
-
"px-4 py-4",
|
|
32005
|
-
"[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
|
|
32006
|
-
"[&_.is-editor-empty]:before:text-muted-foreground/50",
|
|
32007
|
-
"[&_.is-editor-empty]:before:float-left",
|
|
32008
|
-
"[&_.is-editor-empty]:before:pointer-events-none",
|
|
32009
|
-
"[&_.is-editor-empty]:before:h-0",
|
|
32010
|
-
"[&_ul[data-type='taskList']]:list-none",
|
|
32011
|
-
"[&_ul[data-type='taskList']]:pl-0",
|
|
32012
|
-
"[&_ul[data-type='taskList']_li]:flex",
|
|
32013
|
-
"[&_ul[data-type='taskList']_li]:items-start",
|
|
32014
|
-
"[&_ul[data-type='taskList']_li]:gap-2",
|
|
32015
|
-
"[&_ul[data-type='taskList']_li>label]:mt-0.5",
|
|
32016
|
-
"[&_ul[data-type='taskList']_li>label>input]:w-4",
|
|
32017
|
-
"[&_ul[data-type='taskList']_li>label>input]:h-4",
|
|
32018
|
-
"[&_ul[data-type='taskList']_li>label>input]:rounded",
|
|
32019
|
-
"[&_ul[data-type='taskList']_li>label>input]:border-2",
|
|
32020
|
-
"[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
|
|
32021
|
-
"[&_ul[data-type='taskList']_li>label>input]:accent-primary",
|
|
32022
|
-
"[&_pre]:bg-muted/40!",
|
|
32023
|
-
"[&_pre]:text-foreground!",
|
|
32024
|
-
"[&_pre]:border!",
|
|
32025
|
-
"[&_pre]:border-border/60!",
|
|
32026
|
-
"[&_pre_code]:bg-transparent!",
|
|
32027
|
-
"[&_.tableWrapper]:overflow-x-auto",
|
|
32028
|
-
"[&_.tableWrapper]:pb-1.5",
|
|
32029
|
-
"[&_.tableWrapper]:select-text",
|
|
32030
|
-
"[&_.tableWrapper]:[scrollbar-width:thin]",
|
|
32031
|
-
"[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
|
|
32032
|
-
"[&_.tableWrapper::-webkit-scrollbar]:h-2",
|
|
32033
|
-
"[&_.tableWrapper::-webkit-scrollbar]:w-2",
|
|
32034
|
-
"[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
|
|
32035
|
-
"[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
|
|
32036
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
|
|
32037
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
|
|
32038
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
|
|
32039
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
|
|
32040
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
|
|
32041
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
|
|
32042
|
-
"[&_table]:table-fixed",
|
|
32043
|
-
"[&_table]:overflow-hidden",
|
|
32044
|
-
"[&_table]:select-text",
|
|
32045
|
-
"[&_table[data-table-align]]:w-max",
|
|
32046
|
-
"[&_table[data-table-align]]:max-w-full",
|
|
32047
|
-
"[&_table[data-table-align='center']]:mx-auto",
|
|
32048
|
-
"[&_table[data-table-align='right']]:ml-auto",
|
|
32049
|
-
"[&_table[data-table-align='right']]:mr-0",
|
|
32050
|
-
"[&_td]:relative",
|
|
32051
|
-
"[&_td]:align-top",
|
|
32052
|
-
"[&_td]:box-border",
|
|
32053
|
-
"[&_td]:select-text",
|
|
32054
|
-
"[&_th]:relative",
|
|
32055
|
-
"[&_th]:align-top",
|
|
32056
|
-
"[&_th]:box-border",
|
|
32057
|
-
"[&_th]:select-text",
|
|
32058
|
-
"[&_.selectedCell]:after:content-['']",
|
|
32059
|
-
"[&_.selectedCell]:after:absolute",
|
|
32060
|
-
"[&_.selectedCell]:after:inset-0",
|
|
32061
|
-
"[&_.selectedCell]:after:z-[2]",
|
|
32062
|
-
"[&_.selectedCell]:after:bg-primary/15",
|
|
32063
|
-
"[&_.selectedCell]:after:pointer-events-none",
|
|
32064
|
-
"[&_.column-resize-handle]:pointer-events-auto",
|
|
32065
|
-
"[&_.column-resize-handle]:cursor-col-resize",
|
|
32066
|
-
"[&_.column-resize-handle]:absolute",
|
|
32067
|
-
"[&_.column-resize-handle]:top-[-1px]",
|
|
32068
|
-
"[&_.column-resize-handle]:bottom-[-1px]",
|
|
32069
|
-
"[&_.column-resize-handle]:right-[-5px]",
|
|
32070
|
-
"[&_.column-resize-handle]:z-10",
|
|
32071
|
-
"[&_.column-resize-handle]:w-2.5",
|
|
32072
|
-
"[&_.column-resize-handle]:bg-transparent",
|
|
32073
|
-
"[&_.column-resize-handle]:rounded-none",
|
|
32074
|
-
"[&_.column-resize-handle]:opacity-0",
|
|
32075
|
-
"[&_.column-resize-handle]:transition-opacity",
|
|
32076
|
-
"[&_.column-resize-handle]:after:absolute",
|
|
32077
|
-
"[&_.column-resize-handle]:after:top-0",
|
|
32078
|
-
"[&_.column-resize-handle]:after:bottom-0",
|
|
32079
|
-
"[&_.column-resize-handle]:after:left-1/2",
|
|
32080
|
-
"[&_.column-resize-handle]:after:w-0.5",
|
|
32081
|
-
"[&_.column-resize-handle]:after:-translate-x-1/2",
|
|
32082
|
-
"[&_.column-resize-handle]:after:rounded-full",
|
|
32083
|
-
"[&_.column-resize-handle]:after:bg-primary/75",
|
|
32084
|
-
"[&_.column-resize-handle]:after:content-['']",
|
|
32085
|
-
"[&.resize-cursor_.column-resize-handle]:opacity-100",
|
|
32086
|
-
"[&.resize-cursor_.column-resize-handle]:after:bg-primary",
|
|
32087
|
-
"[&.resize-cursor]:cursor-col-resize",
|
|
32088
|
-
"[&.resize-row-cursor]:cursor-row-resize",
|
|
32089
|
-
"[&_img.ProseMirror-selectednode]:ring-2",
|
|
32090
|
-
"[&_img.ProseMirror-selectednode]:ring-primary/60",
|
|
32091
|
-
"[&_img.ProseMirror-selectednode]:ring-offset-2",
|
|
32092
|
-
"[&_img.ProseMirror-selectednode]:ring-offset-background",
|
|
32093
|
-
"[&_hr]:border-t-2",
|
|
32094
|
-
"[&_hr]:border-primary/30",
|
|
32095
|
-
"[&_hr]:my-8",
|
|
32096
|
-
"[&_h1]:text-3xl",
|
|
32097
|
-
"[&_h1]:font-bold",
|
|
32098
|
-
"[&_h1]:mt-6",
|
|
32099
|
-
"[&_h1]:mb-4",
|
|
32100
|
-
"[&_h1]:text-foreground",
|
|
32101
|
-
"[&_h2]:text-2xl",
|
|
32102
|
-
"[&_h2]:font-semibold",
|
|
32103
|
-
"[&_h2]:mt-5",
|
|
32104
|
-
"[&_h2]:mb-3",
|
|
32105
|
-
"[&_h2]:text-foreground",
|
|
32106
|
-
"[&_h3]:text-xl",
|
|
32107
|
-
"[&_h3]:font-semibold",
|
|
32108
|
-
"[&_h3]:mt-4",
|
|
32109
|
-
"[&_h3]:mb-2",
|
|
32110
|
-
"[&_h3]:text-foreground",
|
|
32111
|
-
"[&_ul:not([data-type='taskList'])]:list-disc",
|
|
32112
|
-
"[&_ul:not([data-type='taskList'])]:pl-6",
|
|
32113
|
-
"[&_ul:not([data-type='taskList'])]:my-3",
|
|
32114
|
-
"[&_ol]:list-decimal",
|
|
32115
|
-
"[&_ol]:pl-6",
|
|
32116
|
-
"[&_ol]:my-3",
|
|
32117
|
-
"[&_li]:my-1",
|
|
32118
|
-
"[&_li]:pl-1",
|
|
32119
|
-
"[&_li_p]:my-0",
|
|
32120
|
-
"[&_blockquote]:border-l-4",
|
|
32121
|
-
"[&_blockquote]:border-primary",
|
|
32122
|
-
"[&_blockquote]:pl-4",
|
|
32123
|
-
"[&_blockquote]:py-2",
|
|
32124
|
-
"[&_blockquote]:my-4",
|
|
32125
|
-
"[&_blockquote]:bg-muted/30",
|
|
32126
|
-
"[&_blockquote]:rounded-r-lg",
|
|
32127
|
-
"[&_blockquote]:italic",
|
|
32128
|
-
"[&_blockquote]:text-muted-foreground",
|
|
32129
|
-
"[&_blockquote_p]:my-0",
|
|
32130
|
-
"[&_[data-image-layout='left']+p]:mt-1",
|
|
32131
|
-
"[&_[data-image-layout='left']+p]:min-h-[5rem]",
|
|
32132
|
-
"[&_[data-image-layout='right']+p]:mt-1",
|
|
32133
|
-
"[&_[data-image-layout='right']+p]:min-h-[5rem]",
|
|
32134
|
-
"max-md:[&_[data-image-layout='left']]:float-none",
|
|
32135
|
-
"max-md:[&_[data-image-layout='left']]:mr-0",
|
|
32136
|
-
"max-md:[&_[data-image-layout='left']]:ml-0",
|
|
32137
|
-
"max-md:[&_[data-image-layout='left']]:max-w-full",
|
|
32138
|
-
"max-md:[&_[data-image-layout='right']]:float-none",
|
|
32139
|
-
"max-md:[&_[data-image-layout='right']]:mr-0",
|
|
32140
|
-
"max-md:[&_[data-image-layout='right']]:ml-0",
|
|
32141
|
-
"max-md:[&_[data-image-layout='right']]:max-w-full",
|
|
32142
|
-
"max-md:[&_[data-image-layout='left']+p]:min-h-0",
|
|
32143
|
-
"max-md:[&_[data-image-layout='right']+p]:min-h-0"
|
|
32144
|
-
)
|
|
32145
|
-
}
|
|
32146
|
-
},
|
|
32147
|
-
onUpdate: ({ editor: editor2 }) => {
|
|
32148
|
-
const html = editor2.getHTML();
|
|
32149
|
-
onChange?.(html);
|
|
32150
|
-
onHtmlChange?.(html);
|
|
32151
|
-
onJsonChange?.(editor2.getJSON());
|
|
32155
|
+
const commitRowResizePreview = import_react52.default.useCallback(() => {
|
|
32156
|
+
if (!editor) return;
|
|
32157
|
+
const state = rowResizeStateRef.current;
|
|
32158
|
+
if (!state) return;
|
|
32159
|
+
const nextHeight = state.pendingHeight;
|
|
32160
|
+
if (nextHeight === state.previewHeight) {
|
|
32161
|
+
document.body.style.cursor = "row-resize";
|
|
32162
|
+
showRowGuide(state.tableElement, state.rowElement, state.cellElement);
|
|
32163
|
+
scheduleTableLayoutSync();
|
|
32164
|
+
return;
|
|
32152
32165
|
}
|
|
32153
|
-
|
|
32166
|
+
state.previewHeight = nextHeight;
|
|
32167
|
+
const tr = editor.view.state.tr;
|
|
32168
|
+
tr.setNodeMarkup(state.rowPos, void 0, {
|
|
32169
|
+
...state.rowNode.attrs,
|
|
32170
|
+
rowHeight: nextHeight
|
|
32171
|
+
});
|
|
32172
|
+
tr.setMeta("addToHistory", false);
|
|
32173
|
+
editor.view.dispatch(tr);
|
|
32174
|
+
state.rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
|
|
32175
|
+
const refreshedRow = state.tableElement.rows.item(state.rowElement.rowIndex);
|
|
32176
|
+
if (refreshedRow instanceof HTMLTableRowElement) {
|
|
32177
|
+
state.rowElement = refreshedRow;
|
|
32178
|
+
const refreshedCell = refreshedRow.cells.item(state.cellIndex);
|
|
32179
|
+
if (refreshedCell instanceof HTMLTableCellElement) {
|
|
32180
|
+
state.cellElement = refreshedCell;
|
|
32181
|
+
}
|
|
32182
|
+
}
|
|
32183
|
+
document.body.style.cursor = "row-resize";
|
|
32184
|
+
showRowGuide(state.tableElement, state.rowElement, state.cellElement);
|
|
32185
|
+
scheduleTableLayoutSync();
|
|
32186
|
+
}, [editor, scheduleTableLayoutSync, showRowGuide]);
|
|
32187
|
+
const scheduleRowResizeCommit = import_react52.default.useCallback(() => {
|
|
32188
|
+
if (rowResizeCommitFrameRef.current !== null) return;
|
|
32189
|
+
rowResizeCommitFrameRef.current = window.requestAnimationFrame(() => {
|
|
32190
|
+
rowResizeCommitFrameRef.current = null;
|
|
32191
|
+
commitRowResizePreview();
|
|
32192
|
+
});
|
|
32193
|
+
}, [commitRowResizePreview]);
|
|
32154
32194
|
const syncActiveTableCellFromSelection = import_react52.default.useCallback(() => {
|
|
32155
32195
|
if (!editor) return;
|
|
32156
32196
|
setActiveTableCell(getSelectionTableCell(editor.view));
|
|
32157
32197
|
}, [editor, setActiveTableCell]);
|
|
32158
|
-
(0, import_react52.useImperativeHandle)(
|
|
32159
|
-
ref,
|
|
32160
|
-
() => ({
|
|
32161
|
-
prepareContentForSave: async ({ throwOnError = false } = {}) => {
|
|
32162
|
-
if (!inFlightPrepareRef.current) {
|
|
32163
|
-
const htmlSnapshot = editor?.getHTML() ?? content ?? "";
|
|
32164
|
-
inFlightPrepareRef.current = prepareUEditorContentForSave({
|
|
32165
|
-
html: htmlSnapshot,
|
|
32166
|
-
uploadImageForSave
|
|
32167
|
-
}).finally(() => {
|
|
32168
|
-
inFlightPrepareRef.current = null;
|
|
32169
|
-
});
|
|
32170
|
-
}
|
|
32171
|
-
const result = await inFlightPrepareRef.current;
|
|
32172
|
-
if (throwOnError && result.errors.length > 0) {
|
|
32173
|
-
throw new UEditorPrepareContentForSaveError(result);
|
|
32174
|
-
}
|
|
32175
|
-
return result;
|
|
32176
|
-
}
|
|
32177
|
-
}),
|
|
32178
|
-
[content, editor, uploadImageForSave]
|
|
32179
|
-
);
|
|
32180
|
-
(0, import_react52.useEffect)(() => {
|
|
32181
|
-
if (!editor) return;
|
|
32182
|
-
const nextContent = content ?? "";
|
|
32183
|
-
if (lastAppliedContentRef.current === nextContent) return;
|
|
32184
|
-
lastAppliedContentRef.current = nextContent;
|
|
32185
|
-
if (editor.getHTML() !== nextContent) {
|
|
32186
|
-
editor.commands.setContent(nextContent, { emitUpdate: false });
|
|
32187
|
-
}
|
|
32188
|
-
}, [content, editor]);
|
|
32189
32198
|
(0, import_react52.useEffect)(() => {
|
|
32190
32199
|
if (!editor) return void 0;
|
|
32191
32200
|
const proseMirror = editor.view.dom;
|
|
@@ -32275,6 +32284,7 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32275
32284
|
setHoveredTableCell(cell);
|
|
32276
32285
|
const rowInfo = findTableRowNodeInfo(editor.view, row);
|
|
32277
32286
|
if (!rowInfo) return;
|
|
32287
|
+
const startHeight = row.getBoundingClientRect().height;
|
|
32278
32288
|
rowResizeStateRef.current = {
|
|
32279
32289
|
rowElement: row,
|
|
32280
32290
|
tableElement: table,
|
|
@@ -32283,8 +32293,9 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32283
32293
|
rowPos: rowInfo.pos,
|
|
32284
32294
|
rowNode: rowInfo.node,
|
|
32285
32295
|
startY: event.clientY,
|
|
32286
|
-
startHeight
|
|
32287
|
-
previewHeight:
|
|
32296
|
+
startHeight,
|
|
32297
|
+
previewHeight: startHeight,
|
|
32298
|
+
pendingHeight: startHeight
|
|
32288
32299
|
};
|
|
32289
32300
|
showRowGuide(table, row, cell);
|
|
32290
32301
|
document.body.style.cursor = "row-resize";
|
|
@@ -32298,30 +32309,14 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32298
32309
|
MIN_TABLE_ROW_HEIGHT,
|
|
32299
32310
|
Math.round(state.startHeight + (event.clientY - state.startY))
|
|
32300
32311
|
);
|
|
32301
|
-
if (nextHeight === state.
|
|
32312
|
+
if (nextHeight === state.pendingHeight) {
|
|
32302
32313
|
document.body.style.cursor = "row-resize";
|
|
32303
32314
|
showRowGuide(state.tableElement, state.rowElement, state.cellElement);
|
|
32304
32315
|
return;
|
|
32305
32316
|
}
|
|
32306
|
-
state.
|
|
32307
|
-
applyPreviewRowHeight(state.rowElement, nextHeight);
|
|
32308
|
-
const tr = editor.view.state.tr;
|
|
32309
|
-
tr.setNodeMarkup(state.rowPos, void 0, {
|
|
32310
|
-
...state.rowNode.attrs,
|
|
32311
|
-
rowHeight: nextHeight
|
|
32312
|
-
});
|
|
32313
|
-
editor.view.dispatch(tr);
|
|
32314
|
-
state.rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
|
|
32315
|
-
const refreshedRow = state.tableElement.rows.item(state.rowElement.rowIndex);
|
|
32316
|
-
if (refreshedRow instanceof HTMLTableRowElement) {
|
|
32317
|
-
state.rowElement = refreshedRow;
|
|
32318
|
-
const refreshedCell = refreshedRow.cells.item(state.cellIndex);
|
|
32319
|
-
if (refreshedCell instanceof HTMLTableCellElement) {
|
|
32320
|
-
state.cellElement = refreshedCell;
|
|
32321
|
-
}
|
|
32322
|
-
}
|
|
32317
|
+
state.pendingHeight = nextHeight;
|
|
32323
32318
|
document.body.style.cursor = "row-resize";
|
|
32324
|
-
|
|
32319
|
+
scheduleRowResizeCommit();
|
|
32325
32320
|
};
|
|
32326
32321
|
const handlePointerUp = (event) => {
|
|
32327
32322
|
const state = rowResizeStateRef.current;
|
|
@@ -32330,20 +32325,40 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32330
32325
|
MIN_TABLE_ROW_HEIGHT,
|
|
32331
32326
|
Math.round(state.startHeight + (event.clientY - state.startY))
|
|
32332
32327
|
);
|
|
32333
|
-
|
|
32328
|
+
state.pendingHeight = nextHeight;
|
|
32329
|
+
if (rowResizeCommitFrameRef.current !== null) {
|
|
32330
|
+
window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
|
|
32331
|
+
rowResizeCommitFrameRef.current = null;
|
|
32332
|
+
}
|
|
32333
|
+
commitRowResizePreview();
|
|
32334
|
+
const latestState = rowResizeStateRef.current ?? state;
|
|
32335
|
+
const rowNode = editor.view.state.doc.nodeAt(latestState.rowPos) ?? latestState.rowNode;
|
|
32336
|
+
if (rowNode.attrs.rowHeight !== nextHeight) {
|
|
32337
|
+
const tr = editor.view.state.tr;
|
|
32338
|
+
tr.setNodeMarkup(latestState.rowPos, void 0, {
|
|
32339
|
+
...rowNode.attrs,
|
|
32340
|
+
rowHeight: nextHeight
|
|
32341
|
+
});
|
|
32342
|
+
editor.view.dispatch(tr);
|
|
32343
|
+
}
|
|
32334
32344
|
rowResizeStateRef.current = null;
|
|
32335
32345
|
document.body.style.cursor = "";
|
|
32336
32346
|
clearHoveredTableCell();
|
|
32337
32347
|
clearAllTableResizeHover();
|
|
32348
|
+
scheduleTableLayoutSync();
|
|
32338
32349
|
};
|
|
32339
32350
|
const handleWindowBlur = () => {
|
|
32340
32351
|
const state = rowResizeStateRef.current;
|
|
32341
32352
|
if (!state) return;
|
|
32342
|
-
|
|
32353
|
+
if (rowResizeCommitFrameRef.current !== null) {
|
|
32354
|
+
window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
|
|
32355
|
+
rowResizeCommitFrameRef.current = null;
|
|
32356
|
+
}
|
|
32343
32357
|
rowResizeStateRef.current = null;
|
|
32344
32358
|
document.body.style.cursor = "";
|
|
32345
32359
|
clearHoveredTableCell();
|
|
32346
32360
|
clearAllTableResizeHover();
|
|
32361
|
+
scheduleTableLayoutSync();
|
|
32347
32362
|
};
|
|
32348
32363
|
proseMirror.addEventListener("mousemove", handleEditorMouseMove);
|
|
32349
32364
|
proseMirror.addEventListener("mouseleave", handleEditorMouseLeave);
|
|
@@ -32382,13 +32397,156 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32382
32397
|
editor.off("selectionUpdate", syncActiveTableCellFromSelection);
|
|
32383
32398
|
editor.off("focus", syncActiveTableCellFromSelection);
|
|
32384
32399
|
window.clearTimeout(selectionSyncTimeoutId);
|
|
32400
|
+
if (tableLayoutSyncFrameRef.current !== null) {
|
|
32401
|
+
window.cancelAnimationFrame(tableLayoutSyncFrameRef.current);
|
|
32402
|
+
tableLayoutSyncFrameRef.current = null;
|
|
32403
|
+
}
|
|
32404
|
+
if (rowResizeCommitFrameRef.current !== null) {
|
|
32405
|
+
window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
|
|
32406
|
+
rowResizeCommitFrameRef.current = null;
|
|
32407
|
+
}
|
|
32385
32408
|
document.body.style.cursor = "";
|
|
32386
32409
|
clearActiveTableCell();
|
|
32387
32410
|
clearHoveredTableCell();
|
|
32388
32411
|
clearAllTableResizeHover();
|
|
32389
32412
|
rowResizeStateRef.current = null;
|
|
32390
32413
|
};
|
|
32391
|
-
}, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editor, hideColumnGuide, hideRowGuide, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
|
|
32414
|
+
}, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, commitRowResizePreview, editor, hideColumnGuide, hideRowGuide, scheduleRowResizeCommit, scheduleTableLayoutSync, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
|
|
32415
|
+
return {
|
|
32416
|
+
editorContentRef,
|
|
32417
|
+
tableColumnGuideRef,
|
|
32418
|
+
tableRowGuideRef,
|
|
32419
|
+
activeTableCellHighlightRef
|
|
32420
|
+
};
|
|
32421
|
+
}
|
|
32422
|
+
|
|
32423
|
+
// src/components/UEditor/UEditor.tsx
|
|
32424
|
+
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
32425
|
+
var UEditor = import_react53.default.forwardRef(({
|
|
32426
|
+
content = "",
|
|
32427
|
+
onChange,
|
|
32428
|
+
onHtmlChange,
|
|
32429
|
+
onJsonChange,
|
|
32430
|
+
uploadImage,
|
|
32431
|
+
uploadImageForSave,
|
|
32432
|
+
uploadImageConcurrency = 3,
|
|
32433
|
+
imageInsertMode = "base64",
|
|
32434
|
+
maxImageFileSize,
|
|
32435
|
+
allowedImageMimeTypes,
|
|
32436
|
+
fallbackToDataUrl,
|
|
32437
|
+
placeholder,
|
|
32438
|
+
className,
|
|
32439
|
+
editable = true,
|
|
32440
|
+
autofocus = false,
|
|
32441
|
+
showToolbar = true,
|
|
32442
|
+
showBubbleMenu = true,
|
|
32443
|
+
showFloatingMenu = false,
|
|
32444
|
+
showCharacterCount = true,
|
|
32445
|
+
maxCharacters,
|
|
32446
|
+
minHeight = "200px",
|
|
32447
|
+
maxHeight = "auto",
|
|
32448
|
+
variant = "default",
|
|
32449
|
+
fontFamilies,
|
|
32450
|
+
fontSizes,
|
|
32451
|
+
lineHeights,
|
|
32452
|
+
letterSpacings
|
|
32453
|
+
}, ref) => {
|
|
32454
|
+
const t = useSmartTranslations("UEditor");
|
|
32455
|
+
const effectivePlaceholder = placeholder ?? t("placeholder");
|
|
32456
|
+
const inFlightPrepareRef = (0, import_react53.useRef)(null);
|
|
32457
|
+
const lastAppliedContentRef = (0, import_react53.useRef)(content ?? "");
|
|
32458
|
+
const extensions = (0, import_react53.useMemo)(
|
|
32459
|
+
() => buildUEditorExtensions({
|
|
32460
|
+
placeholder: effectivePlaceholder,
|
|
32461
|
+
translate: t,
|
|
32462
|
+
maxCharacters,
|
|
32463
|
+
uploadImage,
|
|
32464
|
+
imageInsertMode,
|
|
32465
|
+
maxImageFileSize,
|
|
32466
|
+
allowedImageMimeTypes,
|
|
32467
|
+
fallbackToDataUrl,
|
|
32468
|
+
editable
|
|
32469
|
+
}),
|
|
32470
|
+
[effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable]
|
|
32471
|
+
);
|
|
32472
|
+
const editor = (0, import_react54.useEditor)({
|
|
32473
|
+
immediatelyRender: false,
|
|
32474
|
+
extensions,
|
|
32475
|
+
content,
|
|
32476
|
+
editable,
|
|
32477
|
+
autofocus,
|
|
32478
|
+
editorProps: {
|
|
32479
|
+
handleDOMEvents: {
|
|
32480
|
+
keydown: (_view, event) => {
|
|
32481
|
+
if (!(event instanceof KeyboardEvent)) return false;
|
|
32482
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
32483
|
+
event.stopPropagation();
|
|
32484
|
+
}
|
|
32485
|
+
return false;
|
|
32486
|
+
},
|
|
32487
|
+
click: (view, event) => {
|
|
32488
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
32489
|
+
if (event.button !== 0) return false;
|
|
32490
|
+
const target = resolveEventElement(event.target);
|
|
32491
|
+
const anchor = target?.closest?.("a[href]");
|
|
32492
|
+
const href = anchor?.getAttribute("href") ?? "";
|
|
32493
|
+
if (!href) return false;
|
|
32494
|
+
if (!view.state.selection.empty) return false;
|
|
32495
|
+
event.preventDefault();
|
|
32496
|
+
event.stopPropagation();
|
|
32497
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
32498
|
+
return true;
|
|
32499
|
+
}
|
|
32500
|
+
},
|
|
32501
|
+
attributes: {
|
|
32502
|
+
class: UEDITOR_PROSEMIRROR_CLASS_NAME
|
|
32503
|
+
}
|
|
32504
|
+
},
|
|
32505
|
+
onUpdate: ({ editor: editor2 }) => {
|
|
32506
|
+
const html = editor2.getHTML();
|
|
32507
|
+
onChange?.(html);
|
|
32508
|
+
onHtmlChange?.(html);
|
|
32509
|
+
onJsonChange?.(editor2.getJSON());
|
|
32510
|
+
}
|
|
32511
|
+
});
|
|
32512
|
+
const {
|
|
32513
|
+
editorContentRef,
|
|
32514
|
+
tableColumnGuideRef,
|
|
32515
|
+
tableRowGuideRef,
|
|
32516
|
+
activeTableCellHighlightRef
|
|
32517
|
+
} = useUEditorTableInteractions(editor);
|
|
32518
|
+
(0, import_react53.useImperativeHandle)(
|
|
32519
|
+
ref,
|
|
32520
|
+
() => ({
|
|
32521
|
+
prepareContentForSave: async ({ throwOnError = false } = {}) => {
|
|
32522
|
+
if (!inFlightPrepareRef.current) {
|
|
32523
|
+
const htmlSnapshot = editor?.getHTML() ?? content ?? "";
|
|
32524
|
+
inFlightPrepareRef.current = prepareUEditorContentForSave({
|
|
32525
|
+
html: htmlSnapshot,
|
|
32526
|
+
uploadImageForSave,
|
|
32527
|
+
uploadConcurrency: uploadImageConcurrency
|
|
32528
|
+
}).finally(() => {
|
|
32529
|
+
inFlightPrepareRef.current = null;
|
|
32530
|
+
});
|
|
32531
|
+
}
|
|
32532
|
+
const result = await inFlightPrepareRef.current;
|
|
32533
|
+
if (throwOnError && result.errors.length > 0) {
|
|
32534
|
+
throw new UEditorPrepareContentForSaveError(result);
|
|
32535
|
+
}
|
|
32536
|
+
return result;
|
|
32537
|
+
}
|
|
32538
|
+
}),
|
|
32539
|
+
[content, editor, uploadImageForSave, uploadImageConcurrency]
|
|
32540
|
+
);
|
|
32541
|
+
(0, import_react53.useEffect)(() => {
|
|
32542
|
+
if (!editor) return;
|
|
32543
|
+
const nextContent = content ?? "";
|
|
32544
|
+
if (lastAppliedContentRef.current === nextContent) return;
|
|
32545
|
+
lastAppliedContentRef.current = nextContent;
|
|
32546
|
+
if (editor.getHTML() !== nextContent) {
|
|
32547
|
+
editor.commands.setContent(nextContent, { emitUpdate: false });
|
|
32548
|
+
}
|
|
32549
|
+
}, [content, editor]);
|
|
32392
32550
|
if (!editor) {
|
|
32393
32551
|
return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
|
|
32394
32552
|
"div",
|
|
@@ -32418,6 +32576,8 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32418
32576
|
variant,
|
|
32419
32577
|
uploadImage,
|
|
32420
32578
|
imageInsertMode,
|
|
32579
|
+
maxImageFileSize,
|
|
32580
|
+
allowedImageMimeTypes,
|
|
32421
32581
|
fontFamilies,
|
|
32422
32582
|
fontSizes,
|
|
32423
32583
|
lineHeights,
|
|
@@ -32469,7 +32629,7 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32469
32629
|
),
|
|
32470
32630
|
editable && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(TableControls, { editor, containerRef: editorContentRef }),
|
|
32471
32631
|
/* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
|
|
32472
|
-
|
|
32632
|
+
import_react54.EditorContent,
|
|
32473
32633
|
{
|
|
32474
32634
|
editor,
|
|
32475
32635
|
className: "min-h-full"
|