@37signals/lexxy 0.9.9-beta.preview2 → 0.9.9-beta.preview3.domselection1

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 (2) hide show
  1. package/dist/lexxy.esm.js +41 -16
  2. package/package.json +1 -1
package/dist/lexxy.esm.js CHANGED
@@ -2,7 +2,7 @@ import { isActiveAndVisible, createElement, extractPlainTextFromHtml, createAtta
2
2
  export { highlightCode } from './lexxy_helpers.esm.js';
3
3
  import DOMPurify from 'dompurify';
4
4
  import { getStyleObjectFromCSS, getCSSFromStyleObject, $isAtNodeEnd, $getSelectionStyleValueForProperty, $patchStyleText, $ensureForwardRangeSelection, $setBlocksType, $forEachSelectedTextNode } from '@lexical/selection';
5
- import { SKIP_DOM_SELECTION_TAG, CAN_UNDO_COMMAND, COMMAND_PRIORITY_LOW, CAN_REDO_COMMAND, $getSelection, $isRangeSelection, DecoratorNode, $createParagraphNode, $getNodeByKey, $isTextNode, $createRangeSelection, $setSelection, $createTextNode, $isElementNode, $isRootOrShadowRoot, $isRootNode, $createNodeSelection, $isDecoratorNode, $isLineBreakNode, TextNode, createCommand, createState, defineExtension, COMMAND_PRIORITY_NORMAL, $getState, $setState, $hasUpdateTag, PASTE_TAG, FORMAT_TEXT_COMMAND, UNDO_COMMAND, REDO_COMMAND, PASTE_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, COMMAND_PRIORITY_EDITOR, $getEditor, HISTORY_MERGE_TAG, SKIP_SCROLL_INTO_VIEW_TAG, $cloneWithProperties, $getNearestRootOrShadowRoot, $isNodeSelection, $getRoot, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_DOWN_COMMAND, DELETE_CHARACTER_COMMAND, SELECTION_CHANGE_COMMAND, CLICK_COMMAND, isDOMNode, $getNearestNodeFromDOMNode, $addUpdateTag, ElementNode, $splitNode, $getChildCaretAtIndex, $createLineBreakNode, $isParagraphNode, ParagraphNode, RootNode, COMMAND_PRIORITY_HIGH, DRAGSTART_COMMAND, DROP_COMMAND, INSERT_PARAGRAPH_COMMAND, mergeRegister as mergeRegister$1, $findMatchingParent, CLEAR_HISTORY_COMMAND, KEY_ENTER_COMMAND, COMMAND_PRIORITY_CRITICAL, KEY_SPACE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND } from 'lexical';
5
+ import { SKIP_DOM_SELECTION_TAG, CAN_UNDO_COMMAND, COMMAND_PRIORITY_LOW, CAN_REDO_COMMAND, $getSelection, $isRangeSelection, DecoratorNode, $createParagraphNode, $getNodeByKey, $isTextNode, $createRangeSelection, $setSelection, $createTextNode, $isElementNode, $isRootOrShadowRoot, $isRootNode, $createNodeSelection, $isDecoratorNode, $isLineBreakNode, TextNode, createCommand, createState, defineExtension, COMMAND_PRIORITY_NORMAL, $getState, $setState, $hasUpdateTag, PASTE_TAG, FORMAT_TEXT_COMMAND, UNDO_COMMAND, REDO_COMMAND, PASTE_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, COMMAND_PRIORITY_EDITOR, $getEditor, HISTORY_MERGE_TAG, SKIP_SCROLL_INTO_VIEW_TAG, $cloneWithProperties, $getNearestRootOrShadowRoot, $isNodeSelection, $getRoot, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_DOWN_COMMAND, DELETE_CHARACTER_COMMAND, SELECTION_CHANGE_COMMAND, CLICK_COMMAND, isDOMNode, $getNearestNodeFromDOMNode, $addUpdateTag, ElementNode, $splitNode, $getChildCaretAtIndex, $createLineBreakNode, $isParagraphNode, ParagraphNode, RootNode, COMMAND_PRIORITY_HIGH, DRAGSTART_COMMAND, DROP_COMMAND, INSERT_PARAGRAPH_COMMAND, mergeRegister as mergeRegister$1, $findMatchingParent, CLEAR_HISTORY_COMMAND, $onUpdate, KEY_ENTER_COMMAND, COMMAND_PRIORITY_CRITICAL, KEY_SPACE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND } from 'lexical';
6
6
  import { buildEditorFromExtensions } from '@lexical/extension';
7
7
  import { ListNode, ListItemNode, $getListDepth, INSERT_UNORDERED_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, $isListItemNode, $isListNode, registerList } from '@lexical/list';
8
8
  import { LinkNode, $createAutoLinkNode, $toggleLink, $createLinkNode, $isLinkNode, AutoLinkNode } from '@lexical/link';
@@ -2655,6 +2655,13 @@ class RewritableHistoryExtension extends LexxyExtension {
2655
2655
  }
2656
2656
 
2657
2657
  #rewriteHistory(rewrites) {
2658
+ this.#applyRewritesImmediatelyToCurrentState(rewrites);
2659
+ this.#applyRewritesToHistory(rewrites);
2660
+
2661
+ return true
2662
+ }
2663
+
2664
+ #applyRewritesImmediatelyToCurrentState(rewrites) {
2658
2665
  $getEditor().update(() => {
2659
2666
  for (const [ nodeKey, { patch, replace } ] of Object.entries(rewrites)) {
2660
2667
  const node = $getNodeByKey(nodeKey);
@@ -2664,27 +2671,27 @@ class RewritableHistoryExtension extends LexxyExtension {
2664
2671
  if (replace) node.replace(replace);
2665
2672
  }
2666
2673
  }, { discrete: true, tag: this.#getBackgroundUpdateTags() });
2674
+ }
2667
2675
 
2676
+ #applyRewritesToHistory(rewrites) {
2668
2677
  const nodeKeys = Object.keys(rewrites);
2669
2678
 
2670
2679
  for (const entry of this.#allHistoryEntries) {
2671
2680
  if (!this.#entryHasSomeKeys(entry, nodeKeys)) continue
2672
2681
 
2682
+ const editorState = entry.editorState = safeCloneEditorState(entry.editorState);
2683
+
2673
2684
  for (const [ nodeKey, { patch, replace } ] of Object.entries(rewrites)) {
2674
- const node = entry.editorState._nodeMap.get(nodeKey);
2685
+ const node = editorState._nodeMap.get(nodeKey);
2675
2686
  if (!node) continue
2676
2687
 
2677
- entry.editorState = safeCloneEditorState(entry.editorState);
2678
-
2679
2688
  if (patch) {
2680
- entry.editorState._nodeMap.set(nodeKey, $cloneNodeWithPatch(node, patch));
2689
+ this.#patchNodeInEditorState(editorState, node, patch);
2681
2690
  } else if (replace) {
2682
- entry.editorState._nodeMap.set(nodeKey, $cloneNodeAdoptingKey(replace, node));
2691
+ this.#replaceNodeInEditorState(editorState, node, replace);
2683
2692
  }
2684
2693
  }
2685
2694
  }
2686
-
2687
- return true
2688
2695
  }
2689
2696
 
2690
2697
  #entryHasSomeKeys(entry, nodeKeys) {
@@ -2696,6 +2703,14 @@ class RewritableHistoryExtension extends LexxyExtension {
2696
2703
  if (!isEditorFocused(this.editorElement.editor)) { tags.push(SKIP_DOM_SELECTION_TAG); }
2697
2704
  return tags
2698
2705
  }
2706
+
2707
+ #patchNodeInEditorState(editorState, node, patch) {
2708
+ editorState._nodeMap.set(node.__key, $cloneNodeWithPatch(node, patch));
2709
+ }
2710
+
2711
+ #replaceNodeInEditorState(editorState, node, replaceWith) {
2712
+ editorState._nodeMap.set(node.__key, $cloneNodeAdoptingKeys(replaceWith, node));
2713
+ }
2699
2714
  }
