@haklex/rich-editor 0.0.33 → 0.0.35

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.
@@ -12,10 +12,10 @@ import { ListPlugin } from "@lexical/react/LexicalListPlugin";
12
12
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
13
13
  import { TabIndentationPlugin } from "@lexical/react/LexicalTabIndentationPlugin";
14
14
  import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
15
- import { Q as $isAlertQuoteNode, d as RendererWrapper, S as AlertRenderer, T as SpoilerNode, U as MentionNode, V as FootnoteNode, H as KaTeXInlineNode, W as AlertQuoteNode, f as editorTheme, X as $isBannerNode, Y as BannerRenderer, Z as BannerNode, _ as normalizeBannerType, a0 as $isCodeBlockNode, a1 as CodeBlockRenderer, a2 as CodeBlockNode, i as useFootnoteDefinitions, D as FootnoteSectionNode, s as $isGridContainerNode, G as GridContainerNode, b as builtinNodes, K as KaTeXBlockNode, a3 as ImageNode, a4 as VideoNode, L as LinkCardNode, a5 as DetailsNode, M as MermaidNode, F as FootnoteDefinitionsProvider, a6 as $createImageNode, a7 as $createKaTeXInlineNode, a8 as $createKaTeXBlockNode, a9 as $createDetailsNode, aa as $createFootnoteNode, r as $isFootnoteSectionNode, $ as $createFootnoteSectionNode, ab as $createMentionNode, g as extractTextContent, ac as $createSpoilerNode, q as $createMermaidNode, C as ColorSchemeProvider, R as RendererConfigProvider } from "./theme-C_ic3l9g.js";
16
- import { $getNodeByKey, $insertNodes, createEditor, $nodesOfType, $getRoot, createCommand, COMMAND_PRIORITY_EDITOR, $parseSerializedNode, $getSelection, $isRangeSelection, $createParagraphNode, $createTextNode, KEY_ENTER_COMMAND, COMMAND_PRIORITY_HIGH } from "lexical";
17
- import { Info, Lightbulb, TriangleAlert, Flag, LayoutGrid, Plus, Minus } from "lucide-react";
18
- import { useCallback, createElement, useState, useEffect, useRef } from "react";
15
+ import { V as $isAlertQuoteNode, d as RendererWrapper, W as AlertRenderer, X as SpoilerNode, Y as MentionNode, Z as FootnoteNode, L as KaTeXInlineNode, _ as AlertQuoteNode, f as editorTheme, a0 as $isBannerNode, a1 as BannerRenderer, a2 as BannerNode, a3 as normalizeBannerType, a4 as $isCodeBlockNode, a5 as CodeBlockRenderer, a6 as CodeBlockNode, i as useFootnoteDefinitions, G as FootnoteSectionNode, t as $isGridContainerNode, I as GridContainerNode, b as builtinNodes, K as KaTeXBlockNode, J as ImageNode, a7 as VideoNode, O as LinkCardNode, a8 as DetailsNode, Q as MermaidNode, F as FootnoteDefinitionsProvider, p as $createImageNode, T as computeImageMeta, S as OPEN_IMAGE_UPLOAD_DIALOG_COMMAND, a9 as $createKaTeXInlineNode, aa as $createKaTeXBlockNode, ab as $createDetailsNode, ac as $createFootnoteNode, s as $isFootnoteSectionNode, $ as $createFootnoteSectionNode, ad as $createMentionNode, g as extractTextContent, ae as $createSpoilerNode, r as $createMermaidNode, C as ColorSchemeProvider, R as RendererConfigProvider } from "./theme-DOLFsBRg.js";
16
+ import { $getNodeByKey, $insertNodes, createEditor, $nodesOfType, $getRoot, createCommand, COMMAND_PRIORITY_EDITOR, $parseSerializedNode, $getSelection, $isRangeSelection, $createParagraphNode, COMMAND_PRIORITY_HIGH, PASTE_COMMAND, $createTextNode, KEY_ENTER_COMMAND } from "lexical";
17
+ import { Info, Lightbulb, TriangleAlert, Flag, LayoutGrid, Plus, Minus, Check, Upload, Link2 } from "lucide-react";
18
+ import { useCallback, createElement, useState, useEffect, createContext, use, useRef, useMemo } from "react";
19
19
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
20
20
  import { ContentEditable as ContentEditable$1 } from "@lexical/react/LexicalContentEditable";
21
21
  import { LexicalNestedComposer } from "@lexical/react/LexicalNestedComposer";
@@ -23,12 +23,13 @@ import { CodeNode } from "@lexical/code";
23
23
  import { HorizontalRuleNode, INSERT_HORIZONTAL_RULE_COMMAND, $createHorizontalRuleNode } from "@lexical/extension";
24
24
  import { LinkNode, AutoLinkNode, createLinkMatcherWithRegExp, registerAutoLink } from "@lexical/link";
