@kopexa/tiptap 17.2.0 → 17.2.2

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.
Files changed (53) hide show
  1. package/dist/{chunk-E5NW3MJZ.mjs → chunk-3ZPLSXTZ.mjs} +3 -3
  2. package/dist/{chunk-7SRL3P4B.mjs → chunk-5QFCLKHL.mjs} +7 -7
  3. package/dist/{chunk-NEHW62L7.mjs → chunk-6552DQWB.mjs} +2 -2
  4. package/dist/{chunk-5GFFTVMZ.mjs → chunk-DSBJFMHK.mjs} +4 -28
  5. package/dist/chunk-EAAQE5ZV.mjs +283 -0
  6. package/dist/chunk-HTJ2RXOG.mjs +32 -0
  7. package/dist/{chunk-LMCQMSW2.mjs → chunk-KYLBKQ2E.mjs} +12 -154
  8. package/dist/chunk-N3JE67CS.mjs +81 -0
  9. package/dist/{chunk-UU6JK5HX.mjs → chunk-SSJMKQ5G.mjs} +33 -20
  10. package/dist/chunk-Z365KVQY.mjs +34 -0
  11. package/dist/extensions/image/image-view.d.mts +3 -3
  12. package/dist/extensions/image/image-view.d.ts +3 -3
  13. package/dist/extensions/image/image-view.js +13 -181
  14. package/dist/extensions/image/image-view.mjs +2 -2
  15. package/dist/extensions/image/index.d.mts +12 -49
  16. package/dist/extensions/image/index.d.ts +12 -49
  17. package/dist/extensions/image/index.js +18 -231
  18. package/dist/extensions/image/index.mjs +3 -3
  19. package/dist/extensions/image/messages.d.mts +2 -30
  20. package/dist/extensions/image/messages.d.ts +2 -30
  21. package/dist/extensions/image/messages.js +4 -32
  22. package/dist/extensions/image/messages.mjs +1 -1
  23. package/dist/extensions/image-upload/image-upload-view.d.mts +12 -0
  24. package/dist/extensions/image-upload/image-upload-view.d.ts +12 -0
  25. package/dist/extensions/image-upload/image-upload-view.js +338 -0
  26. package/dist/extensions/image-upload/image-upload-view.mjs +12 -0
  27. package/dist/extensions/image-upload/index.d.mts +46 -0
  28. package/dist/extensions/image-upload/index.d.ts +46 -0
  29. package/dist/extensions/image-upload/index.js +414 -0
  30. package/dist/extensions/image-upload/index.mjs +16 -0
  31. package/dist/extensions/image-upload/messages.d.mts +32 -0
  32. package/dist/extensions/image-upload/messages.d.ts +32 -0
  33. package/dist/extensions/image-upload/messages.js +61 -0
  34. package/dist/extensions/image-upload/messages.mjs +7 -0
  35. package/dist/extensions/math/index.mjs +1 -1
  36. package/dist/hooks/use-create-editor.js +562 -393
  37. package/dist/hooks/use-create-editor.mjs +13 -10
  38. package/dist/index.d.mts +4 -1
  39. package/dist/index.d.ts +4 -1
  40. package/dist/index.js +956 -785
  41. package/dist/index.mjs +39 -33
  42. package/dist/presets/basic/editor-header.mjs +14 -14
  43. package/dist/presets/basic/index.js +953 -784
  44. package/dist/presets/basic/index.mjs +32 -29
  45. package/dist/ui/slash-dropdown-menu/index.js +2 -2
  46. package/dist/ui/slash-dropdown-menu/index.mjs +4 -4
  47. package/dist/ui/slash-dropdown-menu/slash-dropdown-menu.js +2 -2
  48. package/dist/ui/slash-dropdown-menu/slash-dropdown-menu.mjs +2 -2
  49. package/dist/ui/slash-dropdown-menu/use-slash-dropdown-menu.js +2 -2
  50. package/dist/ui/slash-dropdown-menu/use-slash-dropdown-menu.mjs +1 -1
  51. package/package.json +25 -24
  52. package/dist/chunk-WAAH3NLG.mjs +0 -77
  53. package/dist/{chunk-QAE2D4KV.mjs → chunk-FDPXD6VC.mjs} +11 -11
@@ -50,9 +50,9 @@ var import_extension_text_style = require("@tiptap/extension-text-style");
50
50
  var import_extension_typography = require("@tiptap/extension-typography");
51
51
  var import_extension_unique_id = require("@tiptap/extension-unique-id");
52
52
  var import_extensions = require("@tiptap/extensions");
53
- var import_react22 = require("@tiptap/react");
53
+ var import_react25 = require("@tiptap/react");
54
54
  var import_starter_kit = require("@tiptap/starter-kit");
55
- var import_react23 = require("react");
55
+ var import_react26 = require("react");
56
56
 
57
57
  // src/context/editor-file-context.tsx
58
58
  var import_react = require("react");
@@ -414,7 +414,7 @@ var CalloutNode = import_core.Node.create({
414
414
  });
415
415
 
416
416
  // src/extensions/image/index.ts
417
- var import_core2 = require("@tiptap/core");
417
+ var import_extension_image = require("@tiptap/extension-image");
418
418
  var import_react8 = require("@tiptap/react");
419
419
 
420
420
  // src/extensions/image/image-view.tsx
