@zm-editor/react 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9495,6 +9495,21 @@ function findNodePosFromDOM(editor, element) {
9495
9495
  const pos = editor.view.posAtDOM(nodeElement, 0);
9496
9496
  debugLog("findNodePosFromDOM", "posAtDOM for direct child returned:", pos);
9497
9497
  if (pos >= 0) {
9498
+ const isReactNodeView = nodeElement.classList.contains("react-renderer");
9499
+ if (isReactNodeView) {
9500
+ const $pos = editor.state.doc.resolve(pos);
9501
+ if ($pos.depth >= 1) {
9502
+ const nodePos = $pos.before(1);
9503
+ const node = editor.state.doc.nodeAt(nodePos);
9504
+ if (node) {
9505
+ debugLog("findNodePosFromDOM", "Found ReactNodeView node via $pos.before(1):", {
9506
+ type: node.type.name,
9507
+ pos: nodePos
9508
+ });
9509
+ return { pos: nodePos, node };
9510
+ }
9511
+ }
9512
+ }
9498
9513
  const nodeAtPos = editor.state.doc.nodeAt(pos);
9499
9514
  if (nodeAtPos) {
9500
9515
  debugLog("findNodePosFromDOM", "Found node at pos:", {
@@ -9503,9 +9518,9 @@ function findNodePosFromDOM(editor, element) {
9503
9518
  });
9504
9519
  return { pos, node: nodeAtPos };
9505
9520
  }
9506
- const $pos = editor.state.doc.resolve(pos);
9507
- if ($pos.depth >= 1) {
9508
- const nodePos = $pos.before(1);
9521
+ const $posResolved = editor.state.doc.resolve(pos);
9522
+ if ($posResolved.depth >= 1) {
9523
+ const nodePos = $posResolved.before(1);
9509
9524
  const node = editor.state.doc.nodeAt(nodePos);
9510
9525
  if (node) {
9511
9526
  debugLog("findNodePosFromDOM", "Found node via $pos.before(1):", {
@@ -9777,7 +9792,8 @@ function getContentTop(element, nodeTypeName) {
9777
9792
  "metadata",
9778
9793
  "openapi",
9779
9794
  "stackTrace",
9780
- "horizontalRule"
9795
+ "horizontalRule",
9796
+ "callout"
9781
9797
  ];
9782
9798
  if (atomNodeTypes.includes(nodeTypeName)) {
9783
9799
  debugLog("getContentTop", `Atom node (${nodeTypeName}): using rect.top=${rect.top}`);
@@ -9834,7 +9850,8 @@ function getNodeLineHeight(element, nodeTypeName) {
9834
9850
  "metadata",
9835
9851
  "openapi",
9836
9852
  "stackTrace",
9837
- "horizontalRule"
9853
+ "horizontalRule",
9854
+ "callout"
9838
9855
  ];
9839
9856
  if (atomNodeTypes.includes(nodeTypeName)) {
9840
9857
  const atomLineHeight = 24;
@@ -11520,8 +11537,10 @@ var ZmEditor = forwardRef(
11520
11537
  const handleEmojiSelect = useCallback(
11521
11538
  (emoji) => {
11522
11539
  if (!editor) return;
11523
- editor.chain().focus().insertContent(emoji).run();
11524
11540
  setShowEmojiPicker(false);
11541
+ requestAnimationFrame(() => {
11542
+ editor.chain().focus().insertContent(emoji).run();
11543
+ });
11525
11544
  },
11526
11545
  [editor]
11527
11546
  );
@@ -11700,12 +11719,12 @@ var SlashMenuComponent = class {
11700
11719
  this.selectedIndex + 1,
11701
11720
  this.props.items.length - 1
11702
11721
  );
11703
- this.render();
11722
+ this.updateSelection();
11704
11723
  return true;
11705
11724
  }
11706
11725
  if (event.key === "ArrowUp") {
11707
11726
  this.selectedIndex = Math.max(this.selectedIndex - 1, 0);
11708
- this.render();
11727
+ this.updateSelection();
11709
11728
  return true;
11710
11729
  }
11711
11730
  if (event.key === "Enter") {
@@ -11729,12 +11748,6 @@ var SlashMenuComponent = class {
11729
11748
  this.element.className = "zm-slash-menu";
11730
11749
  document.body.appendChild(this.element);
11731
11750
  }
11732
- const rect = this.props.clientRect?.();
11733
- if (rect) {
11734
- this.element.style.position = "fixed";
11735
- this.element.style.left = `${rect.left}px`;
11736
- this.element.style.top = `${rect.bottom + 8}px`;
11737
- }
11738
11751
  this.removeEventListeners();
11739
11752
  this.element.innerHTML = "";
11740
11753
  if (this.props.items.length === 0) {
@@ -11742,31 +11755,50 @@ var SlashMenuComponent = class {
11742
11755
  emptyDiv.className = "zm-slash-menu-empty";
11743
11756
  emptyDiv.textContent = this.props.noResultsText ?? "No results found";
11744
11757
  this.element.appendChild(emptyDiv);
11745
- return;
11746
- }
11747
- this.props.items.forEach((item, index) => {
11748
- const itemDiv = document.createElement("div");
11749
- itemDiv.className = `zm-slash-menu-item ${index === this.selectedIndex ? "selected" : ""}`;
11750
- itemDiv.dataset.index = String(index);
11751
- const titleDiv = document.createElement("div");
11752
- titleDiv.className = "zm-slash-menu-item-title";
11753
- titleDiv.textContent = item.title;
11754
- const descDiv = document.createElement("div");
11755
- descDiv.className = "zm-slash-menu-item-description";
11756
- descDiv.textContent = item.description;
11757
- itemDiv.appendChild(titleDiv);
11758
- itemDiv.appendChild(descDiv);
11759
- this.element.appendChild(itemDiv);
11760
- const handler = () => {
11761
- this.props.command(item);
11762
- };
11763
- itemDiv.addEventListener("click", handler);
11764
- this.clickHandlers.push({ element: itemDiv, handler });
11765
- itemDiv.addEventListener("mouseenter", () => {
11766
- this.selectedIndex = index;
11767
- this.updateSelection();
11758
+ } else {
11759
+ this.props.items.forEach((item, index) => {
11760
+ const itemDiv = document.createElement("div");
11761
+ itemDiv.className = `zm-slash-menu-item ${index === this.selectedIndex ? "selected" : ""}`;
11762
+ itemDiv.dataset.index = String(index);
11763
+ const titleDiv = document.createElement("div");
11764
+ titleDiv.className = "zm-slash-menu-item-title";
11765
+ titleDiv.textContent = item.title;
11766
+ const descDiv = document.createElement("div");
11767
+ descDiv.className = "zm-slash-menu-item-description";
11768
+ descDiv.textContent = item.description;
11769
+ itemDiv.appendChild(titleDiv);
11770
+ itemDiv.appendChild(descDiv);
11771
+ this.element.appendChild(itemDiv);
11772
+ const handler = () => {
11773
+ this.props.command(item);
11774
+ };
11775
+ itemDiv.addEventListener("click", handler);
11776
+ this.clickHandlers.push({ element: itemDiv, handler });
11777
+ itemDiv.addEventListener("mouseenter", () => {
11778
+ this.selectedIndex = index;
11779
+ this.updateSelection();
11780
+ });
11768
11781
  });
11769
- });
11782
+ }
11783
+ const rect = this.props.clientRect?.();
11784
+ if (rect) {
11785
+ this.element.style.position = "fixed";
11786
+ this.element.style.left = `${rect.left}px`;
11787
+ const menuMaxHeight = 320;
11788
+ const gap = 8;
11789
+ const menuHeight = Math.min(this.element.scrollHeight, menuMaxHeight);
11790
+ const spaceBelow = window.innerHeight - rect.bottom - gap;
11791
+ const spaceAbove = rect.top - gap;
11792
+ if (spaceAbove >= menuHeight || spaceAbove > spaceBelow) {
11793
+ const availableHeight = Math.min(menuMaxHeight, spaceAbove);
11794
+ this.element.style.top = `${rect.top - Math.min(menuHeight, availableHeight) - gap}px`;
11795
+ this.element.style.maxHeight = `${availableHeight}px`;
11796
+ } else {
11797
+ this.element.style.top = `${rect.bottom + gap}px`;
11798
+ const availableHeight = Math.min(menuMaxHeight, spaceBelow);
11799
+ this.element.style.maxHeight = `${availableHeight}px`;
11800
+ }
11801
+ }
11770
11802
  }
11771
11803
  updateSelection() {
11772
11804
  if (!this.element) return;
@@ -11774,6 +11806,15 @@ var SlashMenuComponent = class {
11774
11806
  items.forEach((item, index) => {
11775
11807
  if (index === this.selectedIndex) {
11776
11808
  item.classList.add("selected");
11809
+ const el = item;
11810
+ const container = this.element;
11811
+ const itemTop = el.offsetTop;
11812
+ const itemBottom = itemTop + el.offsetHeight;
11813
+ if (itemTop < container.scrollTop) {
11814
+ container.scrollTop = itemTop;
11815
+ } else if (itemBottom > container.scrollTop + container.clientHeight) {
11816
+ container.scrollTop = itemBottom - container.clientHeight;
11817
+ }
11777
11818
  } else {
11778
11819
  item.classList.remove("selected");
11779
11820
  }
@@ -11833,12 +11874,12 @@ var MentionMenuComponent = class {
11833
11874
  this.selectedIndex + 1,
11834
11875
  this.props.items.length - 1
11835
11876
  );
11836
- this.render();
11877
+ this.updateSelection();
11837
11878
  return true;
11838
11879
  }
11839
11880
  if (event.key === "ArrowUp") {
11840
11881
  this.selectedIndex = Math.max(this.selectedIndex - 1, 0);
11841
- this.render();
11882
+ this.updateSelection();
11842
11883
  return true;
11843
11884
  }
11844
11885
  if (event.key === "Enter") {
@@ -11862,12 +11903,6 @@ var MentionMenuComponent = class {
11862
11903
  this.element.className = "zm-mention-list";
11863
11904
  document.body.appendChild(this.element);
11864
11905
  }
11865
- const rect = this.props.clientRect?.();
11866
- if (rect) {
11867
- this.element.style.position = "fixed";
11868
- this.element.style.left = `${rect.left}px`;
11869
- this.element.style.top = `${rect.bottom + 8}px`;
11870
- }
11871
11906
  this.removeEventListeners();
11872
11907
  this.element.innerHTML = "";
11873
11908
  if (this.props.items.length === 0) {
@@ -11875,47 +11910,66 @@ var MentionMenuComponent = class {
11875
11910
  emptyDiv.className = "zm-mention-list-empty";
11876
11911
  emptyDiv.textContent = "No users found";
11877
11912
  this.element.appendChild(emptyDiv);
11878
- return;
11913
+ } else {
11914
+ this.props.items.forEach((item, index) => {
11915
+ const itemDiv = document.createElement("div");
11916
+ itemDiv.className = `zm-mention-list-item ${index === this.selectedIndex ? "selected" : ""}`;
11917
+ if (item.avatar) {
11918
+ const avatarImg = document.createElement("img");
11919
+ avatarImg.src = item.avatar;
11920
+ avatarImg.alt = item.label;
11921
+ avatarImg.className = "zm-mention-list-avatar";
11922
+ itemDiv.appendChild(avatarImg);
11923
+ } else {
11924
+ const avatarPlaceholder = document.createElement("div");
11925
+ avatarPlaceholder.className = "zm-mention-list-avatar-placeholder";
11926
+ avatarPlaceholder.textContent = item.label.charAt(0).toUpperCase();
11927
+ itemDiv.appendChild(avatarPlaceholder);
11928
+ }
11929
+ const contentDiv = document.createElement("div");
11930
+ contentDiv.className = "zm-mention-list-content";
11931
+ const labelDiv = document.createElement("div");
11932
+ labelDiv.className = "zm-mention-list-label";
11933
+ labelDiv.textContent = item.label;
11934
+ contentDiv.appendChild(labelDiv);
11935
+ if (item.description) {
11936
+ const descDiv = document.createElement("div");
11937
+ descDiv.className = "zm-mention-list-description";
11938
+ descDiv.textContent = item.description;
11939
+ contentDiv.appendChild(descDiv);
11940
+ }
11941
+ itemDiv.appendChild(contentDiv);
11942
+ this.element.appendChild(itemDiv);
11943
+ const handler = () => {
11944
+ this.props.command(item);
11945
+ };
11946
+ itemDiv.addEventListener("click", handler);
11947
+ this.clickHandlers.push({ element: itemDiv, handler });
11948
+ itemDiv.addEventListener("mouseenter", () => {
11949
+ this.selectedIndex = index;
11950
+ this.updateSelection();
11951
+ });
11952
+ });
11879
11953
  }
11880
- this.props.items.forEach((item, index) => {
11881
- const itemDiv = document.createElement("div");
11882
- itemDiv.className = `zm-mention-list-item ${index === this.selectedIndex ? "selected" : ""}`;
11883
- if (item.avatar) {
11884
- const avatarImg = document.createElement("img");
11885
- avatarImg.src = item.avatar;
11886
- avatarImg.alt = item.label;
11887
- avatarImg.className = "zm-mention-list-avatar";
11888
- itemDiv.appendChild(avatarImg);
11954
+ const rect = this.props.clientRect?.();
11955
+ if (rect) {
11956
+ this.element.style.position = "fixed";
11957
+ this.element.style.left = `${rect.left}px`;
11958
+ const menuMaxHeight = 240;
11959
+ const gap = 8;
11960
+ const menuHeight = Math.min(this.element.scrollHeight, menuMaxHeight);
11961
+ const spaceBelow = window.innerHeight - rect.bottom - gap;
11962
+ const spaceAbove = rect.top - gap;
11963
+ if (spaceAbove >= menuHeight || spaceAbove > spaceBelow) {
11964
+ const availableHeight = Math.min(menuMaxHeight, spaceAbove);
11965
+ this.element.style.top = `${rect.top - Math.min(menuHeight, availableHeight) - gap}px`;
11966
+ this.element.style.maxHeight = `${availableHeight}px`;
11889
11967
  } else {
11890
- const avatarPlaceholder = document.createElement("div");
11891
- avatarPlaceholder.className = "zm-mention-list-avatar-placeholder";
11892
- avatarPlaceholder.textContent = item.label.charAt(0).toUpperCase();
11893
- itemDiv.appendChild(avatarPlaceholder);
11894
- }
11895
- const contentDiv = document.createElement("div");
11896
- contentDiv.className = "zm-mention-list-content";
11897
- const labelDiv = document.createElement("div");
11898
- labelDiv.className = "zm-mention-list-label";
11899
- labelDiv.textContent = item.label;
11900
- contentDiv.appendChild(labelDiv);
11901
- if (item.description) {
11902
- const descDiv = document.createElement("div");
11903
- descDiv.className = "zm-mention-list-description";
11904
- descDiv.textContent = item.description;
11905
- contentDiv.appendChild(descDiv);
11968
+ this.element.style.top = `${rect.bottom + gap}px`;
11969
+ const availableHeight = Math.min(menuMaxHeight, spaceBelow);
11970
+ this.element.style.maxHeight = `${availableHeight}px`;
11906
11971
  }
11907
- itemDiv.appendChild(contentDiv);
11908
- this.element.appendChild(itemDiv);
11909
- const handler = () => {
11910
- this.props.command(item);
11911
- };
11912
- itemDiv.addEventListener("click", handler);
11913
- this.clickHandlers.push({ element: itemDiv, handler });
11914
- itemDiv.addEventListener("mouseenter", () => {
11915
- this.selectedIndex = index;
11916
- this.updateSelection();
11917
- });
11918
- });
11972
+ }
11919
11973
  }
11920
11974
  updateSelection() {
11921
11975
  if (!this.element) return;
@@ -11923,6 +11977,15 @@ var MentionMenuComponent = class {
11923
11977
  items.forEach((item, index) => {
11924
11978
  if (index === this.selectedIndex) {
11925
11979
  item.classList.add("selected");
11980
+ const el = item;
11981
+ const container = this.element;
11982
+ const itemTop = el.offsetTop;
11983
+ const itemBottom = itemTop + el.offsetHeight;
11984
+ if (itemTop < container.scrollTop) {
11985
+ container.scrollTop = itemTop;
11986
+ } else if (itemBottom > container.scrollTop + container.clientHeight) {
11987
+ container.scrollTop = itemBottom - container.clientHeight;
11988
+ }
11926
11989
  } else {
11927
11990
  item.classList.remove("selected");
11928
11991
  }