@trafica/editor 1.0.54 → 1.0.56

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.mjs CHANGED
@@ -894,6 +894,30 @@ function renderDocument(doc, container) {
894
894
  container.appendChild(blockEl);
895
895
  }
896
896
  }
897
+ function patchDocument(prevDoc, nextDoc, container) {
898
+ const prev = prevDoc.children;
899
+ const next = nextDoc.children;
900
+ if (prev.length !== next.length) {
901
+ renderDocument(nextDoc, container);
902
+ return;
903
+ }
904
+ if (container.children.length !== next.length) {
905
+ renderDocument(nextDoc, container);
906
+ return;
907
+ }
908
+ const domChildren = container.children;
909
+ for (let i = 0; i < next.length; i++) {
910
+ if (next[i] !== prev[i]) {
911
+ const oldEl = domChildren[i];
912
+ if (!oldEl) {
913
+ renderDocument(nextDoc, container);
914
+ return;
915
+ }
916
+ const newEl = renderBlock(next[i], [i]);
917
+ container.replaceChild(newEl, oldEl);
918
+ }
919
+ }
920
+ }
897
921
  function renderBlock(node, path) {
898
922
  switch (node.type) {
899
923
  case "paragraph":
@@ -8007,6 +8031,9 @@ function EditorCore({
8007
8031
  }) {
8008
8032
  const containerRef = useRef(null);
8009
8033
  const isRenderingRef = useRef(false);
8034
+ const prevDocRef = useRef(null);
8035
+ const htmlDebounceRef = useRef(null);
8036
+ const jsonDebounceRef = useRef(null);
8010
8037
  const skipRestoreSelectionRef = useRef(false);
8011
8038
  const scrollCaretIntoView = useCallback(() => {
8012
8039
  var _a, _b;
@@ -8102,7 +8129,13 @@ function EditorCore({
8102
8129
  const container = containerRef.current;
8103
8130
  if (!container) return;
8104
8131
  isRenderingRef.current = true;
8105
- renderDocument(state.doc, container);
8132
+ const prevDoc = prevDocRef.current;
8133
+ if (prevDoc) {
8134
+ patchDocument(prevDoc, state.doc, container);
8135
+ } else {
8136
+ renderDocument(state.doc, container);
8137
+ }
8138
+ prevDocRef.current = state.doc;
8106
8139
  if (!container.contains(document.activeElement)) {
8107
8140
  container.focus({ preventScroll: true });
8108
8141
  }
@@ -8112,10 +8145,16 @@ function EditorCore({
8112
8145
  }
8113
8146
  isRenderingRef.current = false;
8114
8147
  if (onHTMLChange) {
8115
- onHTMLChange(htmlSerializer.serialize(state.doc));
8148
+ if (htmlDebounceRef.current) clearTimeout(htmlDebounceRef.current);
8149
+ htmlDebounceRef.current = setTimeout(() => {
8150
+ onHTMLChange(htmlSerializer.serialize(engine.getState().doc));
8151
+ }, 300);
8116
8152
  }
8117
8153
  if (onJSONChange) {
8118
- onJSONChange(jsonSerializer.serialize(state.doc));
8154
+ if (jsonDebounceRef.current) clearTimeout(jsonDebounceRef.current);
8155
+ jsonDebounceRef.current = setTimeout(() => {
8156
+ onJSONChange(jsonSerializer.serialize(engine.getState().doc));
8157
+ }, 300);
8119
8158
  }
8120
8159
  }, [state.doc]);
8121
8160
  useLayoutEffect(() => {
@@ -8190,7 +8229,7 @@ function EditorCore({
8190
8229
  const captured = captureSelection(container);
8191
8230
  if (!captured) return;
8192
8231
  const currentSelection = engine.getState().selection;
8193
- if (currentSelection && JSON.stringify(currentSelection.anchor) === JSON.stringify(captured.anchor) && JSON.stringify(currentSelection.focus) === JSON.stringify(captured.focus)) {
8232
+ if (currentSelection && selectionEqual(currentSelection.anchor, captured.anchor) && selectionEqual(currentSelection.focus, captured.focus)) {
8194
8233
  return;
8195
8234
  }
8196
8235
  skipRestoreSelectionRef.current = true;
@@ -8897,6 +8936,14 @@ var BLOCK_TAGS = "p|h[1-6]|ul|ol|li|blockquote|pre|figure|table|thead|tbody|tr|t
8897
8936
  var _OPEN_ONLY_RE = new RegExp(`^<(${BLOCK_TAGS})(?:\\s[^>]*)?>$`, "i");
8898
8937
  var _CLOSE_ONLY_RE = new RegExp(`^<\\/(${BLOCK_TAGS})>$`, "i");
8899
8938
  var _HR_RE = /^<hr(\s[^>]*)?\/?>$/i;
8939
+ function selectionEqual(a, b) {
8940
+ if (a.offset !== b.offset) return false;
8941
+ if (a.path.length !== b.path.length) return false;
8942
+ for (let i = 0; i < a.path.length; i++) {
8943
+ if (a.path[i] !== b.path[i]) return false;
8944
+ }
8945
+ return true;
8946
+ }
8900
8947
  function leafTextNode(el, end) {
8901
8948
  let node = el;
8902
8949
  while (node.hasChildNodes()) {