@@ -432,6 +432,10 @@ var messages2 = (0, import_react_intl3.defineMessages)({
432
432
  id: "editor.image.loading",
433
433
  defaultMessage: "Loading image..."
434
434
  },
435
+ uploading: {
436
+ id: "editor.image.uploading",
437
+ defaultMessage: "Uploading..."
438
+ },
435
439
  error: {
436
440
  id: "editor.image.error",
437
441
  defaultMessage: "Failed to load image"
@@ -440,38 +444,6 @@ var messages2 = (0, import_react_intl3.defineMessages)({
440
444
  id: "editor.image.upload_error",
441
445
  defaultMessage: "Failed to upload image"
442
446
  },
443
- uploading: {
444
- id: "editor.image.uploading",
445
- defaultMessage: "Uploading..."
446
- },
447
- upload_placeholder: {
448
- id: "editor.image.upload_placeholder",
449
- defaultMessage: "Click to upload or drag & drop"
450
- },
451
- upload_hint: {
452
- id: "editor.image.upload_hint",
453
- defaultMessage: "PNG, JPG, GIF, WebP, SVG"
454
- },
455
- alt_text: {
456
- id: "editor.image.alt_text",
457
- defaultMessage: "Alt text"
458
- },
459
- alt_placeholder: {
460
- id: "editor.image.alt_placeholder",
461
- defaultMessage: "Describe the image..."
462
- },
463
- files_not_supported: {
464
- id: "editor.image.files_not_supported",
465
- defaultMessage: "File upload is not configured"
466
- },
467
- file_too_large: {
468
- id: "editor.image.file_too_large",
469
- defaultMessage: "File is too large (max {maxSize})"
470
- },
471
- invalid_type: {
472
- id: "editor.image.invalid_type",
473
- defaultMessage: "Invalid file type"
474
- },
475
447
  retry: {
476
448
  id: "editor.image.retry",
477
449
  defaultMessage: "Retry"
@@ -488,7 +460,7 @@ function ImageNodeView({ editor, node, getPos }) {
488
460
  var _a;
489
461
  const intl = (0, import_react_intl4.useIntl)();
490
462
  const fileHandler = useEditorFile();
491
- const attrs = node.attrs;
463
+ const { src, alt, title, uploadState, uploadProgress } = node.attrs;
492
464
  const isEditable = (0, import_react6.useEditorState)({
493
465
  editor,
494
466
  selector: ({ editor: e }) => {
@@ -496,7 +468,6 @@ function ImageNodeView({ editor, node, getPos }) {
496
468
  return (_a2 = e == null ? void 0 : e.isEditable) != null ? _a2 : false;
497
469
  }
498
470
  });
499
- const { src, alt, title, uploadState, uploadProgress } = attrs;
500
471
  const [resolvedUrl, setResolvedUrl] = (0, import_react7.useState)(null);
501
472
  const [resolveState, setResolveState] = (0, import_react7.useState)("idle");
502
473
  const needsResolve = (_a = fileHandler == null ? void 0 : fileHandler.isReference(src)) != null ? _a : false;
@@ -508,7 +479,8 @@ function ImageNodeView({ editor, node, getPos }) {
508
479
  return;
509
480
  }
510
481
  if (!fileHandler) {
511
- setResolveState("error");
482
+ setResolvedUrl(src);
483
+ setResolveState("resolved");
512
484
  return;
513
485
  }
514
486
  setResolveState("loading");
@@ -534,156 +506,16 @@ function ImageNodeView({ editor, node, getPos }) {
534
506
  to: pos + node.nodeSize
535
507
  });
536
508
  }, [editor, getPos, node.nodeSize]);
537
- const fileInputRef = (0, import_react7.useRef)(null);
538
- const handleFileSelect = (0, import_react7.useCallback)(
539
- async (file) => {
540
- if (!fileHandler) return;
541
- const pos = getPos();
542
- if (pos === void 0) return;
543
- editor.view.dispatch(
544
- editor.state.tr.setNodeMarkup(pos, void 0, {
545
- ...attrs,
546
- uploadState: "uploading",
547
- uploadProgress: 0
548
- })
549
- );
550
- try {
551
- const ref = await fileHandler.upload(file, (percent) => {
552
- const currentPos = getPos();
553
- if (currentPos === void 0) return;
554
- editor.view.dispatch(
555
- editor.state.tr.setNodeMarkup(currentPos, void 0, {
556
- ...attrs,
557
- uploadState: "uploading",
558
- uploadProgress: percent
559
- })
560
- );
561
- });
562
- const finalPos = getPos();
563
- if (finalPos === void 0) return;
564
- editor.view.dispatch(
565
- editor.state.tr.setNodeMarkup(finalPos, void 0, {
566
- src: ref,
567
- uploadState: null,
568
- uploadProgress: null
569
- })
570
- );
571
- } catch {
572
- const errorPos = getPos();
573
- if (errorPos === void 0) return;
574
- editor.view.dispatch(
575
- editor.state.tr.setNodeMarkup(errorPos, void 0, {
576
- ...attrs,
577
- uploadState: "error",
578
- uploadProgress: null
579
- })
580
- );
581
- }
582
- },
583
- [fileHandler, editor, getPos, attrs]
584
- );
585
- const handleInputChange = (0, import_react7.useCallback)(
586
- (e) => {
587
- var _a2;
588
- const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
589
- if (file) {
590
- handleFileSelect(file);
591
- }
592
- },
593
- [handleFileSelect]
594
- );
595
- const handleDrop = (0, import_react7.useCallback)(
596
- (e) => {
597
- e.preventDefault();
598
- e.stopPropagation();
599
- const file = e.dataTransfer.files[0];
600
- if (file == null ? void 0 : file.type.startsWith("image/")) {
601
- handleFileSelect(file);
602
- }
603
- },
604
- [handleFileSelect]
605
- );
606
- const handleDragOver = (0, import_react7.useCallback)((e) => {
607
- e.preventDefault();
608
- e.stopPropagation();
609
- }, []);
610
- const styles = (0, import_react7.useMemo)(() => (0, import_theme2.imagePlaceholder)({ size: "md" }), []);
611
509
  const errorStyles = (0, import_react7.useMemo)(
612
510
  () => (0, import_theme2.imagePlaceholder)({ size: "md", variant: "error" }),
613
511
  []
614
512
  );
615
- const uploadingStyles = (0, import_react7.useMemo)(
513
+ const loadingStyles = (0, import_react7.useMemo)(
616
514
  () => (0, import_theme2.imagePlaceholder)({ size: "md", variant: "uploading" }),
617
515
  []
618
516
  );
619
- const disabledStyles = (0, import_react7.useMemo)(
620
- () => (0, import_theme2.imagePlaceholder)({ size: "md", variant: "disabled" }),
621
- []
622
- );
623
- const isEmpty = !src;
624
- if (isEmpty && !uploadState) {
625
- if (!fileHandler) {
626
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: disabledStyles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: disabledStyles.content(), children: [
627
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons3.ImageIcon, { className: disabledStyles.icon() }),
628
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: disabledStyles.text(), children: intl.formatMessage(messages2.files_not_supported) }),
629
- isEditable && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
630
- import_button2.IconButton,
631
- {
632
- size: "sm",
633
- variant: "ghost",
634
- onClick: handleRemove,
635
- "aria-label": intl.formatMessage(messages2.remove),
636
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons3.TrashIcon, { className: "size-4" })
637
- }
638
- )
639
- ] }) }) });
640
- }
641
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
642
- "div",
643
- {
644
- className: styles.root(),
645
- onClick: () => {
646
- var _a2;
647
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
648
- },
649
- onDrop: handleDrop,
650
- onDragOver: handleDragOver,
651
- children: [
652
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles.content(), children: [
653
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons3.UploadIcon, { className: styles.icon() }),
654
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.text(), children: intl.formatMessage(messages2.upload_placeholder) }),
655
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.hint(), children: intl.formatMessage(messages2.upload_hint) })
656
- ] }),
657
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
658
- "input",
659
- {
660
- ref: fileInputRef,
661
- type: "file",
662
- accept: "image/*",
663
- className: "hidden",
664
- onChange: handleInputChange
665
- }
666
- ),
667
- isEditable && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
668
- import_button2.IconButton,
669
- {
670
- size: "sm",
671
- variant: "ghost",
672
- className: styles.removeButton(),
673
- onClick: (e) => {
674
- e.stopPropagation();
675
- handleRemove();
676
- },
677
- "aria-label": intl.formatMessage(messages2.remove),
678
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons3.TrashIcon, { className: "size-3.5" })
679
- }
680
- )
681
- ]
682
- }
683
- ) });
684
- }
685
517
  if (uploadState === "uploading") {
686
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: uploadingStyles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: uploadingStyles.content(), children: [
518
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: loadingStyles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: loadingStyles.content(), children: [
687
519
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative size-12", children: [
688
520
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
689
521
  "svg",
@@ -725,14 +557,14 @@ function ImageNodeView({ editor, node, getPos }) {
725
557
  "%"
726
558
  ] })
727
559
  ] }),
728
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: uploadingStyles.text(), children: intl.formatMessage(messages2.uploading) })
560
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: loadingStyles.text(), children: intl.formatMessage(messages2.uploading) })
729
561
  ] }) }) });
730
562
  }
731
563
  if (uploadState === "error") {
732
564
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: errorStyles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: errorStyles.content(), children: [
733
565
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons3.AlertCircleIcon, { className: errorStyles.icon() }),
734
566
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: errorStyles.text(), children: intl.formatMessage(messages2.upload_error) }),
735
- isEditable && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
567
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
736
568
  import_button2.IconButton,
737
569
  {
738
570
  size: "sm",
@@ -741,11 +573,11 @@ function ImageNodeView({ editor, node, getPos }) {
741
573
  "aria-label": intl.formatMessage(messages2.remove),
742
574
  children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons3.TrashIcon, { className: "size-4" })
743
575
  }
744
- ) })
576
+ )
745
577
  ] }) }) });
746
578
  }
747
579
  if (resolveState === "loading") {
748
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `${uploadingStyles.root()} animate-pulse`, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: uploadingStyles.text(), children: intl.formatMessage(messages2.loading) }) }) });
580
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `${loadingStyles.root()} animate-pulse`, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: loadingStyles.text(), children: intl.formatMessage(messages2.loading) }) }) });
749
581
  }