25
25
  import { ListNode, ListItemNode } from "@lexical/list";
26
- import { HeadingNode, QuoteNode } from "@lexical/rich-text";
26
+ import { HeadingNode, QuoteNode, DRAG_DROP_PASTE } from "@lexical/rich-text";
27
27
  import { TableNode, TableCellNode, TableRowNode } from "@lexical/table";
28
+ import { Dialog, DialogPopup, DialogTitle, SegmentedControl } from "@haklex/rich-editor-ui";
29
+ import { b as clsx, g as getVariantClass } from "./utils-fpeaZV1R.js";
28
30
  import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
29
31
  import { CHECK_LIST, TRANSFORMERS } from "@lexical/markdown";
30
32
  import { GIT_ALERT_TRANSFORMER as GIT_ALERT_TRANSFORMER$1, CONTAINER_TRANSFORMER as CONTAINER_TRANSFORMER$1, FOOTNOTE_TRANSFORMER as FOOTNOTE_TRANSFORMER$1, FOOTNOTE_SECTION_TRANSFORMER as FOOTNOTE_SECTION_TRANSFORMER$1, KATEX_INLINE_TRANSFORMER as KATEX_INLINE_TRANSFORMER$1, KATEX_BLOCK_TRANSFORMER as KATEX_BLOCK_TRANSFORMER$1, MENTION_TRANSFORMER as MENTION_TRANSFORMER$1, SPOILER_TRANSFORMER as SPOILER_TRANSFORMER$1, INSERT_TRANSFORMER, SUPERSCRIPT_TRANSFORMER, SUBSCRIPT_TRANSFORMER, IMAGE_BLOCK_TRANSFORMER, VIDEO_BLOCK_TRANSFORMER, CODE_BLOCK_NODE_TRANSFORMER, LINK_CARD_BLOCK_TRANSFORMER, MERMAID_BLOCK_TRANSFORMER, HORIZONTAL_RULE_BLOCK_TRANSFORMER, TABLE_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
31
- import { b as clsx, g as getVariantClass } from "./utils-fpeaZV1R.js";
32
33
  function AlertEditDecorator({
33
34
  nodeKey,
34
35
  alertType,
@@ -807,6 +808,16 @@ const allEditNodes = [
807
808
  ...builtinNodes,
808
809
  ...customEditNodes
809
810
  ];
811
+ const ImageUploadContext = createContext(null);
812
+ function ImageUploadProvider({
813
+ upload,
814
+ children
815
+ }) {
816
+ return /* @__PURE__ */ jsx(ImageUploadContext.Provider, { value: upload, children });
817
+ }
818
+ function useImageUpload() {
819
+ return use(ImageUploadContext);
820
+ }
810
821
  let _resolvedEditNodes = null;
811
822
  function setResolvedEditNodes(nodes) {
812
823
  _resolvedEditNodes = nodes;
@@ -1003,6 +1014,480 @@ function ImagePlugin() {
1003
1014
  }, [editor]);
1004
1015
  return null;
1005
1016
  }
1017
+ var draggingWrapperClass = "rich-image-upload-dragging";
1018
+ var toastStack = "_1x58dbf1";
1019
+ var toast = "_1x58dbf2";
1020
+ var toastVariant = { info: "_1x58dbf3", success: "_1x58dbf4", error: "_1x58dbf5" };
1021
+ var spinner = "_1x58dbf7";
1022
+ var dialogPopup = "_1x58dbf8";
1023
+ var dialogHeader = "_1x58dbf9";
1024
+ var dialogTitle = "_1x58dbfa";
1025
+ var dialogBody = "_1x58dbfb";
1026
+ var tabWrap = "_1x58dbfc";
1027
+ var uploadDropzone = "_1x58dbfd";
1028
+ var uploadDropzoneState = { idle: "_1x58dbfe", active: "_1x58dbff", busy: "_1x58dbfg" };
1029
+ var uploadDropIcon = "_1x58dbfh";
1030
+ var uploadDropTitle = "_1x58dbfi";
1031
+ var uploadDropDesc = "_1x58dbfj";
1032
+ var hiddenInput = "_1x58dbfk";
1033
+ var uploadBusyWrap = "_1x58dbfl";
1034
+ var uploadProgress = "_1x58dbfm";
1035
+ var urlInputRow = "_1x58dbfn";
1036
+ var textInput = "_1x58dbfo";
1037
+ var actionButton = "_1x58dbfq _1x58dbfp";
1038
+ var secondaryButton = "_1x58dbfr _1x58dbfp";
1039
+ var urlPreview = "_1x58dbfs";
1040
+ var urlPreviewImage = "_1x58dbft";
1041
+ var helperText = "_1x58dbfu";
1042
+ var dialogFooter = "_1x58dbfv";
1043
+ var dialogFooterActions = "_1x58dbfw";
1044
+ function isImageFile(file) {
1045
+ return file.type.startsWith("image/");
1046
+ }
1047
+ function hasImageData(dataTransfer) {
1048
+ if (!dataTransfer) return false;
1049
+ if (Array.from(dataTransfer.files).some(isImageFile)) return true;
1050
+ return Array.from(dataTransfer.items).some(
1051
+ (item) => item.type.startsWith("image/")
1052
+ );
1053
+ }
1054
+ function isSafeImageUrl(url) {
1055
+ return !/^(?:javascript\s*:|vbscript\s*:|data\s*:(?!image\/))/i.test(url);
1056
+ }
1057
+ function loadImageByUrl(src) {
1058
+ return new Promise((resolve, reject) => {
1059
+ const image = new Image();
1060
+ image.onload = () => {
1061
+ resolve({
1062
+ width: image.naturalWidth || image.width,
1063
+ height: image.naturalHeight || image.height
1064
+ });
1065
+ };
1066
+ image.onerror = () => reject(new Error("Failed to load image"));
1067
+ image.src = src;
1068
+ });
1069
+ }
1070
+ function readAsDataUrl(file) {
1071
+ return new Promise((resolve, reject) => {
1072
+ const reader = new FileReader();
1073
+ reader.onload = () => resolve(String(reader.result));
1074
+ reader.onerror = () => reject(reader.error ?? new Error("File read failed"));
1075
+ reader.readAsDataURL(file);
1076
+ });
1077
+ }
1078
+ async function defaultImageUpload(file) {
1079
+ return {
1080
+ src: await readAsDataUrl(file),
1081
+ altText: file.name
1082
+ };
1083
+ }
1084
+ function ImageUploadPlugin({ onUpload }) {
1085
+ const [editor] = useLexicalComposerContext();
1086
+ const uploadRef = useRef(onUpload);
1087
+ uploadRef.current = onUpload;
1088
+ const fileInputRef = useRef(null);
1089
+ const toastTimerRef = useRef(null);
1090
+ const [dialogOpen, setDialogOpen] = useState(false);
1091
+ const [tab, setTab] = useState("upload");
1092
+ const [rootDragActive, setRootDragActive] = useState(false);
1093
+ const [dialogDragActive, setDialogDragActive] = useState(false);
1094
+ const [pendingUploads, setPendingUploads] = useState(0);
1095
+ const [dialogUploading, setDialogUploading] = useState(false);
1096
+ const [toast$1, setToast] = useState(null);
1097
+ const [urlInput, setUrlInput] = useState("");
1098
+ const [urlPreview$1, setUrlPreview] = useState(null);
1099
+ const [urlMeta, setUrlMeta] = useState(null);
1100
+ const [urlLoading, setUrlLoading] = useState(false);
1101
+ const [urlError, setUrlError] = useState(null);
1102
+ const tabItems = useMemo(
1103
+ () => [
1104
+ { value: "upload", label: "Upload" },
1105
+ { value: "url", label: "URL" }
1106
+ ],
1107
+ []
1108
+ );
1109
+ const pushToast = useCallback(
1110
+ (kind, message) => {
1111
+ setToast({ kind, message });
1112
+ if (toastTimerRef.current) {
1113
+ window.clearTimeout(toastTimerRef.current);
1114
+ }
1115
+ toastTimerRef.current = window.setTimeout(() => setToast(null), 2200);
1116
+ },
1117
+ []
1118
+ );
1119
+ const insertByUpload = useCallback(
1120
+ async (file, options) => {
1121
+ if (!isImageFile(file)) return false;
1122
+ const closeDialog = Boolean(options?.closeDialog);
1123
+ setPendingUploads((value) => value + 1);
1124
+ if (closeDialog) setDialogUploading(true);
1125
+ try {
1126
+ const [result, meta] = await Promise.all([
1127
+ uploadRef.current(file),
1128
+ computeImageMeta(file)
1129
+ ]);
1130
+ editor.update(() => {
1131
+ const node = $createImageNode({
1132
+ src: result.src,
1133
+ altText: result.altText ?? file.name,
1134
+ width: result.width ?? meta.width,
1135
+ height: result.height ?? meta.height,
1136
+ thumbhash: result.thumbhash ?? meta.thumbhash
1137
+ });
1138
+ $insertNodes([node]);
1139
+ });
1140
+ if (closeDialog) {
1141
+ setDialogOpen(false);
1142
+ setUrlInput("");
1143
+ setUrlPreview(null);
1144
+ setUrlMeta(null);
1145
+ setUrlError(null);
1146
+ }
1147
+ pushToast("success", "Image uploaded");
1148
+ return true;
1149
+ } catch (err) {
1150
+ console.error("[ImageUploadPlugin]", err);
1151
+ pushToast("error", "Image upload failed");
1152
+ return false;
1153
+ } finally {
1154
+ setPendingUploads((value) => Math.max(value - 1, 0));
1155
+ setDialogUploading(false);
1156
+ }
1157
+ },
1158
+ [editor, pushToast]
1159
+ );
1160
+ const handleFiles = useCallback(
1161
+ (files) => {
1162
+ const images = files.filter(isImageFile);
1163
+ if (images.length === 0) return false;
1164
+ for (const file of images) {
1165
+ void insertByUpload(file);
1166
+ }
1167
+ return true;
1168
+ },
1169
+ [insertByUpload]
1170
+ );
1171
+ useEffect(() => {
1172
+ const unregisterDragDrop = editor.registerCommand(
1173
+ DRAG_DROP_PASTE,
1174
+ (files) => handleFiles(files),
1175
+ COMMAND_PRIORITY_HIGH
1176
+ );
1177
+ const unregisterPaste = editor.registerCommand(
1178
+ PASTE_COMMAND,
1179
+ (event) => {
1180
+ const clipboardData = "clipboardData" in event ? event.clipboardData : null;
1181
+ if (!clipboardData) return false;
1182
+ const files = Array.from(clipboardData.files);
1183
+ if (files.some(isImageFile)) {
1184
+ return handleFiles(files);
1185
+ }
1186
+ return false;
1187
+ },
1188
+ COMMAND_PRIORITY_HIGH
1189
+ );
1190
+ const unregisterOpenDialog = editor.registerCommand(
1191
+ OPEN_IMAGE_UPLOAD_DIALOG_COMMAND,
1192
+ () => {
1193
+ setDialogOpen(true);
1194
+ return true;
1195
+ },
1196
+ COMMAND_PRIORITY_EDITOR
1197
+ );
1198
+ const rootElement = editor.getRootElement();
1199
+ const wrapper = rootElement?.parentElement ?? null;
1200
+ if (!wrapper) {
1201
+ return () => {
1202
+ unregisterDragDrop();
1203
+ unregisterPaste();
1204
+ unregisterOpenDialog();
1205
+ };
1206
+ }
1207
+ let dragCounter = 0;
1208
+ const setWrapperDragging = (next) => {
1209
+ setRootDragActive(next);
1210
+ wrapper.classList.toggle(draggingWrapperClass, next);
1211
+ };
1212
+ const onDragEnter = (event) => {
1213
+ if (!hasImageData(event.dataTransfer)) return;
1214
+ dragCounter += 1;
1215
+ setWrapperDragging(true);
1216
+ };
1217
+ const onDragOver = (event) => {
1218
+ if (!hasImageData(event.dataTransfer)) return;
1219
+ event.preventDefault();
1220
+ };
1221
+ const onDragLeave = () => {
1222
+ dragCounter = Math.max(dragCounter - 1, 0);
1223
+ if (dragCounter === 0) {
1224
+ setWrapperDragging(false);
1225
+ }
1226
+ };
1227
+ const onDrop = () => {
1228
+ dragCounter = 0;
1229
+ setWrapperDragging(false);
1230
+ };
1231
+ rootElement?.addEventListener("dragenter", onDragEnter);
1232
+ rootElement?.addEventListener("dragover", onDragOver);
1233
+ rootElement?.addEventListener("dragleave", onDragLeave);
1234
+ rootElement?.addEventListener("drop", onDrop);
1235
+ return () => {
1236
+ if (toastTimerRef.current) {
1237
+ window.clearTimeout(toastTimerRef.current);
1238
+ }
1239
+ unregisterDragDrop();
1240
+ unregisterPaste();
1241
+ unregisterOpenDialog();
1242
+ setWrapperDragging(false);
1243
+ rootElement?.removeEventListener("dragenter", onDragEnter);
1244
+ rootElement?.removeEventListener("dragover", onDragOver);
1245
+ rootElement?.removeEventListener("dragleave", onDragLeave);
1246
+ rootElement?.removeEventListener("drop", onDrop);
1247
+ };
1248
+ }, [editor, handleFiles]);
1249
+ const resetUrlState = useCallback(() => {
1250
+ setUrlInput("");
1251
+ setUrlPreview(null);
1252
+ setUrlMeta(null);
1253
+ setUrlError(null);
1254
+ setUrlLoading(false);
1255
+ }, []);
1256
+ const handleDialogFile = useCallback(
1257
+ async (file) => {
1258
+ if (!file) return;
1259
+ await insertByUpload(file, { closeDialog: true });
1260
+ },
1261
+ [insertByUpload]
1262
+ );
1263
+ const handleUrlPreview = useCallback(async () => {
1264
+ const nextUrl = urlInput.trim();
1265
+ if (!nextUrl) return;
1266
+ if (!isSafeImageUrl(nextUrl)) {
1267
+ setUrlError("Unsupported URL scheme");
1268
+ return;
1269
+ }
1270
+ setUrlLoading(true);
1271
+ setUrlError(null);
1272
+ try {
1273
+ const meta = await loadImageByUrl(nextUrl);
1274
+ setUrlMeta(meta);
1275
+ setUrlPreview(nextUrl);
1276
+ } catch {
1277
+ setUrlPreview(null);
1278
+ setUrlMeta(null);
1279
+ setUrlError("Could not load this image URL");
1280
+ } finally {
1281
+ setUrlLoading(false);
1282
+ }
1283
+ }, [urlInput]);
1284
+ const handleInsertByUrl = useCallback(() => {
1285
+ if (!urlPreview$1 || !isSafeImageUrl(urlPreview$1)) return;
1286
+ editor.update(() => {
1287
+ const node = $createImageNode({
1288
+ src: urlPreview$1,
1289
+ altText: "",
1290
+ width: urlMeta?.width,
1291
+ height: urlMeta?.height
1292
+ });
1293
+ $insertNodes([node]);
1294
+ });
1295
+ pushToast("success", "Image inserted");
1296
+ setDialogOpen(false);
1297
+ resetUrlState();
1298
+ }, [editor, pushToast, resetUrlState, urlMeta, urlPreview$1]);
1299
+ const helperMessage = pendingUploads > 0 ? `Uploading ${pendingUploads} image${pendingUploads > 1 ? "s" : ""}...` : rootDragActive ? "Drop image files to upload" : null;
1300
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1301
+ (helperMessage || toast$1) && /* @__PURE__ */ jsxs("div", { className: toastStack, children: [
1302
+ helperMessage && /* @__PURE__ */ jsxs("div", { className: `${toast} ${toastVariant.info}`, children: [
1303
+ /* @__PURE__ */ jsx("span", { className: spinner }),
1304
+ helperMessage
1305
+ ] }),
1306
+ toast$1 && /* @__PURE__ */ jsxs("div", { className: `${toast} ${toastVariant[toast$1.kind]}`, children: [
1307
+ toast$1.kind === "success" ? /* @__PURE__ */ jsx(Check, { size: 12 }) : /* @__PURE__ */ jsx(Info, { size: 12 }),
1308
+ toast$1.message
1309
+ ] })
1310
+ ] }),
1311
+ /* @__PURE__ */ jsx(
1312
+ Dialog,
1313
+ {
1314
+ open: dialogOpen,
1315
+ onOpenChange: (nextOpen) => {
1316
+ if (!nextOpen && dialogUploading) return;
1317
+ setDialogOpen(nextOpen);
1318
+ if (!nextOpen) {
1319
+ resetUrlState();
1320
+ setDialogUploading(false);
1321
+ setDialogDragActive(false);
1322
+ }
1323
+ },
1324
+ children: /* @__PURE__ */ jsxs(
1325
+ DialogPopup,
1326
+ {
1327
+ className: dialogPopup,
1328
+ showCloseButton: !dialogUploading,
1329
+ children: [
1330
+ /* @__PURE__ */ jsx("div", { className: dialogHeader, children: /* @__PURE__ */ jsx(DialogTitle, { className: dialogTitle, children: "Insert image" }) }),
1331
+ /* @__PURE__ */ jsxs("div", { className: dialogBody, children: [
1332
+ /* @__PURE__ */ jsx("div", { className: tabWrap, children: /* @__PURE__ */ jsx(
1333
+ SegmentedControl,
1334
+ {
1335
+ items: tabItems,
1336
+ value: tab,
1337
+ onChange: setTab,
1338
+ fullWidth: true
1339
+ }
1340
+ ) }),
1341
+ tab === "upload" ? /* @__PURE__ */ jsxs(
1342
+ "div",
1343
+ {
1344
+ role: "button",
1345
+ tabIndex: 0,
1346
+ className: `${uploadDropzone} ${uploadDropzoneState[dialogUploading ? "busy" : dialogDragActive ? "active" : "idle"]}`,
1347
+ onClick: () => {
1348
+ if (!dialogUploading) fileInputRef.current?.click();
1349
+ },
1350
+ onKeyDown: (event) => {
1351
+ if (event.key !== "Enter" && event.key !== " ") return;
1352
+ event.preventDefault();
1353
+ if (!dialogUploading) fileInputRef.current?.click();
1354
+ },
1355
+ onDragEnter: (event) => {
1356
+ if (hasImageData(event.dataTransfer)) {
1357
+ event.preventDefault();
1358
+ setDialogDragActive(true);
1359
+ }
1360
+ },
1361
+ onDragOver: (event) => {
1362
+ if (hasImageData(event.dataTransfer)) {
1363
+ event.preventDefault();
1364
+ }
1365
+ },
1366
+ onDragLeave: () => setDialogDragActive(false),
1367
+ onDrop: (event) => {
1368
+ event.preventDefault();
1369
+ setDialogDragActive(false);
1370
+ const file = Array.from(event.dataTransfer.files).find(
1371
+ isImageFile
1372
+ );
1373
+ void handleDialogFile(file ?? null);
1374
+ },
1375
+ children: [
1376
+ /* @__PURE__ */ jsx(
1377
+ "input",
1378
+ {
1379
+ ref: fileInputRef,
1380
+ className: hiddenInput,
1381
+ type: "file",
1382
+ accept: "image/*",
1383
+ onChange: (event) => {
1384
+ const file = event.currentTarget.files?.[0] ?? null;
1385
+ void handleDialogFile(file);
1386
+ event.currentTarget.value = "";
1387
+ }
1388
+ }
1389
+ ),
1390
+ dialogUploading ? /* @__PURE__ */ jsx("div", { className: uploadBusyWrap, children: /* @__PURE__ */ jsxs("div", { className: uploadProgress, children: [
1391
+ /* @__PURE__ */ jsx("span", { className: spinner }),
1392
+ "Uploading image..."
1393
+ ] }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1394
+ /* @__PURE__ */ jsx("span", { className: uploadDropIcon, children: /* @__PURE__ */ jsx(Upload, { size: 18 }) }),
1395
+ /* @__PURE__ */ jsx("span", { className: uploadDropTitle, children: "Click to upload or drag and drop" }),
1396
+ /* @__PURE__ */ jsx("span", { className: uploadDropDesc, children: "PNG, JPG, GIF, WebP" })
1397
+ ] })
1398
+ ]
1399
+ }
1400
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
1401
+ /* @__PURE__ */ jsxs("div", { className: urlInputRow, children: [
1402
+ /* @__PURE__ */ jsx(
1403
+ "input",
1404
+ {
1405
+ className: textInput,
1406
+ type: "url",
1407
+ placeholder: "https://example.com/image.jpg",
1408
+ value: urlInput,
1409
+ onChange: (event) => {
1410
+ setUrlInput(event.target.value);
1411
+ setUrlError(null);
1412
+ setUrlPreview(null);
1413
+ setUrlMeta(null);
1414
+ },
1415
+ onKeyDown: (event) => {
1416
+ if (event.key === "Enter") {
1417
+ event.preventDefault();
1418
+ if (urlPreview$1) {
1419
+ handleInsertByUrl();
1420
+ } else {
1421
+ void handleUrlPreview();
1422
+ }
1423
+ }
1424
+ }
1425
+ }
1426
+ ),
1427
+ /* @__PURE__ */ jsx(
1428
+ "button",
1429
+ {
1430
+ type: "button",
1431
+ className: secondaryButton,
1432
+ disabled: urlLoading || !urlInput.trim(),
1433
+ onClick: () => void handleUrlPreview(),
1434
+ children: urlLoading ? "Loading" : "Preview"
1435
+ }
1436
+ ),
1437
+ /* @__PURE__ */ jsx(
1438
+ "button",
1439
+ {
1440
+ type: "button",
1441
+ className: actionButton,
1442
+ disabled: !urlPreview$1,
1443
+ onClick: handleInsertByUrl,
1444
+ children: "Insert"
1445
+ }
1446
+ )
1447
+ ] }),
1448
+ urlError && /* @__PURE__ */ jsxs(
1449
+ "span",
1450
+ {
1451
+ className: `${helperText} ${toastVariant.error}`,
1452
+ children: [
1453
+ /* @__PURE__ */ jsx(Info, { size: 12 }),
1454
+ urlError
1455
+ ]
1456
+ }
1457
+ ),
1458
+ urlPreview$1 && /* @__PURE__ */ jsx("div", { className: urlPreview, children: /* @__PURE__ */ jsx(
1459
+ "img",
1460
+ {
1461
+ className: urlPreviewImage,
1462
+ src: urlPreview$1,
1463
+ alt: "Preview"
1464
+ }
1465
+ ) })
1466
+ ] })
1467
+ ] }),
1468
+ /* @__PURE__ */ jsxs("div", { className: dialogFooter, children: [
1469
+ /* @__PURE__ */ jsxs("span", { className: helperText, children: [
1470
+ /* @__PURE__ */ jsx(Link2, { size: 12 }),
1471
+ "You can also paste images or drag files directly into the editor."
1472
+ ] }),
1473
+ /* @__PURE__ */ jsx("div", { className: dialogFooterActions, children: /* @__PURE__ */ jsx(
1474
+ "button",
1475
+ {
1476
+ type: "button",
1477
+ className: secondaryButton,
1478
+ onClick: () => setDialogOpen(false),
1479
+ disabled: dialogUploading,
1480
+ children: "Close"
1481
+ }
1482
+ ) })
1483
+ ] })
1484
+ ]
1485
+ }
1486
+ )
1487
+ }
1488
+ )
1489
+ ] });
1490
+ }
1006
1491
  const INSERT_KATEX_INLINE_COMMAND = createCommand(
1007
1492
  "INSERT_KATEX_INLINE"
1008
1493
  );
