@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.js
CHANGED
|
@@ -23109,7 +23109,7 @@ function useLocale2() {
|
|
|
23109
23109
|
}
|
|
23110
23110
|
|
|
23111
23111
|
// src/components/UEditor/UEditor.tsx
|
|
23112
|
-
import
|
|
23112
|
+
import React75, { useEffect as useEffect36, useImperativeHandle as useImperativeHandle3, useMemo as useMemo24, useRef as useRef32 } from "react";
|
|
23113
23113
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
23114
23114
|
|
|
23115
23115
|
// src/components/UEditor/extensions.ts
|
|
@@ -23496,6 +23496,49 @@ var SlashCommand = Extension.create({
|
|
|
23496
23496
|
// src/components/UEditor/clipboard-images.ts
|
|
23497
23497
|
import { Extension as Extension2 } from "@tiptap/core";
|
|
23498
23498
|
import { Plugin } from "@tiptap/pm/state";
|
|
23499
|
+
|
|
23500
|
+
// src/components/UEditor/url-safety.ts
|
|
23501
|
+
var LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
23502
|
+
var IMAGE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
23503
|
+
function normalizeUrlInput(raw) {
|
|
23504
|
+
return raw.trim().replace(/[\u0000-\u001F\u007F\s]+/g, "");
|
|
23505
|
+
}
|
|
23506
|
+
function isProtocolRelativeUrl(value) {
|
|
23507
|
+
return value.startsWith("//");
|
|
23508
|
+
}
|
|
23509
|
+
function isRelativeUrl(value) {
|
|
23510
|
+
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("#");
|
|
23511
|
+
}
|
|
23512
|
+
function isDataImageUrl(value) {
|
|
23513
|
+
return /^data:image\/(?:png|jpe?g|gif|webp|svg\+xml|bmp|x-icon|avif);base64,/i.test(value);
|
|
23514
|
+
}
|
|
23515
|
+
function isSafeUEditorUrl(raw, kind) {
|
|
23516
|
+
const value = normalizeUrlInput(raw);
|
|
23517
|
+
if (!value) return false;
|
|
23518
|
+
if (kind === "image" && isDataImageUrl(value)) return true;
|
|
23519
|
+
if (isRelativeUrl(value)) return true;
|
|
23520
|
+
if (isProtocolRelativeUrl(value)) return false;
|
|
23521
|
+
try {
|
|
23522
|
+
const parsed = new URL(value);
|
|
23523
|
+
return kind === "image" ? IMAGE_PROTOCOLS.has(parsed.protocol) : LINK_PROTOCOLS.has(parsed.protocol);
|
|
23524
|
+
} catch {
|
|
23525
|
+
return false;
|
|
23526
|
+
}
|
|
23527
|
+
}
|
|
23528
|
+
function sanitizeUEditorUrl(raw, kind) {
|
|
23529
|
+
const value = raw.trim();
|
|
23530
|
+
if (!value) return "";
|
|
23531
|
+
if (isSafeUEditorUrl(value, kind)) return normalizeUrlInput(value);
|
|
23532
|
+
if (kind === "link" && !isProtocolRelativeUrl(value) && !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value)) {
|
|
23533
|
+
const withProtocol = `https://${value}`;
|
|
23534
|
+
return isSafeUEditorUrl(withProtocol, kind) ? withProtocol : "";
|
|
23535
|
+
}
|
|
23536
|
+
return "";
|
|
23537
|
+
}
|
|
23538
|
+
|
|
23539
|
+
// src/components/UEditor/clipboard-images.ts
|
|
23540
|
+
var DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
23541
|
+
var DEFAULT_UEDITOR_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"];
|
|
23499
23542
|
function getImageFiles(dataTransfer) {
|
|
23500
23543
|
if (!dataTransfer) return [];
|
|
23501
23544
|
const itemFiles = [];
|
|
@@ -23527,7 +23570,7 @@ async function resolveImageSrc(file, options) {
|
|
|
23527
23570
|
if (options.insertMode === "upload" && options.upload) {
|
|
23528
23571
|
try {
|
|
23529
23572
|
const result = await options.upload(file);
|
|
23530
|
-
const src = typeof result === "string" ? result : "";
|
|
23573
|
+
const src = typeof result === "string" ? sanitizeUEditorUrl(result, "image") : "";
|
|
23531
23574
|
if (src) return src;
|
|
23532
23575
|
} catch (err) {
|
|
23533
23576
|
if (!options.fallbackToDataUrl) throw err;
|
|
@@ -23539,8 +23582,8 @@ var ClipboardImages = Extension2.create({
|
|
|
23539
23582
|
name: "clipboardImages",
|
|
23540
23583
|
addOptions() {
|
|
23541
23584
|
return {
|
|
23542
|
-
maxFileSize:
|
|
23543
|
-
allowedMimeTypes:
|
|
23585
|
+
maxFileSize: DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
|
|
23586
|
+
allowedMimeTypes: DEFAULT_UEDITOR_IMAGE_MIME_TYPES,
|
|
23544
23587
|
upload: void 0,
|
|
23545
23588
|
fallbackToDataUrl: true,
|
|
23546
23589
|
insertMode: "base64"
|
|
@@ -24399,6 +24442,9 @@ function buildUEditorExtensions({
|
|
|
24399
24442
|
maxCharacters,
|
|
24400
24443
|
uploadImage,
|
|
24401
24444
|
imageInsertMode = "base64",
|
|
24445
|
+
maxImageFileSize,
|
|
24446
|
+
allowedImageMimeTypes,
|
|
24447
|
+
fallbackToDataUrl,
|
|
24402
24448
|
editable = true
|
|
24403
24449
|
}) {
|
|
24404
24450
|
return [
|
|
@@ -24452,12 +24498,20 @@ function buildUEditorExtensions({
|
|
|
24452
24498
|
HorizontalRule,
|
|
24453
24499
|
Link.configure({
|
|
24454
24500
|
openOnClick: false,
|
|
24501
|
+
protocols: ["http", "https", "mailto", "tel"],
|
|
24502
|
+
isAllowedUri: (url) => isSafeUEditorUrl(url ?? "", "link"),
|
|
24455
24503
|
HTMLAttributes: {
|
|
24456
24504
|
class: "text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer"
|
|
24457
24505
|
}
|
|
24458
24506
|
}),
|
|
24459
24507
|
resizable_image_default,
|
|
24460
|
-
ClipboardImages.configure({
|
|
24508
|
+
ClipboardImages.configure({
|
|
24509
|
+
upload: uploadImage,
|
|
24510
|
+
insertMode: imageInsertMode,
|
|
24511
|
+
...maxImageFileSize !== void 0 ? { maxFileSize: maxImageFileSize } : {},
|
|
24512
|
+
...allowedImageMimeTypes ? { allowedMimeTypes: allowedImageMimeTypes } : {},
|
|
24513
|
+
...fallbackToDataUrl !== void 0 ? { fallbackToDataUrl } : {}
|
|
24514
|
+
}),
|
|
24461
24515
|
TextStyle,
|
|
24462
24516
|
font_family_default,
|
|
24463
24517
|
font_size_default,
|
|
@@ -24713,11 +24767,7 @@ import { useEffect as useEffect33, useRef as useRef28, useState as useState43 }
|
|
|
24713
24767
|
import { Check as Check10, X as X19 } from "lucide-react";
|
|
24714
24768
|
import { jsx as jsx78, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
24715
24769
|
function normalizeUrl(raw) {
|
|
24716
|
-
|
|
24717
|
-
if (!url) return "";
|
|
24718
|
-
if (url.startsWith("#") || url.startsWith("/")) return url;
|
|
24719
|
-
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url)) return url;
|
|
24720
|
-
return `https://${url}`;
|
|
24770
|
+
return sanitizeUEditorUrl(raw, "link");
|
|
24721
24771
|
}
|
|
24722
24772
|
var LinkInput = ({
|
|
24723
24773
|
onSubmit,
|
|
@@ -24762,8 +24812,9 @@ var ImageInput = ({ onSubmit, onCancel }) => {
|
|
|
24762
24812
|
}, []);
|
|
24763
24813
|
const handleSubmit = (e) => {
|
|
24764
24814
|
e.preventDefault();
|
|
24765
|
-
|
|
24766
|
-
|
|
24815
|
+
const safeUrl = sanitizeUEditorUrl(url, "image");
|
|
24816
|
+
if (safeUrl) {
|
|
24817
|
+
onSubmit(safeUrl, alt);
|
|
24767
24818
|
}
|
|
24768
24819
|
};
|
|
24769
24820
|
return /* @__PURE__ */ jsxs66("form", { onSubmit: handleSubmit, className: "p-3 space-y-3", children: [
|
|
@@ -24949,6 +25000,8 @@ var EditorToolbar = ({
|
|
|
24949
25000
|
variant,
|
|
24950
25001
|
uploadImage,
|
|
24951
25002
|
imageInsertMode = "base64",
|
|
25003
|
+
maxImageFileSize = DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
|
|
25004
|
+
allowedImageMimeTypes = DEFAULT_UEDITOR_IMAGE_MIME_TYPES,
|
|
24952
25005
|
fontFamilies,
|
|
24953
25006
|
fontSizes,
|
|
24954
25007
|
lineHeights,
|
|
@@ -25016,10 +25069,13 @@ var EditorToolbar = ({
|
|
|
25016
25069
|
setImageUploadError(null);
|
|
25017
25070
|
for (const file of files) {
|
|
25018
25071
|
if (!file.type.startsWith("image/")) continue;
|
|
25072
|
+
if (file.size > maxImageFileSize) continue;
|
|
25073
|
+
if (allowedImageMimeTypes.length > 0 && !allowedImageMimeTypes.includes(file.type)) continue;
|
|
25019
25074
|
try {
|
|
25020
25075
|
const src = imageInsertMode === "upload" && uploadImage ? await uploadImage(file) : await fileToDataUrl2(file);
|
|
25021
|
-
|
|
25022
|
-
|
|
25076
|
+
const safeSrc = sanitizeUEditorUrl(src, "image");
|
|
25077
|
+
if (!safeSrc) continue;
|
|
25078
|
+
editor.chain().focus().setImage({ src: safeSrc, alt: file.name }).run();
|
|
25023
25079
|
editor.commands.createParagraphNear();
|
|
25024
25080
|
} catch {
|
|
25025
25081
|
setImageUploadError(t("imageInput.uploadError"));
|
|
@@ -26230,12 +26286,12 @@ var MIME_EXTENSION_MAP = {
|
|
|
26230
26286
|
"image/x-icon": "ico",
|
|
26231
26287
|
"image/avif": "avif"
|
|
26232
26288
|
};
|
|
26233
|
-
function
|
|
26289
|
+
function isDataImageUrl2(value) {
|
|
26234
26290
|
return /^data:image\//i.test(value.trim());
|
|
26235
26291
|
}
|
|
26236
26292
|
function parseDataImageUrl(dataUrl) {
|
|
26237
26293
|
const value = dataUrl.trim();
|
|
26238
|
-
if (!
|
|
26294
|
+
if (!isDataImageUrl2(value)) return null;
|
|
26239
26295
|
const commaIndex = value.indexOf(",");
|
|
26240
26296
|
if (commaIndex < 0) return null;
|
|
26241
26297
|
const header = value.slice(5, commaIndex);
|
|
@@ -26269,19 +26325,33 @@ function createFileFromDataImageUrl(dataUrl, index) {
|
|
|
26269
26325
|
}
|
|
26270
26326
|
function normalizeUploadResult(result) {
|
|
26271
26327
|
if (typeof result === "string") {
|
|
26272
|
-
const url2 = result
|
|
26328
|
+
const url2 = sanitizeUEditorUrl(result, "image");
|
|
26273
26329
|
if (!url2) throw new Error("Upload handler returned an empty URL.");
|
|
26274
26330
|
return { url: url2 };
|
|
26275
26331
|
}
|
|
26276
26332
|
if (!result || typeof result !== "object") {
|
|
26277
26333
|
throw new Error("Upload handler returned invalid result.");
|
|
26278
26334
|
}
|
|
26279
|
-
const url = typeof result.url === "string" ? result.url
|
|
26335
|
+
const url = typeof result.url === "string" ? sanitizeUEditorUrl(result.url, "image") : "";
|
|
26280
26336
|
if (!url) throw new Error("Upload handler object result is missing `url`.");
|
|
26281
26337
|
const { url: _ignoredUrl, ...rest } = result;
|
|
26282
26338
|
const meta = Object.keys(rest).length > 0 ? rest : void 0;
|
|
26283
26339
|
return { url, meta };
|
|
26284
26340
|
}
|
|
26341
|
+
async function runWithConcurrency(items, concurrency, worker) {
|
|
26342
|
+
const limit = Math.max(1, Math.floor(concurrency));
|
|
26343
|
+
const results = new Array(items.length);
|
|
26344
|
+
let nextIndex = 0;
|
|
26345
|
+
async function runNext() {
|
|
26346
|
+
while (nextIndex < items.length) {
|
|
26347
|
+
const currentIndex = nextIndex;
|
|
26348
|
+
nextIndex += 1;
|
|
26349
|
+
results[currentIndex] = await worker(items[currentIndex]);
|
|
26350
|
+
}
|
|
26351
|
+
}
|
|
26352
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, runNext));
|
|
26353
|
+
return results;
|
|
26354
|
+
}
|
|
26285
26355
|
function getErrorReason(error) {
|
|
26286
26356
|
if (error instanceof Error && error.message) return error.message;
|
|
26287
26357
|
if (typeof error === "string" && error.trim()) return error;
|
|
@@ -26293,7 +26363,7 @@ function decodeHtmlEntities(value) {
|
|
|
26293
26363
|
function normalizeImageUrl(url) {
|
|
26294
26364
|
const input = decodeHtmlEntities(url.trim());
|
|
26295
26365
|
if (!input) return "";
|
|
26296
|
-
if (
|
|
26366
|
+
if (isDataImageUrl2(input)) return input;
|
|
26297
26367
|
const isAbsolute = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(input);
|
|
26298
26368
|
if (!isAbsolute) {
|
|
26299
26369
|
return input.split("#")[0] ?? input;
|
|
@@ -26377,7 +26447,8 @@ var UEditorPrepareContentForSaveError = class extends Error {
|
|
|
26377
26447
|
};
|
|
26378
26448
|
async function prepareUEditorContentForSave({
|
|
26379
26449
|
html,
|
|
26380
|
-
uploadImageForSave
|
|
26450
|
+
uploadImageForSave,
|
|
26451
|
+
uploadConcurrency = 3
|
|
26381
26452
|
}) {
|
|
26382
26453
|
if (!html || !html.includes("<img")) {
|
|
26383
26454
|
return createResult({ html, uploaded: [], inlineUploaded: [], errors: [] });
|
|
@@ -26390,7 +26461,7 @@ async function prepareUEditorContentForSave({
|
|
|
26390
26461
|
for (const match of imgMatches) {
|
|
26391
26462
|
if (!match.srcAttr) continue;
|
|
26392
26463
|
const src = match.srcAttr.value.trim();
|
|
26393
|
-
if (!
|
|
26464
|
+
if (!isDataImageUrl2(src)) continue;
|
|
26394
26465
|
base64Candidates.push({
|
|
26395
26466
|
id: `${match.start}:${match.end}`,
|
|
26396
26467
|
match,
|
|
@@ -26416,8 +26487,10 @@ async function prepareUEditorContentForSave({
|
|
|
26416
26487
|
const inlineUploaded = [];
|
|
26417
26488
|
const errors = [];
|
|
26418
26489
|
const replacements = /* @__PURE__ */ new Map();
|
|
26419
|
-
const uploadResults = await
|
|
26420
|
-
base64Candidates
|
|
26490
|
+
const uploadResults = await runWithConcurrency(
|
|
26491
|
+
base64Candidates,
|
|
26492
|
+
uploadConcurrency,
|
|
26493
|
+
async (candidate) => {
|
|
26421
26494
|
try {
|
|
26422
26495
|
const file = createFileFromDataImageUrl(candidate.src, candidate.index);
|
|
26423
26496
|
const uploadResult = await uploadImageForSave(file);
|
|
@@ -26426,7 +26499,7 @@ async function prepareUEditorContentForSave({
|
|
|
26426
26499
|
} catch (error) {
|
|
26427
26500
|
return { candidate, error: getErrorReason(error) };
|
|
26428
26501
|
}
|
|
26429
|
-
}
|
|
26502
|
+
}
|
|
26430
26503
|
);
|
|
26431
26504
|
for (const item of uploadResults) {
|
|
26432
26505
|
if ("error" in item) {
|
|
@@ -30642,6 +30715,111 @@ import {
|
|
|
30642
30715
|
Table as TableIcon2,
|
|
30643
30716
|
Trash2 as Trash24
|
|
30644
30717
|
} from "lucide-react";
|
|
30718
|
+
|
|
30719
|
+
// src/components/UEditor/table-dom-utils.ts
|
|
30720
|
+
var MIN_TABLE_ROW_HEIGHT = 36;
|
|
30721
|
+
var COLUMN_RESIZE_LINE_THICKNESS = 2;
|
|
30722
|
+
var ROW_RESIZE_LINE_THICKNESS = 2;
|
|
30723
|
+
var UEDITOR_TABLE_LAYOUT_CHANGE_EVENT = "ueditor-table-layout-change";
|
|
30724
|
+
var TABLE_RESIZE_HIT_ZONE = 10;
|
|
30725
|
+
function findTableRowNodeInfo(view, rowElement) {
|
|
30726
|
+
const firstCell = rowElement.querySelector("th,td");
|
|
30727
|
+
if (!firstCell) return null;
|
|
30728
|
+
const cellPos = view.posAtDOM(firstCell, 0);
|
|
30729
|
+
const $pos = view.state.doc.resolve(cellPos);
|
|
30730
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
30731
|
+
const node = $pos.node(depth);
|
|
30732
|
+
if (node.type.name === "tableRow") {
|
|
30733
|
+
return {
|
|
30734
|
+
pos: $pos.before(depth),
|
|
30735
|
+
node
|
|
30736
|
+
};
|
|
30737
|
+
}
|
|
30738
|
+
}
|
|
30739
|
+
return null;
|
|
30740
|
+
}
|
|
30741
|
+
function resolveEventElement(target) {
|
|
30742
|
+
if (target instanceof Element) return target;
|
|
30743
|
+
if (target instanceof Node) return target.parentElement;
|
|
30744
|
+
return null;
|
|
30745
|
+
}
|
|
30746
|
+
function getSelectionTableCell(view) {
|
|
30747
|
+
const browserSelection = window.getSelection();
|
|
30748
|
+
const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
|
|
30749
|
+
const anchorCell = anchorElement?.closest?.("th,td");
|
|
30750
|
+
if (anchorCell instanceof HTMLElement) {
|
|
30751
|
+
return anchorCell;
|
|
30752
|
+
}
|
|
30753
|
+
const { from } = view.state.selection;
|
|
30754
|
+
const domAtPos = view.domAtPos(from);
|
|
30755
|
+
const element = resolveEventElement(domAtPos.node);
|
|
30756
|
+
const cell = element?.closest?.("th,td");
|
|
30757
|
+
return cell instanceof HTMLElement ? cell : null;
|
|
30758
|
+
}
|
|
30759
|
+
function isRowResizeHotspot(cell, clientX, clientY) {
|
|
30760
|
+
const rect = cell.getBoundingClientRect();
|
|
30761
|
+
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
30762
|
+
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
30763
|
+
return nearBottom && !nearRight;
|
|
30764
|
+
}
|
|
30765
|
+
function isColumnResizeHotspot(cell, clientX, clientY) {
|
|
30766
|
+
const rect = cell.getBoundingClientRect();
|
|
30767
|
+
const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
|
|
30768
|
+
const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
|
|
30769
|
+
return nearRight && !nearBottom;
|
|
30770
|
+
}
|
|
30771
|
+
function getRelativeBoundaryMetrics(surface, table, row, cell) {
|
|
30772
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
30773
|
+
const tableRect = table.getBoundingClientRect();
|
|
30774
|
+
const rowRect = row.getBoundingClientRect();
|
|
30775
|
+
const cellRect = cell.getBoundingClientRect();
|
|
30776
|
+
return {
|
|
30777
|
+
left: tableRect.left - surfaceRect.left + surface.scrollLeft,
|
|
30778
|
+
top: tableRect.top - surfaceRect.top + surface.scrollTop,
|
|
30779
|
+
width: tableRect.width,
|
|
30780
|
+
height: tableRect.height,
|
|
30781
|
+
rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
|
|
30782
|
+
columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
|
|
30783
|
+
};
|
|
30784
|
+
}
|
|
30785
|
+
function getRelativeCellMetrics(surface, cell) {
|
|
30786
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
30787
|
+
const cellRect = cell.getBoundingClientRect();
|
|
30788
|
+
return {
|
|
30789
|
+
left: cellRect.left - surfaceRect.left + surface.scrollLeft,
|
|
30790
|
+
top: cellRect.top - surfaceRect.top + surface.scrollTop,
|
|
30791
|
+
width: cellRect.width,
|
|
30792
|
+
height: cellRect.height
|
|
30793
|
+
};
|
|
30794
|
+
}
|
|
30795
|
+
function getRelativeSelectedCellsMetrics(surface) {
|
|
30796
|
+
const selectedCells = Array.from(
|
|
30797
|
+
surface.querySelectorAll("td.selectedCell, th.selectedCell")
|
|
30798
|
+
);
|
|
30799
|
+
if (selectedCells.length === 0) {
|
|
30800
|
+
return null;
|
|
30801
|
+
}
|
|
30802
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
30803
|
+
let left = Number.POSITIVE_INFINITY;
|
|
30804
|
+
let top = Number.POSITIVE_INFINITY;
|
|
30805
|
+
let right = Number.NEGATIVE_INFINITY;
|
|
30806
|
+
let bottom = Number.NEGATIVE_INFINITY;
|
|
30807
|
+
selectedCells.forEach((cell) => {
|
|
30808
|
+
const rect = cell.getBoundingClientRect();
|
|
30809
|
+
left = Math.min(left, rect.left);
|
|
30810
|
+
top = Math.min(top, rect.top);
|
|
30811
|
+
right = Math.max(right, rect.right);
|
|
30812
|
+
bottom = Math.max(bottom, rect.bottom);
|
|
30813
|
+
});
|
|
30814
|
+
return {
|
|
30815
|
+
left: left - surfaceRect.left + surface.scrollLeft,
|
|
30816
|
+
top: top - surfaceRect.top + surface.scrollTop,
|
|
30817
|
+
width: right - left,
|
|
30818
|
+
height: bottom - top
|
|
30819
|
+
};
|
|
30820
|
+
}
|
|
30821
|
+
|
|
30822
|
+
// src/components/UEditor/table-controls.tsx
|
|
30645
30823
|
import { Fragment as Fragment27, jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
30646
30824
|
var FALLBACK_TABLE_ROW_HEIGHT = 44;
|
|
30647
30825
|
var FALLBACK_TABLE_COLUMN_WIDTH = 160;
|
|
@@ -30941,6 +31119,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
30941
31119
|
surface.addEventListener("mouseover", handleSurfaceMouseMove);
|
|
30942
31120
|
surface.addEventListener("mousemove", handleSurfaceMouseMove);
|
|
30943
31121
|
surface.addEventListener("scroll", refreshCurrentLayout, { passive: true });
|
|
31122
|
+
surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
|
|
30944
31123
|
window.addEventListener("resize", refreshCurrentLayout);
|
|
30945
31124
|
editor.on("selectionUpdate", syncFromSelection);
|
|
30946
31125
|
editor.on("update", refreshCurrentLayout);
|
|
@@ -30952,6 +31131,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
30952
31131
|
surface.removeEventListener("mouseover", handleSurfaceMouseMove);
|
|
30953
31132
|
surface.removeEventListener("mousemove", handleSurfaceMouseMove);
|
|
30954
31133
|
surface.removeEventListener("scroll", refreshCurrentLayout);
|
|
31134
|
+
surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
|
|
30955
31135
|
window.removeEventListener("resize", refreshCurrentLayout);
|
|
30956
31136
|
editor.off("selectionUpdate", syncFromSelection);
|
|
30957
31137
|
editor.off("update", refreshCurrentLayout);
|
|
@@ -31635,163 +31815,163 @@ function TableControls({ editor, containerRef }) {
|
|
|
31635
31815
|
] });
|
|
31636
31816
|
}
|
|
31637
31817
|
|
|
31638
|
-
// src/components/UEditor/
|
|
31639
|
-
|
|
31640
|
-
|
|
31641
|
-
|
|
31642
|
-
|
|
31643
|
-
|
|
31644
|
-
|
|
31645
|
-
|
|
31646
|
-
|
|
31647
|
-
|
|
31648
|
-
|
|
31649
|
-
|
|
31650
|
-
|
|
31651
|
-
|
|
31652
|
-
|
|
31653
|
-
|
|
31654
|
-
|
|
31655
|
-
|
|
31656
|
-
|
|
31657
|
-
|
|
31658
|
-
|
|
31659
|
-
|
|
31660
|
-
|
|
31661
|
-
|
|
31662
|
-
|
|
31663
|
-
|
|
31664
|
-
|
|
31665
|
-
|
|
31666
|
-
|
|
31667
|
-
|
|
31668
|
-
|
|
31669
|
-
|
|
31670
|
-
|
|
31671
|
-
|
|
31672
|
-
|
|
31673
|
-
|
|
31674
|
-
|
|
31675
|
-
|
|
31676
|
-
|
|
31677
|
-
|
|
31678
|
-
|
|
31679
|
-
|
|
31680
|
-
|
|
31681
|
-
|
|
31682
|
-
|
|
31683
|
-
|
|
31684
|
-
|
|
31685
|
-
|
|
31686
|
-
|
|
31687
|
-
|
|
31688
|
-
|
|
31689
|
-
|
|
31690
|
-
|
|
31691
|
-
|
|
31692
|
-
|
|
31693
|
-
|
|
31694
|
-
|
|
31695
|
-
|
|
31696
|
-
|
|
31697
|
-
|
|
31698
|
-
|
|
31699
|
-
|
|
31700
|
-
|
|
31701
|
-
|
|
31702
|
-
|
|
31703
|
-
|
|
31704
|
-
|
|
31705
|
-
|
|
31706
|
-
|
|
31707
|
-
|
|
31708
|
-
|
|
31709
|
-
|
|
31710
|
-
|
|
31711
|
-
|
|
31712
|
-
|
|
31713
|
-
|
|
31714
|
-
|
|
31715
|
-
|
|
31716
|
-
|
|
31717
|
-
|
|
31718
|
-
|
|
31719
|
-
|
|
31720
|
-
|
|
31721
|
-
|
|
31722
|
-
|
|
31723
|
-
|
|
31724
|
-
|
|
31725
|
-
|
|
31726
|
-
|
|
31727
|
-
|
|
31728
|
-
|
|
31729
|
-
|
|
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
|
-
const inFlightPrepareRef = useRef31(null);
|
|
31788
|
-
const lastAppliedContentRef = useRef31(content ?? "");
|
|
31818
|
+
// src/components/UEditor/editor-styles.ts
|
|
31819
|
+
var UEDITOR_PROSEMIRROR_CLASS_NAME = cn(
|
|
31820
|
+
"prose prose-sm sm:prose dark:prose-invert max-w-none",
|
|
31821
|
+
"focus:outline-none",
|
|
31822
|
+
"px-4 py-4",
|
|
31823
|
+
"[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
|
|
31824
|
+
"[&_.is-editor-empty]:before:text-muted-foreground/50",
|
|
31825
|
+
"[&_.is-editor-empty]:before:float-left",
|
|
31826
|
+
"[&_.is-editor-empty]:before:pointer-events-none",
|
|
31827
|
+
"[&_.is-editor-empty]:before:h-0",
|
|
31828
|
+
"[&_ul[data-type='taskList']]:list-none",
|
|
31829
|
+
"[&_ul[data-type='taskList']]:pl-0",
|
|
31830
|
+
"[&_ul[data-type='taskList']_li]:flex",
|
|
31831
|
+
"[&_ul[data-type='taskList']_li]:items-start",
|
|
31832
|
+
"[&_ul[data-type='taskList']_li]:gap-2",
|
|
31833
|
+
"[&_ul[data-type='taskList']_li>label]:mt-0.5",
|
|
31834
|
+
"[&_ul[data-type='taskList']_li>label>input]:w-4",
|
|
31835
|
+
"[&_ul[data-type='taskList']_li>label>input]:h-4",
|
|
31836
|
+
"[&_ul[data-type='taskList']_li>label>input]:rounded",
|
|
31837
|
+
"[&_ul[data-type='taskList']_li>label>input]:border-2",
|
|
31838
|
+
"[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
|
|
31839
|
+
"[&_ul[data-type='taskList']_li>label>input]:accent-primary",
|
|
31840
|
+
"[&_pre]:bg-muted/40!",
|
|
31841
|
+
"[&_pre]:text-foreground!",
|
|
31842
|
+
"[&_pre]:border!",
|
|
31843
|
+
"[&_pre]:border-border/60!",
|
|
31844
|
+
"[&_pre_code]:bg-transparent!",
|
|
31845
|
+
"[&_.tableWrapper]:overflow-x-auto",
|
|
31846
|
+
"[&_.tableWrapper]:pb-1.5",
|
|
31847
|
+
"[&_.tableWrapper]:select-text",
|
|
31848
|
+
"[&_.tableWrapper]:[scrollbar-width:thin]",
|
|
31849
|
+
"[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
|
|
31850
|
+
"[&_.tableWrapper::-webkit-scrollbar]:h-2",
|
|
31851
|
+
"[&_.tableWrapper::-webkit-scrollbar]:w-2",
|
|
31852
|
+
"[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
|
|
31853
|
+
"[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
|
|
31854
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
|
|
31855
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
|
|
31856
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
|
|
31857
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
|
|
31858
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
|
|
31859
|
+
"[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
|
|
31860
|
+
"[&_table]:table-fixed",
|
|
31861
|
+
"[&_table]:overflow-hidden",
|
|
31862
|
+
"[&_table]:select-text",
|
|
31863
|
+
"[&_table[data-table-align]]:w-max",
|
|
31864
|
+
"[&_table[data-table-align]]:max-w-full",
|
|
31865
|
+
"[&_table[data-table-align='center']]:mx-auto",
|
|
31866
|
+
"[&_table[data-table-align='right']]:ml-auto",
|
|
31867
|
+
"[&_table[data-table-align='right']]:mr-0",
|
|
31868
|
+
"[&_td]:relative",
|
|
31869
|
+
"[&_td]:align-top",
|
|
31870
|
+
"[&_td]:box-border",
|
|
31871
|
+
"[&_td]:select-text",
|
|
31872
|
+
"[&_th]:relative",
|
|
31873
|
+
"[&_th]:align-top",
|
|
31874
|
+
"[&_th]:box-border",
|
|
31875
|
+
"[&_th]:select-text",
|
|
31876
|
+
"[&_.selectedCell]:after:content-['']",
|
|
31877
|
+
"[&_.selectedCell]:after:absolute",
|
|
31878
|
+
"[&_.selectedCell]:after:inset-0",
|
|
31879
|
+
"[&_.selectedCell]:after:z-[2]",
|
|
31880
|
+
"[&_.selectedCell]:after:bg-primary/15",
|
|
31881
|
+
"[&_.selectedCell]:after:pointer-events-none",
|
|
31882
|
+
"[&_.column-resize-handle]:pointer-events-auto",
|
|
31883
|
+
"[&_.column-resize-handle]:cursor-col-resize",
|
|
31884
|
+
"[&_.column-resize-handle]:absolute",
|
|
31885
|
+
"[&_.column-resize-handle]:top-[-1px]",
|
|
31886
|
+
"[&_.column-resize-handle]:bottom-[-1px]",
|
|
31887
|
+
"[&_.column-resize-handle]:right-[-5px]",
|
|
31888
|
+
"[&_.column-resize-handle]:z-10",
|
|
31889
|
+
"[&_.column-resize-handle]:w-2.5",
|
|
31890
|
+
"[&_.column-resize-handle]:bg-transparent",
|
|
31891
|
+
"[&_.column-resize-handle]:rounded-none",
|
|
31892
|
+
"[&_.column-resize-handle]:opacity-0",
|
|
31893
|
+
"[&_.column-resize-handle]:transition-opacity",
|
|
31894
|
+
"[&_.column-resize-handle]:after:absolute",
|
|
31895
|
+
"[&_.column-resize-handle]:after:top-0",
|
|
31896
|
+
"[&_.column-resize-handle]:after:bottom-0",
|
|
31897
|
+
"[&_.column-resize-handle]:after:left-1/2",
|
|
31898
|
+
"[&_.column-resize-handle]:after:w-0.5",
|
|
31899
|
+
"[&_.column-resize-handle]:after:-translate-x-1/2",
|
|
31900
|
+
"[&_.column-resize-handle]:after:rounded-full",
|
|
31901
|
+
"[&_.column-resize-handle]:after:bg-primary/75",
|
|
31902
|
+
"[&_.column-resize-handle]:after:content-['']",
|
|
31903
|
+
"[&.resize-cursor_.column-resize-handle]:opacity-100",
|
|
31904
|
+
"[&.resize-cursor_.column-resize-handle]:after:bg-primary",
|
|
31905
|
+
"[&.resize-cursor]:cursor-col-resize",
|
|
31906
|
+
"[&.resize-row-cursor]:cursor-row-resize",
|
|
31907
|
+
"[&_img.ProseMirror-selectednode]:ring-2",
|
|
31908
|
+
"[&_img.ProseMirror-selectednode]:ring-primary/60",
|
|
31909
|
+
"[&_img.ProseMirror-selectednode]:ring-offset-2",
|
|
31910
|
+
"[&_img.ProseMirror-selectednode]:ring-offset-background",
|
|
31911
|
+
"[&_hr]:border-t-2",
|
|
31912
|
+
"[&_hr]:border-primary/30",
|
|
31913
|
+
"[&_hr]:my-8",
|
|
31914
|
+
"[&_h1]:text-3xl",
|
|
31915
|
+
"[&_h1]:font-bold",
|
|
31916
|
+
"[&_h1]:mt-6",
|
|
31917
|
+
"[&_h1]:mb-4",
|
|
31918
|
+
"[&_h1]:text-foreground",
|
|
31919
|
+
"[&_h2]:text-2xl",
|
|
31920
|
+
"[&_h2]:font-semibold",
|
|
31921
|
+
"[&_h2]:mt-5",
|
|
31922
|
+
"[&_h2]:mb-3",
|
|
31923
|
+
"[&_h2]:text-foreground",
|
|
31924
|
+
"[&_h3]:text-xl",
|
|
31925
|
+
"[&_h3]:font-semibold",
|
|
31926
|
+
"[&_h3]:mt-4",
|
|
31927
|
+
"[&_h3]:mb-2",
|
|
31928
|
+
"[&_h3]:text-foreground",
|
|
31929
|
+
"[&_ul:not([data-type='taskList'])]:list-disc",
|
|
31930
|
+
"[&_ul:not([data-type='taskList'])]:pl-6",
|
|
31931
|
+
"[&_ul:not([data-type='taskList'])]:my-3",
|
|
31932
|
+
"[&_ol]:list-decimal",
|
|
31933
|
+
"[&_ol]:pl-6",
|
|
31934
|
+
"[&_ol]:my-3",
|
|
31935
|
+
"[&_li]:my-1",
|
|
31936
|
+
"[&_li]:pl-1",
|
|
31937
|
+
"[&_li_p]:my-0",
|
|
31938
|
+
"[&_blockquote]:border-l-4",
|
|
31939
|
+
"[&_blockquote]:border-primary",
|
|
31940
|
+
"[&_blockquote]:pl-4",
|
|
31941
|
+
"[&_blockquote]:py-2",
|
|
31942
|
+
"[&_blockquote]:my-4",
|
|
31943
|
+
"[&_blockquote]:bg-muted/30",
|
|
31944
|
+
"[&_blockquote]:rounded-r-lg",
|
|
31945
|
+
"[&_blockquote]:italic",
|
|
31946
|
+
"[&_blockquote]:text-muted-foreground",
|
|
31947
|
+
"[&_blockquote_p]:my-0",
|
|
31948
|
+
"[&_[data-image-layout='left']+p]:mt-1",
|
|
31949
|
+
"[&_[data-image-layout='left']+p]:min-h-[5rem]",
|
|
31950
|
+
"[&_[data-image-layout='right']+p]:mt-1",
|
|
31951
|
+
"[&_[data-image-layout='right']+p]:min-h-[5rem]",
|
|
31952
|
+
"max-md:[&_[data-image-layout='left']]:float-none",
|
|
31953
|
+
"max-md:[&_[data-image-layout='left']]:mr-0",
|
|
31954
|
+
"max-md:[&_[data-image-layout='left']]:ml-0",
|
|
31955
|
+
"max-md:[&_[data-image-layout='left']]:max-w-full",
|
|
31956
|
+
"max-md:[&_[data-image-layout='right']]:float-none",
|
|
31957
|
+
"max-md:[&_[data-image-layout='right']]:mr-0",
|
|
31958
|
+
"max-md:[&_[data-image-layout='right']]:ml-0",
|
|
31959
|
+
"max-md:[&_[data-image-layout='right']]:max-w-full",
|
|
31960
|
+
"max-md:[&_[data-image-layout='left']+p]:min-h-0",
|
|
31961
|
+
"max-md:[&_[data-image-layout='right']+p]:min-h-0"
|
|
31962
|
+
);
|
|
31963
|
+
|
|
31964
|
+
// src/components/UEditor/use-table-interactions.ts
|
|
31965
|
+
import React74, { useEffect as useEffect35, useRef as useRef31 } from "react";
|
|
31966
|
+
function useUEditorTableInteractions(editor) {
|
|
31789
31967
|
const editorContentRef = useRef31(null);
|
|
31790
31968
|
const tableColumnGuideRef = useRef31(null);
|
|
31791
31969
|
const tableRowGuideRef = useRef31(null);
|
|
31792
31970
|
const activeTableCellHighlightRef = useRef31(null);
|
|
31793
31971
|
const hoveredTableCellRef = useRef31(null);
|
|
31794
31972
|
const activeTableCellRef = useRef31(null);
|
|
31973
|
+
const tableLayoutSyncFrameRef = useRef31(null);
|
|
31974
|
+
const rowResizeCommitFrameRef = useRef31(null);
|
|
31795
31975
|
const rowResizeStateRef = useRef31(null);
|
|
31796
31976
|
const setEditorResizeCursor = React74.useCallback((cursor) => {
|
|
31797
31977
|
const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
|
|
@@ -31833,6 +32013,14 @@ var UEditor = React74.forwardRef(({
|
|
|
31833
32013
|
highlight.style.width = `${metrics.width}px`;
|
|
31834
32014
|
highlight.style.height = `${metrics.height}px`;
|
|
31835
32015
|
}, []);
|
|
32016
|
+
const scheduleTableLayoutSync = React74.useCallback(() => {
|
|
32017
|
+
if (tableLayoutSyncFrameRef.current !== null) return;
|
|
32018
|
+
tableLayoutSyncFrameRef.current = window.requestAnimationFrame(() => {
|
|
32019
|
+
tableLayoutSyncFrameRef.current = null;
|
|
32020
|
+
updateActiveCellHighlight(activeTableCellRef.current);
|
|
32021
|
+
editorContentRef.current?.dispatchEvent(new CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT));
|
|
32022
|
+
});
|
|
32023
|
+
}, [updateActiveCellHighlight]);
|
|
31836
32024
|
const setActiveTableCell = React74.useCallback((cell) => {
|
|
31837
32025
|
if (activeTableCellRef.current === cell) return;
|
|
31838
32026
|
activeTableCellRef.current = cell;
|
|
@@ -31874,228 +32062,49 @@ var UEditor = React74.forwardRef(({
|
|
|
31874
32062
|
surface.classList.add("resize-row-cursor");
|
|
31875
32063
|
setEditorResizeCursor("row-resize");
|
|
31876
32064
|
}, [setEditorResizeCursor]);
|
|
31877
|
-
const
|
|
31878
|
-
()
|
|
31879
|
-
|
|
31880
|
-
|
|
31881
|
-
|
|
31882
|
-
|
|
31883
|
-
|
|
31884
|
-
|
|
31885
|
-
|
|
31886
|
-
|
|
31887
|
-
editorProps: {
|
|
31888
|
-
handleDOMEvents: {
|
|
31889
|
-
keydown: (_view, event) => {
|
|
31890
|
-
if (!(event instanceof KeyboardEvent)) return false;
|
|
31891
|
-
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
31892
|
-
event.stopPropagation();
|
|
31893
|
-
}
|
|
31894
|
-
return false;
|
|
31895
|
-
},
|
|
31896
|
-
click: (view, event) => {
|
|
31897
|
-
if (!(event instanceof MouseEvent)) return false;
|
|
31898
|
-
if (event.button !== 0) return false;
|
|
31899
|
-
const target = resolveEventElement(event.target);
|
|
31900
|
-
const anchor = target?.closest?.("a[href]");
|
|
31901
|
-
const href = anchor?.getAttribute("href") ?? "";
|
|
31902
|
-
if (!href) return false;
|
|
31903
|
-
if (!view.state.selection.empty) return false;
|
|
31904
|
-
event.preventDefault();
|
|
31905
|
-
event.stopPropagation();
|
|
31906
|
-
window.open(href, "_blank", "noopener,noreferrer");
|
|
31907
|
-
return true;
|
|
31908
|
-
}
|
|
31909
|
-
},
|
|
31910
|
-
attributes: {
|
|
31911
|
-
class: cn(
|
|
31912
|
-
"prose prose-sm sm:prose dark:prose-invert max-w-none",
|
|
31913
|
-
"focus:outline-none",
|
|
31914
|
-
"px-4 py-4",
|
|
31915
|
-
"[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
|
|
31916
|
-
"[&_.is-editor-empty]:before:text-muted-foreground/50",
|
|
31917
|
-
"[&_.is-editor-empty]:before:float-left",
|
|
31918
|
-
"[&_.is-editor-empty]:before:pointer-events-none",
|
|
31919
|
-
"[&_.is-editor-empty]:before:h-0",
|
|
31920
|
-
"[&_ul[data-type='taskList']]:list-none",
|
|
31921
|
-
"[&_ul[data-type='taskList']]:pl-0",
|
|
31922
|
-
"[&_ul[data-type='taskList']_li]:flex",
|
|
31923
|
-
"[&_ul[data-type='taskList']_li]:items-start",
|
|
31924
|
-
"[&_ul[data-type='taskList']_li]:gap-2",
|
|
31925
|
-
"[&_ul[data-type='taskList']_li>label]:mt-0.5",
|
|
31926
|
-
"[&_ul[data-type='taskList']_li>label>input]:w-4",
|
|
31927
|
-
"[&_ul[data-type='taskList']_li>label>input]:h-4",
|
|
31928
|
-
"[&_ul[data-type='taskList']_li>label>input]:rounded",
|
|
31929
|
-
"[&_ul[data-type='taskList']_li>label>input]:border-2",
|
|
31930
|
-
"[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
|
|
31931
|
-
"[&_ul[data-type='taskList']_li>label>input]:accent-primary",
|
|
31932
|
-
"[&_pre]:bg-muted/40!",
|
|
31933
|
-
"[&_pre]:text-foreground!",
|
|
31934
|
-
"[&_pre]:border!",
|
|
31935
|
-
"[&_pre]:border-border/60!",
|
|
31936
|
-
"[&_pre_code]:bg-transparent!",
|
|
31937
|
-
"[&_.tableWrapper]:overflow-x-auto",
|
|
31938
|
-
"[&_.tableWrapper]:pb-1.5",
|
|
31939
|
-
"[&_.tableWrapper]:select-text",
|
|
31940
|
-
"[&_.tableWrapper]:[scrollbar-width:thin]",
|
|
31941
|
-
"[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
|
|
31942
|
-
"[&_.tableWrapper::-webkit-scrollbar]:h-2",
|
|
31943
|
-
"[&_.tableWrapper::-webkit-scrollbar]:w-2",
|
|
31944
|
-
"[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
|
|
31945
|
-
"[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
|
|
31946
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
|
|
31947
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
|
|
31948
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
|
|
31949
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
|
|
31950
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
|
|
31951
|
-
"[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
|
|
31952
|
-
"[&_table]:table-fixed",
|
|
31953
|
-
"[&_table]:overflow-hidden",
|
|
31954
|
-
"[&_table]:select-text",
|
|
31955
|
-
"[&_table[data-table-align]]:w-max",
|
|
31956
|
-
"[&_table[data-table-align]]:max-w-full",
|
|
31957
|
-
"[&_table[data-table-align='center']]:mx-auto",
|
|
31958
|
-
"[&_table[data-table-align='right']]:ml-auto",
|
|
31959
|
-
"[&_table[data-table-align='right']]:mr-0",
|
|
31960
|
-
"[&_td]:relative",
|
|
31961
|
-
"[&_td]:align-top",
|
|
31962
|
-
"[&_td]:box-border",
|
|
31963
|
-
"[&_td]:select-text",
|
|
31964
|
-
"[&_th]:relative",
|
|
31965
|
-
"[&_th]:align-top",
|
|
31966
|
-
"[&_th]:box-border",
|
|
31967
|
-
"[&_th]:select-text",
|
|
31968
|
-
"[&_.selectedCell]:after:content-['']",
|
|
31969
|
-
"[&_.selectedCell]:after:absolute",
|
|
31970
|
-
"[&_.selectedCell]:after:inset-0",
|
|
31971
|
-
"[&_.selectedCell]:after:z-[2]",
|
|
31972
|
-
"[&_.selectedCell]:after:bg-primary/15",
|
|
31973
|
-
"[&_.selectedCell]:after:pointer-events-none",
|
|
31974
|
-
"[&_.column-resize-handle]:pointer-events-auto",
|
|
31975
|
-
"[&_.column-resize-handle]:cursor-col-resize",
|
|
31976
|
-
"[&_.column-resize-handle]:absolute",
|
|
31977
|
-
"[&_.column-resize-handle]:top-[-1px]",
|
|
31978
|
-
"[&_.column-resize-handle]:bottom-[-1px]",
|
|
31979
|
-
"[&_.column-resize-handle]:right-[-5px]",
|
|
31980
|
-
"[&_.column-resize-handle]:z-10",
|
|
31981
|
-
"[&_.column-resize-handle]:w-2.5",
|
|
31982
|
-
"[&_.column-resize-handle]:bg-transparent",
|
|
31983
|
-
"[&_.column-resize-handle]:rounded-none",
|
|
31984
|
-
"[&_.column-resize-handle]:opacity-0",
|
|
31985
|
-
"[&_.column-resize-handle]:transition-opacity",
|
|
31986
|
-
"[&_.column-resize-handle]:after:absolute",
|
|
31987
|
-
"[&_.column-resize-handle]:after:top-0",
|
|
31988
|
-
"[&_.column-resize-handle]:after:bottom-0",
|
|
31989
|
-
"[&_.column-resize-handle]:after:left-1/2",
|
|
31990
|
-
"[&_.column-resize-handle]:after:w-0.5",
|
|
31991
|
-
"[&_.column-resize-handle]:after:-translate-x-1/2",
|
|
31992
|
-
"[&_.column-resize-handle]:after:rounded-full",
|
|
31993
|
-
"[&_.column-resize-handle]:after:bg-primary/75",
|
|
31994
|
-
"[&_.column-resize-handle]:after:content-['']",
|
|
31995
|
-
"[&.resize-cursor_.column-resize-handle]:opacity-100",
|
|
31996
|
-
"[&.resize-cursor_.column-resize-handle]:after:bg-primary",
|
|
31997
|
-
"[&.resize-cursor]:cursor-col-resize",
|
|
31998
|
-
"[&.resize-row-cursor]:cursor-row-resize",
|
|
31999
|
-
"[&_img.ProseMirror-selectednode]:ring-2",
|
|
32000
|
-
"[&_img.ProseMirror-selectednode]:ring-primary/60",
|
|
32001
|
-
"[&_img.ProseMirror-selectednode]:ring-offset-2",
|
|
32002
|
-
"[&_img.ProseMirror-selectednode]:ring-offset-background",
|
|
32003
|
-
"[&_hr]:border-t-2",
|
|
32004
|
-
"[&_hr]:border-primary/30",
|
|
32005
|
-
"[&_hr]:my-8",
|
|
32006
|
-
"[&_h1]:text-3xl",
|
|
32007
|
-
"[&_h1]:font-bold",
|
|
32008
|
-
"[&_h1]:mt-6",
|
|
32009
|
-
"[&_h1]:mb-4",
|
|
32010
|
-
"[&_h1]:text-foreground",
|
|
32011
|
-
"[&_h2]:text-2xl",
|
|
32012
|
-
"[&_h2]:font-semibold",
|
|
32013
|
-
"[&_h2]:mt-5",
|
|
32014
|
-
"[&_h2]:mb-3",
|
|
32015
|
-
"[&_h2]:text-foreground",
|
|
32016
|
-
"[&_h3]:text-xl",
|
|
32017
|
-
"[&_h3]:font-semibold",
|
|
32018
|
-
"[&_h3]:mt-4",
|
|
32019
|
-
"[&_h3]:mb-2",
|
|
32020
|
-
"[&_h3]:text-foreground",
|
|
32021
|
-
"[&_ul:not([data-type='taskList'])]:list-disc",
|
|
32022
|
-
"[&_ul:not([data-type='taskList'])]:pl-6",
|
|
32023
|
-
"[&_ul:not([data-type='taskList'])]:my-3",
|
|
32024
|
-
"[&_ol]:list-decimal",
|
|
32025
|
-
"[&_ol]:pl-6",
|
|
32026
|
-
"[&_ol]:my-3",
|
|
32027
|
-
"[&_li]:my-1",
|
|
32028
|
-
"[&_li]:pl-1",
|
|
32029
|
-
"[&_li_p]:my-0",
|
|
32030
|
-
"[&_blockquote]:border-l-4",
|
|
32031
|
-
"[&_blockquote]:border-primary",
|
|
32032
|
-
"[&_blockquote]:pl-4",
|
|
32033
|
-
"[&_blockquote]:py-2",
|
|
32034
|
-
"[&_blockquote]:my-4",
|
|
32035
|
-
"[&_blockquote]:bg-muted/30",
|
|
32036
|
-
"[&_blockquote]:rounded-r-lg",
|
|
32037
|
-
"[&_blockquote]:italic",
|
|
32038
|
-
"[&_blockquote]:text-muted-foreground",
|
|
32039
|
-
"[&_blockquote_p]:my-0",
|
|
32040
|
-
"[&_[data-image-layout='left']+p]:mt-1",
|
|
32041
|
-
"[&_[data-image-layout='left']+p]:min-h-[5rem]",
|
|
32042
|
-
"[&_[data-image-layout='right']+p]:mt-1",
|
|
32043
|
-
"[&_[data-image-layout='right']+p]:min-h-[5rem]",
|
|
32044
|
-
"max-md:[&_[data-image-layout='left']]:float-none",
|
|
32045
|
-
"max-md:[&_[data-image-layout='left']]:mr-0",
|
|
32046
|
-
"max-md:[&_[data-image-layout='left']]:ml-0",
|
|
32047
|
-
"max-md:[&_[data-image-layout='left']]:max-w-full",
|
|
32048
|
-
"max-md:[&_[data-image-layout='right']]:float-none",
|
|
32049
|
-
"max-md:[&_[data-image-layout='right']]:mr-0",
|
|
32050
|
-
"max-md:[&_[data-image-layout='right']]:ml-0",
|
|
32051
|
-
"max-md:[&_[data-image-layout='right']]:max-w-full",
|
|
32052
|
-
"max-md:[&_[data-image-layout='left']+p]:min-h-0",
|
|
32053
|
-
"max-md:[&_[data-image-layout='right']+p]:min-h-0"
|
|
32054
|
-
)
|
|
32055
|
-
}
|
|
32056
|
-
},
|
|
32057
|
-
onUpdate: ({ editor: editor2 }) => {
|
|
32058
|
-
const html = editor2.getHTML();
|
|
32059
|
-
onChange?.(html);
|
|
32060
|
-
onHtmlChange?.(html);
|
|
32061
|
-
onJsonChange?.(editor2.getJSON());
|
|
32065
|
+
const commitRowResizePreview = React74.useCallback(() => {
|
|
32066
|
+
if (!editor) return;
|
|
32067
|
+
const state = rowResizeStateRef.current;
|
|
32068
|
+
if (!state) return;
|
|
32069
|
+
const nextHeight = state.pendingHeight;
|
|
32070
|
+
if (nextHeight === state.previewHeight) {
|
|
32071
|
+
document.body.style.cursor = "row-resize";
|
|
32072
|
+
showRowGuide(state.tableElement, state.rowElement, state.cellElement);
|
|
32073
|
+
scheduleTableLayoutSync();
|
|
32074
|
+
return;
|
|
32062
32075
|
}
|
|
32063
|
-
|
|
32076
|
+
state.previewHeight = nextHeight;
|
|
32077
|
+
const tr = editor.view.state.tr;
|
|
32078
|
+
tr.setNodeMarkup(state.rowPos, void 0, {
|
|
32079
|
+
...state.rowNode.attrs,
|
|
32080
|
+
rowHeight: nextHeight
|
|
32081
|
+
});
|
|
32082
|
+
tr.setMeta("addToHistory", false);
|
|
32083
|
+
editor.view.dispatch(tr);
|
|
32084
|
+
state.rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
|
|
32085
|
+
const refreshedRow = state.tableElement.rows.item(state.rowElement.rowIndex);
|
|
32086
|
+
if (refreshedRow instanceof HTMLTableRowElement) {
|
|
32087
|
+
state.rowElement = refreshedRow;
|
|
32088
|
+
const refreshedCell = refreshedRow.cells.item(state.cellIndex);
|
|
32089
|
+
if (refreshedCell instanceof HTMLTableCellElement) {
|
|
32090
|
+
state.cellElement = refreshedCell;
|
|
32091
|
+
}
|
|
32092
|
+
}
|
|
32093
|
+
document.body.style.cursor = "row-resize";
|
|
32094
|
+
showRowGuide(state.tableElement, state.rowElement, state.cellElement);
|
|
32095
|
+
scheduleTableLayoutSync();
|
|
32096
|
+
}, [editor, scheduleTableLayoutSync, showRowGuide]);
|
|
32097
|
+
const scheduleRowResizeCommit = React74.useCallback(() => {
|
|
32098
|
+
if (rowResizeCommitFrameRef.current !== null) return;
|
|
32099
|
+
rowResizeCommitFrameRef.current = window.requestAnimationFrame(() => {
|
|
32100
|
+
rowResizeCommitFrameRef.current = null;
|
|
32101
|
+
commitRowResizePreview();
|
|
32102
|
+
});
|
|
32103
|
+
}, [commitRowResizePreview]);
|
|
32064
32104
|
const syncActiveTableCellFromSelection = React74.useCallback(() => {
|
|
32065
32105
|
if (!editor) return;
|
|
32066
32106
|
setActiveTableCell(getSelectionTableCell(editor.view));
|
|
32067
32107
|
}, [editor, setActiveTableCell]);
|
|
32068
|
-
useImperativeHandle3(
|
|
32069
|
-
ref,
|
|
32070
|
-
() => ({
|
|
32071
|
-
prepareContentForSave: async ({ throwOnError = false } = {}) => {
|
|
32072
|
-
if (!inFlightPrepareRef.current) {
|
|
32073
|
-
const htmlSnapshot = editor?.getHTML() ?? content ?? "";
|
|
32074
|
-
inFlightPrepareRef.current = prepareUEditorContentForSave({
|
|
32075
|
-
html: htmlSnapshot,
|
|
32076
|
-
uploadImageForSave
|
|
32077
|
-
}).finally(() => {
|
|
32078
|
-
inFlightPrepareRef.current = null;
|
|
32079
|
-
});
|
|
32080
|
-
}
|
|
32081
|
-
const result = await inFlightPrepareRef.current;
|
|
32082
|
-
if (throwOnError && result.errors.length > 0) {
|
|
32083
|
-
throw new UEditorPrepareContentForSaveError(result);
|
|
32084
|
-
}
|
|
32085
|
-
return result;
|
|
32086
|
-
}
|
|
32087
|
-
}),
|
|
32088
|
-
[content, editor, uploadImageForSave]
|
|
32089
|
-
);
|
|
32090
|
-
useEffect35(() => {
|
|
32091
|
-
if (!editor) return;
|
|
32092
|
-
const nextContent = content ?? "";
|
|
32093
|
-
if (lastAppliedContentRef.current === nextContent) return;
|
|
32094
|
-
lastAppliedContentRef.current = nextContent;
|
|
32095
|
-
if (editor.getHTML() !== nextContent) {
|
|
32096
|
-
editor.commands.setContent(nextContent, { emitUpdate: false });
|
|
32097
|
-
}
|
|
32098
|
-
}, [content, editor]);
|
|
32099
32108
|
useEffect35(() => {
|
|
32100
32109
|
if (!editor) return void 0;
|
|
32101
32110
|
const proseMirror = editor.view.dom;
|
|
@@ -32185,6 +32194,7 @@ var UEditor = React74.forwardRef(({
|
|
|
32185
32194
|
setHoveredTableCell(cell);
|
|
32186
32195
|
const rowInfo = findTableRowNodeInfo(editor.view, row);
|
|
32187
32196
|
if (!rowInfo) return;
|
|
32197
|
+
const startHeight = row.getBoundingClientRect().height;
|
|
32188
32198
|
rowResizeStateRef.current = {
|
|
32189
32199
|
rowElement: row,
|
|
32190
32200
|
tableElement: table,
|
|
@@ -32193,8 +32203,9 @@ var UEditor = React74.forwardRef(({
|
|
|
32193
32203
|
rowPos: rowInfo.pos,
|
|
32194
32204
|
rowNode: rowInfo.node,
|
|
32195
32205
|
startY: event.clientY,
|
|
32196
|
-
startHeight
|
|
32197
|
-
previewHeight:
|
|
32206
|
+
startHeight,
|
|
32207
|
+
previewHeight: startHeight,
|
|
32208
|
+
pendingHeight: startHeight
|
|
32198
32209
|
};
|
|
32199
32210
|
showRowGuide(table, row, cell);
|
|
32200
32211
|
document.body.style.cursor = "row-resize";
|
|
@@ -32208,30 +32219,14 @@ var UEditor = React74.forwardRef(({
|
|
|
32208
32219
|
MIN_TABLE_ROW_HEIGHT,
|
|
32209
32220
|
Math.round(state.startHeight + (event.clientY - state.startY))
|
|
32210
32221
|
);
|
|
32211
|
-
if (nextHeight === state.
|
|
32222
|
+
if (nextHeight === state.pendingHeight) {
|
|
32212
32223
|
document.body.style.cursor = "row-resize";
|
|
32213
32224
|
showRowGuide(state.tableElement, state.rowElement, state.cellElement);
|
|
32214
32225
|
return;
|
|
32215
32226
|
}
|
|
32216
|
-
state.
|
|
32217
|
-
applyPreviewRowHeight(state.rowElement, nextHeight);
|
|
32218
|
-
const tr = editor.view.state.tr;
|
|
32219
|
-
tr.setNodeMarkup(state.rowPos, void 0, {
|
|
32220
|
-
...state.rowNode.attrs,
|
|
32221
|
-
rowHeight: nextHeight
|
|
32222
|
-
});
|
|
32223
|
-
editor.view.dispatch(tr);
|
|
32224
|
-
state.rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
|
|
32225
|
-
const refreshedRow = state.tableElement.rows.item(state.rowElement.rowIndex);
|
|
32226
|
-
if (refreshedRow instanceof HTMLTableRowElement) {
|
|
32227
|
-
state.rowElement = refreshedRow;
|
|
32228
|
-
const refreshedCell = refreshedRow.cells.item(state.cellIndex);
|
|
32229
|
-
if (refreshedCell instanceof HTMLTableCellElement) {
|
|
32230
|
-
state.cellElement = refreshedCell;
|
|
32231
|
-
}
|
|
32232
|
-
}
|
|
32227
|
+
state.pendingHeight = nextHeight;
|
|
32233
32228
|
document.body.style.cursor = "row-resize";
|
|
32234
|
-
|
|
32229
|
+
scheduleRowResizeCommit();
|
|
32235
32230
|
};
|
|
32236
32231
|
const handlePointerUp = (event) => {
|
|
32237
32232
|
const state = rowResizeStateRef.current;
|
|
@@ -32240,20 +32235,40 @@ var UEditor = React74.forwardRef(({
|
|
|
32240
32235
|
MIN_TABLE_ROW_HEIGHT,
|
|
32241
32236
|
Math.round(state.startHeight + (event.clientY - state.startY))
|
|
32242
32237
|
);
|
|
32243
|
-
|
|
32238
|
+
state.pendingHeight = nextHeight;
|
|
32239
|
+
if (rowResizeCommitFrameRef.current !== null) {
|
|
32240
|
+
window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
|
|
32241
|
+
rowResizeCommitFrameRef.current = null;
|
|
32242
|
+
}
|
|
32243
|
+
commitRowResizePreview();
|
|
32244
|
+
const latestState = rowResizeStateRef.current ?? state;
|
|
32245
|
+
const rowNode = editor.view.state.doc.nodeAt(latestState.rowPos) ?? latestState.rowNode;
|
|
32246
|
+
if (rowNode.attrs.rowHeight !== nextHeight) {
|
|
32247
|
+
const tr = editor.view.state.tr;
|
|
32248
|
+
tr.setNodeMarkup(latestState.rowPos, void 0, {
|
|
32249
|
+
...rowNode.attrs,
|
|
32250
|
+
rowHeight: nextHeight
|
|
32251
|
+
});
|
|
32252
|
+
editor.view.dispatch(tr);
|
|
32253
|
+
}
|
|
32244
32254
|
rowResizeStateRef.current = null;
|
|
32245
32255
|
document.body.style.cursor = "";
|
|
32246
32256
|
clearHoveredTableCell();
|
|
32247
32257
|
clearAllTableResizeHover();
|
|
32258
|
+
scheduleTableLayoutSync();
|
|
32248
32259
|
};
|
|
32249
32260
|
const handleWindowBlur = () => {
|
|
32250
32261
|
const state = rowResizeStateRef.current;
|
|
32251
32262
|
if (!state) return;
|
|
32252
|
-
|
|
32263
|
+
if (rowResizeCommitFrameRef.current !== null) {
|
|
32264
|
+
window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
|
|
32265
|
+
rowResizeCommitFrameRef.current = null;
|
|
32266
|
+
}
|
|
32253
32267
|
rowResizeStateRef.current = null;
|
|
32254
32268
|
document.body.style.cursor = "";
|
|
32255
32269
|
clearHoveredTableCell();
|
|
32256
32270
|
clearAllTableResizeHover();
|
|
32271
|
+
scheduleTableLayoutSync();
|
|
32257
32272
|
};
|
|
32258
32273
|
proseMirror.addEventListener("mousemove", handleEditorMouseMove);
|
|
32259
32274
|
proseMirror.addEventListener("mouseleave", handleEditorMouseLeave);
|
|
@@ -32292,13 +32307,156 @@ var UEditor = React74.forwardRef(({
|
|
|
32292
32307
|
editor.off("selectionUpdate", syncActiveTableCellFromSelection);
|
|
32293
32308
|
editor.off("focus", syncActiveTableCellFromSelection);
|
|
32294
32309
|
window.clearTimeout(selectionSyncTimeoutId);
|
|
32310
|
+
if (tableLayoutSyncFrameRef.current !== null) {
|
|
32311
|
+
window.cancelAnimationFrame(tableLayoutSyncFrameRef.current);
|
|
32312
|
+
tableLayoutSyncFrameRef.current = null;
|
|
32313
|
+
}
|
|
32314
|
+
if (rowResizeCommitFrameRef.current !== null) {
|
|
32315
|
+
window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
|
|
32316
|
+
rowResizeCommitFrameRef.current = null;
|
|
32317
|
+
}
|
|
32295
32318
|
document.body.style.cursor = "";
|
|
32296
32319
|
clearActiveTableCell();
|
|
32297
32320
|
clearHoveredTableCell();
|
|
32298
32321
|
clearAllTableResizeHover();
|
|
32299
32322
|
rowResizeStateRef.current = null;
|
|
32300
32323
|
};
|
|
32301
|
-
}, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editor, hideColumnGuide, hideRowGuide, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
|
|
32324
|
+
}, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, commitRowResizePreview, editor, hideColumnGuide, hideRowGuide, scheduleRowResizeCommit, scheduleTableLayoutSync, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
|
|
32325
|
+
return {
|
|
32326
|
+
editorContentRef,
|
|
32327
|
+
tableColumnGuideRef,
|
|
32328
|
+
tableRowGuideRef,
|
|
32329
|
+
activeTableCellHighlightRef
|
|
32330
|
+
};
|
|
32331
|
+
}
|
|
32332
|
+
|
|
32333
|
+
// src/components/UEditor/UEditor.tsx
|
|
32334
|
+
import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
32335
|
+
var UEditor = React75.forwardRef(({
|
|
32336
|
+
content = "",
|
|
32337
|
+
onChange,
|
|
32338
|
+
onHtmlChange,
|
|
32339
|
+
onJsonChange,
|
|
32340
|
+
uploadImage,
|
|
32341
|
+
uploadImageForSave,
|
|
32342
|
+
uploadImageConcurrency = 3,
|
|
32343
|
+
imageInsertMode = "base64",
|
|
32344
|
+
maxImageFileSize,
|
|
32345
|
+
allowedImageMimeTypes,
|
|
32346
|
+
fallbackToDataUrl,
|
|
32347
|
+
placeholder,
|
|
32348
|
+
className,
|
|
32349
|
+
editable = true,
|
|
32350
|
+
autofocus = false,
|
|
32351
|
+
showToolbar = true,
|
|
32352
|
+
showBubbleMenu = true,
|
|
32353
|
+
showFloatingMenu = false,
|
|
32354
|
+
showCharacterCount = true,
|
|
32355
|
+
maxCharacters,
|
|
32356
|
+
minHeight = "200px",
|
|
32357
|
+
maxHeight = "auto",
|
|
32358
|
+
variant = "default",
|
|
32359
|
+
fontFamilies,
|
|
32360
|
+
fontSizes,
|
|
32361
|
+
lineHeights,
|
|
32362
|
+
letterSpacings
|
|
32363
|
+
}, ref) => {
|
|
32364
|
+
const t = useSmartTranslations("UEditor");
|
|
32365
|
+
const effectivePlaceholder = placeholder ?? t("placeholder");
|
|
32366
|
+
const inFlightPrepareRef = useRef32(null);
|
|
32367
|
+
const lastAppliedContentRef = useRef32(content ?? "");
|
|
32368
|
+
const extensions = useMemo24(
|
|
32369
|
+
() => buildUEditorExtensions({
|
|
32370
|
+
placeholder: effectivePlaceholder,
|
|
32371
|
+
translate: t,
|
|
32372
|
+
maxCharacters,
|
|
32373
|
+
uploadImage,
|
|
32374
|
+
imageInsertMode,
|
|
32375
|
+
maxImageFileSize,
|
|
32376
|
+
allowedImageMimeTypes,
|
|
32377
|
+
fallbackToDataUrl,
|
|
32378
|
+
editable
|
|
32379
|
+
}),
|
|
32380
|
+
[effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable]
|
|
32381
|
+
);
|
|
32382
|
+
const editor = useEditor({
|
|
32383
|
+
immediatelyRender: false,
|
|
32384
|
+
extensions,
|
|
32385
|
+
content,
|
|
32386
|
+
editable,
|
|
32387
|
+
autofocus,
|
|
32388
|
+
editorProps: {
|
|
32389
|
+
handleDOMEvents: {
|
|
32390
|
+
keydown: (_view, event) => {
|
|
32391
|
+
if (!(event instanceof KeyboardEvent)) return false;
|
|
32392
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
32393
|
+
event.stopPropagation();
|
|
32394
|
+
}
|
|
32395
|
+
return false;
|
|
32396
|
+
},
|
|
32397
|
+
click: (view, event) => {
|
|
32398
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
32399
|
+
if (event.button !== 0) return false;
|
|
32400
|
+
const target = resolveEventElement(event.target);
|
|
32401
|
+
const anchor = target?.closest?.("a[href]");
|
|
32402
|
+
const href = anchor?.getAttribute("href") ?? "";
|
|
32403
|
+
if (!href) return false;
|
|
32404
|
+
if (!view.state.selection.empty) return false;
|
|
32405
|
+
event.preventDefault();
|
|
32406
|
+
event.stopPropagation();
|
|
32407
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
32408
|
+
return true;
|
|
32409
|
+
}
|
|
32410
|
+
},
|
|
32411
|
+
attributes: {
|
|
32412
|
+
class: UEDITOR_PROSEMIRROR_CLASS_NAME
|
|
32413
|
+
}
|
|
32414
|
+
},
|
|
32415
|
+
onUpdate: ({ editor: editor2 }) => {
|
|
32416
|
+
const html = editor2.getHTML();
|
|
32417
|
+
onChange?.(html);
|
|
32418
|
+
onHtmlChange?.(html);
|
|
32419
|
+
onJsonChange?.(editor2.getJSON());
|
|
32420
|
+
}
|
|
32421
|
+
});
|
|
32422
|
+
const {
|
|
32423
|
+
editorContentRef,
|
|
32424
|
+
tableColumnGuideRef,
|
|
32425
|
+
tableRowGuideRef,
|
|
32426
|
+
activeTableCellHighlightRef
|
|
32427
|
+
} = useUEditorTableInteractions(editor);
|
|
32428
|
+
useImperativeHandle3(
|
|
32429
|
+
ref,
|
|
32430
|
+
() => ({
|
|
32431
|
+
prepareContentForSave: async ({ throwOnError = false } = {}) => {
|
|
32432
|
+
if (!inFlightPrepareRef.current) {
|
|
32433
|
+
const htmlSnapshot = editor?.getHTML() ?? content ?? "";
|
|
32434
|
+
inFlightPrepareRef.current = prepareUEditorContentForSave({
|
|
32435
|
+
html: htmlSnapshot,
|
|
32436
|
+
uploadImageForSave,
|
|
32437
|
+
uploadConcurrency: uploadImageConcurrency
|
|
32438
|
+
}).finally(() => {
|
|
32439
|
+
inFlightPrepareRef.current = null;
|
|
32440
|
+
});
|
|
32441
|
+
}
|
|
32442
|
+
const result = await inFlightPrepareRef.current;
|
|
32443
|
+
if (throwOnError && result.errors.length > 0) {
|
|
32444
|
+
throw new UEditorPrepareContentForSaveError(result);
|
|
32445
|
+
}
|
|
32446
|
+
return result;
|
|
32447
|
+
}
|
|
32448
|
+
}),
|
|
32449
|
+
[content, editor, uploadImageForSave, uploadImageConcurrency]
|
|
32450
|
+
);
|
|
32451
|
+
useEffect36(() => {
|
|
32452
|
+
if (!editor) return;
|
|
32453
|
+
const nextContent = content ?? "";
|
|
32454
|
+
if (lastAppliedContentRef.current === nextContent) return;
|
|
32455
|
+
lastAppliedContentRef.current = nextContent;
|
|
32456
|
+
if (editor.getHTML() !== nextContent) {
|
|
32457
|
+
editor.commands.setContent(nextContent, { emitUpdate: false });
|
|
32458
|
+
}
|
|
32459
|
+
}, [content, editor]);
|
|
32302
32460
|
if (!editor) {
|
|
32303
32461
|
return /* @__PURE__ */ jsx83(
|
|
32304
32462
|
"div",
|
|
@@ -32328,6 +32486,8 @@ var UEditor = React74.forwardRef(({
|
|
|
32328
32486
|
variant,
|
|
32329
32487
|
uploadImage,
|
|
32330
32488
|
imageInsertMode,
|
|
32489
|
+
maxImageFileSize,
|
|
32490
|
+
allowedImageMimeTypes,
|
|
32331
32491
|
fontFamilies,
|
|
32332
32492
|
fontSizes,
|
|
32333
32493
|
lineHeights,
|