750
582
  if (resolveState === "error") {
751
583
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react6.NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: errorStyles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: errorStyles.content(), children: [
@@ -800,34 +632,345 @@ function ImageNodeView({ editor, node, getPos }) {
800
632
  }
801
633
 
802
634
  // src/extensions/image/index.ts
803
- var ImageNode = import_core2.Node.create({
804
- name: "image",
635
+ var ImageNode = import_extension_image.Image.extend({
636
+ addAttributes() {
637
+ var _a;
638
+ return {
639
+ ...(_a = this.parent) == null ? void 0 : _a.call(this),
640
+ // Upload state for drag & drop / paste uploads
641
+ uploadState: {
642
+ default: null,
643
+ rendered: false
644
+ },
645
+ uploadProgress: {
646
+ default: null,
647
+ rendered: false
648
+ }
649
+ };
650
+ },
651
+ addNodeView() {
652
+ return (0, import_react8.ReactNodeViewRenderer)(ImageNodeView);
653
+ }
654
+ });
655
+
656
+ // src/extensions/image-upload/index.ts
657
+ var import_core2 = require("@tiptap/core");
658
+ var import_react11 = require("@tiptap/react");
659
+
660
+ // src/extensions/image-upload/image-upload-view.tsx
661
+ var import_button3 = require("@kopexa/button");
662
+ var import_icons4 = require("@kopexa/icons");
663
+ var import_theme3 = require("@kopexa/theme");
664
+ var import_react9 = require("@tiptap/react");
665
+ var import_react10 = require("react");
666
+ var import_react_intl6 = require("react-intl");
667
+
668
+ // src/extensions/image-upload/messages.ts
669
+ var import_react_intl5 = require("react-intl");
670
+ var messages3 = (0, import_react_intl5.defineMessages)({
671
+ upload_error: {
672
+ id: "editor.image.upload_error",
673
+ defaultMessage: "Failed to upload image"
674
+ },
675
+ uploading: {
676
+ id: "editor.image.uploading",
677
+ defaultMessage: "Uploading..."
678
+ },
679
+ upload_placeholder: {
680
+ id: "editor.image.upload_placeholder",
681
+ defaultMessage: "Click to upload or drag & drop"
682
+ },
683
+ upload_hint: {
684
+ id: "editor.image.upload_hint",
685
+ defaultMessage: "PNG, JPG, GIF, WebP, SVG"
686
+ },
687
+ click_to_retry: {
688
+ id: "editor.image.click_to_retry",
689
+ defaultMessage: "Click to try again"
690
+ },
691
+ files_not_supported: {
692
+ id: "editor.image.files_not_supported",
693
+ defaultMessage: "File upload is not configured"
694
+ },
695
+ remove: {
696
+ id: "editor.image.remove",
697
+ defaultMessage: "Remove"
698
+ }
699
+ });
700
+
701
+ // src/extensions/image-upload/image-upload-view.tsx
702
+ var import_jsx_runtime5 = require("react/jsx-runtime");
703
+ function ImageUploadNodeView({ editor, node, getPos }) {
704
+ const intl = (0, import_react_intl6.useIntl)();
705
+ const fileHandler = useEditorFile();
706
+ const isEditable = (0, import_react9.useEditorState)({
707
+ editor,
708
+ selector: ({ editor: e }) => {
709
+ var _a;
710
+ return (_a = e == null ? void 0 : e.isEditable) != null ? _a : false;
711
+ }
712
+ });
713
+ const [uploadState, setUploadState] = (0, import_react10.useState)("idle");
714
+ const [uploadProgress, setUploadProgress] = (0, import_react10.useState)(0);
715
+ const [isDragOver, setIsDragOver] = (0, import_react10.useState)(false);
716
+ const fileInputRef = (0, import_react10.useRef)(null);
717
+ const handleRemove = (0, import_react10.useCallback)(() => {
718
+ const pos = getPos();
719
+ if (pos === void 0) return;
720
+ editor.commands.deleteRange({
721
+ from: pos,
722
+ to: pos + node.nodeSize
723
+ });
724
+ }, [editor, getPos, node.nodeSize]);
725
+ const handleFileSelect = (0, import_react10.useCallback)(
726
+ async (file) => {
727
+ if (!fileHandler) return;
728
+ const pos = getPos();
729
+ if (pos === void 0) return;
730
+ setUploadState("uploading");
731
+ setUploadProgress(0);
732
+ try {
733
+ const ref = await fileHandler.upload(file, (percent) => {
734
+ setUploadProgress(percent);
735
+ });
736
+ const currentPos = getPos();
737
+ if (currentPos === void 0) return;
738
+ editor.chain().focus().deleteRange({ from: currentPos, to: currentPos + node.nodeSize }).insertContentAt(currentPos, {
739
+ type: "image",
740
+ attrs: {
741
+ src: ref,
742
+ alt: file.name.replace(/\.[^/.]+$/, ""),
743
+ title: file.name.replace(/\.[^/.]+$/, "")
744
+ }
745
+ }).run();
746
+ } catch (error) {
747
+ console.error("[ImageUpload] Upload failed:", error);
748
+ setUploadState("error");
749
+ setUploadProgress(0);
750
+ }
751
+ },
752
+ [fileHandler, editor, getPos, node.nodeSize]
753
+ );
754
+ const handleInputChange = (0, import_react10.useCallback)(
755
+ (e) => {
756
+ var _a;
757
+ const file = (_a = e.target.files) == null ? void 0 : _a[0];
758
+ if (file) {
759
+ handleFileSelect(file);
760
+ }
761
+ e.target.value = "";
762
+ },
763
+ [handleFileSelect]
764
+ );
765
+ const handleDrop = (0, import_react10.useCallback)(
766
+ (e) => {
767
+ e.preventDefault();
768
+ e.stopPropagation();
769
+ setIsDragOver(false);
770
+ const file = e.dataTransfer.files[0];
771
+ if (file == null ? void 0 : file.type.startsWith("image/")) {
772
+ handleFileSelect(file);
773
+ }
774
+ },
775
+ [handleFileSelect]
776
+ );
777
+ const handleDragOver = (0, import_react10.useCallback)((e) => {
778
+ e.preventDefault();
779
+ e.stopPropagation();
780
+ }, []);
781
+ const handleDragEnter = (0, import_react10.useCallback)((e) => {
782
+ e.preventDefault();
783
+ e.stopPropagation();
784
+ setIsDragOver(true);
785
+ }, []);
786
+ const handleDragLeave = (0, import_react10.useCallback)((e) => {
787
+ e.preventDefault();
788
+ e.stopPropagation();
789
+ if (!e.currentTarget.contains(e.relatedTarget)) {
790
+ setIsDragOver(false);
791
+ }
792
+ }, []);
793
+ const handleClick = (0, import_react10.useCallback)(() => {
794
+ var _a;
795
+ if (uploadState === "idle" || uploadState === "error") {
796
+ (_a = fileInputRef.current) == null ? void 0 : _a.click();
797
+ }
798
+ }, [uploadState]);
799
+ const styles = (0, import_react10.useMemo)(
800
+ () => (0, import_theme3.imagePlaceholder)({
801
+ size: "md",
802
+ variant: isDragOver ? "default" : void 0
803
+ }),
804
+ [isDragOver]
805
+ );
806
+ const errorStyles = (0, import_react10.useMemo)(
807
+ () => (0, import_theme3.imagePlaceholder)({ size: "md", variant: "error" }),
808
+ []
809
+ );
810
+ const uploadingStyles = (0, import_react10.useMemo)(
811
+ () => (0, import_theme3.imagePlaceholder)({ size: "md", variant: "uploading" }),
812
+ []
813
+ );
814
+ const disabledStyles = (0, import_react10.useMemo)(
815
+ () => (0, import_theme3.imagePlaceholder)({ size: "md", variant: "disabled" }),
816
+ []
817
+ );
818
+ if (!fileHandler) {
819
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react9.NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: disabledStyles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: disabledStyles.content(), children: [
820
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.ImageIcon, { className: disabledStyles.icon() }),
821
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: disabledStyles.text(), children: intl.formatMessage(messages3.files_not_supported) }),
822
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
823
+ import_button3.IconButton,
824
+ {
825
+ size: "sm",
826
+ variant: "ghost",
827
+ onClick: handleRemove,
828
+ "aria-label": intl.formatMessage(messages3.remove),
829
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.TrashIcon, { className: "size-4" })
830
+ }
831
+ )
832
+ ] }) }) });
833
+ }
834
+ if (uploadState === "uploading") {
835
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react9.NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: uploadingStyles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: uploadingStyles.content(), children: [
836
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative size-12", children: [
837
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
838
+ "svg",
839
+ {
840
+ className: "size-12 -rotate-90",
841
+ viewBox: "0 0 36 36",
842
+ "aria-hidden": "true",
843
+ children: [
844
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
845
+ "circle",
846
+ {
847
+ cx: "18",
848
+ cy: "18",
849
+ r: "16",
850
+ fill: "none",
851
+ className: "stroke-muted",
852
+ strokeWidth: "2"
853
+ }
854
+ ),
855
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
856
+ "circle",
857
+ {
858
+ cx: "18",
859
+ cy: "18",
860
+ r: "16",
861
+ fill: "none",
862
+ className: "stroke-primary",
863
+ strokeWidth: "2",
864
+ strokeDasharray: 100,
865
+ strokeDashoffset: 100 - uploadProgress,
866
+ strokeLinecap: "round"
867
+ }
868
+ )
869
+ ]
870
+ }
871
+ ),
872
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "absolute inset-0 flex items-center justify-center text-xs font-medium", children: [
873
+ uploadProgress,
874
+ "%"
875
+ ] })
876
+ ] }),
877
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: uploadingStyles.text(), children: intl.formatMessage(messages3.uploading) })
878
+ ] }) }) });
879
+ }
880
+ if (uploadState === "error") {
881
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react9.NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: errorStyles.root(), onClick: handleClick, children: [
882
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: errorStyles.content(), children: [
883
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.AlertCircleIcon, { className: errorStyles.icon() }),
884
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: errorStyles.text(), children: intl.formatMessage(messages3.upload_error) }),
885
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: errorStyles.hint(), children: intl.formatMessage(messages3.click_to_retry) })
886
+ ] }),
887
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
888
+ "input",
889
+ {
890
+ ref: fileInputRef,
891
+ type: "file",
892
+ accept: "image/*",
893
+ className: "hidden",
894
+ onChange: handleInputChange
895
+ }
896
+ ),
897
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
898
+ import_button3.IconButton,
899
+ {
900
+ size: "sm",
901
+ variant: "ghost",
902
+ className: errorStyles.removeButton(),
903
+ onClick: (e) => {
904
+ e.stopPropagation();
905
+ handleRemove();
906
+ },
907
+ "aria-label": intl.formatMessage(messages3.remove),
908
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.TrashIcon, { className: "size-3.5" })
909
+ }
910
+ )
911
+ ] }) });
912
+ }
913
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react9.NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
914
+ "div",
915
+ {
916
+ className: `${styles.root()} ${isDragOver ? "border-primary bg-primary/10" : ""}`,
917
+ onClick: handleClick,
918
+ onDrop: handleDrop,
919
+ onDragOver: handleDragOver,
920
+ onDragEnter: handleDragEnter,
921
+ onDragLeave: handleDragLeave,
922
+ children: [
923
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: styles.content(), children: [
924
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.UploadIcon, { className: styles.icon() }),
925
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: styles.text(), children: intl.formatMessage(messages3.upload_placeholder) }),
926
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: styles.hint(), children: intl.formatMessage(messages3.upload_hint) })
927
+ ] }),
928
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
929
+ "input",
930
+ {
931
+ ref: fileInputRef,
932
+ type: "file",
933
+ accept: "image/*",
934
+ className: "hidden",
935
+ onChange: handleInputChange
936
+ }
937
+ ),
938
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
939
+ import_button3.IconButton,
940
+ {
941
+ size: "sm",
942
+ variant: "ghost",
943
+ className: styles.removeButton(),
944
+ onClick: (e) => {
945
+ e.stopPropagation();
946
+ handleRemove();
947
+ },
948
+ "aria-label": intl.formatMessage(messages3.remove),
949
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.TrashIcon, { className: "size-3.5" })
950
+ }
951
+ )
952
+ ]
953
+ }
954
+ ) });
955
+ }
956
+
957
+ // src/extensions/image-upload/index.ts
958
+ var ImageUploadNode = import_core2.Node.create({
959
+ name: "imageUpload",
805
960
  group: "block",
806
961
  atom: true,
807
962
  draggable: true,
963
+ selectable: true,
808
964
  addOptions() {
809
965
  return {
810
- allowBase64: true,
966
+ accept: "image/*",
967
+ maxSize: 0,
811
968
  HTMLAttributes: {}
812
969
  };
813
970
  },
814
971
  addAttributes() {
815
972
  return {
816
- src: {
817
- default: null
818
- },
819
- alt: {
820
- default: null
821
- },
822
- title: {
823
- default: null
824
- },
825
- width: {
826
- default: null
827
- },
828
- height: {
829
- default: null
830
- },
973
+ // Upload state tracking
831
974
  uploadState: {
832
975
  default: null,
833
976
  rendered: false
@@ -841,35 +984,51 @@ var ImageNode = import_core2.Node.create({
841
984
  parseHTML() {
842
985
  return [
843
986
  {
844
- tag: "img[src]"
987
+ tag: 'div[data-type="image-upload"]'
845
988
  }
846
989
  ];
847
990
  },
848
991
  renderHTML({ HTMLAttributes }) {
849
- return [
850
- "img",
851
- (0, import_core2.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes)
852
- ];
992
+ return ["div", { ...HTMLAttributes, "data-type": "image-upload" }];
853
993
  },
854
994
  addNodeView() {
855
- return (0, import_react8.ReactNodeViewRenderer)(ImageNodeView);
995
+ return (0, import_react11.ReactNodeViewRenderer)(ImageUploadNodeView);
856
996
  },
857
997
  addCommands() {
858
998
  return {
859
- setImage: (options) => ({ commands }) => {
999
+ setImageUpload: () => ({ commands }) => {
860
1000
  return commands.insertContent({
861
- type: this.name,
862
- attrs: options
1001
+ type: this.name
863
1002
  });
864
1003
  }
865
1004
  };
1005
+ },
1006
+ addKeyboardShortcuts() {
1007
+ return {
1008
+ Enter: ({ editor }) => {
1009
+ const { selection } = editor.state;
1010
+ const { $from } = selection;
1011
+ const node = $from.nodeAfter;
1012
+ if ((node == null ? void 0 : node.type.name) === "imageUpload" && editor.isActive("imageUpload")) {
1013
+ const nodeEl = editor.view.nodeDOM($from.pos);
1014
+ if (nodeEl instanceof HTMLElement) {
1015
+ const input = nodeEl.querySelector('input[type="file"]');
1016
+ if (input instanceof HTMLElement) {
1017
+ input.click();
1018
+ return true;
1019
+ }
1020
+ }
1021
+ }
1022
+ return false;
1023
+ }
1024
+ };
866
1025
  }
867
1026
  });
868
1027
 
869
1028
  // src/extensions/link/index.ts
870
1029
  var import_extension_link = __toESM(require("@tiptap/extension-link"));
871
1030
  var import_state = require("@tiptap/pm/state");
872
- var import_react9 = require("@tiptap/react");
1031
+ var import_react12 = require("@tiptap/react");
873
1032
  var Link = import_extension_link.default.extend({
874
1033
  inclusive: false,
875
1034
  parseHTML() {
@@ -897,7 +1056,7 @@ var Link = import_extension_link.default.extend({
897
1056
  const { schema, doc, tr } = view.state;
898
1057
  let range;
899
1058
  if (schema.marks.link) {
900
- range = (0, import_react9.getMarkRange)(doc.resolve(pos), schema.marks.link);
1059
+ range = (0, import_react12.getMarkRange)(doc.resolve(pos), schema.marks.link);
901
1060
  }
902
1061
  if (!range) {
903
1062
  return;
@@ -923,22 +1082,22 @@ var Link = import_extension_link.default.extend({
923
1082
 
924
1083
  // src/extensions/math/index.ts
925
1084
  var import_core4 = require("@tiptap/core");
926
- var import_react15 = require("@tiptap/react");
1085
+ var import_react18 = require("@tiptap/react");
927
1086
 
928
1087
  // src/extensions/math/math-block-view.tsx
929
- var import_button3 = require("@kopexa/button");
1088
+ var import_button4 = require("@kopexa/button");
930
1089
  var import_dialog2 = require("@kopexa/dialog");
931
- var import_icons4 = require("@kopexa/icons");
1090
+ var import_icons5 = require("@kopexa/icons");
932
1091
  var import_label2 = require("@kopexa/label");
933
- var import_react10 = require("@tiptap/react");
1092
+ var import_react13 = require("@tiptap/react");
934
1093
  var import_katex = __toESM(require("katex"));
935
1094
  var import_katex_min = require("katex/dist/katex.min.css");
936
- var import_react11 = require("react");
937
- var import_react_intl6 = require("react-intl");
1095
+ var import_react14 = require("react");
1096
+ var import_react_intl8 = require("react-intl");
938
1097
 
939
1098
  // src/extensions/math/messages.ts
940
- var import_react_intl5 = require("react-intl");
941
- var messages3 = (0, import_react_intl5.defineMessages)({
1099
+ var import_react_intl7 = require("react-intl");
1100
+ var messages4 = (0, import_react_intl7.defineMessages)({
942
1101
  title: {
943
1102
  id: "editor.math.title",
944
1103
  defaultMessage: "Formula",
@@ -987,28 +1146,28 @@ var messages3 = (0, import_react_intl5.defineMessages)({
987
1146
  });
988
1147
 
989
1148
  // src/extensions/math/math-block-view.tsx
990
- var import_jsx_runtime5 = require("react/jsx-runtime");
1149
+ var import_jsx_runtime6 = require("react/jsx-runtime");
991
1150
  function MathBlockView({ editor, node, getPos }) {
992
- const intl = (0, import_react_intl6.useIntl)();
1151
+ const intl = (0, import_react_intl8.useIntl)();
993
1152
  const attrs = node.attrs;
994
1153
  const { latex = "" } = attrs;
995
- const isEditable = (0, import_react10.useEditorState)({
1154
+ const isEditable = (0, import_react13.useEditorState)({
996
1155
  editor,
997
1156
  selector: ({ editor: e }) => {
998
1157
  var _a;
999
1158
  return (_a = e == null ? void 0 : e.isEditable) != null ? _a : false;
1000
1159
  }
1001
1160
  });
1002
- const [isOpen, setIsOpen] = (0, import_react11.useState)(false);
1003
- const [localLatex, setLocalLatex] = (0, import_react11.useState)(latex);
1004
- const [error, setError] = (0, import_react11.useState)(null);
1005
- (0, import_react11.useEffect)(() => {
1161
+ const [isOpen, setIsOpen] = (0, import_react14.useState)(false);
1162
+ const [localLatex, setLocalLatex] = (0, import_react14.useState)(latex);
1163
+ const [error, setError] = (0, import_react14.useState)(null);
1164
+ (0, import_react14.useEffect)(() => {
1006
1165
  if (isOpen) {
1007
1166
  setLocalLatex(latex);
1008
1167
  setError(null);
1009
1168
  }
1010
1169
  }, [isOpen, latex]);
1011
- const renderedHtml = (0, import_react11.useMemo)(() => {
1170
+ const renderedHtml = (0, import_react14.useMemo)(() => {
1012
1171
  if (!latex) return null;
1013
1172
  try {
1014
1173
  return import_katex.default.renderToString(latex, {
@@ -1020,7 +1179,7 @@ function MathBlockView({ editor, node, getPos }) {
1020
1179
  return null;
1021
1180
  }
1022
1181
  }, [latex]);
1023
- const previewHtml = (0, import_react11.useMemo)(() => {
1182
+ const previewHtml = (0, import_react14.useMemo)(() => {
1024
1183
  if (!localLatex) return null;
1025
1184
  try {
1026
1185
  setError(null);
@@ -1030,11 +1189,11 @@ function MathBlockView({ editor, node, getPos }) {
1030
1189
  output: "html"
1031
1190
  });
1032
1191
  } catch (_e) {
1033
- setError(intl.formatMessage(messages3.invalid_latex));
1192
+ setError(intl.formatMessage(messages4.invalid_latex));
1034
1193
  return null;
1035
1194
  }
1036
1195
  }, [localLatex, intl]);
1037
- const handleSave = (0, import_react11.useCallback)(() => {
1196
+ const handleSave = (0, import_react14.useCallback)(() => {
1038
1197
  const pos = getPos();
1039
1198
  if (pos === void 0) return;
1040
1199
  editor.view.dispatch(
@@ -1042,12 +1201,12 @@ function MathBlockView({ editor, node, getPos }) {
1042
1201
  );
1043
1202
  setIsOpen(false);
1044
1203
  }, [editor, localLatex, getPos]);
1045
- const handleCancel = (0, import_react11.useCallback)(() => {
1204
+ const handleCancel = (0, import_react14.useCallback)(() => {
1046
1205
  setLocalLatex(latex);
1047
1206
  setError(null);
1048
1207
  setIsOpen(false);
1049
1208
  }, [latex]);
1050
- const handleOpenEditor = (0, import_react11.useCallback)(
1209
+ const handleOpenEditor = (0, import_react14.useCallback)(
1051
1210
  (e) => {
1052
1211
  e.stopPropagation();
1053
1212
  e.preventDefault();
@@ -1058,73 +1217,73 @@ function MathBlockView({ editor, node, getPos }) {
1058
1217
  [isEditable]
1059
1218
  );
1060
1219
  const isEmpty = !latex;
1061
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1062
- import_react10.NodeViewWrapper,
1220
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1221
+ import_react13.NodeViewWrapper,
1063
1222
  {
1064
1223
  className: "my-4 relative group",
1065
1224
  "data-type": "math-block",
1066
1225
  "data-latex": latex,
1067
1226
  children: [
1068
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1227
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1069
1228
  "button",
1070
1229
  {
1071
1230
  type: "button",
1072
1231
  className: "w-full flex items-center justify-center min-h-16 p-4 rounded-md border border-border bg-muted/30 cursor-pointer hover:bg-muted/50 transition-colors",
1073
1232
  onClick: handleOpenEditor,
1074
- children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
1075
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-lg font-serif", children: "\u2211" }),
1076
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-sm", children: intl.formatMessage(messages3.empty_formula) })
1077
- ] }) : renderedHtml ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1233
+ children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
1234
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-lg font-serif", children: "\u2211" }),
1235
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm", children: intl.formatMessage(messages4.empty_formula) })
1236
+ ] }) : renderedHtml ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1078
1237
  "div",
1079
1238
  {
1080
1239
  className: "katex-display",
1081
1240
  dangerouslySetInnerHTML: { __html: renderedHtml }
1082
1241
  }
1083
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-destructive text-sm", children: intl.formatMessage(messages3.invalid_latex) })
1242
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-destructive text-sm", children: intl.formatMessage(messages4.invalid_latex) })
1084
1243
  }
1085
1244
  ),
1086
- isEditable && !isEmpty && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1087
- import_button3.IconButton,
1245
+ isEditable && !isEmpty && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1246
+ import_button4.IconButton,
1088
1247
  {
1089
1248
  size: "sm",
1090
1249
  variant: "ghost",
1091
1250
  className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity",
1092
- "aria-label": intl.formatMessage(messages3.edit),
1251
+ "aria-label": intl.formatMessage(messages4.edit),
1093
1252
  onClick: handleOpenEditor,
1094
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.EditIcon, { className: "size-3.5" })
1253
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.EditIcon, { className: "size-3.5" })
1095
1254
  }
1096
1255
  ),
1097
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dialog2.Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, size: "md", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_dialog2.Dialog.Content, { children: [
1098
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dialog2.Dialog.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dialog2.Dialog.Title, { children: intl.formatMessage(messages3.title) }) }),
1099
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dialog2.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-4", children: [
1100
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-1.5", children: [
1101
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_label2.Label, { className: "text-sm", children: intl.formatMessage(messages3.latex_input) }),
1102
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1256
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog2.Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, size: "md", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_dialog2.Dialog.Content, { children: [
1257
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog2.Dialog.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog2.Dialog.Title, { children: intl.formatMessage(messages4.title) }) }),
1258
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog2.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-4", children: [
1259
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5", children: [
1260
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_label2.Label, { className: "text-sm", children: intl.formatMessage(messages4.latex_input) }),
1261
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1103
1262
  "textarea",
1104
1263
  {
1105
1264
  className: "w-full min-h-24 p-3 rounded-md border border-input bg-background font-mono text-sm resize-y focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
1106
1265
  value: localLatex,
1107
1266
  onChange: (e) => setLocalLatex(e.target.value),
1108
- placeholder: intl.formatMessage(messages3.latex_placeholder),
1267
+ placeholder: intl.formatMessage(messages4.latex_placeholder),
1109
1268
  spellCheck: false
1110
1269
  }
1111
1270
  ),
1112
- error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-destructive", children: error })
1271
+ error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs text-destructive", children: error })
1113
1272
  ] }),
1114
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-1.5", children: [
1115
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_label2.Label, { className: "text-sm", children: intl.formatMessage(messages3.preview) }),
1116
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "min-h-16 p-4 rounded-md border border-border bg-muted/30 flex items-center justify-center", children: previewHtml ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1273
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5", children: [
1274
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_label2.Label, { className: "text-sm", children: intl.formatMessage(messages4.preview) }),
1275
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "min-h-16 p-4 rounded-md border border-border bg-muted/30 flex items-center justify-center", children: previewHtml ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1117
1276
  "div",
1118
1277
  {
1119
1278
  className: "katex-display",
1120
1279
  dangerouslySetInnerHTML: { __html: previewHtml }
1121
1280
  }
1122
- ) : localLatex ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-muted-foreground text-sm", children: intl.formatMessage(messages3.invalid_latex) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-muted-foreground text-sm", children: intl.formatMessage(messages3.latex_placeholder) }) })
1281
+ ) : localLatex ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-muted-foreground text-sm", children: intl.formatMessage(messages4.invalid_latex) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-muted-foreground text-sm", children: intl.formatMessage(messages4.latex_placeholder) }) })
1123
1282
  ] })
1124
1283
  ] }) }),
1125
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_dialog2.Dialog.Footer, { children: [
1126
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_button3.Button, { variant: "ghost", onClick: handleCancel, children: intl.formatMessage(messages3.cancel) }),
1127
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_button3.Button, { onClick: handleSave, disabled: !!error && !!localLatex, children: intl.formatMessage(messages3.save) })
1284
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_dialog2.Dialog.Footer, { children: [
1285
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_button4.Button, { variant: "ghost", onClick: handleCancel, children: intl.formatMessage(messages4.cancel) }),
1286
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_button4.Button, { onClick: handleSave, disabled: !!error && !!localLatex, children: intl.formatMessage(messages4.save) })
1128
1287
  ] })
