lexxy 0.9.19.alpha.2 → 0.9.19.alpha.3
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 +188 -84
- data/app/assets/javascript/lexxy.js.br +0 -0
- data/app/assets/javascript/lexxy.js.gz +0 -0
- data/app/assets/javascript/lexxy.js.map +1 -1
- 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 +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf2150a951764595691835dfe6bb97aa8a0bf4be41600e611f94156646aaba51
|
|
4
|
+
data.tar.gz: f24a3dc76fec3b0d924b3f9cd2839c1faa747ff9a051e5c57075530c6ca0abbd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9e1e04f1e9bd1f32513f1c64efbd69ca49519307906851d6c11958232a3a0307a0dd31f512007df583bee752c52e97dac2fa87be8bc13dcd2d1d7ef57aa0dc06
|
|
7
|
+
data.tar.gz: 231f6d4ad4a687800ac5ed43941af7cdea2386549cbc26c3df538db628a6847406013065f0c452c0bc2acfa093afa759a7007cce0639ecbdd9953ecd727da77f
|
|
@@ -6301,6 +6301,14 @@ class ListenerBin {
|
|
|
6301
6301
|
}
|
|
6302
6302
|
}
|
|
6303
6303
|
|
|
6304
|
+
function handlingDefault(handler) {
|
|
6305
|
+
return event => {
|
|
6306
|
+
const handled = handler(event);
|
|
6307
|
+
if (handled) event.preventDefault();
|
|
6308
|
+
return handled
|
|
6309
|
+
}
|
|
6310
|
+
}
|
|
6311
|
+
|
|
6304
6312
|
function createElement(name, properties, content = "") {
|
|
6305
6313
|
const element = document.createElement(name);
|
|
6306
6314
|
for (const [ key, value ] of Object.entries(properties || {})) {
|
|
@@ -9189,6 +9197,30 @@ var theme = {
|
|
|
9189
9197
|
}
|
|
9190
9198
|
};
|
|
9191
9199
|
|
|
9200
|
+
class UploadRequests {
|
|
9201
|
+
#requestsByKey = new Map()
|
|
9202
|
+
|
|
9203
|
+
track(key, request) {
|
|
9204
|
+
this.#requestsByKey.set(key, request);
|
|
9205
|
+
}
|
|
9206
|
+
|
|
9207
|
+
forget(key) {
|
|
9208
|
+
this.#requestsByKey.delete(key);
|
|
9209
|
+
}
|
|
9210
|
+
|
|
9211
|
+
abort(key) {
|
|
9212
|
+
const request = this.#requestsByKey.get(key);
|
|
9213
|
+
if (request) {
|
|
9214
|
+
this.#requestsByKey.delete(key);
|
|
9215
|
+
request.abort();
|
|
9216
|
+
}
|
|
9217
|
+
}
|
|
9218
|
+
|
|
9219
|
+
clear() {
|
|
9220
|
+
this.#requestsByKey.clear();
|
|
9221
|
+
}
|
|
9222
|
+
}
|
|
9223
|
+
|
|
9192
9224
|
/**
|
|
9193
9225
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
9194
9226
|
*
|
|
@@ -10574,10 +10606,10 @@ class Selection {
|
|
|
10574
10606
|
|
|
10575
10607
|
#processSelectionChangeCommands() {
|
|
10576
10608
|
this.#listeners.track(
|
|
10577
|
-
this.editor.registerCommand(Ne$1, this.#selectPreviousNode.bind(this), io),
|
|
10578
|
-
this.editor.registerCommand(ke$2, this.#selectNextNode.bind(this), io),
|
|
10579
|
-
this.editor.registerCommand(we$1, this.#selectPreviousTopLevelNode.bind(this), io),
|
|
10580
|
-
this.editor.registerCommand(Ee$3, this.#selectNextTopLevelNode.bind(this), io),
|
|
10609
|
+
this.editor.registerCommand(Ne$1, handlingDefault(this.#selectPreviousNode.bind(this)), io),
|
|
10610
|
+
this.editor.registerCommand(ke$2, handlingDefault(this.#selectNextNode.bind(this)), io),
|
|
10611
|
+
this.editor.registerCommand(we$1, handlingDefault(this.#selectPreviousTopLevelNode.bind(this)), io),
|
|
10612
|
+
this.editor.registerCommand(Ee$3, handlingDefault(this.#selectNextTopLevelNode.bind(this)), io),
|
|
10581
10613
|
|
|
10582
10614
|
this.editor.registerCommand(fe$4, this.#selectDecoratorNodeBeforeDeletion.bind(this), io),
|
|
10583
10615
|
|
|
@@ -10676,49 +10708,58 @@ class Selection {
|
|
|
10676
10708
|
}
|
|
10677
10709
|
}
|
|
10678
10710
|
|
|
10679
|
-
|
|
10680
|
-
if (event
|
|
10711
|
+
#selectPreviousNode(event) {
|
|
10712
|
+
if (event.shiftKey) {
|
|
10713
|
+
return this.#withCurrentNodeSelectionNode((currentNode) => {
|
|
10714
|
+
const selection = this.#rangeSelectDecorator(currentNode, "forward");
|
|
10681
10715
|
|
|
10682
|
-
|
|
10683
|
-
|
|
10716
|
+
// Can't rely on native pass-through with Playwright on firefox
|
|
10717
|
+
selection.modify("extend", true, "character");
|
|
10718
|
+
return true
|
|
10719
|
+
})
|
|
10684
10720
|
} else {
|
|
10685
|
-
return this.#
|
|
10721
|
+
return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.selectPrevious())
|
|
10722
|
+
|| this.#selectInLexical(this.nodeBeforeCursor)
|
|
10686
10723
|
}
|
|
10687
10724
|
}
|
|
10688
10725
|
|
|
10689
|
-
|
|
10690
|
-
if (event
|
|
10726
|
+
#selectNextNode(event) {
|
|
10727
|
+
if (event.shiftKey) {
|
|
10728
|
+
return this.#withCurrentNodeSelectionNode((currentNode) => {
|
|
10729
|
+
const selection = this.#rangeSelectDecorator(currentNode, "forward");
|
|
10691
10730
|
|
|
10692
|
-
|
|
10693
|
-
|
|
10731
|
+
// Can't rely on native pass-through with Playwright on firefox
|
|
10732
|
+
selection.modify("extend", false, "character");
|
|
10733
|
+
return true
|
|
10734
|
+
})
|
|
10694
10735
|
} else {
|
|
10695
|
-
return this.#
|
|
10736
|
+
return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.selectNext(0, 0))
|
|
10737
|
+
|| this.#selectInLexical(this.nodeAfterCursor)
|
|
10696
10738
|
}
|
|
10697
10739
|
}
|
|
10698
10740
|
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10741
|
+
#selectPreviousTopLevelNode() {
|
|
10742
|
+
return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.getTopLevelElement().selectPrevious())
|
|
10743
|
+
|| this.#selectInLexical(this.topLevelNodeBeforeCursor)
|
|
10744
|
+
}
|
|
10745
|
+
|
|
10746
|
+
#selectNextTopLevelNode() {
|
|
10747
|
+
return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.getTopLevelElement().selectNext(0, 0))
|
|
10748
|
+
|| this.#selectInLexical(this.topLevelNodeAfterCursor)
|
|
10705
10749
|
}
|
|
10706
10750
|
|
|
10707
|
-
|
|
10751
|
+
#withCurrentNodeSelectionNode(fn) {
|
|
10708
10752
|
if (this.hasNodeSelection) {
|
|
10709
|
-
return
|
|
10710
|
-
} else {
|
|
10711
|
-
return this.#selectInLexical(this.topLevelNodeAfterCursor)
|
|
10753
|
+
return fn(Qr().getNodes()[0])
|
|
10712
10754
|
}
|
|
10713
10755
|
}
|
|
10714
10756
|
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
});
|
|
10757
|
+
#rangeSelectDecorator(node, direction = "forward") {
|
|
10758
|
+
if (ji(node)) {
|
|
10759
|
+
const [ anchorOffset, focusOffset ] = direction === "forward" ? [ 0, 1 ] : [ 1, 0 ];
|
|
10760
|
+
const indexAtNode = node.getIndexWithinParent();
|
|
10761
|
+
|
|
10762
|
+
return node.getParent().select(indexAtNode + anchorOffset, indexAtNode + focusOffset)
|
|
10722
10763
|
}
|
|
10723
10764
|
}
|
|
10724
10765
|
|
|
@@ -11340,9 +11381,9 @@ function $findOrCreateGalleryForImage(node) {
|
|
|
11340
11381
|
class Uploader {
|
|
11341
11382
|
#files
|
|
11342
11383
|
|
|
11343
|
-
static for(editorElement, files) {
|
|
11384
|
+
static for(editorElement, files, options = {}) {
|
|
11344
11385
|
const UploaderKlass = GalleryUploader.handle(editorElement, files) ? GalleryUploader : Uploader;
|
|
11345
|
-
return new UploaderKlass(editorElement, files)
|
|
11386
|
+
return new UploaderKlass(editorElement, files, options)
|
|
11346
11387
|
}
|
|
11347
11388
|
|
|
11348
11389
|
constructor(editorElement, files, options = {}) {
|
|
@@ -11364,7 +11405,13 @@ class Uploader {
|
|
|
11364
11405
|
}
|
|
11365
11406
|
|
|
11366
11407
|
$createUploadNodes() {
|
|
11367
|
-
this.nodes = this.files.map(file => this
|
|
11408
|
+
this.nodes = this.files.map(file => this.#createUploadNode(file));
|
|
11409
|
+
}
|
|
11410
|
+
|
|
11411
|
+
#createUploadNode(file) {
|
|
11412
|
+
return this.options.pending
|
|
11413
|
+
? this.contents.$createPendingUploadNode(file)
|
|
11414
|
+
: this.contents.$createUploadNode(file)
|
|
11368
11415
|
}
|
|
11369
11416
|
|
|
11370
11417
|
$insertUploadNodes() {
|
|
@@ -11622,6 +11669,8 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
11622
11669
|
this.#dispatchEvent("lexxy:upload-start", { file: this.file });
|
|
11623
11670
|
|
|
11624
11671
|
upload.create((error, blob) => {
|
|
11672
|
+
this.#forgetUploadRequest();
|
|
11673
|
+
|
|
11625
11674
|
if (error) {
|
|
11626
11675
|
this.#dispatchEvent("lexxy:upload-end", { file: this.file, error });
|
|
11627
11676
|
this.#handleUploadError(error);
|
|
@@ -11644,12 +11693,26 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
11644
11693
|
directUploadWillStoreFileWithXHR: (request) => {
|
|
11645
11694
|
if (shouldAuthenticateUploads) request.withCredentials = true;
|
|
11646
11695
|
|
|
11696
|
+
this.#rememberUploadRequest(request);
|
|
11697
|
+
|
|
11647
11698
|
const uploadProgressHandler = (event) => this.#handleUploadProgress(event, request);
|
|
11648
11699
|
request.upload.addEventListener("progress", uploadProgressHandler);
|
|
11649
11700
|
}
|
|
11650
11701
|
}
|
|
11651
11702
|
}
|
|
11652
11703
|
|
|
11704
|
+
#forgetUploadRequest() {
|
|
11705
|
+
this.#editorElement.uploadRequests.forget(this.getKey());
|
|
11706
|
+
}
|
|
11707
|
+
|
|
11708
|
+
#rememberUploadRequest(request) {
|
|
11709
|
+
this.#editorElement.uploadRequests.track(this.getKey(), request);
|
|
11710
|
+
}
|
|
11711
|
+
|
|
11712
|
+
get #editorElement() {
|
|
11713
|
+
return this.editor.getRootElement()?.closest("lexxy-editor")
|
|
11714
|
+
}
|
|
11715
|
+
|
|
11653
11716
|
#setUploadStarted() {
|
|
11654
11717
|
this.#setProgress(1);
|
|
11655
11718
|
}
|
|
@@ -12027,11 +12090,6 @@ class Contents {
|
|
|
12027
12090
|
inserter.insertNodes(nodes);
|
|
12028
12091
|
}
|
|
12029
12092
|
|
|
12030
|
-
insertAtCursorEnsuringLineBelow(node) {
|
|
12031
|
-
this.insertAtCursor(node);
|
|
12032
|
-
this.#insertLineBelowIfLastNode(node);
|
|
12033
|
-
}
|
|
12034
|
-
|
|
12035
12093
|
applyParagraphFormat() {
|
|
12036
12094
|
const selection = Qr();
|
|
12037
12095
|
if (!Fr(selection)) return
|
|
@@ -12173,17 +12231,27 @@ class Contents {
|
|
|
12173
12231
|
const fullText = anchorNode.getTextContent();
|
|
12174
12232
|
const offset = anchor.offset;
|
|
12175
12233
|
|
|
12176
|
-
const
|
|
12177
|
-
|
|
12178
|
-
const lastIndex = textBeforeCursor.lastIndexOf(string);
|
|
12234
|
+
const lastIndex = fullText.slice(0, offset).lastIndexOf(string);
|
|
12179
12235
|
if (lastIndex !== -1) {
|
|
12180
|
-
result =
|
|
12236
|
+
result = fullText.slice(lastIndex + string.length, this.#endOffsetAt(fullText, offset));
|
|
12181
12237
|
}
|
|
12182
12238
|
});
|
|
12183
12239
|
|
|
12184
12240
|
return result
|
|
12185
12241
|
}
|
|
12186
12242
|
|
|
12243
|
+
// The query runs from the trigger up to the next whitespace, even when the
|
|
12244
|
+
// cursor sits inside an existing word — inserting "@" before "Jack" must
|
|
12245
|
+
// filter by "Jack" rather than treating the prompt as empty.
|
|
12246
|
+
#endOffsetAt(fullText, cursorOffset) {
|
|
12247
|
+
const whitespaceOffset = fullText.slice(cursorOffset).search(/\s/);
|
|
12248
|
+
if (whitespaceOffset === -1) {
|
|
12249
|
+
return fullText.length
|
|
12250
|
+
} else {
|
|
12251
|
+
return cursorOffset + whitespaceOffset
|
|
12252
|
+
}
|
|
12253
|
+
}
|
|
12254
|
+
|
|
12187
12255
|
containsTextBackUntil(string) {
|
|
12188
12256
|
let result = false;
|
|
12189
12257
|
|
|
@@ -12214,10 +12282,10 @@ class Contents {
|
|
|
12214
12282
|
const { anchorNode, offset } = this.#getTextAnchorData();
|
|
12215
12283
|
if (!anchorNode) return
|
|
12216
12284
|
|
|
12217
|
-
const lastIndex = this.#
|
|
12285
|
+
const lastIndex = this.#findReplacementStart(anchorNode, offset, stringToReplace);
|
|
12218
12286
|
if (lastIndex === -1) return
|
|
12219
12287
|
|
|
12220
|
-
this.#performTextReplacement(anchorNode, selection,
|
|
12288
|
+
this.#performTextReplacement(anchorNode, selection, lastIndex, stringToReplace, replacementNodes);
|
|
12221
12289
|
}
|
|
12222
12290
|
|
|
12223
12291
|
uploadFiles(files, { selectLast } = {}) {
|
|
@@ -12250,24 +12318,46 @@ class Contents {
|
|
|
12250
12318
|
})
|
|
12251
12319
|
}
|
|
12252
12320
|
|
|
12321
|
+
$createPendingUploadNode(file) {
|
|
12322
|
+
return $createActionTextAttachmentUploadNode({
|
|
12323
|
+
file,
|
|
12324
|
+
uploadUrl: null,
|
|
12325
|
+
blobUrlTemplate: this.editorElement.blobUrlTemplate,
|
|
12326
|
+
contentType: file.type,
|
|
12327
|
+
})
|
|
12328
|
+
}
|
|
12329
|
+
|
|
12253
12330
|
insertPendingAttachment(file) {
|
|
12254
12331
|
if (!this.editorElement.supportsAttachments) return null
|
|
12255
12332
|
|
|
12256
12333
|
let nodeKey = null;
|
|
12257
12334
|
this.editor.update(() => {
|
|
12258
|
-
const uploadNode =
|
|
12259
|
-
file,
|
|
12260
|
-
uploadUrl: null,
|
|
12261
|
-
blobUrlTemplate: this.editorElement.blobUrlTemplate,
|
|
12262
|
-
editor: this.editor
|
|
12263
|
-
});
|
|
12335
|
+
const uploadNode = this.$createPendingUploadNode(file);
|
|
12264
12336
|
this.insertAtCursor(uploadNode);
|
|
12265
12337
|
nodeKey = uploadNode.getKey();
|
|
12266
|
-
}
|
|
12338
|
+
});
|
|
12339
|
+
|
|
12340
|
+
return nodeKey ? this.#pendingAttachmentHandle(nodeKey) : null
|
|
12341
|
+
}
|
|
12267
12342
|
|
|
12268
|
-
|
|
12343
|
+
insertPendingAttachments(files) {
|
|
12344
|
+
const fileList = Array.from(files);
|
|
12345
|
+
if (!this.editorElement.supportsAttachments || fileList.length === 0) return []
|
|
12269
12346
|
|
|
12347
|
+
let nodeKeys = [];
|
|
12348
|
+
this.editor.update(() => {
|
|
12349
|
+
const uploader = Uploader.for(this.editorElement, fileList, { pending: true });
|
|
12350
|
+
uploader.$uploadFiles();
|
|
12351
|
+
nodeKeys = (uploader.nodes ?? []).map(node => node.getKey());
|
|
12352
|
+
});
|
|
12353
|
+
|
|
12354
|
+
return nodeKeys.map(nodeKey => this.#pendingAttachmentHandle(nodeKey))
|
|
12355
|
+
}
|
|
12356
|
+
|
|
12357
|
+
#pendingAttachmentHandle(initialNodeKey) {
|
|
12270
12358
|
const editor = this.editor;
|
|
12359
|
+
let nodeKey = initialNodeKey;
|
|
12360
|
+
|
|
12271
12361
|
return {
|
|
12272
12362
|
setAttributes(blob) {
|
|
12273
12363
|
editor.update(() => {
|
|
@@ -12472,17 +12562,6 @@ class Contents {
|
|
|
12472
12562
|
}
|
|
12473
12563
|
}
|
|
12474
12564
|
|
|
12475
|
-
#insertLineBelowIfLastNode(node) {
|
|
12476
|
-
this.editor.update(() => {
|
|
12477
|
-
const nextSibling = node.getNextSibling();
|
|
12478
|
-
if (!nextSibling) {
|
|
12479
|
-
const newParagraph = eo();
|
|
12480
|
-
node.insertAfter(newParagraph);
|
|
12481
|
-
newParagraph.selectStart();
|
|
12482
|
-
}
|
|
12483
|
-
});
|
|
12484
|
-
}
|
|
12485
|
-
|
|
12486
12565
|
#unwrap(node) {
|
|
12487
12566
|
const children = node.getChildren();
|
|
12488
12567
|
|
|
@@ -12515,19 +12594,27 @@ class Contents {
|
|
|
12515
12594
|
return { anchorNode, offset: anchor.offset }
|
|
12516
12595
|
}
|
|
12517
12596
|
|
|
12518
|
-
|
|
12597
|
+
// The replaced span can straddle the cursor (e.g. "@Jack" when "@" was just
|
|
12598
|
+
// inserted before "Jack"), so we anchor on the trigger before the cursor and
|
|
12599
|
+
// verify the whole string matches there rather than searching text up to it.
|
|
12600
|
+
#findReplacementStart(anchorNode, offset, stringToReplace) {
|
|
12519
12601
|
const fullText = anchorNode.getTextContent();
|
|
12520
|
-
const
|
|
12521
|
-
|
|
12602
|
+
const triggerIndex = fullText.slice(0, offset).lastIndexOf(stringToReplace[0]);
|
|
12603
|
+
|
|
12604
|
+
if (triggerIndex !== -1 && fullText.startsWith(stringToReplace, triggerIndex)) {
|
|
12605
|
+
return triggerIndex
|
|
12606
|
+
} else {
|
|
12607
|
+
return -1
|
|
12608
|
+
}
|
|
12522
12609
|
}
|
|
12523
12610
|
|
|
12524
|
-
#performTextReplacement(anchorNode, selection,
|
|
12611
|
+
#performTextReplacement(anchorNode, selection, startIndex, stringToReplace, replacementNodes) {
|
|
12525
12612
|
const fullText = anchorNode.getTextContent();
|
|
12526
|
-
const textBeforeString = fullText.slice(0,
|
|
12527
|
-
const
|
|
12613
|
+
const textBeforeString = fullText.slice(0, startIndex);
|
|
12614
|
+
const textAfterString = fullText.slice(startIndex + stringToReplace.length);
|
|
12528
12615
|
|
|
12529
12616
|
const textNodeBefore = this.#cloneTextNodeFormatting(anchorNode, selection, textBeforeString);
|
|
12530
|
-
const textNodeAfter = this.#cloneTextNodeFormatting(anchorNode, selection,
|
|
12617
|
+
const textNodeAfter = this.#cloneTextNodeFormatting(anchorNode, selection, textAfterString || " ");
|
|
12531
12618
|
|
|
12532
12619
|
anchorNode.replace(textNodeBefore);
|
|
12533
12620
|
|
|
@@ -12535,7 +12622,7 @@ class Contents {
|
|
|
12535
12622
|
lastInsertedNode.insertAfter(textNodeAfter);
|
|
12536
12623
|
|
|
12537
12624
|
this.#appendLineBreakIfNeeded(textNodeAfter.getParentOrThrow());
|
|
12538
|
-
const cursorOffset =
|
|
12625
|
+
const cursorOffset = textAfterString ? 0 : 1;
|
|
12539
12626
|
textNodeAfter.select(cursorOffset, cursorOffset);
|
|
12540
12627
|
}
|
|
12541
12628
|
|
|
@@ -13851,11 +13938,12 @@ class AttachmentsExtension extends LexxyExtension {
|
|
|
13851
13938
|
|
|
13852
13939
|
#handleUploadMutations(mutations) {
|
|
13853
13940
|
const previousUploadsCount = this.#uploadsCount;
|
|
13854
|
-
for (const [ , mutation ] of mutations) {
|
|
13941
|
+
for (const [ key, mutation ] of mutations) {
|
|
13855
13942
|
if (mutation === "created") {
|
|
13856
13943
|
this.#uploadsCount++;
|
|
13857
13944
|
} else if (mutation === "destroyed") {
|
|
13858
13945
|
this.#uploadsCount--;
|
|
13946
|
+
this.editorElement.uploadRequests.abort(key);
|
|
13859
13947
|
}
|
|
13860
13948
|
}
|
|
13861
13949
|
|
|
@@ -14299,6 +14387,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14299
14387
|
|
|
14300
14388
|
#validity = new Map()
|
|
14301
14389
|
#validationTextArea = document.createElement("textarea")
|
|
14390
|
+
#uploadRequests
|
|
14302
14391
|
|
|
14303
14392
|
constructor() {
|
|
14304
14393
|
super();
|
|
@@ -14306,6 +14395,10 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14306
14395
|
this.internals.role = "presentation";
|
|
14307
14396
|
}
|
|
14308
14397
|
|
|
14398
|
+
get uploadRequests() {
|
|
14399
|
+
return this.#uploadRequests
|
|
14400
|
+
}
|
|
14401
|
+
|
|
14309
14402
|
connectedCallback() {
|
|
14310
14403
|
this.id ||= generateDomId("lexxy-editor");
|
|
14311
14404
|
this.config = new EditorConfiguration(this);
|
|
@@ -14326,6 +14419,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14326
14419
|
this.#disposables.push(this.clipboard);
|
|
14327
14420
|
|
|
14328
14421
|
this.adapter = new BrowserAdapter();
|
|
14422
|
+
this.#uploadRequests = new UploadRequests();
|
|
14329
14423
|
|
|
14330
14424
|
const commandDispatcher = CommandDispatcher.configureFor(this);
|
|
14331
14425
|
this.#disposables.push(commandDispatcher);
|
|
@@ -15099,6 +15193,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
15099
15193
|
#reset() {
|
|
15100
15194
|
this.#dispose();
|
|
15101
15195
|
this.#resetValidity();
|
|
15196
|
+
this.#uploadRequests?.clear();
|
|
15102
15197
|
this.editorContentElement?.remove();
|
|
15103
15198
|
this.editorContentElement = null;
|
|
15104
15199
|
|
|
@@ -15465,24 +15560,33 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
15465
15560
|
const { node, offset } = this.#selection.selectedNodeWithOffset();
|
|
15466
15561
|
if (!node) return
|
|
15467
15562
|
|
|
15468
|
-
if (
|
|
15469
|
-
|
|
15470
|
-
const textBeforeCursor = fullText.slice(0, offset);
|
|
15471
|
-
const lastTriggerIndex = textBeforeCursor.lastIndexOf(this.trigger);
|
|
15472
|
-
const triggerEndIndex = lastTriggerIndex + this.trigger.length - 1;
|
|
15473
|
-
|
|
15474
|
-
// If trigger is not found, or cursor is at or before the trigger end position, hide popover
|
|
15475
|
-
if (lastTriggerIndex === -1 || offset <= triggerEndIndex) {
|
|
15476
|
-
this.#hidePopover();
|
|
15477
|
-
}
|
|
15563
|
+
if (this.#cursorIsTypingSearchTerm(node, offset)) {
|
|
15564
|
+
return
|
|
15478
15565
|
} else {
|
|
15479
|
-
// Cursor is not in a text node or at offset 0, hide popover
|
|
15480
15566
|
this.#hidePopover();
|
|
15481
15567
|
}
|
|
15482
15568
|
});
|
|
15483
15569
|
}));
|
|
15484
15570
|
}
|
|
15485
15571
|
|
|
15572
|
+
// The popover should stay open only while the cursor sits at the end of the
|
|
15573
|
+
// trigger and its search term. When the cursor moves away — before the
|
|
15574
|
+
// trigger, or past the token into later text — the text between the trigger
|
|
15575
|
+
// and the cursor breaks that run and we dismiss. A newline always breaks the
|
|
15576
|
+
// run; a space breaks it only for triggers that don't support spaces in
|
|
15577
|
+
// searches, since those that do (e.g. `person:`) expect multi-word terms.
|
|
15578
|
+
#cursorIsTypingSearchTerm(node, offset) {
|
|
15579
|
+
if (!Tr(node) || offset === 0) return false
|
|
15580
|
+
|
|
15581
|
+
const textBeforeCursor = node.getTextContent().slice(0, offset);
|
|
15582
|
+
const lastTriggerIndex = textBeforeCursor.lastIndexOf(this.trigger);
|
|
15583
|
+
if (lastTriggerIndex === -1) return false
|
|
15584
|
+
|
|
15585
|
+
const searchTerm = textBeforeCursor.slice(lastTriggerIndex + this.trigger.length);
|
|
15586
|
+
const breakPattern = this.supportsSpaceInSearches ? /\n/ : /[ \n]/;
|
|
15587
|
+
return !breakPattern.test(searchTerm)
|
|
15588
|
+
}
|
|
15589
|
+
|
|
15486
15590
|
get #editor() {
|
|
15487
15591
|
return this.#editorElement.editor
|
|
15488
15592
|
}
|
|
Binary file
|
|
Binary file
|