lexxy 0.1.18.beta → 0.1.20.beta
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.
- checksums.yaml +4 -4
- data/app/assets/javascript/lexxy.js +159 -25
- data/app/assets/javascript/lexxy.js.br +0 -0
- data/app/assets/javascript/lexxy.js.gz +0 -0
- data/app/assets/javascript/lexxy.min.js +2 -2
- data/app/assets/javascript/lexxy.min.js.br +0 -0
- data/app/assets/javascript/lexxy.min.js.gz +0 -0
- data/lib/lexxy/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 28ddded3fff65c55a5e194a1ba8246411fad9193b32ab319cc5a6330ab999420
|
|
4
|
+
data.tar.gz: 98a6bf19a11687400a21baed5117d65de05f02e595f3d7684f1fb70f8c8ffeea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00025443273a087c88de7463ab211f85e1e887ee3e33958f4813101c370f6f5949d79e88ba1c3e4347f77d4a5aaebf0231215f2af86e3fdaab35ce230572927f
|
|
7
|
+
data.tar.gz: ebb4db2b79be6937eca5af5e77aa62c8efd41a8e5bb6af0576865dd2f415f6d8de26f2e8c476e60c5f648ef0ce37cd1333e2490efd5c8c4fc5b4f28367d0f870
|
|
@@ -5869,6 +5869,10 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
5869
5869
|
return new ActionTextAttachmentUploadNode({ ...node }, node.__key)
|
|
5870
5870
|
}
|
|
5871
5871
|
|
|
5872
|
+
static importJSON(serializedNode) {
|
|
5873
|
+
return new ActionTextAttachmentUploadNode({ ...serializedNode })
|
|
5874
|
+
}
|
|
5875
|
+
|
|
5872
5876
|
constructor({ file, uploadUrl, blobUrlTemplate, editor, progress }, key) {
|
|
5873
5877
|
super({ contentType: file.type }, key);
|
|
5874
5878
|
this.file = file;
|
|
@@ -5908,6 +5912,17 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
5908
5912
|
return { element: img }
|
|
5909
5913
|
}
|
|
5910
5914
|
|
|
5915
|
+
exportJSON() {
|
|
5916
|
+
return {
|
|
5917
|
+
type: "action_text_attachment_upload",
|
|
5918
|
+
version: 1,
|
|
5919
|
+
progress: this.progress,
|
|
5920
|
+
uploadUrl: this.uploadUrl,
|
|
5921
|
+
blobUrlTemplate: this.blobUrlTemplate,
|
|
5922
|
+
...super.exportJSON()
|
|
5923
|
+
}
|
|
5924
|
+
}
|
|
5925
|
+
|
|
5911
5926
|
#createDOMForImage() {
|
|
5912
5927
|
return createElement("img")
|
|
5913
5928
|
}
|
|
@@ -6193,8 +6208,10 @@ class CommandDispatcher {
|
|
|
6193
6208
|
|
|
6194
6209
|
dispatchInsertHorizontalDivider() {
|
|
6195
6210
|
this.editor.update(() => {
|
|
6196
|
-
this.contents.
|
|
6211
|
+
this.contents.insertAtCursorEnsuringLineBelow(new HorizontalDividerNode());
|
|
6197
6212
|
});
|
|
6213
|
+
|
|
6214
|
+
this.editor.focus();
|
|
6198
6215
|
}
|
|
6199
6216
|
|
|
6200
6217
|
dispatchRotateHeadingFormat() {
|
|
@@ -6406,6 +6423,52 @@ class Selection {
|
|
|
6406
6423
|
});
|
|
6407
6424
|
}
|
|
6408
6425
|
|
|
6426
|
+
selectedNodeWithOffset() {
|
|
6427
|
+
const selection = Lr();
|
|
6428
|
+
if (!selection) return { node: null, offset: 0 }
|
|
6429
|
+
|
|
6430
|
+
if (yr(selection)) {
|
|
6431
|
+
return {
|
|
6432
|
+
node: selection.anchor.getNode(),
|
|
6433
|
+
offset: selection.anchor.offset
|
|
6434
|
+
}
|
|
6435
|
+
} else if (xr(selection)) {
|
|
6436
|
+
const [ node ] = selection.getNodes();
|
|
6437
|
+
return {
|
|
6438
|
+
node,
|
|
6439
|
+
offset: 0
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
|
|
6443
|
+
return { node: null, offset: 0 }
|
|
6444
|
+
}
|
|
6445
|
+
|
|
6446
|
+
preservingSelection(fn) {
|
|
6447
|
+
let selectionState = null;
|
|
6448
|
+
|
|
6449
|
+
this.editor.getEditorState().read(() => {
|
|
6450
|
+
const selection = Lr();
|
|
6451
|
+
if (selection && yr(selection)) {
|
|
6452
|
+
selectionState = {
|
|
6453
|
+
anchor: { key: selection.anchor.key, offset: selection.anchor.offset },
|
|
6454
|
+
focus: { key: selection.focus.key, offset: selection.focus.offset }
|
|
6455
|
+
};
|
|
6456
|
+
}
|
|
6457
|
+
});
|
|
6458
|
+
|
|
6459
|
+
fn();
|
|
6460
|
+
|
|
6461
|
+
if (selectionState) {
|
|
6462
|
+
this.editor.update(() => {
|
|
6463
|
+
const selection = Lr();
|
|
6464
|
+
if (selection && yr(selection)) {
|
|
6465
|
+
selection.anchor.set(selectionState.anchor.key, selectionState.anchor.offset, "text");
|
|
6466
|
+
selection.focus.set(selectionState.focus.key, selectionState.focus.offset, "text");
|
|
6467
|
+
}
|
|
6468
|
+
});
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
|
|
6409
6472
|
get hasSelectedWordsInSingleLine() {
|
|
6410
6473
|
const selection = Lr();
|
|
6411
6474
|
if (!yr(selection)) return false
|
|
@@ -6774,22 +6837,24 @@ class Selection {
|
|
|
6774
6837
|
const node = this.nodeAfterCursor;
|
|
6775
6838
|
if (node instanceof ki) {
|
|
6776
6839
|
this.#selectInLexical(node);
|
|
6840
|
+
return true
|
|
6777
6841
|
} else {
|
|
6778
6842
|
this.#contents.deleteSelectedNodes();
|
|
6779
6843
|
}
|
|
6780
6844
|
|
|
6781
|
-
return
|
|
6845
|
+
return false
|
|
6782
6846
|
}
|
|
6783
6847
|
|
|
6784
6848
|
#deletePreviousOrNext() {
|
|
6785
6849
|
const node = this.nodeBeforeCursor;
|
|
6786
6850
|
if (node instanceof ki) {
|
|
6787
6851
|
this.#selectInLexical(node);
|
|
6852
|
+
return true
|
|
6788
6853
|
} else {
|
|
6789
6854
|
this.#contents.deleteSelectedNodes();
|
|
6790
6855
|
}
|
|
6791
6856
|
|
|
6792
|
-
return
|
|
6857
|
+
return false
|
|
6793
6858
|
}
|
|
6794
6859
|
|
|
6795
6860
|
#getValidSelectionRange() {
|
|
@@ -7361,6 +7426,11 @@ class Contents {
|
|
|
7361
7426
|
});
|
|
7362
7427
|
}
|
|
7363
7428
|
|
|
7429
|
+
insertAtCursorEnsuringLineBelow(node) {
|
|
7430
|
+
this.insertAtCursor(node);
|
|
7431
|
+
this.#insertLineBelowIfLastNode(node);
|
|
7432
|
+
}
|
|
7433
|
+
|
|
7364
7434
|
insertNodeWrappingEachSelectedLine(newNodeFn) {
|
|
7365
7435
|
this.editor.update(() => {
|
|
7366
7436
|
const selection = Lr();
|
|
@@ -7645,6 +7715,17 @@ class Contents {
|
|
|
7645
7715
|
return this.editorElement.selection
|
|
7646
7716
|
}
|
|
7647
7717
|
|
|
7718
|
+
#insertLineBelowIfLastNode(node) {
|
|
7719
|
+
this.editor.update(() => {
|
|
7720
|
+
const nextSibling = node.getNextSibling();
|
|
7721
|
+
if (!nextSibling) {
|
|
7722
|
+
const newParagraph = Li();
|
|
7723
|
+
node.insertAfter(newParagraph);
|
|
7724
|
+
newParagraph.selectStart();
|
|
7725
|
+
}
|
|
7726
|
+
});
|
|
7727
|
+
}
|
|
7728
|
+
|
|
7648
7729
|
#unwrap(node) {
|
|
7649
7730
|
const children = node.getChildren();
|
|
7650
7731
|
|
|
@@ -7987,7 +8068,8 @@ class Contents {
|
|
|
7987
8068
|
lastInsertedNode.insertAfter(textNodeAfter);
|
|
7988
8069
|
|
|
7989
8070
|
this.#appendLineBreakIfNeeded(textNodeAfter.getParentOrThrow());
|
|
7990
|
-
|
|
8071
|
+
const cursorOffset = textAfterCursor ? 0 : 1;
|
|
8072
|
+
textNodeAfter.select(cursorOffset, cursorOffset);
|
|
7991
8073
|
}
|
|
7992
8074
|
|
|
7993
8075
|
#insertReplacementNodes(startNode, replacementNodes) {
|
|
@@ -8849,6 +8931,14 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
8849
8931
|
return this.hasAttribute("supports-space-in-searches")
|
|
8850
8932
|
}
|
|
8851
8933
|
|
|
8934
|
+
get open() {
|
|
8935
|
+
return this.popoverElement?.classList?.contains("lexxy-prompt-menu--visible")
|
|
8936
|
+
}
|
|
8937
|
+
|
|
8938
|
+
get closed() {
|
|
8939
|
+
return !this.open
|
|
8940
|
+
}
|
|
8941
|
+
|
|
8852
8942
|
get #doesSpaceSelect() {
|
|
8853
8943
|
return !this.supportsSpaceInSearches
|
|
8854
8944
|
}
|
|
@@ -8869,20 +8959,14 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
8869
8959
|
#addTriggerListener() {
|
|
8870
8960
|
const unregister = this.#editor.registerUpdateListener(() => {
|
|
8871
8961
|
this.#editor.read(() => {
|
|
8872
|
-
const
|
|
8873
|
-
if (!
|
|
8874
|
-
let node;
|
|
8875
|
-
if (yr(selection)) {
|
|
8876
|
-
node = selection.anchor.getNode();
|
|
8877
|
-
} else if (xr(selection)) {
|
|
8878
|
-
[ node ] = selection.getNodes();
|
|
8879
|
-
}
|
|
8962
|
+
const { node, offset } = this.#selection.selectedNodeWithOffset();
|
|
8963
|
+
if (!node) return
|
|
8880
8964
|
|
|
8881
|
-
if (node &&
|
|
8882
|
-
const
|
|
8883
|
-
const
|
|
8965
|
+
if (lr(node) && offset > 0) {
|
|
8966
|
+
const fullText = node.getTextContent();
|
|
8967
|
+
const charBeforeCursor = fullText[offset - 1];
|
|
8884
8968
|
|
|
8885
|
-
if (
|
|
8969
|
+
if (charBeforeCursor === this.trigger) {
|
|
8886
8970
|
unregister();
|
|
8887
8971
|
this.#showPopover();
|
|
8888
8972
|
}
|
|
@@ -8891,6 +8975,38 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
8891
8975
|
});
|
|
8892
8976
|
}
|
|
8893
8977
|
|
|
8978
|
+
#addCursorPositionListener() {
|
|
8979
|
+
this.cursorPositionListener = this.#editor.registerUpdateListener(() => {
|
|
8980
|
+
if (this.closed) return
|
|
8981
|
+
|
|
8982
|
+
this.#editor.read(() => {
|
|
8983
|
+
const { node, offset } = this.#selection.selectedNodeWithOffset();
|
|
8984
|
+
if (!node) return
|
|
8985
|
+
|
|
8986
|
+
if (lr(node) && offset > 0) {
|
|
8987
|
+
const fullText = node.getTextContent();
|
|
8988
|
+
const textBeforeCursor = fullText.slice(0, offset);
|
|
8989
|
+
const lastTriggerIndex = textBeforeCursor.lastIndexOf(this.trigger);
|
|
8990
|
+
|
|
8991
|
+
// If trigger is not found, or cursor is at or before the trigger position, hide popover
|
|
8992
|
+
if (lastTriggerIndex === -1 || offset <= lastTriggerIndex) {
|
|
8993
|
+
this.#hidePopover();
|
|
8994
|
+
}
|
|
8995
|
+
} else {
|
|
8996
|
+
// Cursor is not in a text node or at offset 0, hide popover
|
|
8997
|
+
this.#hidePopover();
|
|
8998
|
+
}
|
|
8999
|
+
});
|
|
9000
|
+
});
|
|
9001
|
+
}
|
|
9002
|
+
|
|
9003
|
+
#removeCursorPositionListener() {
|
|
9004
|
+
if (this.cursorPositionListener) {
|
|
9005
|
+
this.cursorPositionListener();
|
|
9006
|
+
this.cursorPositionListener = null;
|
|
9007
|
+
}
|
|
9008
|
+
}
|
|
9009
|
+
|
|
8894
9010
|
get #editor() {
|
|
8895
9011
|
return this.#editorElement.editor
|
|
8896
9012
|
}
|
|
@@ -8914,6 +9030,7 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
8914
9030
|
this.#editorElement.addEventListener("lexxy:change", this.#filterOptions);
|
|
8915
9031
|
|
|
8916
9032
|
this.#registerKeyListeners();
|
|
9033
|
+
this.#addCursorPositionListener();
|
|
8917
9034
|
}
|
|
8918
9035
|
|
|
8919
9036
|
#registerKeyListeners() {
|
|
@@ -8924,6 +9041,22 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
8924
9041
|
if (this.#doesSpaceSelect) {
|
|
8925
9042
|
this.keyListeners.push(this.#editor.registerCommand(be$1, this.#handleSelectedOption.bind(this), Bi));
|
|
8926
9043
|
}
|
|
9044
|
+
|
|
9045
|
+
// Register arrow keys with HIGH priority to prevent Lexical's selection handlers from running
|
|
9046
|
+
this.keyListeners.push(this.#editor.registerCommand(ke$1, this.#handleArrowUp.bind(this), Bi));
|
|
9047
|
+
this.keyListeners.push(this.#editor.registerCommand(Te$1, this.#handleArrowDown.bind(this), Bi));
|
|
9048
|
+
}
|
|
9049
|
+
|
|
9050
|
+
#handleArrowUp(event) {
|
|
9051
|
+
this.#moveSelectionUp();
|
|
9052
|
+
event.preventDefault();
|
|
9053
|
+
return true
|
|
9054
|
+
}
|
|
9055
|
+
|
|
9056
|
+
#handleArrowDown(event) {
|
|
9057
|
+
this.#moveSelectionDown();
|
|
9058
|
+
event.preventDefault();
|
|
9059
|
+
return true
|
|
8927
9060
|
}
|
|
8928
9061
|
|
|
8929
9062
|
#selectFirstOption() {
|
|
@@ -8941,8 +9074,14 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
8941
9074
|
#selectOption(listItem) {
|
|
8942
9075
|
this.#clearSelection();
|
|
8943
9076
|
listItem.toggleAttribute("aria-selected", true);
|
|
9077
|
+
listItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
8944
9078
|
listItem.focus();
|
|
8945
|
-
|
|
9079
|
+
|
|
9080
|
+
// Preserve selection to prevent cursor jump
|
|
9081
|
+
this.#selection.preservingSelection(() => {
|
|
9082
|
+
this.#editorElement.focus();
|
|
9083
|
+
});
|
|
9084
|
+
|
|
8946
9085
|
this.#editorContentElement.setAttribute("aria-controls", this.popoverElement.id);
|
|
8947
9086
|
this.#editorContentElement.setAttribute("aria-activedescendant", listItem.id);
|
|
8948
9087
|
this.#editorContentElement.setAttribute("aria-haspopup", "listbox");
|
|
@@ -8991,6 +9130,7 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
8991
9130
|
this.#editorElement.removeEventListener("keydown", this.#handleKeydownOnPopover);
|
|
8992
9131
|
|
|
8993
9132
|
this.#unregisterKeyListeners();
|
|
9133
|
+
this.#removeCursorPositionListener();
|
|
8994
9134
|
|
|
8995
9135
|
await nextFrame();
|
|
8996
9136
|
this.#addTriggerListener();
|
|
@@ -9009,6 +9149,7 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
9009
9149
|
|
|
9010
9150
|
if (this.#editorContents.containsTextBackUntil(this.trigger)) {
|
|
9011
9151
|
await this.#showFilteredOptions();
|
|
9152
|
+
await nextFrame();
|
|
9012
9153
|
this.#positionPopover();
|
|
9013
9154
|
} else {
|
|
9014
9155
|
this.#hidePopover();
|
|
@@ -9049,15 +9190,8 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
9049
9190
|
this.#hidePopover();
|
|
9050
9191
|
this.#editorElement.focus();
|
|
9051
9192
|
event.stopPropagation();
|
|
9052
|
-
} else if (event.key === "ArrowDown") {
|
|
9053
|
-
this.#moveSelectionDown();
|
|
9054
|
-
event.preventDefault();
|
|
9055
|
-
event.stopPropagation();
|
|
9056
|
-
} else if (event.key === "ArrowUp") {
|
|
9057
|
-
this.#moveSelectionUp();
|
|
9058
|
-
event.preventDefault();
|
|
9059
|
-
event.stopPropagation();
|
|
9060
9193
|
}
|
|
9194
|
+
// Arrow keys are now handled via Lexical commands with HIGH priority
|
|
9061
9195
|
}
|
|
9062
9196
|
|
|
9063
9197
|
#moveSelectionDown() {
|
|
Binary file
|
|
Binary file
|