1129
1288
  ] }) })
1130
1289
  ]
@@ -1134,39 +1293,39 @@ function MathBlockView({ editor, node, getPos }) {
1134
1293
 
1135
1294
  // src/extensions/math/inline-math.ts
1136
1295
  var import_core3 = require("@tiptap/core");
1137
- var import_react14 = require("@tiptap/react");
1296
+ var import_react17 = require("@tiptap/react");
1138
1297
 
1139
1298
  // src/extensions/math/inline-math-view.tsx
1140
- var import_button4 = require("@kopexa/button");
1299
+ var import_button5 = require("@kopexa/button");
1141
1300
  var import_dialog3 = require("@kopexa/dialog");
1142
1301
  var import_label3 = require("@kopexa/label");
1143
- var import_react12 = require("@tiptap/react");
1302
+ var import_react15 = require("@tiptap/react");
1144
1303
  var import_katex2 = __toESM(require("katex"));
1145
1304
  var import_katex_min2 = require("katex/dist/katex.min.css");
1146
- var import_react13 = require("react");
1147
- var import_react_intl7 = require("react-intl");
1148
- var import_jsx_runtime6 = require("react/jsx-runtime");
1305
+ var import_react16 = require("react");
1306
+ var import_react_intl9 = require("react-intl");
1307
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1149
1308
  function InlineMathView({ editor, node, getPos }) {
1150
- const intl = (0, import_react_intl7.useIntl)();
1309
+ const intl = (0, import_react_intl9.useIntl)();
1151
1310
  const attrs = node.attrs;
1152
1311
  const { latex = "" } = attrs;
1153
- const isEditable = (0, import_react12.useEditorState)({
1312
+ const isEditable = (0, import_react15.useEditorState)({
1154
1313
  editor,
1155
1314
  selector: ({ editor: e }) => {
1156
1315
  var _a;
1157
1316
  return (_a = e == null ? void 0 : e.isEditable) != null ? _a : false;
1158
1317
  }
1159
1318
  });
1160
- const [isOpen, setIsOpen] = (0, import_react13.useState)(false);
1161
- const [localLatex, setLocalLatex] = (0, import_react13.useState)(latex);
1162
- const [error, setError] = (0, import_react13.useState)(null);
1163
- (0, import_react13.useEffect)(() => {
1319
+ const [isOpen, setIsOpen] = (0, import_react16.useState)(false);
1320
+ const [localLatex, setLocalLatex] = (0, import_react16.useState)(latex);
1321
+ const [error, setError] = (0, import_react16.useState)(null);
1322
+ (0, import_react16.useEffect)(() => {
1164
1323
  if (isOpen) {
1165
1324
  setLocalLatex(latex);
1166
1325
  setError(null);
1167
1326
  }
1168
1327
  }, [isOpen, latex]);
1169
- const renderedHtml = (0, import_react13.useMemo)(() => {
1328
+ const renderedHtml = (0, import_react16.useMemo)(() => {
1170
1329
  if (!latex) return null;
1171
1330
  try {
1172
1331
  return import_katex2.default.renderToString(latex, {
@@ -1178,7 +1337,7 @@ function InlineMathView({ editor, node, getPos }) {
1178
1337
  return null;
1179
1338
  }
1180
1339
  }, [latex]);
1181
- const previewHtml = (0, import_react13.useMemo)(() => {
1340
+ const previewHtml = (0, import_react16.useMemo)(() => {
1182
1341
  if (!localLatex) return null;
1183
1342
  try {
1184
1343
  setError(null);
@@ -1188,11 +1347,11 @@ function InlineMathView({ editor, node, getPos }) {
1188
1347
  output: "html"
1189
1348
  });
1190
1349
  } catch (_e) {
1191
- setError(intl.formatMessage(messages3.invalid_latex));
1350
+ setError(intl.formatMessage(messages4.invalid_latex));
1192
1351
  return null;
1193
1352
  }
1194
1353
  }, [localLatex, intl]);
1195
- const handleSave = (0, import_react13.useCallback)(() => {
1354
+ const handleSave = (0, import_react16.useCallback)(() => {
1196
1355
  const pos = getPos();
1197
1356
  if (pos === void 0) return;
1198
1357
  editor.view.dispatch(
@@ -1200,12 +1359,12 @@ function InlineMathView({ editor, node, getPos }) {
1200
1359
  );
1201
1360
  setIsOpen(false);
1202
1361
  }, [editor, localLatex, getPos]);
1203
- const handleCancel = (0, import_react13.useCallback)(() => {
1362
+ const handleCancel = (0, import_react16.useCallback)(() => {
1204
1363
  setLocalLatex(latex);
1205
1364
  setError(null);
1206
1365
  setIsOpen(false);
1207
1366
  }, [latex]);
1208
- const handleClick = (0, import_react13.useCallback)(
1367
+ const handleClick = (0, import_react16.useCallback)(
1209
1368
  (e) => {
1210
1369
  e.stopPropagation();
1211
1370
  e.preventDefault();
@@ -1216,58 +1375,58 @@ function InlineMathView({ editor, node, getPos }) {
1216
1375
  [isEditable]
1217
1376
  );
1218
1377
  const isEmpty = !latex;
1219
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1220
- import_react12.NodeViewWrapper,
1378
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1379
+ import_react15.NodeViewWrapper,
1221
1380
  {
1222
1381
  as: "span",
1223
1382
  className: "inline-math-wrapper",
1224
1383
  "data-type": "inline-math",
1225
1384
  "data-latex": latex,
1226
1385
  children: [
1227
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1386
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1228
1387
  "span",
1229
1388
  {
1230
1389
  className: `inline-math cursor-pointer rounded px-0.5 transition-colors ${isEditable ? "hover:bg-primary/10 hover:ring-1 hover:ring-primary/20" : ""} ${isEmpty ? "text-muted-foreground italic" : ""}`,
1231
1390
  onClick: handleClick,
1232
- children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-xs", children: "$?$" }) : renderedHtml ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1391
+ children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-xs", children: "$?$" }) : renderedHtml ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1233
1392
  "span",
1234
1393
  {
1235
1394
  dangerouslySetInnerHTML: { __html: renderedHtml }
1236
1395
  }
1237
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-destructive text-xs", children: latex })
1396
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-destructive text-xs", children: latex })
1238
1397
  }
1239
1398
  ),
1240
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog3.Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_dialog3.Dialog.Content, { children: [
1241
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog3.Dialog.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog3.Dialog.Title, { children: intl.formatMessage(messages3.title) }) }),
1242
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dialog3.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-4", children: [
1243
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5", children: [
1244
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_label3.Label, { className: "text-sm", children: intl.formatMessage(messages3.latex_input) }),
1245
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1399
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog3.Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_dialog3.Dialog.Content, { children: [
1400
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog3.Dialog.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog3.Dialog.Title, { children: intl.formatMessage(messages4.title) }) }),
1401
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog3.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-4", children: [
1402
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
1403
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_label3.Label, { className: "text-sm", children: intl.formatMessage(messages4.latex_input) }),
1404
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1246
1405
  "input",
1247
1406
  {
1248
1407
  type: "text",
1249
1408
  className: "w-full p-2 rounded-md border border-input bg-background font-mono text-sm focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
1250
1409
  value: localLatex,
1251
1410
  onChange: (e) => setLocalLatex(e.target.value),
1252
- placeholder: intl.formatMessage(messages3.latex_placeholder),
1411
+ placeholder: intl.formatMessage(messages4.latex_placeholder),
1253
1412
  spellCheck: false
1254
1413
  }
1255
1414
  ),
1256
- error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs text-destructive", children: error })
1415
+ error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-xs text-destructive", children: error })
1257
1416
  ] }),
1258
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5", children: [
1259
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_label3.Label, { className: "text-sm", children: intl.formatMessage(messages3.preview) }),
1260
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "min-h-10 p-3 rounded-md border border-border bg-muted/30 flex items-center justify-center", children: previewHtml ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1417
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
1418
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_label3.Label, { className: "text-sm", children: intl.formatMessage(messages4.preview) }),
1419
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "min-h-10 p-3 rounded-md border border-border bg-muted/30 flex items-center justify-center", children: previewHtml ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1261
1420
  "span",
1262
1421
  {
1263
1422
  dangerouslySetInnerHTML: { __html: previewHtml }
1264
1423
  }
1265
- ) : localLatex ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-muted-foreground text-sm", children: intl.formatMessage(messages3.invalid_latex) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-muted-foreground text-sm", children: "$...$" }) })
1424
+ ) : localLatex ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-muted-foreground text-sm", children: intl.formatMessage(messages4.invalid_latex) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-muted-foreground text-sm", children: "$...$" }) })
1266
1425
  ] })
