@trafica/editor 1.0.37 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7833,848 +7833,6 @@ var jsonSerializer = {
7833
7833
  }
7834
7834
  }
7835
7835
  };
7836
- function Editor({
7837
- engine,
7838
- placeholder = "Start writing...",
7839
- className = "",
7840
- readOnly = false,
7841
- onHTMLChange,
7842
- onJSONChange,
7843
- onOpenLinkPopup,
7844
- onUploadImage: _onUploadImage
7845
- }) {
7846
- const containerRef = react.useRef(null);
7847
- const isRenderingRef = react.useRef(false);
7848
- const scrollCaretIntoView = react.useCallback(() => {
7849
- var _a, _b;
7850
- const sel = window.getSelection();
7851
- if (!sel || sel.rangeCount === 0) return;
7852
- const range = sel.getRangeAt(0).cloneRange();
7853
- range.collapse(true);
7854
- const caretRect = range.getBoundingClientRect();
7855
- let rect = caretRect;
7856
- if (!rect || rect.top === 0 && rect.bottom === 0 && rect.left === 0) {
7857
- const node = range.startContainer;
7858
- const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
7859
- if (el) rect = el.getBoundingClientRect();
7860
- }
7861
- if (!rect || rect.bottom === 0) return;
7862
- let scrollEl = (_b = (_a = containerRef.current) == null ? void 0 : _a.parentElement) != null ? _b : null;
7863
- while (scrollEl) {
7864
- const style = window.getComputedStyle(scrollEl);
7865
- const overflow = style.overflow + style.overflowY;
7866
- if (/auto|scroll/.test(overflow)) break;
7867
- scrollEl = scrollEl.parentElement;
7868
- }
7869
- const PADDING = 24;
7870
- if (scrollEl) {
7871
- const containerRect = scrollEl.getBoundingClientRect();
7872
- if (rect.bottom > containerRect.bottom - PADDING) {
7873
- scrollEl.scrollBy({ top: rect.bottom - containerRect.bottom + PADDING, behavior: "smooth" });
7874
- } else if (rect.top < containerRect.top + PADDING) {
7875
- scrollEl.scrollBy({ top: rect.top - containerRect.top - PADDING, behavior: "smooth" });
7876
- }
7877
- } else {
7878
- if (rect.bottom > window.innerHeight - PADDING) {
7879
- window.scrollBy({ top: rect.bottom - window.innerHeight + PADDING, behavior: "smooth" });
7880
- } else if (rect.top < PADDING) {
7881
- window.scrollBy({ top: rect.top - PADDING, behavior: "smooth" });
7882
- }
7883
- }
7884
- }, []);
7885
- const isComposingRef = react.useRef(false);
7886
- const stateRef = react.useRef(engine.getState());
7887
- const [selectedImagePath, setSelectedImagePath] = react.useState(null);
7888
- const [findReplaceOpen, setFindReplaceOpen] = react.useState(false);
7889
- const [findReplaceMode, setFindReplaceMode] = react.useState("find");
7890
- const [linkPopupOpen, setLinkPopupOpen] = react.useState(false);
7891
- const [isSourceMode, setIsSourceMode] = react.useState(false);
7892
- const [sourceHTML, setSourceHTML] = react.useState("");
7893
- const [editorHeight, setEditorHeight] = react.useState(null);
7894
- const editorRootRef = react.useRef(null);
7895
- const resizeDragRef = react.useRef(null);
7896
- const [linkTooltip, setLinkTooltip] = react.useState(null);
7897
- const linkTooltipTimerRef = react.useRef(null);
7898
- const handleToggleSource = react.useCallback(() => {
7899
- if (!isSourceMode) {
7900
- const html = htmlSerializer.serialize(engine.getState().doc);
7901
- setSourceHTML(prettyPrintHTML(html));
7902
- setIsSourceMode(true);
7903
- } else {
7904
- const newDoc = htmlSerializer.deserialize(sourceHTML);
7905
- const tr = createTransaction();
7906
- tr.steps.push(tr_replaceDoc(newDoc));
7907
- engine.dispatch(tr);
7908
- setIsSourceMode(false);
7909
- }
7910
- }, [isSourceMode, sourceHTML, engine]);
7911
- react.useEffect(() => {
7912
- const onMouseMove = (e) => {
7913
- const drag = resizeDragRef.current;
7914
- if (!drag) return;
7915
- const newHeight = Math.max(120, drag.startHeight + (e.clientY - drag.startY));
7916
- setEditorHeight(newHeight);
7917
- };
7918
- const onMouseUp = () => {
7919
- resizeDragRef.current = null;
7920
- };
7921
- document.addEventListener("mousemove", onMouseMove);
7922
- document.addEventListener("mouseup", onMouseUp);
7923
- return () => {
7924
- document.removeEventListener("mousemove", onMouseMove);
7925
- document.removeEventListener("mouseup", onMouseUp);
7926
- };
7927
- }, []);
7928
- const [tableContextMenu, setTableContextMenu] = react.useState(null);
7929
- const [tableSelection, setTableSelection] = react.useState(null);
7930
- const cellDragRef = react.useRef(null);
7931
- const colResizeRef = react.useRef(null);
7932
- const state = useEditorState(engine);
7933
- const inTableCellPos = state.selection ? findCellPosition(state.doc, state.selection.anchor.path) : null;
7934
- react.useLayoutEffect(() => {
7935
- stateRef.current = state;
7936
- }, [state]);
7937
- react.useLayoutEffect(() => {
7938
- const container = containerRef.current;
7939
- if (!container) return;
7940
- isRenderingRef.current = true;
7941
- renderDocument(state.doc, container);
7942
- if (!container.contains(document.activeElement)) {
7943
- container.focus({ preventScroll: true });
7944
- }
7945
- if (state.selection) {
7946
- restoreSelection(container, state.selection);
7947
- scrollCaretIntoView();
7948
- }
7949
- isRenderingRef.current = false;
7950
- if (onHTMLChange) {
7951
- onHTMLChange(htmlSerializer.serialize(state.doc));
7952
- }
7953
- if (onJSONChange) {
7954
- onJSONChange(jsonSerializer.serialize(state.doc));
7955
- }
7956
- }, [state.doc]);
7957
- react.useLayoutEffect(() => {
7958
- const container = containerRef.current;
7959
- if (!container || !state.selection) return;
7960
- restoreSelection(container, state.selection);
7961
- scrollCaretIntoView();
7962
- }, [state.selection]);
7963
- react.useEffect(() => {
7964
- const container = containerRef.current;
7965
- if (!container || readOnly) return;
7966
- return attachClipboardHandlers(container, engine);
7967
- }, [engine, readOnly]);
7968
- react.useEffect(() => {
7969
- const container = containerRef.current;
7970
- if (!container) return;
7971
- container.querySelectorAll(".editor-cell-selected").forEach((el) => {
7972
- el.classList.remove("editor-cell-selected");
7973
- });
7974
- if (!tableSelection) return;
7975
- const { tablePath, anchorCell, focusCell } = tableSelection;
7976
- const minRow = Math.min(anchorCell[0], focusCell[0]);
7977
- const maxRow = Math.max(anchorCell[0], focusCell[0]);
7978
- const minCol = Math.min(anchorCell[1], focusCell[1]);
7979
- const maxCol = Math.max(anchorCell[1], focusCell[1]);
7980
- for (let r = minRow; r <= maxRow; r++) {
7981
- for (let c = minCol; c <= maxCol; c++) {
7982
- const cellPath = [...tablePath, r, c];
7983
- const td = container.querySelector(
7984
- `[data-block-path="${JSON.stringify(cellPath)}"]`
7985
- );
7986
- if (td) td.classList.add("editor-cell-selected");
7987
- }
7988
- }
7989
- }, [tableSelection, state.doc]);
7990
- react.useEffect(() => {
7991
- const container = containerRef.current;
7992
- if (!container) return;
7993
- container.querySelectorAll(".editor-cell-active").forEach((el) => {
7994
- el.classList.remove("editor-cell-active");
7995
- });
7996
- if (!inTableCellPos) {
7997
- setTableSelection(null);
7998
- return;
7999
- }
8000
- if (tableSelection) {
8001
- const { anchorCell, focusCell, tablePath } = tableSelection;
8002
- const sameTable = JSON.stringify(tablePath) === JSON.stringify(inTableCellPos.tablePath);
8003
- const singleCell = anchorCell[0] === focusCell[0] && anchorCell[1] === focusCell[1];
8004
- if (!sameTable || singleCell) {
8005
- setTableSelection(null);
8006
- }
8007
- }
8008
- const cellPath = [...inTableCellPos.tablePath, inTableCellPos.row, inTableCellPos.col];
8009
- const td = container.querySelector(
8010
- `[data-block-path="${JSON.stringify(cellPath)}"]`
8011
- );
8012
- if (td) td.classList.add("editor-cell-active");
8013
- }, [inTableCellPos, state.doc]);
8014
- react.useEffect(() => {
8015
- const onSelectionChange = () => {
8016
- if (isRenderingRef.current) return;
8017
- const container = containerRef.current;
8018
- if (!container) return;
8019
- if (!isSelectionInContainer(container)) return;
8020
- const captured = captureSelection(container);
8021
- if (!captured) return;
8022
- const currentSelection = engine.getState().selection;
8023
- if (currentSelection && JSON.stringify(currentSelection.anchor) === JSON.stringify(captured.anchor) && JSON.stringify(currentSelection.focus) === JSON.stringify(captured.focus)) {
8024
- return;
8025
- }
8026
- const tr = createTransaction();
8027
- tr.steps.push(tr_setSelection(captured));
8028
- engine.dispatch(tr);
8029
- };
8030
- document.addEventListener(
8031
- "selectionchange",
8032
- onSelectionChange
8033
- );
8034
- return () => {
8035
- document.removeEventListener(
8036
- "selectionchange",
8037
- onSelectionChange
8038
- );
8039
- };
8040
- }, [engine]);
8041
- const handleFocus = react.useCallback(() => {
8042
- const currentState = engine.getState();
8043
- if (!currentState.selection) {
8044
- const tr = createTransaction();
8045
- tr.steps.push(
8046
- tr_setSelection(
8047
- makeCollapsedSelection({ path: [0], offset: 0 })
8048
- )
8049
- );
8050
- engine.dispatch(tr);
8051
- }
8052
- }, [engine]);
8053
- const handleKeyDown = react.useCallback(
8054
- (e) => {
8055
- var _a, _b, _c;
8056
- if (readOnly) return;
8057
- if ((e.ctrlKey || e.metaKey) && e.key === "f") {
8058
- e.preventDefault();
8059
- setFindReplaceMode("find");
8060
- setFindReplaceOpen(true);
8061
- return;
8062
- }
8063
- if ((e.ctrlKey || e.metaKey) && e.key === "h") {
8064
- e.preventDefault();
8065
- setFindReplaceMode("replace");
8066
- setFindReplaceOpen(true);
8067
- return;
8068
- }
8069
- if ((e.ctrlKey || e.metaKey) && e.key === "k") {
8070
- e.preventDefault();
8071
- setLinkPopupOpen(true);
8072
- onOpenLinkPopup == null ? void 0 : onOpenLinkPopup();
8073
- return;
8074
- }
8075
- if ((e.ctrlKey || e.metaKey) && (e.key === "a" || e.key === "A")) {
8076
- e.preventDefault();
8077
- const container = containerRef.current;
8078
- if (container) {
8079
- const spans = container.querySelectorAll("[data-path]");
8080
- const first = spans[0];
8081
- const last = spans[spans.length - 1];
8082
- if (first && last) {
8083
- const sel = window.getSelection();
8084
- const range = document.createRange();
8085
- range.setStart((_a = leafTextNode(first, "first")) != null ? _a : first, 0);
8086
- const lastLeaf = leafTextNode(last, "last");
8087
- range.setEnd(lastLeaf != null ? lastLeaf : last, (_c = (_b = lastLeaf == null ? void 0 : lastLeaf.textContent) == null ? void 0 : _b.length) != null ? _c : 0);
8088
- sel == null ? void 0 : sel.removeAllRanges();
8089
- sel == null ? void 0 : sel.addRange(range);
8090
- }
8091
- }
8092
- return;
8093
- }
8094
- if (selectedImagePath && (e.key === "Delete" || e.key === "Backspace")) {
8095
- e.preventDefault();
8096
- deleteImageAtPath(selectedImagePath)(engine);
8097
- setSelectedImagePath(null);
8098
- return;
8099
- }
8100
- if (selectedImagePath) setSelectedImagePath(null);
8101
- if (e.key === "Tab") {
8102
- const { doc, selection: sel } = engine.getState();
8103
- if (sel) {
8104
- const bp = findContentBlockPath(doc, sel.anchor.path);
8105
- const block = bp ? getNodeAtPath(doc, bp) : null;
8106
- if ((block == null ? void 0 : block.type) === "code_block") {
8107
- e.preventDefault();
8108
- insertText(" ")(engine);
8109
- return;
8110
- }
8111
- if ((block == null ? void 0 : block.type) === "list_item") {
8112
- e.preventDefault();
8113
- if (e.shiftKey) {
8114
- outdentListItem(engine);
8115
- } else {
8116
- indentListItem(engine);
8117
- }
8118
- return;
8119
- }
8120
- if (findCellPosition(doc, sel.anchor.path)) {
8121
- e.preventDefault();
8122
- }
8123
- }
8124
- }
8125
- const handled = engine.handleKeyDown(
8126
- e.nativeEvent
8127
- );
8128
- if (handled) return;
8129
- if (e.key === "Enter" && !e.shiftKey) {
8130
- e.preventDefault();
8131
- handleEnter(engine);
8132
- return;
8133
- }
8134
- if (e.key === "Backspace") {
8135
- e.preventDefault();
8136
- handleBackspace(engine);
8137
- return;
8138
- }
8139
- if (e.key === "Delete") {
8140
- e.preventDefault();
8141
- handleDelete(engine);
8142
- return;
8143
- }
8144
- if (e.key === "Enter" && e.shiftKey) {
8145
- e.preventDefault();
8146
- insertText("\n")(engine);
8147
- return;
8148
- }
8149
- },
8150
- [engine, readOnly, onOpenLinkPopup, selectedImagePath]
8151
- );
8152
- react.useEffect(() => {
8153
- const container = containerRef.current;
8154
- if (!container || readOnly) return;
8155
- const onBeforeInput = (e) => {
8156
- if (e.isComposing || isComposingRef.current) return;
8157
- switch (e.inputType) {
8158
- case "insertText":
8159
- case "insertReplacementText": {
8160
- if (!e.data) return;
8161
- e.preventDefault();
8162
- insertText(e.data)(engine);
8163
- return;
8164
- }
8165
- case "insertParagraph": {
8166
- e.preventDefault();
8167
- handleEnter(engine);
8168
- return;
8169
- }
8170
- case "insertLineBreak": {
8171
- e.preventDefault();
8172
- insertText("\n")(engine);
8173
- return;
8174
- }
8175
- case "deleteContentBackward":
8176
- case "deleteWordBackward":
8177
- case "deleteSoftLineBackward": {
8178
- e.preventDefault();
8179
- handleBackspace(engine);
8180
- return;
8181
- }
8182
- case "insertFromPaste":
8183
- case "insertFromDrop":
8184
- return;
8185
- default:
8186
- e.preventDefault();
8187
- }
8188
- };
8189
- container.addEventListener("beforeinput", onBeforeInput);
8190
- return () => container.removeEventListener("beforeinput", onBeforeInput);
8191
- }, [engine, readOnly]);
8192
- react.useEffect(() => {
8193
- const container = containerRef.current;
8194
- if (!container || readOnly) return;
8195
- const onCompositionStart = () => {
8196
- isComposingRef.current = true;
8197
- };
8198
- const onCompositionEnd = (e) => {
8199
- isComposingRef.current = false;
8200
- if (e.data) insertText(e.data)(engine);
8201
- };
8202
- container.addEventListener("compositionstart", onCompositionStart);
8203
- container.addEventListener("compositionend", onCompositionEnd);
8204
- return () => {
8205
- container.removeEventListener("compositionstart", onCompositionStart);
8206
- container.removeEventListener("compositionend", onCompositionEnd);
8207
- };
8208
- }, [engine, readOnly]);
8209
- react.useEffect(() => {
8210
- const container = containerRef.current;
8211
- if (!container) return;
8212
- const onMouseOver = (e) => {
8213
- var _a;
8214
- const anchor = e.target.closest("a.editor-link");
8215
- if (!anchor) return;
8216
- const href = (_a = anchor.getAttribute("href")) != null ? _a : "";
8217
- if (!href) return;
8218
- if (linkTooltipTimerRef.current) clearTimeout(linkTooltipTimerRef.current);
8219
- linkTooltipTimerRef.current = setTimeout(() => {
8220
- const rect = anchor.getBoundingClientRect();
8221
- const containerRect = container.getBoundingClientRect();
8222
- setLinkTooltip({
8223
- href,
8224
- x: rect.left - containerRect.left,
8225
- y: rect.bottom - containerRect.top + 6
8226
- });
8227
- }, 200);
8228
- };
8229
- const onMouseOut = (e) => {
8230
- const anchor = e.target.closest("a.editor-link");
8231
- if (!anchor) return;
8232
- if (linkTooltipTimerRef.current) clearTimeout(linkTooltipTimerRef.current);
8233
- setLinkTooltip(null);
8234
- };
8235
- const onClick = (e) => {
8236
- if (!(e.ctrlKey || e.metaKey)) return;
8237
- const anchor = e.target.closest("a.editor-link");
8238
- if (!anchor) return;
8239
- e.preventDefault();
8240
- const href = anchor.getAttribute("href");
8241
- if (href) window.open(href, "_blank", "noopener,noreferrer");
8242
- };
8243
- container.addEventListener("mouseover", onMouseOver);
8244
- container.addEventListener("mouseout", onMouseOut);
8245
- container.addEventListener("click", onClick);
8246
- return () => {
8247
- container.removeEventListener("mouseover", onMouseOver);
8248
- container.removeEventListener("mouseout", onMouseOut);
8249
- container.removeEventListener("click", onClick);
8250
- if (linkTooltipTimerRef.current) clearTimeout(linkTooltipTimerRef.current);
8251
- };
8252
- }, []);
8253
- react.useEffect(() => {
8254
- const onMouseMove = (e) => {
8255
- const drag = colResizeRef.current;
8256
- if (!drag) return;
8257
- const delta = e.clientX - drag.startX;
8258
- const newWidth = Math.max(40, drag.startWidth + delta);
8259
- const container = containerRef.current;
8260
- if (container) {
8261
- const colEl = container.querySelector(
8262
- `col[data-col-index="${drag.colIndex}"]`
8263
- );
8264
- if (colEl) colEl.style.width = `${newWidth}px`;
8265
- }
8266
- };
8267
- const onMouseUp = (e) => {
8268
- const drag = colResizeRef.current;
8269
- if (!drag) return;
8270
- const delta = e.clientX - drag.startX;
8271
- const newWidth = Math.max(40, drag.startWidth + delta);
8272
- colResizeRef.current = null;
8273
- setColumnWidth(drag.tablePath, drag.colIndex, newWidth)(engine);
8274
- };
8275
- document.addEventListener("mousemove", onMouseMove);
8276
- document.addEventListener("mouseup", onMouseUp);
8277
- return () => {
8278
- document.removeEventListener("mousemove", onMouseMove);
8279
- document.removeEventListener("mouseup", onMouseUp);
8280
- };
8281
- }, [engine]);
8282
- react.useEffect(() => {
8283
- const onMouseMove = (e) => {
8284
- var _a, _b;
8285
- const drag = cellDragRef.current;
8286
- if (!drag) return;
8287
- const td = e.target.closest("[data-cell-row]");
8288
- if (!td) return;
8289
- const row = parseInt((_a = td.dataset.cellRow) != null ? _a : "0");
8290
- const col = parseInt((_b = td.dataset.cellCol) != null ? _b : "0");
8291
- const tdTablePath = td.dataset.cellTablePath ? JSON.parse(td.dataset.cellTablePath) : null;
8292
- if (!tdTablePath || JSON.stringify(tdTablePath) !== JSON.stringify(drag.tablePath)) return;
8293
- setTableSelection({
8294
- tablePath: drag.tablePath,
8295
- anchorCell: [drag.startRow, drag.startCol],
8296
- focusCell: [row, col]
8297
- });
8298
- };
8299
- const onMouseUp = () => {
8300
- cellDragRef.current = null;
8301
- };
8302
- document.addEventListener("mousemove", onMouseMove);
8303
- document.addEventListener("mouseup", onMouseUp);
8304
- return () => {
8305
- document.removeEventListener("mousemove", onMouseMove);
8306
- document.removeEventListener("mouseup", onMouseUp);
8307
- };
8308
- }, []);
8309
- const handleContextMenu = react.useCallback(
8310
- (e) => {
8311
- var _a, _b, _c, _d, _e, _f;
8312
- const td = e.target.closest("[data-cell-row]");
8313
- if (!td) return;
8314
- e.preventDefault();
8315
- const row = parseInt((_a = td.dataset.cellRow) != null ? _a : "0");
8316
- const col = parseInt((_b = td.dataset.cellCol) != null ? _b : "0");
8317
- const tablePath = td.dataset.cellTablePath ? JSON.parse(td.dataset.cellTablePath) : null;
8318
- if (!tablePath) return;
8319
- const cellNode = getNodeAtPath(
8320
- engine.getState().doc,
8321
- [...tablePath, row, col]
8322
- );
8323
- const isMerged = !!cellNode && (((_d = (_c = cellNode.attrs) == null ? void 0 : _c.colspan) != null ? _d : 1) > 1 || ((_f = (_e = cellNode.attrs) == null ? void 0 : _e.rowspan) != null ? _f : 1) > 1);
8324
- setTableContextMenu({ x: e.clientX, y: e.clientY, tablePath, row, col, isMerged });
8325
- },
8326
- [engine]
8327
- );
8328
- const handleMouseDown = react.useCallback(
8329
- (e) => {
8330
- var _a, _b, _c, _d;
8331
- if (readOnly) return;
8332
- const target = e.target;
8333
- if (target.dataset.resizeImagePath) {
8334
- e.preventDefault();
8335
- const imagePath = JSON.parse(target.dataset.resizeImagePath);
8336
- const corner = (_a = target.dataset.resizeImagePos) != null ? _a : "se";
8337
- const container = containerRef.current;
8338
- let startWidth = 300;
8339
- if (container) {
8340
- const fig2 = container.querySelector(`[data-image-path="${JSON.stringify(imagePath)}"]`);
8341
- const img = fig2 == null ? void 0 : fig2.querySelector("img");
8342
- if (img) startWidth = img.getBoundingClientRect().width || 300;
8343
- }
8344
- imageResizeRef.current = {
8345
- imagePath,
8346
- corner,
8347
- startX: e.clientX,
8348
- startY: e.clientY,
8349
- startWidth,
8350
- startHeight: 0
8351
- };
8352
- return;
8353
- }
8354
- const fig = target.closest("[data-image-path]");
8355
- if (fig == null ? void 0 : fig.dataset.imagePath) {
8356
- e.preventDefault();
8357
- setSelectedImagePath(JSON.parse(fig.dataset.imagePath));
8358
- return;
8359
- }
8360
- setSelectedImagePath(null);
8361
- if (target.dataset.resizeTable) {
8362
- e.preventDefault();
8363
- const tablePath = JSON.parse(target.dataset.resizeTable);
8364
- const colIndex = parseInt((_b = target.dataset.resizeCol) != null ? _b : "0");
8365
- const container = containerRef.current;
8366
- let startWidth = 120;
8367
- if (container) {
8368
- const colEl = container.querySelector(
8369
- `col[data-col-index="${colIndex}"]`
8370
- );
8371
- if (colEl) startWidth = colEl.getBoundingClientRect().width || 120;
8372
- }
8373
- colResizeRef.current = { tablePath, colIndex, startX: e.clientX, startWidth };
8374
- return;
8375
- }
8376
- const td = target.closest("[data-cell-row]");
8377
- if (!td) setTableSelection(null);
8378
- if (td && !readOnly) {
8379
- const row = parseInt((_c = td.dataset.cellRow) != null ? _c : "0");
8380
- const col = parseInt((_d = td.dataset.cellCol) != null ? _d : "0");
8381
- const tdTablePath = td.dataset.cellTablePath ? JSON.parse(td.dataset.cellTablePath) : null;
8382
- if (tdTablePath) {
8383
- cellDragRef.current = { tablePath: tdTablePath, startRow: row, startCol: col };
8384
- setTableSelection({
8385
- tablePath: tdTablePath,
8386
- anchorCell: [row, col],
8387
- focusCell: [row, col]
8388
- });
8389
- }
8390
- }
8391
- const checkTarget = target.dataset.checkPath ? target : target.closest("[data-check-path]");
8392
- if (checkTarget == null ? void 0 : checkTarget.dataset.checkPath) {
8393
- e.preventDefault();
8394
- toggleCheckItemAt(JSON.parse(checkTarget.dataset.checkPath))(engine);
8395
- }
8396
- },
8397
- [engine, readOnly]
8398
- );
8399
- const handleClick = react.useCallback(() => {
8400
- const container = containerRef.current;
8401
- if (!container) return;
8402
- const selection = captureSelection(container);
8403
- if (!selection) return;
8404
- const tr = createTransaction();
8405
- tr.steps.push(
8406
- tr_setSelection(selection)
8407
- );
8408
- engine.dispatch(tr);
8409
- }, [engine]);
8410
- const imageResizeRef = react.useRef(null);
8411
- react.useEffect(() => {
8412
- const onMouseMove = (e) => {
8413
- const drag = imageResizeRef.current;
8414
- if (!drag) return;
8415
- const deltaX = e.clientX - drag.startX;
8416
- const isRight = drag.corner === "ne" || drag.corner === "se";
8417
- const newWidth = Math.max(60, drag.startWidth + (isRight ? deltaX : -deltaX));
8418
- const container = containerRef.current;
8419
- if (container) {
8420
- const fig = container.querySelector(
8421
- `[data-image-path="${JSON.stringify(drag.imagePath)}"]`
8422
- );
8423
- const img = fig == null ? void 0 : fig.querySelector("img");
8424
- if (img) img.style.width = `${newWidth}px`;
8425
- }
8426
- };
8427
- const onMouseUp = (e) => {
8428
- const drag = imageResizeRef.current;
8429
- if (!drag) return;
8430
- const deltaX = e.clientX - drag.startX;
8431
- const isRight = drag.corner === "ne" || drag.corner === "se";
8432
- const newWidth = Math.max(60, drag.startWidth + (isRight ? deltaX : -deltaX));
8433
- imageResizeRef.current = null;
8434
- setImageAttr(drag.imagePath, { width: newWidth })(engine);
8435
- };
8436
- document.addEventListener("mousemove", onMouseMove);
8437
- document.addEventListener("mouseup", onMouseUp);
8438
- return () => {
8439
- document.removeEventListener("mousemove", onMouseMove);
8440
- document.removeEventListener("mouseup", onMouseUp);
8441
- };
8442
- }, [engine]);
8443
- react.useEffect(() => {
8444
- const container = containerRef.current;
8445
- if (!container) return;
8446
- container.querySelectorAll("[data-image-path]").forEach((el) => {
8447
- el.removeAttribute("data-selected");
8448
- });
8449
- if (selectedImagePath) {
8450
- const fig = container.querySelector(
8451
- `[data-image-path="${JSON.stringify(selectedImagePath)}"]`
8452
- );
8453
- if (fig) fig.setAttribute("data-selected", "true");
8454
- }
8455
- }, [selectedImagePath, state.doc]);
8456
- react.useEffect(() => {
8457
- const container = containerRef.current;
8458
- if (!container || readOnly) return;
8459
- const onDragOver = (e) => {
8460
- var _a;
8461
- if ((_a = e.dataTransfer) == null ? void 0 : _a.types.includes("Files")) e.preventDefault();
8462
- };
8463
- const onDrop = (e) => {
8464
- var _a;
8465
- e.preventDefault();
8466
- const file = (_a = e.dataTransfer) == null ? void 0 : _a.files[0];
8467
- if (!file || !file.type.startsWith("image/")) return;
8468
- const blobUrl = URL.createObjectURL(file);
8469
- insertImage(blobUrl, file.name.replace(/\.[^.]+$/, ""))(engine);
8470
- };
8471
- container.addEventListener("dragover", onDragOver);
8472
- container.addEventListener("drop", onDrop);
8473
- return () => {
8474
- container.removeEventListener("dragover", onDragOver);
8475
- container.removeEventListener("drop", onDrop);
8476
- };
8477
- }, [engine, readOnly]);
8478
- const isVisualEmpty = state.doc.children.length === 1 && state.doc.children[0].type === "paragraph" && state.doc.children[0].children.length === 0;
8479
- return /* @__PURE__ */ jsxRuntime.jsxs(
8480
- "div",
8481
- {
8482
- ref: editorRootRef,
8483
- className: `editor-root relative flex flex-col ${className}`,
8484
- style: editorHeight ? { minHeight: editorHeight } : void 0,
8485
- children: [
8486
- !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
8487
- Toolbar,
8488
- {
8489
- engine,
8490
- onFindReplace: (mode) => {
8491
- setFindReplaceMode(mode);
8492
- setFindReplaceOpen(true);
8493
- },
8494
- linkPopupOpen,
8495
- onLinkPopupClose: () => setLinkPopupOpen(false),
8496
- isSourceMode,
8497
- onToggleSource: handleToggleSource
8498
- }
8499
- ),
8500
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: isSourceMode ? /* @__PURE__ */ jsxRuntime.jsx(
8501
- "textarea",
8502
- {
8503
- "aria-label": "HTML source editor",
8504
- value: sourceHTML,
8505
- onChange: (e) => {
8506
- setSourceHTML(e.target.value);
8507
- const t = e.target;
8508
- t.style.height = "auto";
8509
- t.style.height = t.scrollHeight + "px";
8510
- },
8511
- ref: (el) => {
8512
- if (el) {
8513
- el.style.height = "auto";
8514
- el.style.height = el.scrollHeight + "px";
8515
- }
8516
- },
8517
- spellCheck: false,
8518
- className: "w-full block px-6 py-4 font-mono text-sm leading-relaxed bg-gray-950 text-green-300 outline-none resize-none border-0 overflow-hidden"
8519
- }
8520
- ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8521
- isVisualEmpty && /* @__PURE__ */ jsxRuntime.jsx(
8522
- "div",
8523
- {
8524
- className: "\r\n absolute\r\n top-6\r\n left-6\r\n pointer-events-none\r\n select-none\r\n text-base\r\n text-gray-400\r\n dark:text-gray-500\r\n ",
8525
- "aria-hidden": "true",
8526
- children: placeholder
8527
- }
8528
- ),
8529
- /* @__PURE__ */ jsxRuntime.jsx(
8530
- "div",
8531
- {
8532
- ref: containerRef,
8533
- contentEditable: !readOnly,
8534
- suppressContentEditableWarning: true,
8535
- role: "textbox",
8536
- "aria-multiline": "true",
8537
- "aria-label": "Rich text editor",
8538
- spellCheck: true,
8539
- onMouseDown: handleMouseDown,
8540
- onContextMenu: handleContextMenu,
8541
- onFocus: handleFocus,
8542
- onClick: handleClick,
8543
- onKeyDown: handleKeyDown,
8544
- className: [
8545
- "editor-canvas",
8546
- "min-h-[300px]",
8547
- "px-6",
8548
- "py-4",
8549
- "outline-none",
8550
- "text-base",
8551
- "leading-relaxed",
8552
- "text-gray-900",
8553
- "dark:text-gray-100",
8554
- readOnly ? "cursor-default" : "cursor-text"
8555
- ].join(" ")
8556
- }
8557
- ),
8558
- linkTooltip && /* @__PURE__ */ jsxRuntime.jsxs(
8559
- "div",
8560
- {
8561
- role: "tooltip",
8562
- style: { left: linkTooltip.x, top: linkTooltip.y },
8563
- className: "absolute z-50 pointer-events-none flex items-center gap-1.5 bg-gray-900 dark:bg-gray-700 text-white text-xs px-2.5 py-1.5 rounded shadow-lg max-w-xs",
8564
- children: [
8565
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "11", height: "11", viewBox: "0 0 16 16", fill: "none", className: "shrink-0 opacity-70", "aria-hidden": "true", children: [
8566
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.5 3.5H4A2.5 2.5 0 0 0 4 8.5h2", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" }),
8567
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.5 3.5H12A2.5 2.5 0 0 1 12 8.5h-2", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" }),
8568
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.5 6h5", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" })
8569
- ] }),
8570
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: linkTooltip.href }),
8571
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 opacity-50 ml-1", children: "Ctrl+click to open" })
8572
- ]
8573
- }
8574
- )
8575
- ] }) }),
8576
- inTableCellPos && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
8577
- TableToolbar,
8578
- {
8579
- engine,
8580
- tablePath: inTableCellPos.tablePath,
8581
- cellPos: { row: inTableCellPos.row, col: inTableCellPos.col },
8582
- tableSelection,
8583
- editorContainer: containerRef
8584
- }
8585
- ),
8586
- tableContextMenu && /* @__PURE__ */ jsxRuntime.jsx(
8587
- TableContextMenu,
8588
- {
8589
- x: tableContextMenu.x,
8590
- y: tableContextMenu.y,
8591
- tablePath: tableContextMenu.tablePath,
8592
- row: tableContextMenu.row,
8593
- col: tableContextMenu.col,
8594
- isMerged: tableContextMenu.isMerged,
8595
- tableSelection,
8596
- engine,
8597
- onClose: () => setTableContextMenu(null)
8598
- }
8599
- ),
8600
- findReplaceOpen && /* @__PURE__ */ jsxRuntime.jsx(
8601
- FindReplaceModal,
8602
- {
8603
- engine,
8604
- editorContainer: containerRef,
8605
- initialMode: findReplaceMode,
8606
- onClose: () => setFindReplaceOpen(false)
8607
- }
8608
- ),
8609
- selectedImagePath && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
8610
- ImageToolbar,
8611
- {
8612
- engine,
8613
- imagePath: selectedImagePath,
8614
- editorContainer: containerRef,
8615
- onClose: () => setSelectedImagePath(null)
8616
- }
8617
- ),
8618
- !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
8619
- "div",
8620
- {
8621
- title: "Drag to resize",
8622
- onMouseDown: (e) => {
8623
- e.preventDefault();
8624
- const rootEl = editorRootRef.current;
8625
- if (!rootEl) return;
8626
- resizeDragRef.current = {
8627
- startY: e.clientY,
8628
- startHeight: rootEl.getBoundingClientRect().height
8629
- };
8630
- },
8631
- className: "absolute bottom-0 right-0 w-4 h-4 cursor-s-resize flex items-end justify-end pr-0.5 pb-0.5 select-none",
8632
- "aria-hidden": "true",
8633
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 1L1 7M7 4L4 7M7 7L7 7", stroke: "#9ca3af", strokeWidth: "1.2", strokeLinecap: "round" }) })
8634
- }
8635
- )
8636
- ]
8637
- }
8638
- );
8639
- }
8640
- var BLOCK_TAGS = "p|h[1-6]|ul|ol|li|blockquote|pre|figure|table|thead|tbody|tr|th|td";
8641
- var _OPEN_ONLY_RE = new RegExp(`^<(${BLOCK_TAGS})(?:\\s[^>]*)?>$`, "i");
8642
- var _CLOSE_ONLY_RE = new RegExp(`^<\\/(${BLOCK_TAGS})>$`, "i");
8643
- var _HR_RE = /^<hr(\s[^>]*)?\/?>$/i;
8644
- function leafTextNode(el, end) {
8645
- let node = el;
8646
- while (node.hasChildNodes()) {
8647
- node = end === "first" ? node.firstChild : node.lastChild;
8648
- }
8649
- return node.nodeType === Node.TEXT_NODE ? node : null;
8650
- }
8651
- function prettyPrintHTML(html) {
8652
- const blockOpen = new RegExp(`(<(?:${BLOCK_TAGS})(?:\\s[^>]*)?>)`, "gi");
8653
- const blockClose = new RegExp(`(<\\/(?:${BLOCK_TAGS})>)`, "gi");
8654
- const spread = html.replace(blockOpen, "\n$1").replace(blockClose, "$1\n").replace(/<hr(\s[^>]*)?\/?>(\s*)/gi, "\n<hr />\n");
8655
- let depth = 0;
8656
- const result = [];
8657
- for (const raw of spread.split("\n")) {
8658
- const line = raw.trim();
8659
- if (!line) continue;
8660
- if (_HR_RE.test(line)) {
8661
- result.push(" ".repeat(depth) + line);
8662
- continue;
8663
- }
8664
- if (_CLOSE_ONLY_RE.test(line)) {
8665
- depth = Math.max(0, depth - 1);
8666
- result.push(" ".repeat(depth) + line);
8667
- continue;
8668
- }
8669
- if (_OPEN_ONLY_RE.test(line)) {
8670
- result.push(" ".repeat(depth) + line);
8671
- depth++;
8672
- continue;
8673
- }
8674
- result.push(" ".repeat(depth) + line);
8675
- }
8676
- return result.join("\n");
8677
- }
8678
7836
  function EditorCore({
8679
7837
  engine,
8680
7838
  placeholder = "Start writing...",
@@ -8691,6 +7849,7 @@ function EditorCore({
8691
7849
  }) {
8692
7850
  const containerRef = react.useRef(null);
8693
7851
  const isRenderingRef = react.useRef(false);
7852
+ const skipRestoreSelectionRef = react.useRef(false);
8694
7853
  const scrollCaretIntoView = react.useCallback(() => {
8695
7854
  var _a, _b;
8696
7855
  const sel = window.getSelection();
@@ -8744,7 +7903,7 @@ function EditorCore({
8744
7903
  const handleToggleSource = react.useCallback(() => {
8745
7904
  if (!isSourceMode) {
8746
7905
  const html = htmlSerializer.serialize(engine.getState().doc);
8747
- setSourceHTML(prettyPrintHTML2(html));
7906
+ setSourceHTML(prettyPrintHTML(html));
8748
7907
  setIsSourceMode(true);
8749
7908
  } else {
8750
7909
  const newDoc = htmlSerializer.deserialize(sourceHTML);
@@ -8803,8 +7962,14 @@ function EditorCore({
8803
7962
  react.useLayoutEffect(() => {
8804
7963
  const container = containerRef.current;
8805
7964
  if (!container || !state.selection) return;
7965
+ if (skipRestoreSelectionRef.current) {
7966
+ skipRestoreSelectionRef.current = false;
7967
+ return;
7968
+ }
7969
+ isRenderingRef.current = true;
8806
7970
  restoreSelection(container, state.selection);
8807
7971
  scrollCaretIntoView();
7972
+ isRenderingRef.current = false;
8808
7973
  }, [state.selection]);
8809
7974
  react.useEffect(() => {
8810
7975
  const container = containerRef.current;
@@ -8869,6 +8034,7 @@ function EditorCore({
8869
8034
  if (currentSelection && JSON.stringify(currentSelection.anchor) === JSON.stringify(captured.anchor) && JSON.stringify(currentSelection.focus) === JSON.stringify(captured.focus)) {
8870
8035
  return;
8871
8036
  }
8037
+ skipRestoreSelectionRef.current = true;
8872
8038
  const tr = createTransaction();
8873
8039
  tr.steps.push(tr_setSelection(captured));
8874
8040
  engine.dispatch(tr);
@@ -8932,8 +8098,8 @@ function EditorCore({
8932
8098
  if (first && last) {
8933
8099
  const sel = window.getSelection();
8934
8100
  const range = document.createRange();
8935
- range.setStart((_a = leafTextNode2(first, "first")) != null ? _a : first, 0);
8936
- const lastLeaf = leafTextNode2(last, "last");
8101
+ range.setStart((_a = leafTextNode(first, "first")) != null ? _a : first, 0);
8102
+ const lastLeaf = leafTextNode(last, "last");
8937
8103
  range.setEnd(lastLeaf != null ? lastLeaf : last, (_c = (_b = lastLeaf == null ? void 0 : lastLeaf.textContent) == null ? void 0 : _b.length) != null ? _c : 0);
8938
8104
  sel == null ? void 0 : sel.removeAllRanges();
8939
8105
  sel == null ? void 0 : sel.addRange(range);
@@ -9251,10 +8417,9 @@ function EditorCore({
9251
8417
  if (!container) return;
9252
8418
  const selection = captureSelection(container);
9253
8419
  if (!selection) return;
8420
+ skipRestoreSelectionRef.current = true;
9254
8421
  const tr = createTransaction();
9255
- tr.steps.push(
9256
- tr_setSelection(selection)
9257
- );
8422
+ tr.steps.push(tr_setSelection(selection));
9258
8423
  engine.dispatch(tr);
9259
8424
  }, [engine]);
9260
8425
  const imageResizeRef = react.useRef(null);
@@ -9489,36 +8654,36 @@ function EditorCore({
9489
8654
  }
9490
8655
  );
9491
8656
  }
9492
- var BLOCK_TAGS2 = "p|h[1-6]|ul|ol|li|blockquote|pre|figure|table|thead|tbody|tr|th|td";
9493
- var _OPEN_ONLY_RE2 = new RegExp(`^<(${BLOCK_TAGS2})(?:\\s[^>]*)?>$`, "i");
9494
- var _CLOSE_ONLY_RE2 = new RegExp(`^<\\/(${BLOCK_TAGS2})>$`, "i");
9495
- var _HR_RE2 = /^<hr(\s[^>]*)?\/?>$/i;
9496
- function leafTextNode2(el, end) {
8657
+ var BLOCK_TAGS = "p|h[1-6]|ul|ol|li|blockquote|pre|figure|table|thead|tbody|tr|th|td";
8658
+ var _OPEN_ONLY_RE = new RegExp(`^<(${BLOCK_TAGS})(?:\\s[^>]*)?>$`, "i");
8659
+ var _CLOSE_ONLY_RE = new RegExp(`^<\\/(${BLOCK_TAGS})>$`, "i");
8660
+ var _HR_RE = /^<hr(\s[^>]*)?\/?>$/i;
8661
+ function leafTextNode(el, end) {
9497
8662
  let node = el;
9498
8663
  while (node.hasChildNodes()) {
9499
8664
  node = end === "first" ? node.firstChild : node.lastChild;
9500
8665
  }
9501
8666
  return node.nodeType === Node.TEXT_NODE ? node : null;
9502
8667
  }
9503
- function prettyPrintHTML2(html) {
9504
- const blockOpen = new RegExp(`(<(?:${BLOCK_TAGS2})(?:\\s[^>]*)?>)`, "gi");
9505
- const blockClose = new RegExp(`(<\\/(?:${BLOCK_TAGS2})>)`, "gi");
8668
+ function prettyPrintHTML(html) {
8669
+ const blockOpen = new RegExp(`(<(?:${BLOCK_TAGS})(?:\\s[^>]*)?>)`, "gi");
8670
+ const blockClose = new RegExp(`(<\\/(?:${BLOCK_TAGS})>)`, "gi");
9506
8671
  const spread = html.replace(blockOpen, "\n$1").replace(blockClose, "$1\n").replace(/<hr(\s[^>]*)?\/?>(\s*)/gi, "\n<hr />\n");
9507
8672
  let depth = 0;
9508
8673
  const result = [];
9509
8674
  for (const raw of spread.split("\n")) {
9510
8675
  const line = raw.trim();
9511
8676
  if (!line) continue;
9512
- if (_HR_RE2.test(line)) {
8677
+ if (_HR_RE.test(line)) {
9513
8678
  result.push(" ".repeat(depth) + line);
9514
8679
  continue;
9515
8680
  }
9516
- if (_CLOSE_ONLY_RE2.test(line)) {
8681
+ if (_CLOSE_ONLY_RE.test(line)) {
9517
8682
  depth = Math.max(0, depth - 1);
9518
8683
  result.push(" ".repeat(depth) + line);
9519
8684
  continue;
9520
8685
  }
9521
- if (_OPEN_ONLY_RE2.test(line)) {
8686
+ if (_OPEN_ONLY_RE.test(line)) {
9522
8687
  result.push(" ".repeat(depth) + line);
9523
8688
  depth++;
9524
8689
  continue;
@@ -9990,6 +9155,117 @@ function execCommand(engine, command, ...args) {
9990
9155
  function registerCommand(name, fn) {
9991
9156
  REGISTRY[name] = fn;
9992
9157
  }
9158
+ var Editor = react.forwardRef(function Editor2({
9159
+ value,
9160
+ onChange,
9161
+ defaultValue,
9162
+ toolbar,
9163
+ theme: _theme,
9164
+ placeholder = "Start writing...",
9165
+ className = "",
9166
+ style,
9167
+ minHeight,
9168
+ maxHeight,
9169
+ readOnly = false,
9170
+ plugins,
9171
+ onFocus,
9172
+ onBlur,
9173
+ onReady,
9174
+ onUploadImage
9175
+ }, ref) {
9176
+ const engine = useEditorEngine();
9177
+ const pluginsRegisteredRef = react.useRef(false);
9178
+ if (!pluginsRegisteredRef.current && (plugins == null ? void 0 : plugins.length)) {
9179
+ pluginsRegisteredRef.current = true;
9180
+ for (const plugin of plugins) {
9181
+ engine.registerPlugin(plugin);
9182
+ }
9183
+ }
9184
+ const defaultLoadedRef = react.useRef(false);
9185
+ react.useEffect(() => {
9186
+ if (defaultLoadedRef.current) return;
9187
+ defaultLoadedRef.current = true;
9188
+ if (defaultValue) {
9189
+ const doc = htmlSerializer.deserialize(defaultValue);
9190
+ const tr = createTransaction();
9191
+ tr.steps.push(tr_replaceDoc(doc));
9192
+ engine.dispatch(tr);
9193
+ }
9194
+ }, []);
9195
+ const lastExternalValueRef = react.useRef(void 0);
9196
+ react.useEffect(() => {
9197
+ if (value === void 0) return;
9198
+ if (value === lastExternalValueRef.current) return;
9199
+ lastExternalValueRef.current = value;
9200
+ const doc = htmlSerializer.deserialize(value);
9201
+ const tr = createTransaction();
9202
+ tr.steps.push(tr_replaceDoc(doc));
9203
+ engine.dispatch(tr);
9204
+ }, [value, engine]);
9205
+ const api = {
9206
+ getHTML: () => htmlSerializer.serialize(engine.getState().doc),
9207
+ setHTML: (html) => {
9208
+ const doc = htmlSerializer.deserialize(html);
9209
+ const tr = createTransaction();
9210
+ tr.steps.push(tr_replaceDoc(doc));
9211
+ engine.dispatch(tr);
9212
+ },
9213
+ getJSON: () => engine.getState().doc,
9214
+ getMarkdown: () => markdownSerializer.serialize(engine.getState().doc),
9215
+ focus: () => {
9216
+ const el = document.querySelector('[role="textbox"]');
9217
+ el == null ? void 0 : el.focus();
9218
+ },
9219
+ blur: () => {
9220
+ const el = document.querySelector('[role="textbox"]');
9221
+ el == null ? void 0 : el.blur();
9222
+ },
9223
+ clear: () => {
9224
+ const doc = htmlSerializer.deserialize("");
9225
+ const tr = createTransaction();
9226
+ tr.steps.push(tr_replaceDoc(doc));
9227
+ engine.dispatch(tr);
9228
+ },
9229
+ undo: () => undo(engine),
9230
+ redo: () => redo(engine),
9231
+ execCommand: (command, ...args) => execCommand(engine, command, ...args),
9232
+ registerCommand: (name, fn) => registerCommand(name, fn),
9233
+ getEngine: () => engine
9234
+ };
9235
+ react.useImperativeHandle(ref, () => api);
9236
+ react.useEffect(() => {
9237
+ onReady == null ? void 0 : onReady(api);
9238
+ }, []);
9239
+ const containerStyle = { ...style };
9240
+ if (minHeight !== void 0) {
9241
+ containerStyle.minHeight = typeof minHeight === "number" ? `${minHeight}px` : minHeight;
9242
+ }
9243
+ if (maxHeight !== void 0) {
9244
+ containerStyle.maxHeight = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
9245
+ containerStyle.overflow = "auto";
9246
+ }
9247
+ const hideToolbar = toolbar === false;
9248
+ const toolbarConfig = toolbar === false || toolbar === void 0 ? void 0 : Array.isArray(toolbar) ? toolbar : void 0;
9249
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
9250
+ EditorCore,
9251
+ {
9252
+ engine,
9253
+ placeholder,
9254
+ className,
9255
+ readOnly,
9256
+ onHTMLChange: (html) => {
9257
+ lastExternalValueRef.current = html;
9258
+ onChange == null ? void 0 : onChange(html);
9259
+ },
9260
+ onFocus,
9261
+ onBlur,
9262
+ hideToolbar,
9263
+ toolbarConfig,
9264
+ onUploadImage
9265
+ }
9266
+ ) });
9267
+ });
9268
+ Editor.displayName = "Editor";
9993
9269
 
9994
9270
  exports.BASIC_TOOLBAR = BASIC_TOOLBAR;
9995
9271
  exports.DEFAULT_TOOLBAR = DEFAULT_TOOLBAR;