@@ -1369,6 +1854,7 @@ function RichEditor({
1369
1854
  onEditorReady,
1370
1855
  extraNodes,
1371
1856
  rendererConfig,
1857
+ imageUpload,
1372
1858
  debounceMs,
1373
1859
  children
1374
1860
  }) {
@@ -1385,13 +1871,14 @@ function RichEditor({
1385
1871
  ...initialValue ? { editorState: JSON.stringify(initialValue) } : {}
1386
1872
  };
1387
1873
  const variantClass = getVariantClass(variant);
1874
+ const resolvedImageUpload = imageUpload ?? defaultImageUpload;
1388
1875
  return /* @__PURE__ */ jsx(PortalThemeProvider, { className: variantClass, theme, children: /* @__PURE__ */ jsx(ColorSchemeProvider, { colorScheme: theme, children: /* @__PURE__ */ jsx(
1389
1876
  RendererConfigProvider,
1390
1877
  {
1391
1878
  config: rendererConfig,
1392
1879
  mode: "editor",
1393
1880
  variant,
1394
- children: /* @__PURE__ */ jsx(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx(FootnotePlugin, { children: /* @__PURE__ */ jsxs(
1881
+ children: /* @__PURE__ */ jsx(ImageUploadProvider, { upload: resolvedImageUpload, children: /* @__PURE__ */ jsx(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx(FootnotePlugin, { children: /* @__PURE__ */ jsxs(
1395
1882
  "div",
1396
1883
  {
1397
1884
  className: clsx("rich-editor", variantClass, className),
@@ -1420,6 +1907,7 @@ function RichEditor({
1420
1907
  /* @__PURE__ */ jsx(OnChangePlugin, { onChange, debounceMs }),
1421
1908
  /* @__PURE__ */ jsx(SubmitShortcutPlugin, { onSubmit }),
1422
1909
  /* @__PURE__ */ jsx(ImagePlugin, {}),
1910
+ /* @__PURE__ */ jsx(ImageUploadPlugin, { onUpload: resolvedImageUpload }),
1423
1911
  /* @__PURE__ */ jsx(KaTeXPlugin, {}),
1424
1912
  /* @__PURE__ */ jsx(AlertPlugin, {}),
1425
1913
  /* @__PURE__ */ jsx(MermaidPlugin, {}),
@@ -1432,7 +1920,7 @@ function RichEditor({
1432
1920
  actions && /* @__PURE__ */ jsx("div", { className: "rich-editor__actions", children: actions })
1433
1921
  ]
1434
1922
  }
1435
- ) }) })
1923
+ ) }) }) })
1436
1924
  }
1437
1925
  ) }) });
1438
1926
  }
@@ -1450,5 +1938,7 @@ export {
1450
1938
  INSERT_KATEX_INLINE_COMMAND as f,
1451
1939
  getResolvedEditNodes as g,
1452
1940
  INSERT_MERMAID_COMMAND as h,
1453
- setResolvedEditNodes as s
1941
+ defaultImageUpload as i,
1942
+ setResolvedEditNodes as s,
1943
+ useImageUpload as u
1454
1944
  };
@@ -1,3 +1,3 @@
1
1
  import { RichEditorProps } from '../types';
2
- export declare function RichEditor({ initialValue, onChange, variant, theme, placeholder, onSubmit, autoFocus, className, contentClassName, style, actions, onEditorReady, extraNodes, rendererConfig, debounceMs, children, }: RichEditorProps): import("react").JSX.Element;
2
+ export declare function RichEditor({ initialValue, onChange, variant, theme, placeholder, onSubmit, autoFocus, className, contentClassName, style, actions, onEditorReady, extraNodes, rendererConfig, imageUpload, debounceMs, children, }: RichEditorProps): import("react").JSX.Element;
3
3
  //# sourceMappingURL=RichEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RichEditor.d.ts","sourceRoot":"","sources":["../../src/components/RichEditor.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAI/C,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,QAAQ,EACR,OAAmB,EACnB,KAAe,EACf,WAAkC,EAClC,QAAQ,EACR,SAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,KAAK,EACL,OAAO,EACP,aAAa,EACb,UAAU,EACV,cAAc,EACd,UAAU,EACV,QAAQ,GACT,EAAE,eAAe,+BAoEjB"}
1
+ {"version":3,"file":"RichEditor.d.ts","sourceRoot":"","sources":["../../src/components/RichEditor.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAI/C,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,QAAQ,EACR,OAAmB,EACnB,KAAe,EACf,WAAkC,EAClC,QAAQ,EACR,SAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,KAAK,EACL,OAAO,EACP,aAAa,EACb,UAAU,EACV,cAAc,EACd,WAAW,EACX,UAAU,EACV,QAAQ,GACT,EAAE,eAAe,+BAwEjB"}
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from 'react';
2
+ import { ImageUploadFn } from '../plugins/ImageUploadPlugin';
3
+ export declare function ImageUploadProvider({ upload, children, }: {
4
+ upload: ImageUploadFn;
5
+ children: ReactNode;
6
+ }): import("react").JSX.Element;
7
+ export declare function useImageUpload(): ImageUploadFn | null;
8
+ //# sourceMappingURL=ImageUploadContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageUploadContext.d.ts","sourceRoot":"","sources":["../../src/context/ImageUploadContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAIjE,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,SAAS,CAAA;CACpB,+BAMA;AAED,wBAAgB,cAAc,IAAI,aAAa,GAAG,IAAI,CAErD"}
package/dist/editor.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { R, a, c, g, s } from "./RichEditor-CSw4Bj02.js";
2
- import { a as a2, b, c as c2 } from "./theme-C_ic3l9g.js";
1
+ import { R, a, c, g, s } from "./RichEditor-C6rSAXFC.js";
2
+ import { a as a2, b, c as c2 } from "./theme-DOLFsBRg.js";
3
3
  export {
4
4
  R as RichEditor,
5
5
  a as allEditNodes,
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export type { ColorScheme } from './context/ColorSchemeContext';
5
5
  export { ColorSchemeProvider, useColorScheme, } from './context/ColorSchemeContext';
6
6
  export type { FootnoteDefinitionsContextValue } from './context/FootnoteDefinitionsContext';
7
7
  export { FootnoteDefinitionsProvider, useFootnoteContent, useFootnoteDefinitions, useFootnoteDisplayNumber, } from './context/FootnoteDefinitionsContext';
8
+ export { useImageUpload } from './context/ImageUploadContext';
8
9
  export type { RendererMode } from './context/RendererConfigContext';
9
10
  export { useRendererMode, useVariant } from './context/RendererConfigContext';
10
11
  export * from './styles';
@@ -23,7 +24,9 @@ export type { AlertType } from './nodes/AlertQuoteNode';
23
24
  export { ALERT_LABELS, ALERT_TYPES } from './nodes/AlertQuoteNode';
24
25
  export { INSERT_ALERT_COMMAND } from './plugins/AlertPlugin';
25
26
  export { FootnotePlugin } from './plugins/FootnotePlugin';
27
+ export { OPEN_IMAGE_UPLOAD_DIALOG_COMMAND } from './plugins/image-upload-command';
26
28
  export { INSERT_IMAGE_COMMAND } from './plugins/ImagePlugin';
29
+ export { defaultImageUpload, type ImageUploadFn, type ImageUploadResult, } from './plugins/ImageUploadPlugin';
27
30
  export { INSERT_KATEX_BLOCK_COMMAND, INSERT_KATEX_INLINE_COMMAND, } from './plugins/KaTeXPlugin';
28
31
  export { INSERT_MERMAID_COMMAND } from './plugins/MermaidPlugin';
29
32
  export type { BannerType } from './nodes/BannerNode';
@@ -33,6 +36,8 @@ export { $createGridContainerNode, $isGridContainerNode, GridContainerNode, } fr
33
36
  export { FootnoteSectionEditNode } from './nodes/FootnoteSectionEditNode';
34
37
  export type { SerializedFootnoteSectionNode } from './nodes/FootnoteSectionNode';
35
38
  export { $createFootnoteSectionNode, $isFootnoteSectionNode, FootnoteSectionNode, } from './nodes/FootnoteSectionNode';
39
+ export type { ImageNodePayload, SerializedImageNode } from './nodes/ImageNode';
40
+ export { $createImageNode, $isImageNode, ImageNode } from './nodes/ImageNode';
36
41
  export type { AlertRendererProps } from './components/renderers/AlertRenderer';
37
42
  export type { BannerRendererProps } from './components/renderers/BannerRenderer';
38
43
  export type { CodeBlockRendererProps } from './components/renderers/CodeBlockRenderer';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC7D,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC/D,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,8BAA8B,CAAA;AACrC,YAAY,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAA;AAC3F,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,sCAAsC,CAAA;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAC7E,cAAc,UAAU,CAAA;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AACjE,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAG7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAGnE,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAGpD,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAG5B,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAGlE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAGhE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGhE,YAAY,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAA;AAC5E,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,2BAA2B,CAAA;AAGlC,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AACzE,YAAY,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAA;AAChF,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,6BAA6B,CAAA;AAGpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAA;AAC9E,YAAY,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAA;AAChF,YAAY,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAA;AACtF,YAAY,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAA;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAA;AAC1E,YAAY,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAA;AAClG,YAAY,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAA;AAC9E,YAAY,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAA;AAC9E,YAAY,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAA;AACpF,YAAY,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAA;AAClF,YAAY,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAA;AAClF,YAAY,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAA;AAC9E,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,YAAY,EACV,QAAQ,EACR,wBAAwB,GACzB,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAA;AAC1E,YAAY,EACV,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,YAAY,GACb,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAA;AACpE,YAAY,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC1E,YAAY,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAG7E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGrE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,wCAAwC,CAAA;AAG/C,YAAY,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAA;AAChG,OAAO,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAA;AAGtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}