1267
1426
  ] }) }),
1268
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_dialog3.Dialog.Footer, { children: [
1269
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_button4.Button, { variant: "ghost", onClick: handleCancel, children: intl.formatMessage(messages3.cancel) }),
1270
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_button4.Button, { onClick: handleSave, disabled: !!error && !!localLatex, children: intl.formatMessage(messages3.save) })
1427
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_dialog3.Dialog.Footer, { children: [
1428
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_button5.Button, { variant: "ghost", onClick: handleCancel, children: intl.formatMessage(messages4.cancel) }),
1429
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_button5.Button, { onClick: handleSave, disabled: !!error && !!localLatex, children: intl.formatMessage(messages4.save) })
1271
1430
  ] })
1272
1431
  ] }) })
1273
1432
  ]
@@ -1313,7 +1472,7 @@ var InlineMath = import_core3.Node.create({
1313
1472
  ];
1314
1473
  },
1315
1474
  addNodeView() {
1316
- return (0, import_react14.ReactNodeViewRenderer)(InlineMathView, {
1475
+ return (0, import_react17.ReactNodeViewRenderer)(InlineMathView, {
1317
1476
  as: "span"
1318
1477
  });
1319
1478
  },
@@ -1381,7 +1540,7 @@ var MathBlock = import_core4.Node.create({
1381
1540
  ];
1382
1541
  },
1383
1542
  addNodeView() {
1384
- return (0, import_react15.ReactNodeViewRenderer)(MathBlockView);
1543
+ return (0, import_react18.ReactNodeViewRenderer)(MathBlockView);
1385
1544
  },
1386
1545
  addCommands() {
1387
1546
  return {
@@ -1425,8 +1584,8 @@ var MathBlock = import_core4.Node.create({
1425
1584
  // src/extensions/selection/index.ts
1426
1585
  var import_state2 = require("@tiptap/pm/state");
1427
1586
  var import_view = require("@tiptap/pm/view");
1428
- var import_react16 = require("@tiptap/react");
1429
- var Selection = import_react16.Extension.create({
1587
+ var import_react19 = require("@tiptap/react");
1588
+ var Selection = import_react19.Extension.create({
1430
1589
  name: "selection",
1431
1590
  addProseMirrorPlugins() {
1432
1591
  const { editor } = this;
@@ -1441,7 +1600,7 @@ var Selection = import_react16.Extension.create({
1441
1600
  if (editor.isFocused === true || !editor.isEditable) {
1442
1601
  return null;
1443
1602
  }
1444
- if ((0, import_react16.isNodeSelection)(state.selection)) {
1603
+ if ((0, import_react19.isNodeSelection)(state.selection)) {
1445
1604
  return null;
1446
1605
  }
1447
1606
  return import_view.DecorationSet.create(state.doc, [
@@ -1458,18 +1617,18 @@ var Selection = import_react16.Extension.create({
1458
1617
 
1459
1618
  // src/extensions/toc/index.ts
1460
1619
  var import_core5 = require("@tiptap/core");
1461
- var import_react20 = require("@tiptap/react");
1620
+ var import_react23 = require("@tiptap/react");
1462
1621
 
1463
1622
  // src/extensions/toc/toc-view.tsx
1464
- var import_icons6 = require("@kopexa/icons");
1465
- var import_theme3 = require("@kopexa/theme");
1466
- var import_react18 = require("@tiptap/react");
1467
- var import_react19 = require("react");
1468
- var import_react_intl10 = require("react-intl");
1623
+ var import_icons7 = require("@kopexa/icons");
1624
+ var import_theme4 = require("@kopexa/theme");
1625
+ var import_react21 = require("@tiptap/react");
1626
+ var import_react22 = require("react");
1627
+ var import_react_intl12 = require("react-intl");
1469
1628
 
1470
1629
  // src/extensions/toc/messages.ts
1471
- var import_react_intl8 = require("react-intl");
1472
- var messages4 = (0, import_react_intl8.defineMessages)({
1630
+ var import_react_intl10 = require("react-intl");
1631
+ var messages5 = (0, import_react_intl10.defineMessages)({
1473
1632
  title: {
1474
1633
  id: "editor.toc.title",
1475
1634
  defaultMessage: "Table of Contents",
@@ -1543,15 +1702,15 @@ var messages4 = (0, import_react_intl8.defineMessages)({
1543
1702
  });
1544
1703
 
1545
1704
  // src/extensions/toc/toc-settings.tsx
1546
- var import_button5 = require("@kopexa/button");
1705
+ var import_button6 = require("@kopexa/button");
1547
1706
  var import_dialog4 = require("@kopexa/dialog");
1548
- var import_icons5 = require("@kopexa/icons");
1707
+ var import_icons6 = require("@kopexa/icons");
1549
1708
  var import_label4 = require("@kopexa/label");
1550
1709
  var import_select2 = require("@kopexa/select");
1551
1710
  var import_switch = require("@kopexa/switch");
1552
- var import_react17 = require("react");
1553
- var import_react_intl9 = require("react-intl");
1554
- var import_jsx_runtime7 = require("react/jsx-runtime");
1711
+ var import_react20 = require("react");
1712
+ var import_react_intl11 = require("react-intl");
1713
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1555
1714
  var HEADING_LEVELS = [
1556
1715
  { value: "1", label: "H1" },
1557
1716
  { value: "2", label: "H2" },
@@ -1561,15 +1720,15 @@ var HEADING_LEVELS = [
1561
1720
  { value: "6", label: "H6" }
1562
1721
  ];
1563
1722
  function TocSettings({ editor, attrs, getPos }) {
1564
- const intl = (0, import_react_intl9.useIntl)();
1565
- const [isOpen, setIsOpen] = (0, import_react17.useState)(false);
1566
- const [localAttrs, setLocalAttrs] = (0, import_react17.useState)(attrs);
1567
- (0, import_react17.useEffect)(() => {
1723
+ const intl = (0, import_react_intl11.useIntl)();
1724
+ const [isOpen, setIsOpen] = (0, import_react20.useState)(false);
1725
+ const [localAttrs, setLocalAttrs] = (0, import_react20.useState)(attrs);
1726
+ (0, import_react20.useEffect)(() => {
1568
1727
  if (isOpen) {
1569
1728
  setLocalAttrs(attrs);
1570
1729
  }
1571
1730
  }, [isOpen, attrs]);
1572
- const handleSave = (0, import_react17.useCallback)(() => {
1731
+ const handleSave = (0, import_react20.useCallback)(() => {
1573
1732
  const pos = getPos();
1574
1733
  if (pos === void 0) return;
1575
1734
  editor.view.dispatch(
@@ -1577,11 +1736,11 @@ function TocSettings({ editor, attrs, getPos }) {
1577
1736
  );
1578
1737
  setIsOpen(false);
1579
1738
  }, [editor, localAttrs, getPos]);
1580
- const handleCancel = (0, import_react17.useCallback)(() => {
1739
+ const handleCancel = (0, import_react20.useCallback)(() => {
1581
1740
  setLocalAttrs(attrs);
1582
1741
  setIsOpen(false);
1583
1742
  }, [attrs]);
1584
- const handleMinLevelChange = (0, import_react17.useCallback)((value) => {
1743
+ const handleMinLevelChange = (0, import_react20.useCallback)((value) => {
1585
1744
  const minLevel = Number.parseInt(String(value), 10);
1586
1745
  setLocalAttrs((prev) => ({
1587
1746
  ...prev,
@@ -1590,7 +1749,7 @@ function TocSettings({ editor, attrs, getPos }) {
1590
1749
  maxLevel: Math.max(prev.maxLevel, minLevel)
1591
1750
  }));
1592
1751
  }, []);
1593
- const handleMaxLevelChange = (0, import_react17.useCallback)((value) => {
1752
+ const handleMaxLevelChange = (0, import_react20.useCallback)((value) => {
1594
1753
  const maxLevel = Number.parseInt(String(value), 10);
1595
1754
  setLocalAttrs((prev) => ({
1596
1755
  ...prev,
@@ -1599,10 +1758,10 @@ function TocSettings({ editor, attrs, getPos }) {
1599
1758
  minLevel: Math.min(prev.minLevel, maxLevel)
1600
1759
  }));
1601
1760
  }, []);
1602
- const handleNumberedChange = (0, import_react17.useCallback)((checked) => {
1761
+ const handleNumberedChange = (0, import_react20.useCallback)((checked) => {
1603
1762
  setLocalAttrs((prev) => ({ ...prev, numbered: checked }));
1604
1763
  }, []);
1605
- const handleStyleChange = (0, import_react17.useCallback)((value) => {
1764
+ const handleStyleChange = (0, import_react20.useCallback)((value) => {
1606
1765
  setLocalAttrs((prev) => ({
1607
1766
  ...prev,
1608
1767
  style: String(value)
@@ -1611,36 +1770,36 @@ function TocSettings({ editor, attrs, getPos }) {
1611
1770
  if (!editor.isEditable) {
1612
1771
  return null;
1613
1772
  }
1614
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1615
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1616
- import_button5.IconButton,
1773
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1774
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1775
+ import_button6.IconButton,
1617
1776
  {
1618
1777
  size: "sm",
1619
1778
  variant: "ghost",
1620
- "aria-label": intl.formatMessage(messages4.settings),
1779
+ "aria-label": intl.formatMessage(messages5.settings),
1621
1780
  onClick: (e) => {
1622
1781
  e.stopPropagation();
1623
1782
  e.preventDefault();
1624
1783
  setIsOpen(true);
1625
1784
  },
1626
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_icons5.SettingsIcon, { className: "size-3.5" })
1785
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_icons6.SettingsIcon, { className: "size-3.5" })
1627
1786
  }
1628
1787
  ),
1629
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog4.Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_dialog4.Dialog.Content, { children: [
1630
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog4.Dialog.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog4.Dialog.Title, { children: intl.formatMessage(messages4.settings) }) }),
1631
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_dialog4.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-4", children: [
1632
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
1633
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
1634
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages4.min_level) }),
1635
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1788
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_dialog4.Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_dialog4.Dialog.Content, { children: [
1789
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_dialog4.Dialog.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_dialog4.Dialog.Title, { children: intl.formatMessage(messages5.settings) }) }),
1790
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_dialog4.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-4", children: [
1791
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "grid grid-cols-2 gap-3", children: [
1792
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1.5", children: [
1793
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages5.min_level) }),
1794
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1636
1795
  import_select2.Select,
1637
1796
  {
1638
1797
  size: "sm",
1639
1798
  value: String(localAttrs.minLevel),
1640
1799
  onValueChange: handleMinLevelChange,
1641
1800
  children: [
1642
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Value, {}) }),
1643
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Content, { children: HEADING_LEVELS.map((level) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1801
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Value, {}) }),
1802
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Content, { children: HEADING_LEVELS.map((level) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1644
1803
  import_select2.Select.Item,
1645
1804
  {
1646
1805
  value: level.value,
@@ -1653,17 +1812,17 @@ function TocSettings({ editor, attrs, getPos }) {
1653
1812
  }
1654
1813
  )
1655
1814
  ] }),
1656
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
1657
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages4.max_level) }),
1658
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1815
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1.5", children: [
1816
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages5.max_level) }),
1817
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1659
1818
  import_select2.Select,
1660
1819
  {
1661
1820
  size: "sm",
1662
1821
  value: String(localAttrs.maxLevel),
1663
1822
  onValueChange: handleMaxLevelChange,
1664
1823
  children: [
1665
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Value, {}) }),
1666
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Content, { children: HEADING_LEVELS.map((level) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1824
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Value, {}) }),
1825
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Content, { children: HEADING_LEVELS.map((level) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1667
1826
  import_select2.Select.Item,
1668
1827
  {
1669
1828
  value: level.value,
@@ -1677,12 +1836,12 @@ function TocSettings({ editor, attrs, getPos }) {
1677
1836
  )
1678
1837
  ] })
1679
1838
  ] }),
1680
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
1681
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-0.5", children: [
1682
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages4.numbered) }),
1683
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-xs text-muted-foreground", children: intl.formatMessage(messages4.numbered_hint) })
1839
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
1840
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-0.5", children: [
1841
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages5.numbered) }),
1842
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-xs text-muted-foreground", children: intl.formatMessage(messages5.numbered_hint) })
1684
1843
  ] }),
1685
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1844
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1686
1845
  import_switch.Switch,
1687
1846
  {
1688
1847
  size: "sm",
@@ -1691,36 +1850,36 @@ function TocSettings({ editor, attrs, getPos }) {
1691
1850
  }
1692
1851
  )
1693
1852
  ] }),
1694
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
1695
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages4.style) }),
1696
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1853
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1.5", children: [
1854
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_label4.Label, { className: "text-sm", children: intl.formatMessage(messages5.style) }),
1855
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1697
1856
  import_select2.Select,
1698
1857
  {
1699
1858
  size: "sm",
1700
1859
  value: localAttrs.style,
1701
1860
  onValueChange: handleStyleChange,
1702
1861
  children: [
1703
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Value, {}) }),
1704
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_select2.Select.Content, { children: [
1705
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Item, { value: "default", children: intl.formatMessage(messages4.style_default) }),
1706
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Item, { value: "flat", children: intl.formatMessage(messages4.style_flat) }),
1707
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_select2.Select.Item, { value: "compact", children: intl.formatMessage(messages4.style_compact) })
1862
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Value, {}) }),
1863
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_select2.Select.Content, { children: [
1864
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Item, { value: "default", children: intl.formatMessage(messages5.style_default) }),
1865
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Item, { value: "flat", children: intl.formatMessage(messages5.style_flat) }),
1866
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_select2.Select.Item, { value: "compact", children: intl.formatMessage(messages5.style_compact) })
1708
1867
  ] })