2700
2715
 
2701
2716
  function $cloneNodeWithPatch(node, patch) {
@@ -2704,12 +2719,12 @@ function $cloneNodeWithPatch(node, patch) {
2704
2719
  return clone
2705
2720
  }
2706
2721
 
2707
- function $cloneNodeAdoptingKey(source, keyNode) {
2708
- const clone = $cloneWithProperties(source);
2709
- clone.__key = keyNode.__key;
2710
- clone.__parent = keyNode.__parent;
2711
- clone.__prev = keyNode.__prev;
2712
- clone.__next = keyNode.__next;
2722
+ function $cloneNodeAdoptingKeys(node, previousNode) {
2723
+ const clone = $cloneWithProperties(node);
2724
+ clone.__key = previousNode.__key;
2725
+ clone.__parent = previousNode.__parent;
2726
+ clone.__prev = previousNode.__prev;
2727
+ clone.__next = previousNode.__next;
2713
2728
  return clone
2714
2729
  }
2715
2730
 
@@ -6932,7 +6947,7 @@ class LexicalEditorElement extends HTMLElement {
6932
6947
  }
6933
6948
 
6934
6949
  get #isContentFocused() {
6935
- return !!this.editorContentElement && this.editorContentElement.contains(document.activeElement)
6950
+ return !!this.editor && isEditorFocused(this.editor)
6936
6951
  }
6937
6952
 
6938
6953
  get value() {
@@ -6946,14 +6961,24 @@ class LexicalEditorElement extends HTMLElement {
6946
6961
  }
6947
6962
 
6948
6963
  set value(html) {
6964
+ const editorHasFocus = this.#isContentFocused;
6965
+
6949
6966
  this.editor.update(() => {
6967
+ if (editorHasFocus) {
6968
+ // Address Safari inconsistently placing the cursor in the contenteditable by forcing focus back onto the editor
6969
+ // Use direct `editor.focus` to bypass the pre-existing focus optimization and skip the callback
6970
+ $onUpdate(() => this.editor.focus());
6971
+ } else {
6972
+ $addUpdateTag(SKIP_DOM_SELECTION_TAG);
6973
+ }
6974
+
6950
6975
  $getRoot()
6951
6976
  .clear()
6952
6977
  .selectEnd()
6953
6978
  .insertNodes(this.#parseHtmlIntoLexicalNodes(html));
6954
6979
 
6955
6980
  this.#toggleEmptyStatus();
6956
- }, { discrete: true, tag: SKIP_DOM_SELECTION_TAG });
6981
+ }, { discrete: true });
6957
6982
  }
6958
6983
 
6959
6984
  get canUndo() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@37signals/lexxy",
3
- "version": "0.9.9-beta.preview2",
3
+ "version": "0.9.9-beta.preview3.domselection1",
4
4
  "description": "Lexxy - A modern rich text editor for Rails.",
5
5
  "module": "dist/lexxy.esm.js",
6
6
  "type": "module",