1709
1868
  ]
1710
1869
  }
1711
1870
  )
1712
1871
  ] })
1713
1872
  ] }) }),
1714
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_dialog4.Dialog.Footer, { children: [
1715
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_button5.Button, { variant: "ghost", onClick: handleCancel, children: intl.formatMessage(messages4.cancel) }),
1716
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_button5.Button, { onClick: handleSave, children: intl.formatMessage(messages4.save) })
1873
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_dialog4.Dialog.Footer, { children: [
1874
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_button6.Button, { variant: "ghost", onClick: handleCancel, children: intl.formatMessage(messages5.cancel) }),
1875
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_button6.Button, { onClick: handleSave, children: intl.formatMessage(messages5.save) })
1717
1876
  ] })
1718
1877
  ] }) })
1719
1878
  ] });
1720
1879
  }
1721
1880
 
1722
1881
  // src/extensions/toc/toc-view.tsx
1723
- var import_jsx_runtime8 = require("react/jsx-runtime");
1882
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1724
1883
  function generateHeadingNumbers(headings, minLevel) {
1725
1884
  const counters = [0, 0, 0, 0, 0, 0];
1726
1885
  return headings.map((heading) => {
@@ -1742,8 +1901,8 @@ function generateHeadingNumbers(headings, minLevel) {
1742
1901
  });
1743
1902
  }
1744
1903
  function TocNodeView({ editor, node, getPos }) {
1745
- const [headings, setHeadings] = (0, import_react19.useState)([]);
1746
- const intl = (0, import_react_intl10.useIntl)();
1904
+ const [headings, setHeadings] = (0, import_react22.useState)([]);
1905
+ const intl = (0, import_react_intl12.useIntl)();
1747
1906
  const attrs = node.attrs;
1748
1907
  const {
1749
1908
  minLevel = 1,
@@ -1751,8 +1910,8 @@ function TocNodeView({ editor, node, getPos }) {
1751
1910
  numbered = false,
1752
1911
  style = "default"
1753
1912
  } = attrs;
1754
- const styles = (0, import_react19.useMemo)(() => (0, import_theme3.toc)({ style }), [style]);
1755
- const updateHeadings = (0, import_react19.useCallback)(() => {
1913
+ const styles = (0, import_react22.useMemo)(() => (0, import_theme4.toc)({ style }), [style]);
1914
+ const updateHeadings = (0, import_react22.useCallback)(() => {
1756
1915
  const items = [];
1757
1916
  const { doc } = editor.state;
1758
1917
  doc.descendants((docNode, pos) => {
@@ -1772,14 +1931,14 @@ function TocNodeView({ editor, node, getPos }) {
1772
1931
  const numberedHeadings = generateHeadingNumbers(items, minLevel);
1773
1932
  setHeadings(numberedHeadings);
1774
1933
  }, [editor, minLevel, maxLevel]);
1775
- (0, import_react19.useEffect)(() => {
1934
+ (0, import_react22.useEffect)(() => {
1776
1935
  updateHeadings();
1777
1936
  editor.on("update", updateHeadings);
1778
1937
  return () => {
1779
1938
  editor.off("update", updateHeadings);
1780
1939
  };
1781
1940
  }, [editor, updateHeadings]);
1782
- const handleClick = (0, import_react19.useCallback)(
1941
+ const handleClick = (0, import_react22.useCallback)(
1783
1942
  (pos, id) => {
1784
1943
  var _a;
1785
1944
  editor.chain().focus().setTextSelection(pos).run();
@@ -1800,13 +1959,13 @@ function TocNodeView({ editor, node, getPos }) {
1800
1959
  const getIndent = (level) => {
1801
1960
  return (level - minLevel) * 16;
1802
1961
  };
1803
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react18.NodeViewWrapper, { className: styles.root(), "data-type": "toc", children: [
1804
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: styles.header(), children: [
1805
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: styles.headerContent(), children: [
1806
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_icons6.ListIcon, { className: styles.headerIcon() }),
1807
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: styles.headerTitle(), children: intl.formatMessage(messages4.title) })
1962
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react21.NodeViewWrapper, { className: styles.root(), "data-type": "toc", children: [
1963
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: styles.header(), children: [
1964
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: styles.headerContent(), children: [
1965
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_icons7.ListIcon, { className: styles.headerIcon() }),
1966
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: styles.headerTitle(), children: intl.formatMessage(messages5.title) })
1808
1967
  ] }),
1809
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: styles.headerActions(), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1968
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: styles.headerActions(), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1810
1969
  TocSettings,
1811
1970
  {
1812
1971
  editor,
@@ -1815,7 +1974,7 @@ function TocNodeView({ editor, node, getPos }) {
1815
1974
  }
1816
1975
  ) })
1817
1976
  ] }),
1818
- isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: styles.emptyState(), children: intl.formatMessage(messages4.empty_state) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("nav", { className: styles.nav(), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: styles.list(), children: headings.map((heading) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1977
+ isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: styles.emptyState(), children: intl.formatMessage(messages5.empty_state) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("nav", { className: styles.nav(), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { className: styles.list(), children: headings.map((heading) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1819
1978
  "li",
1820
1979
  {
1821
1980
  className: styles.item(),
@@ -1823,14 +1982,14 @@ function TocNodeView({ editor, node, getPos }) {
1823
1982
  paddingLeft: `${getIndent(heading.level)}px`
1824
1983
  },
1825
1984
  children: [
1826
- numbered && heading.number && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: styles.itemNumber(), children: heading.number }),
1827
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1985
+ numbered && heading.number && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: styles.itemNumber(), children: heading.number }),
1986
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1828
1987
  "button",
1829
1988
  {
1830
1989
  type: "button",
1831
1990
  onClick: () => handleClick(heading.pos, heading.id),
1832
1991
  className: styles.itemButton(),
1833
- children: heading.text || intl.formatMessage(messages4.empty_heading)
1992
+ children: heading.text || intl.formatMessage(messages5.empty_heading)
1834
1993
  }
1835
1994
  )
1836
1995
  ]
@@ -1899,7 +2058,7 @@ var TocNode = import_core5.Node.create({
1899
2058
  ];
1900
2059
  },
1901
2060
  addNodeView() {
1902
- return (0, import_react20.ReactNodeViewRenderer)(TocNodeView);
2061
+ return (0, import_react23.ReactNodeViewRenderer)(TocNodeView);
1903
2062
  },
1904
2063
  addCommands() {
1905
2064
  return {
@@ -1928,7 +2087,7 @@ var TocNode = import_core5.Node.create({
1928
2087
 
1929
2088
  // src/extensions/trailing-node/index.ts
1930
2089
  var import_state3 = require("@tiptap/pm/state");
1931
- var import_react21 = require("@tiptap/react");
2090
+ var import_react24 = require("@tiptap/react");
1932
2091
  function nodeEqualsType({
1933
2092
  types,
1934
2093
  node
@@ -1939,7 +2098,7 @@ function nodeEqualsType({
1939
2098
  }
1940
2099
  return node.type === types;
1941
2100
  }
1942
- var TrailingNode = import_react21.Extension.create({
2101
+ var TrailingNode = import_react24.Extension.create({
1943
2102
  name: "trailingNode",
1944
2103
  addOptions() {
1945
2104
  return {
@@ -2215,7 +2374,19 @@ var useCreateEditor = ({
2215
2374
  }) => {
2216
2375
  const fileHandlerFromContext = useEditorFile();
2217
2376
  const fileHandler = fileHandlerProp != null ? fileHandlerProp : fileHandlerFromContext;
2218
- const editor = (0, import_react22.useEditor)({
2377
+ const extensions = (0, import_react26.useMemo)(
2378
+ () => getExtensions({
2379
+ editable,
2380
+ placeholder,
2381
+ enableControls,
2382
+ controlResolver,
2383
+ fileHandler
2384
+ }),
2385
+ // Only recreate extensions when these values change
2386
+ // Note: fileHandler and controlResolver are object references, so they should be stable
2387
+ [editable, placeholder, enableControls, controlResolver, fileHandler]
2388
+ );
2389
+ const editor = (0, import_react25.useEditor)({
2219
2390
  editorProps: {
2220
2391
  attributes: {
2221
2392
  autocomplete: "off",
@@ -2226,13 +2397,7 @@ var useCreateEditor = ({
2226
2397
  },
2227
2398
  immediatelyRender: false,
2228
2399
  shouldRerenderOnTransaction: false,
2229
- extensions: getExtensions({
2230
- editable,
2231
- placeholder,
2232
- enableControls,
2233
- controlResolver,
2234
- fileHandler
2235
- }),
2400
+ extensions,
2236
2401
  editable,
2237
2402
  onUpdate: ({ editor: editor2 }) => {
2238
2403
  onChange == null ? void 0 : onChange(editor2.getJSON());
@@ -2240,7 +2405,7 @@ var useCreateEditor = ({
2240
2405
  content: safeParseContent(content),
2241
2406
  ...options
2242
2407
  });
2243
- (0, import_react23.useEffect)(() => {
2408
+ (0, import_react26.useEffect)(() => {
2244
2409
  if (editor && editor.isEditable !== editable) {
2245
2410
  editor.setEditable(editable);
2246
2411
  }
@@ -2304,8 +2469,12 @@ function getExtensions({
2304
2469
  CalloutNode,
2305
2470
  MathBlock,
2306
2471
  InlineMath,
2307
- // Image support - always include for display
2308
- ImageNode,
2472
+ // Image support - extended with file reference resolution
2473
+ ImageNode.configure({
2474
+ allowBase64: true
2475
+ }),
2476
+ // Image upload placeholder
2477
+ ImageUploadNode,
2309
2478
  import_extensions.Placeholder.configure({
2310
2479
  placeholder,
2311
2480
  emptyNodeClass: "is-empty with-slash"